Subversion Repositories Kolibri OS

Rev

Rev 4874 | Blame | Compare with Previous | 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 *restrict <[dst]>, const char *restrict <[src]>,
  11.                       size_t <[length]>);
  12.  
  13. TRAD_SYNOPSIS
  14.         #include <string.h>
  15.         char *strncat(<[dst]>, <[src]>, <[length]>)
  16.         char *<[dst]>;
  17.         char *<[src]>;
  18.         size_t <[length]>;
  19.  
  20. DESCRIPTION
  21.         <<strncat>> appends not more than <[length]> characters from
  22.         the string pointed to by <[src]> (including the terminating
  23.         null character) to the end of the string pointed to by
  24.         <[dst]>.  The initial character of <[src]> overwrites the null
  25.         character at the end of <[dst]>.  A terminating null character
  26.         is always appended to the result
  27.  
  28. WARNINGS
  29.         Note that a null is always appended, so that if the copy is
  30.         limited by the <[length]> argument, the number of characters
  31.         appended to <[dst]> is <<n + 1>>.
  32.  
  33. RETURNS
  34.         This function returns the initial value of <[dst]>
  35.  
  36. PORTABILITY
  37. <<strncat>> is ANSI C.
  38.  
  39. <<strncat>> requires no supporting OS subroutines.
  40.  
  41. QUICKREF
  42.         strncat ansi pure
  43. */
  44.  
  45. #include <string.h>
  46. #include <limits.h>
  47.  
  48. /* Nonzero if X is aligned on a "long" boundary.  */
  49. #define ALIGNED(X) \
  50.   (((long)X & (sizeof (long) - 1)) == 0)
  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. char *
  68. _DEFUN (strncat, (s1, s2, n),
  69.         char *__restrict s1 _AND
  70.         _CONST char *__restrict s2 _AND
  71.         size_t n)
  72. {
  73. #if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
  74.   char *s = s1;
  75.  
  76.   while (*s1)
  77.     s1++;
  78.   while (n-- != 0 && (*s1++ = *s2++))
  79.     {
  80.       if (n == 0)
  81.         *s1 = '\0';
  82.     }
  83.  
  84.   return s;
  85. #else
  86.   char *s = s1;
  87.  
  88.   /* Skip over the data in s1 as quickly as possible.  */
  89.   if (ALIGNED (s1))
  90.     {
  91.       unsigned long *aligned_s1 = (unsigned long *)s1;
  92.       while (!DETECTNULL (*aligned_s1))
  93.         aligned_s1++;
  94.  
  95.       s1 = (char *)aligned_s1;
  96.     }
  97.  
  98.   while (*s1)
  99.     s1++;
  100.  
  101.   /* s1 now points to the its trailing null character, now copy
  102.      up to N bytes from S2 into S1 stopping if a NULL is encountered
  103.      in S2.
  104.  
  105.      It is not safe to use strncpy here since it copies EXACTLY N
  106.      characters, NULL padding if necessary.  */
  107.   while (n-- != 0 && (*s1++ = *s2++))
  108.     {
  109.       if (n == 0)
  110.         *s1 = '\0';
  111.     }
  112.        
  113.   return s;
  114. #endif /* not PREFER_SIZE_OVER_SPEED */
  115. }
  116.