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 #define IN_STPCPY 32 #define _GNU_SOURCE 33 #include <string.h> 34 #include <limits.h> 35 #include <stdint.h> 36 37 /*SUPPRESS 560*/ 38 /*SUPPRESS 530*/ 39 40 /* Nonzero if either X or Y is not aligned on a "long" boundary. */ 41 #define UNALIGNED(X, Y) \ 42 (((uintptr_t)X & (sizeof (long) - 1)) | ((uintptr_t)Y & (sizeof (long) - 1))) 43 44 #if LONG_MAX == 2147483647L 45 #define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) 46 #else 47 #if LONG_MAX == 9223372036854775807L 48 /* Nonzero if X (a long int) contains a NULL byte. */ 49 #define DETECTNULL(X) (((X) - 0x0101010101010101) & ~(X) & 0x8080808080808080) 50 #else 51 #error long int is not a 32bit or 64bit type. 52 #endif 53 #endif 54 55 #ifndef DETECTNULL 56 #error long int is not a 32bit or 64bit byte 57 #endif 58 59 char* stpcpy(char * __restrict dst,const char * __restrict src)60stpcpy (char *__restrict dst, 61 const char *__restrict src) 62 { 63 #if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__) && \ 64 !defined(PICOLIBC_NO_OUT_OF_BOUNDS_READS) 65 long *aligned_dst; 66 const long *aligned_src; 67 68 /* If SRC or DEST is unaligned, then copy bytes. */ 69 if (!UNALIGNED (src, dst)) 70 { 71 aligned_dst = (long*)dst; 72 aligned_src = (long*)src; 73 74 /* SRC and DEST are both "long int" aligned, try to do "long int" 75 sized copies. */ 76 while (!DETECTNULL(*aligned_src)) 77 { 78 *aligned_dst++ = *aligned_src++; 79 } 80 81 dst = (char*)aligned_dst; 82 src = (char*)aligned_src; 83 } 84 #endif /* not PREFER_SIZE_OVER_SPEED */ 85 86 while ((*dst++ = *src++)) 87 ; 88 return --dst; 89 } 90