1 /* Copyright (c) 2007 Corinna Vinschen <corinna@vinschen.de> */ 2 /* 3 FUNCTION 4 <<stpcpy>>---copy string returning a pointer to its end 5 6 INDEX 7 stpcpy 8 9 SYNOPSIS 10 #include <string.h> 11 char *stpcpy(char *restrict <[dst]>, const char *restrict <[src]>); 12 13 DESCRIPTION 14 <<stpcpy>> copies the string pointed to by <[src]> 15 (including the terminating null character) to the array 16 pointed to by <[dst]>. 17 18 RETURNS 19 This function returns a pointer to the end of the destination string, 20 thus pointing to the trailing '\0'. 21 22 PORTABILITY 23 <<stpcpy>> is a GNU extension, candidate for inclusion into POSIX/SUSv4. 24 25 <<stpcpy>> requires no supporting OS subroutines. 26 27 QUICKREF 28 stpcpy gnu 29 */ 30 31 #include <string.h> 32 #include <limits.h> 33 #include <stdint.h> 34 35 /*SUPPRESS 560*/ 36 /*SUPPRESS 530*/ 37 38 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 39 #define UNALIGNED(X, Y) \ 40 (((uintptr_t)X & (sizeof (long) - 1)) | ((uintptr_t)Y & (sizeof (long) - 1))) 41 42 #if LONG_MAX == 2147483647L 43 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) 44 #else 45 #if LONG_MAX == 9223372036854775807L 46 /* Nonzero if X (a long int) contains a NULL byte. */ 47 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 48 #else 49 #error long int is not a 32bit or 64bit type. 50 #endif 51 #endif 52 53 #ifndef DETECTNULL 54 #error long int is not a 32bit or 64bit byte 55 #endif 56 57 char* stpcpy(char * __restrict dst,const char * __restrict src)58stpcpy (char *__restrict dst, 59 const char *__restrict src) 60 { 61 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && \ 62 !defined(PICOLIBC_NO_OUT_OF_BOUNDS_READS) 63 long *aligned_dst; 64 const long *aligned_src; 65 66 /* If SRC or DEST is unaligned, then copy bytes. */ 67 if (!UNALIGNED (src, dst)) 68 { 69 aligned_dst = (long*)dst; 70 aligned_src = (long*)src; 71 72 /* SRC and DEST are both "long int" aligned, try to do "long int" 73 sized copies. */ 74 while (!DETECTNULL(*aligned_src)) 75 { 76 *aligned_dst++ = *aligned_src++; 77 } 78 79 dst = (char*)aligned_dst; 80 src = (char*)aligned_src; 81 } 82 #endif /* not PREFER_SIZE_OVER_SPEED */ 83 84 while ((*dst++ = *src++)) 85 ; 86 return --dst; 87 } 88