Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2. FUNCTION
  3.         <<strncat>>---concatenate strings
  4.  
  5. INDEX
  6.         strncat
  7.  
  8. ANSI_SYNOPSIS
  9.         #include <string.h>
  10.         char *strncat(char *<[dst]>, const char *<[src]>, size_t <[length]>);
  11.  
  12. TRAD_SYNOPSIS
  13.         #include <string.h>
  14.         char *strncat(<[dst]>, <[src]>, <[length]>)
  15.         char *<[dst]>;
  16.         char *<[src]>;
  17.         size_t <[length]>;
  18.  
  19. DESCRIPTION
  20.         <<strncat>> appends not more than <[length]> characters from
  21.         the string pointed to by <[src]> (including the terminating
  22.         null character) to the end of the string pointed to by
  23.         <[dst]>.  The initial character of <[src]> overwrites the null
  24.         character at the end of <[dst]>.  A terminating null character
  25.         is always appended to the result
  26.  
  27. WARNINGS
  28.         Note that a null is always appended, so that if the copy is
  29.         limited by the <[length]> argument, the number of characters
  30.         appended to <[dst]> is <<n + 1>>.
  31.  
  32. RETURNS
  33.         This function returns the initial value of <[dst]>
  34.  
  35. PORTABILITY
  36. <<strncat>> is ANSI C.
  37.  
  38. <<strncat>> requires no supporting OS subroutines.
  39.  
  40. QUICKREF
  41.         strncat ansi pure
  42. */
  43.  
  44. #include <string.h>
  45. #include <limits.h>
  46.  
  47. /* Nonzero if X is aligned on a "long" boundary.  */
  48. #define ALIGNED(X) \
  49.   (((long)X & (sizeof (long) - 1)) == 0)
  50.  
  51. #if LONG_MAX == 2147483647L
  52. #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080)
  53. #else
  54. #if LONG_MAX == 9223372036854775807L
  55. /* Nonzero if X (a long int) contains a NULL byte. */
  56. #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080)
  57. #else
  58. #error long int is not a 32bit or 64bit type.
  59. #endif
  60. #endif
  61.  
  62. #ifndef DETECTNULL
  63. #error long int is not a 32bit or 64bit byte
  64. #endif
  65.  
  66. char *
  67. _DEFUN (strncat, (s1, s2, n),
  68.         char *s1 _AND
  69.         _CONST char *s2 _AND
  70.         size_t n)
  71. {
  72. #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
  73.   char *s = s1;
  74.  
  75.   while (*s1)
  76.     s1++;
  77.   while (n-- != 0 && (*s1++ = *s2++))
  78.     {
  79.       if (n == 0)
  80.         *s1 = '\0';
  81.     }
  82.  
  83.   return s;
  84. #else
  85.   char *s = s1;
  86.  
  87.   /* Skip over the data in s1 as quickly as possible.  */
  88.   if (ALIGNED (s1))
  89.     {
  90.       unsigned long *aligned_s1 = (unsigned long *)s1;
  91.       while (!DETECTNULL (*aligned_s1))
  92.         aligned_s1++;
  93.  
  94.       s1 = (char *)aligned_s1;
  95.     }
  96.  
  97.   while (*s1)
  98.     s1++;
  99.  
  100.   /* s1 now points to the its trailing null character, now copy
  101.      up to N bytes from S2 into S1 stopping if a NULL is encountered
  102.      in S2.
  103.  
  104.      It is not safe to use strncpy here since it copies EXACTLY N
  105.      characters, NULL padding if necessary.  */
  106.   while (n-- != 0 && (*s1++ = *s2++))
  107.     {
  108.       if (n == 0)
  109.         *s1 = '\0';
  110.     }
  111.        
  112.   return s;
  113. #endif /* not PREFER_SIZE_OVER_SPEED */
  114. }
  115.