Subversion Repositories Kolibri OS

Rev

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