1 /* Machine-independant string function optimizations.
2 Copyright (C) 1997-2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
21 # error "Never use <bits/string2.h> directly; include <string.h> instead."
24 #ifndef __NO_STRING_INLINES
26 /* Unlike the definitions in the header <bits/string.h> the
27 definitions contained here are not optimized down to assembler
28 level. Those optimizations are not always a good idea since this
29 means the code size increases a lot. Instead the definitions here
30 optimize some functions in a way which do not dramatically
31 increase the code size and which do not use assembler. The main
32 trick is to use GCC's `__builtin_constant_p' function.
34 Every function XXX which has a defined version in
35 <bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX
36 to make sure we don't get redefinitions.
38 We must use here macros instead of inline functions since the
39 trick won't work with the latter. */
41 #ifndef __STRING_INLINE
43 # define __STRING_INLINE inline
45 # define __STRING_INLINE __extern_inline
49 #if _STRING_INLINE_unaligned
50 # include <bits/types.h>
52 /* These are a few types we need for the optimizations if we cannot
53 use unaligned memory accesses. */
54 # define __STRING2_COPY_TYPE(N) \
55 typedef struct { unsigned char __arr[N]; } \
56 __attribute__ ((__packed__)) __STRING2_COPY_ARR##N
57 __STRING2_COPY_TYPE (2);
58 __STRING2_COPY_TYPE (3);
59 __STRING2_COPY_TYPE (4);
60 __STRING2_COPY_TYPE (5);
61 __STRING2_COPY_TYPE (6);
62 __STRING2_COPY_TYPE (7);
63 __STRING2_COPY_TYPE (8);
64 # undef __STRING2_COPY_TYPE
67 /* Dereferencing a pointer arg to run sizeof on it fails for the void
68 pointer case, so we use this instead.
69 Note that __x is evaluated twice. */
70 #define __string2_1bptr_p(__x) \
71 ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
73 /* Set N bytes of S to C. */
74 #if !defined _HAVE_STRING_ARCH_memset
75 # define __bzero(s, n) __builtin_memset (s, '\0', n)
78 # if defined _FORCE_INLINES
79 # if _STRING_INLINE_unaligned
80 __STRING_INLINE
void *
81 __mempcpy_small (void *__dest1
,
82 char __src0_1
, char __src2_1
, char __src4_1
, char __src6_1
,
83 __uint16_t __src0_2
, __uint16_t __src4_2
,
84 __uint32_t __src0_4
, __uint32_t __src4_4
,
93 switch ((unsigned int) __srclen
)
97 __u
= __extension__ ((void *) __u
+ 1);
100 __u
->__usi
= __src0_2
;
101 __u
= __extension__ ((void *) __u
+ 2);
104 __u
->__usi
= __src0_2
;
105 __u
= __extension__ ((void *) __u
+ 2);
107 __u
= __extension__ ((void *) __u
+ 1);
110 __u
->__ui
= __src0_4
;
111 __u
= __extension__ ((void *) __u
+ 4);
114 __u
->__ui
= __src0_4
;
115 __u
= __extension__ ((void *) __u
+ 4);
117 __u
= __extension__ ((void *) __u
+ 1);
120 __u
->__ui
= __src0_4
;
121 __u
= __extension__ ((void *) __u
+ 4);
122 __u
->__usi
= __src4_2
;
123 __u
= __extension__ ((void *) __u
+ 2);
126 __u
->__ui
= __src0_4
;
127 __u
= __extension__ ((void *) __u
+ 4);
128 __u
->__usi
= __src4_2
;
129 __u
= __extension__ ((void *) __u
+ 2);
131 __u
= __extension__ ((void *) __u
+ 1);
134 __u
->__ui
= __src0_4
;
135 __u
= __extension__ ((void *) __u
+ 4);
136 __u
->__ui
= __src4_4
;
137 __u
= __extension__ ((void *) __u
+ 4);
143 __STRING_INLINE
void *
144 __mempcpy_small (void *__dest
, char __src1
,
145 __STRING2_COPY_ARR2 __src2
, __STRING2_COPY_ARR3 __src3
,
146 __STRING2_COPY_ARR4 __src4
, __STRING2_COPY_ARR5 __src5
,
147 __STRING2_COPY_ARR6 __src6
, __STRING2_COPY_ARR7 __src7
,
148 __STRING2_COPY_ARR8 __src8
, size_t __srclen
)
152 __STRING2_COPY_ARR2 __sca2
;
153 __STRING2_COPY_ARR3 __sca3
;
154 __STRING2_COPY_ARR4 __sca4
;
155 __STRING2_COPY_ARR5 __sca5
;
156 __STRING2_COPY_ARR6 __sca6
;
157 __STRING2_COPY_ARR7 __sca7
;
158 __STRING2_COPY_ARR8 __sca8
;
160 switch ((unsigned int) __srclen
)
166 __extension__ __u
->__sca2
= __src2
;
169 __extension__ __u
->__sca3
= __src3
;
172 __extension__ __u
->__sca4
= __src4
;
175 __extension__ __u
->__sca5
= __src5
;
178 __extension__ __u
->__sca6
= __src6
;
181 __extension__ __u
->__sca7
= __src7
;
184 __extension__ __u
->__sca8
= __src8
;
187 return __extension__ ((void *) __u
+ __srclen
);
193 /* Return pointer to C in S. */
194 #ifndef _HAVE_STRING_ARCH_strchr
195 extern void *__rawmemchr (const void *__s
, int __c
);
196 # define strchr(s, c) \
197 (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \
199 ? (char *) __rawmemchr (s, c) \
200 : __builtin_strchr (s, c)))
204 /* Copy SRC to DEST. */
205 #if defined _FORCE_INLINES
206 # if _STRING_INLINE_unaligned
207 __STRING_INLINE
char *
208 __strcpy_small (char *__dest
,
209 __uint16_t __src0_2
, __uint16_t __src4_2
,
210 __uint32_t __src0_4
, __uint32_t __src4_4
,
217 } *__u
= (void *) __dest
;
218 switch ((unsigned int) __srclen
)
224 __u
->__usi
= __src0_2
;
227 __u
->__usi
= __src0_2
;
228 __u
= __extension__ ((void *) __u
+ 2);
232 __u
->__ui
= __src0_4
;
235 __u
->__ui
= __src0_4
;
236 __u
= __extension__ ((void *) __u
+ 4);
240 __u
->__ui
= __src0_4
;
241 __u
= __extension__ ((void *) __u
+ 4);
242 __u
->__usi
= __src4_2
;
245 __u
->__ui
= __src0_4
;
246 __u
= __extension__ ((void *) __u
+ 4);
247 __u
->__usi
= __src4_2
;
248 __u
= __extension__ ((void *) __u
+ 2);
252 __u
->__ui
= __src0_4
;
253 __u
= __extension__ ((void *) __u
+ 4);
254 __u
->__ui
= __src4_4
;
260 __STRING_INLINE
char *
261 __strcpy_small (char *__dest
,
262 __STRING2_COPY_ARR2 __src2
, __STRING2_COPY_ARR3 __src3
,
263 __STRING2_COPY_ARR4 __src4
, __STRING2_COPY_ARR5 __src5
,
264 __STRING2_COPY_ARR6 __src6
, __STRING2_COPY_ARR7 __src7
,
265 __STRING2_COPY_ARR8 __src8
, size_t __srclen
)
269 __STRING2_COPY_ARR2 __sca2
;
270 __STRING2_COPY_ARR3 __sca3
;
271 __STRING2_COPY_ARR4 __sca4
;
272 __STRING2_COPY_ARR5 __sca5
;
273 __STRING2_COPY_ARR6 __sca6
;
274 __STRING2_COPY_ARR7 __sca7
;
275 __STRING2_COPY_ARR8 __sca8
;
276 } *__u
= (void *) __dest
;
277 switch ((unsigned int) __srclen
)
283 __extension__ __u
->__sca2
= __src2
;
286 __extension__ __u
->__sca3
= __src3
;
289 __extension__ __u
->__sca4
= __src4
;
292 __extension__ __u
->__sca5
= __src5
;
295 __extension__ __u
->__sca6
= __src6
;
298 __extension__ __u
->__sca7
= __src7
;
301 __extension__ __u
->__sca8
= __src8
;
310 /* Copy SRC to DEST, returning pointer to final NUL byte. */
312 # ifndef _HAVE_STRING_ARCH_stpcpy
313 # define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
314 /* In glibc we use this function frequently but for namespace reasons
315 we have to use the name `__stpcpy'. */
316 # define stpcpy(dest, src) __stpcpy (dest, src)
319 # if defined _FORCE_INLINES
320 # if _STRING_INLINE_unaligned
321 __STRING_INLINE
char *
322 __stpcpy_small (char *__dest
,
323 __uint16_t __src0_2
, __uint16_t __src4_2
,
324 __uint32_t __src0_4
, __uint32_t __src4_4
,
329 unsigned short int __usi
;
332 } *__u
= (void *) __dest
;
333 switch ((unsigned int) __srclen
)
339 __u
->__usi
= __src0_2
;
340 __u
= __extension__ ((void *) __u
+ 1);
343 __u
->__usi
= __src0_2
;
344 __u
= __extension__ ((void *) __u
+ 2);
348 __u
->__ui
= __src0_4
;
349 __u
= __extension__ ((void *) __u
+ 3);
352 __u
->__ui
= __src0_4
;
353 __u
= __extension__ ((void *) __u
+ 4);
357 __u
->__ui
= __src0_4
;
358 __u
= __extension__ ((void *) __u
+ 4);
359 __u
->__usi
= __src4_2
;
360 __u
= __extension__ ((void *) __u
+ 1);
363 __u
->__ui
= __src0_4
;
364 __u
= __extension__ ((void *) __u
+ 4);
365 __u
->__usi
= __src4_2
;
366 __u
= __extension__ ((void *) __u
+ 2);
370 __u
->__ui
= __src0_4
;
371 __u
= __extension__ ((void *) __u
+ 4);
372 __u
->__ui
= __src4_4
;
373 __u
= __extension__ ((void *) __u
+ 3);
379 __STRING_INLINE
char *
380 __stpcpy_small (char *__dest
,
381 __STRING2_COPY_ARR2 __src2
, __STRING2_COPY_ARR3 __src3
,
382 __STRING2_COPY_ARR4 __src4
, __STRING2_COPY_ARR5 __src5
,
383 __STRING2_COPY_ARR6 __src6
, __STRING2_COPY_ARR7 __src7
,
384 __STRING2_COPY_ARR8 __src8
, size_t __srclen
)
388 __STRING2_COPY_ARR2 __sca2
;
389 __STRING2_COPY_ARR3 __sca3
;
390 __STRING2_COPY_ARR4 __sca4
;
391 __STRING2_COPY_ARR5 __sca5
;
392 __STRING2_COPY_ARR6 __sca6
;
393 __STRING2_COPY_ARR7 __sca7
;
394 __STRING2_COPY_ARR8 __sca8
;
395 } *__u
= (void *) __dest
;
396 switch ((unsigned int) __srclen
)
402 __extension__ __u
->__sca2
= __src2
;
405 __extension__ __u
->__sca3
= __src3
;
408 __extension__ __u
->__sca4
= __src4
;
411 __extension__ __u
->__sca5
= __src5
;
414 __extension__ __u
->__sca6
= __src6
;
417 __extension__ __u
->__sca7
= __src7
;
420 __extension__ __u
->__sca8
= __src8
;
423 return __dest
+ __srclen
- 1;
430 /* Copy no more than N characters of SRC to DEST. */
431 #ifndef _HAVE_STRING_ARCH_strncpy
432 # define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)
436 /* Append no more than N characters from SRC onto DEST. */
437 #ifndef _HAVE_STRING_ARCH_strncat
438 # ifdef _USE_STRING_ARCH_strchr
439 # define strncat(dest, src, n) \
440 (__extension__ ({ char *__dest = (dest); \
441 __builtin_constant_p (src) && __builtin_constant_p (n) \
442 ? (strlen (src) < ((size_t) (n)) \
443 ? strcat (__dest, src) \
444 : (*((char *) __mempcpy (strchr (__dest, '\0'), \
445 src, n)) = '\0', __dest)) \
446 : strncat (dest, src, n); }))
448 # define strncat(dest, src, n) __builtin_strncat (dest, src, n)
453 /* Compare characters of S1 and S2. */
454 #ifndef _HAVE_STRING_ARCH_strcmp
455 # define strcmp(s1, s2) \
457 ({ size_t __s1_len, __s2_len; \
458 (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
459 && (__s1_len = strlen (s1), __s2_len = strlen (s2), \
460 (!__string2_1bptr_p (s1) || __s1_len >= 4) \
461 && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \
462 ? __builtin_strcmp (s1, s2) \
463 : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
464 && (__s1_len = strlen (s1), __s1_len < 4) \
465 ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
466 ? __builtin_strcmp (s1, s2) \
467 : __strcmp_cg (s1, s2, __s1_len)) \
468 : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
469 && (__s2_len = strlen (s2), __s2_len < 4) \
470 ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
471 ? __builtin_strcmp (s1, s2) \
472 : -__strcmp_cg (s2, s1, __s2_len)) \
473 : __builtin_strcmp (s1, s2)))); })
475 # define __strcmp_cg(s1, s2, l1) \
476 (__extension__ ({ const unsigned char *__s2 = \
477 (const unsigned char *) (const char *) (s2); \
479 (((const unsigned char *) (const char *) (s1))[0] \
481 if (l1 > 0 && __result == 0) \
483 __result = (((const unsigned char *) \
484 (const char *) (s1))[1] - __s2[1]); \
485 if (l1 > 1 && __result == 0) \
487 __result = (((const unsigned char *) \
488 (const char *) (s1))[2] - __s2[2]); \
489 if (l1 > 2 && __result == 0) \
490 __result = (((const unsigned char *) \
491 (const char *) (s1))[3] \
499 /* Compare N characters of S1 and S2. */
500 #ifndef _HAVE_STRING_ARCH_strncmp
501 # define strncmp(s1, s2, n) \
502 (__extension__ (__builtin_constant_p (n) \
503 && ((__builtin_constant_p (s1) \
504 && strlen (s1) < ((size_t) (n))) \
505 || (__builtin_constant_p (s2) \
506 && strlen (s2) < ((size_t) (n)))) \
507 ? strcmp (s1, s2) : strncmp (s1, s2, n)))
511 /* Return the length of the initial segment of S which
512 consists entirely of characters not in REJECT. */
513 #ifndef _HAVE_STRING_ARCH_strcspn
514 # define strcspn(s, reject) __builtin_strcspn (s, reject)
518 /* Return the length of the initial segment of S which
519 consists entirely of characters in ACCEPT. */
520 #ifndef _HAVE_STRING_ARCH_strspn
521 # define strspn(s, accept) __builtin_strspn (s, accept)
525 /* Find the first occurrence in S of any character in ACCEPT. */
526 #ifndef _HAVE_STRING_ARCH_strpbrk
527 # define strpbrk(s, accept) __builtin_strpbrk (s, accept)
531 #if !defined _HAVE_STRING_ARCH_strtok_r || defined _FORCE_INLINES
532 # ifndef _HAVE_STRING_ARCH_strtok_r
533 # define __strtok_r(s, sep, nextp) \
534 (__extension__ (__builtin_constant_p (sep) && __string2_1bptr_p (sep) \
535 && ((const char *) (sep))[0] != '\0' \
536 && ((const char *) (sep))[1] == '\0' \
537 ? __strtok_r_1c (s, ((const char *) (sep))[0], nextp) \
538 : __strtok_r (s, sep, nextp)))
541 __STRING_INLINE
char *__strtok_r_1c (char *__s
, char __sep
, char **__nextp
);
542 __STRING_INLINE
char *
543 __strtok_r_1c (char *__s
, char __sep
, char **__nextp
)
548 while (*__s
== __sep
)
565 # define strtok_r(s, sep, nextp) __strtok_r (s, sep, nextp)
570 #if !defined _HAVE_STRING_ARCH_strsep || defined _FORCE_INLINES
571 # ifndef _HAVE_STRING_ARCH_strsep
573 extern char *__strsep_g (char **__stringp
, const char *__delim
);
574 # define __strsep(s, reject) \
576 ({ char __r0, __r1, __r2; \
577 (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
578 && (__r0 = ((const char *) (reject))[0], \
579 ((const char *) (reject))[0] != '\0') \
580 ? ((__r1 = ((const char *) (reject))[1], \
581 ((const char *) (reject))[1] == '\0') \
582 ? __strsep_1c (s, __r0) \
583 : ((__r2 = ((const char *) (reject))[2], __r2 == '\0') \
584 ? __strsep_2c (s, __r0, __r1) \
585 : (((const char *) (reject))[3] == '\0' \
586 ? __strsep_3c (s, __r0, __r1, __r2) \
587 : __strsep_g (s, reject)))) \
588 : __strsep_g (s, reject)); })
591 __STRING_INLINE
char *__strsep_1c (char **__s
, char __reject
);
592 __STRING_INLINE
char *
593 __strsep_1c (char **__s
, char __reject
)
595 char *__retval
= *__s
;
596 if (__retval
!= NULL
&& (*__s
= strchr (__retval
, __reject
)) != NULL
)
601 __STRING_INLINE
char *__strsep_2c (char **__s
, char __reject1
, char __reject2
);
602 __STRING_INLINE
char *
603 __strsep_2c (char **__s
, char __reject1
, char __reject2
)
605 char *__retval
= *__s
;
606 if (__retval
!= NULL
)
608 char *__cp
= __retval
;
616 if (*__cp
== __reject1
|| *__cp
== __reject2
)
628 __STRING_INLINE
char *__strsep_3c (char **__s
, char __reject1
, char __reject2
,
630 __STRING_INLINE
char *
631 __strsep_3c (char **__s
, char __reject1
, char __reject2
, char __reject3
)
633 char *__retval
= *__s
;
634 if (__retval
!= NULL
)
636 char *__cp
= __retval
;
644 if (*__cp
== __reject1
|| *__cp
== __reject2
|| *__cp
== __reject3
)
656 # define strsep(s, reject) __strsep (s, reject)
660 /* We need the memory allocation functions for inline strdup().
661 Referring to stdlib.h (even minimally) is not allowed
662 in any of the tight standards compliant modes. */
665 # if !defined _HAVE_STRING_ARCH_strdup || !defined _HAVE_STRING_ARCH_strndup
666 # define __need_malloc_and_calloc
670 # ifndef _HAVE_STRING_ARCH_strdup
672 extern char *__strdup (const char *__string
) __THROW __attribute_malloc__
;
673 # define __strdup(s) \
674 (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \
675 ? (((const char *) (s))[0] == '\0' \
676 ? (char *) calloc ((size_t) 1, (size_t) 1) \
677 : ({ size_t __len = strlen (s) + 1; \
678 char *__retval = (char *) malloc (__len); \
679 if (__retval != NULL) \
680 __retval = (char *) memcpy (__retval, s, __len); \
684 # if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
685 # define strdup(s) __strdup (s)
689 # ifndef _HAVE_STRING_ARCH_strndup
691 extern char *__strndup (const char *__string
, size_t __n
)
692 __THROW __attribute_malloc__
;
693 # define __strndup(s, n) \
694 (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \
695 ? (((const char *) (s))[0] == '\0' \
696 ? (char *) calloc ((size_t) 1, (size_t) 1) \
697 : ({ size_t __len = strlen (s) + 1; \
702 __retval = (char *) malloc (__len); \
703 if (__retval != NULL) \
705 __retval[__len - 1] = '\0'; \
706 __retval = (char *) memcpy (__retval, s, \
712 # ifdef __USE_XOPEN2K8
713 # define strndup(s, n) __strndup (s, n)
717 #endif /* Use misc. or use GNU. */
719 #ifndef _FORCE_INLINES
720 # undef __STRING_INLINE
723 #endif /* No string inlines. */