Subversion Repositories Kolibri OS

Rev

Rev 4874 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2. FUNCTION
  3.         <<stpncpy>>---counted copy string returning a pointer to its end
  4.  
  5. INDEX
  6.         stpncpy
  7.  
  8. ANSI_SYNOPSIS
  9.         #include <string.h>
  10.         char *stpncpy(char *restrict <[dst]>, const char *restrict <[src]>,
  11.                       size_t <[length]>);
  12.  
  13. TRAD_SYNOPSIS
  14.         #include <string.h>
  15.         char *stpncpy(<[dst]>, <[src]>, <[length]>)
  16.         char *<[dst]>;
  17.         char *<[src]>;
  18.         size_t <[length]>;
  19.  
  20. DESCRIPTION
  21.         <<stpncpy>> copies not more than <[length]> characters from the
  22.         the string pointed to by <[src]> (including the terminating
  23.         null character) to the array pointed to by <[dst]>.  If the
  24.         string pointed to by <[src]> is shorter than <[length]>
  25.         characters, null characters are appended to the destination
  26.         array until a total of <[length]> characters have been
  27.         written.
  28.  
  29. RETURNS
  30.         This function returns a pointer to the end of the destination string,
  31.         thus pointing to the trailing '\0', or, if the destination string is
  32.         not null-terminated, pointing to dst + n.
  33.  
  34. PORTABILITY
  35. <<stpncpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4.
  36.  
  37. <<stpncpy>> requires no supporting OS subroutines.
  38.  
  39. QUICKREF
  40.         stpncpy gnu
  41. */
  42.  
  43. #include <string.h>
  44. #include <limits.h>
  45.  
  46. /*SUPPRESS 560*/
  47. /*SUPPRESS 530*/
  48.  
  49. /* Nonzero if either X or Y is not aligned on a "long" boundary.  */
  50. #define UNALIGNED(X, Y) \
  51.   (((long)X & (sizeof (long) - 1)) | ((long)Y & (sizeof (long) - 1)))
  52.  
  53. #if LONG_MAX == 2147483647L
  54. #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
  55. #else
  56. #if LONG_MAX == 9223372036854775807L
  57. /* Nonzero if X (a long int) contains a NULL byte. */
  58. #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
  59. #else
  60. #error long int is not a 32bit or 64bit type.
  61. #endif
  62. #endif
  63.  
  64. #ifndef DETECTNULL
  65. #error long int is not a 32bit or 64bit byte
  66. #endif
  67.  
  68. #define TOO_SMALL(LEN) ((LEN) < sizeof (long))
  69.  
  70. char *
  71. _DEFUN (stpncpy, (dst, src),
  72.         char *__restrict dst _AND
  73.         _CONST char *__restrict src _AND
  74.         size_t count)
  75. {
  76.   char *ret = NULL;
  77.  
  78. #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
  79.   long *aligned_dst;
  80.   _CONST long *aligned_src;
  81.  
  82.   /* If SRC and DEST is aligned and count large enough, then copy words.  */
  83.   if (!UNALIGNED (src, dst) && !TOO_SMALL (count))
  84.     {
  85.       aligned_dst = (long*)dst;
  86.       aligned_src = (long*)src;
  87.  
  88.       /* SRC and DEST are both "long int" aligned, try to do "long int"
  89.          sized copies.  */
  90.       while (count >= sizeof (long int) && !DETECTNULL(*aligned_src))
  91.         {
  92.           count -= sizeof (long int);
  93.           *aligned_dst++ = *aligned_src++;
  94.         }
  95.  
  96.       dst = (char*)aligned_dst;
  97.       src = (char*)aligned_src;
  98.     }
  99. #endif /* not PREFER_SIZE_OVER_SPEED */
  100.  
  101.   while (count > 0)
  102.     {
  103.       --count;
  104.       if ((*dst++ = *src++) == '\0')
  105.         {
  106.           ret = dst - 1;
  107.           break;
  108.         }
  109.     }
  110.  
  111.   while (count-- > 0)
  112.     *dst++ = '\0';
  113.  
  114.   return ret ? ret : dst;
  115. }
  116.