1 /* Machine-independant string function optimizations.
2 Copyright (C) 1997 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 Library General Public License as
8 published by the Free Software Foundation; either version 2 of the
9 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 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with the GNU C Library; see the file COPYING.LIB. If not,
18 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
22 # error "Never use <bits/string2.h> directly; include <string.h> instead."
25 #ifndef __NO_STRING_INLINES
27 /* Unlike the definitions in the header <bits/string.h> the
28 definitions contained here are not optimizing down to assembler
29 level. These optimizations are not always a good idea since this
30 means the code size increases a lot. Instead the definitions here
31 optimize some functions in a way which does not dramatically
32 increase the code size and which does not use assembler. The main
33 trick is to use GNU CC's `__builtin_constant_p' function.
35 Every function XXX which has a defined version in
36 <bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX
37 to make sure we don't get redefinitions.
39 We must use here macros instead of inline functions since the
40 trick won't work with the later. */
43 # define __STRING_INLINE inline
45 # define __STRING_INLINE extern __inline
48 #if _STRING_ARCH_unaligned
49 /* If we can do unaligned memory accesses we must know the endianess. */
51 # include <bits/types.h>
53 # if __BYTE_ORDER == __LITTLE_ENDIAN
54 # define __STRING2_SMALL_GET16(src, idx) \
55 (((src)[idx + 1] << 8) | (src)[idx])
56 # define __STRING2_SMALL_GET32(src, idx) \
57 ((((src)[idx + 3] << 8 | (src)[idx + 2]) << 8 \
58 | (src)[idx + 1]) << 8 | (src)[idx])
60 # define __STRING2_SMALL_GET16(src, idx) \
61 (((src)[idx] << 8) | (src)[idx + 1])
62 # define __STRING2_SMALL_GET32(src, idx) \
63 ((((src)[idx] << 8 | (src)[idx + 1]) << 8 \
64 | (src)[idx + 2]) << 8 | (src)[idx + 3])
67 /* These are a few types we need for the optimizations if we cannot
68 use unaligned memory accesses. */
69 # define __STRING2_COPY_TYPE(N) \
70 typedef struct { char __arr[N]; } \
71 __STRING2_COPY_ARR##N __attribute__ ((packed))
72 __STRING2_COPY_TYPE (2);
73 __STRING2_COPY_TYPE (3);
74 __STRING2_COPY_TYPE (4);
75 __STRING2_COPY_TYPE (5);
76 __STRING2_COPY_TYPE (6);
77 __STRING2_COPY_TYPE (7);
78 __STRING2_COPY_TYPE (8);
79 # undef __STRING2_COPY_TYPE
82 /* Dereferencing a pointer arg to run sizeof on it fails for the
83 void pointer case, so we use this instead. */
84 #define __string2_1bptr_p(x) (((size_t) ((x) + 1) - (size_t) (x)) == 1)
87 /* Set N bytes of S to C. */
88 #ifndef _HAVE_STRING_ARCH_memset
89 # define memset(s, c, n) \
90 (__extension__ (__builtin_constant_p (c) && (c) == '\0' \
91 ? ({ void *__s = (s); __bzero (__s, n); __s; }) \
96 /* Copy SRC to DEST. */
97 #ifndef _HAVE_STRING_ARCH_strcpy
98 # define strcpy(dest, src) \
99 (__extension__ (__builtin_constant_p (src) \
100 ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \
101 ? __strcpy_small (dest, src, strlen (src) + 1) \
102 : (char *) memcpy (dest, src, strlen (src) + 1)) \
103 : strcpy (dest, src)))
105 # if _STRING_ARCH_unaligned
106 # define __strcpy_small(dest, src, srclen) \
107 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
114 *((__uint16_t *) __dest) = \
115 __STRING2_SMALL_GET16 (src, 0); \
118 *((__uint16_t *) __dest) = \
119 __STRING2_SMALL_GET16 (src, 0); \
120 *(__dest + 2) = '\0'; \
123 *((__uint32_t *) __dest) = \
124 __STRING2_SMALL_GET32 (src, 0); \
127 *((__uint32_t *) __dest) = \
128 __STRING2_SMALL_GET32 (src, 0); \
129 *(__dest + 4) = '\0'; \
132 *((__uint32_t *) __dest) = \
133 __STRING2_SMALL_GET32 (src, 0); \
134 *((__uint16_t *) (__dest + 4)) = \
135 __STRING2_SMALL_GET16 (src, 4); \
138 *((__uint32_t *) __dest) = \
139 __STRING2_SMALL_GET32 (src, 0); \
140 *((__uint16_t *) (__dest + 4)) = \
141 __STRING2_SMALL_GET16 (src, 4); \
142 *(__dest + 6) = '\0'; \
145 *((__uint32_t *) __dest) = \
146 __STRING2_SMALL_GET32 (src, 0); \
147 *((__uint32_t *) (__dest + 4)) = \
148 __STRING2_SMALL_GET32 (src, 4); \
153 # define __strcpy_small(dest, src, srclen) \
154 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
161 *((__STRING2_COPY_ARR2 *) __dest) = \
162 ((__STRING2_COPY_ARR2) { { (src)[0], '\0' } }); \
165 *((__STRING2_COPY_ARR3 *) __dest) = \
166 ((__STRING2_COPY_ARR3) { { (src)[0], (src)[1], \
170 *((__STRING2_COPY_ARR4 *) __dest) = \
171 ((__STRING2_COPY_ARR4) { { (src)[0], (src)[1], \
172 (src)[2], '\0' } }); \
175 *((__STRING2_COPY_ARR5 *) __dest) = \
176 ((__STRING2_COPY_ARR5) { { (src)[0], (src)[1], \
177 (src)[2], (src)[3], \
181 *((__STRING2_COPY_ARR6 *) __dest) = \
182 ((__STRING2_COPY_ARR6) { { (src)[0], (src)[1], \
183 (src)[2], (src)[3], \
184 (src)[4], '\0' } }); \
187 *((__STRING2_COPY_ARR7 *) __dest) = \
188 ((__STRING2_COPY_ARR7) { { (src)[0], (src)[1], \
189 (src)[2], (src)[3], \
190 (src)[4], (src)[5], \
194 *((__STRING2_COPY_ARR8 *) __dest) = \
195 ((__STRING2_COPY_ARR8) { { (src)[0], (src)[1], \
196 (src)[2], (src)[3], \
197 (src)[4], (src)[5], \
198 (src)[6], '\0' } }); \
206 /* Copy SRC to DEST, returning pointer to final NUL byte. */
208 # ifndef _HAVE_STRING_ARCH_stpcpy
209 # define __stpcpy(dest, src) \
210 (__extension__ (__builtin_constant_p (src) \
211 ? (__string2_1bptr_p (src) && strlen (src) + 1 <= 8 \
212 ? __stpcpy_small (dest, src, strlen (src) + 1) \
213 : ((char *) __mempcpy (dest, src, strlen (src) + 1) - 1))\
214 : __stpcpy (dest, src)))
215 /* In glibc we use this function frequently but for namespace reasons
216 we have to use the name `__stpcpy'. */
217 # define stpcpy(dest, src) __stpcpy (dest, src)
219 # if _STRING_ARCH_unaligned
220 # define __stpcpy_small(dest, src, srclen) \
221 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
228 *((__uint16_t *) __dest) = \
229 __STRING2_SMALL_GET16 (src, 0); \
233 *((__uint16_t *) __dest) = \
234 __STRING2_SMALL_GET16 (src, 0); \
235 __dest += sizeof (__uint16_t); \
239 *((__uint32_t *) __dest) = \
240 __STRING2_SMALL_GET32 (src, 0); \
244 *((__uint32_t *) __dest) = \
245 __STRING2_SMALL_GET32 (src, 0); \
246 __dest += sizeof (__uint32_t); \
250 *((__uint32_t *) __dest) = \
251 __STRING2_SMALL_GET32 (src, 0); \
252 *((__uint16_t *) (__dest + 4)) = \
253 __STRING2_SMALL_GET16 (src, 4); \
257 *((__uint32_t *) __dest) = \
258 __STRING2_SMALL_GET32 (src, 0); \
259 *((__uint16_t *) (__dest + 4)) = \
260 __STRING2_SMALL_GET16 (src, 4); \
265 *((__uint32_t *) __dest) = \
266 __STRING2_SMALL_GET32 (src, 0); \
267 *((__uint32_t *) (__dest + 4)) = \
268 __STRING2_SMALL_GET32 (src, 4); \
274 # define __stpcpy_small(dest, src, srclen) \
275 (__extension__ ({ unsigned char *__dest = (unsigned char *) (dest); \
282 *((__STRING2_COPY_ARR2 *) __dest) = \
283 ((__STRING2_COPY_ARR2) { { (src)[0], '\0' } }); \
286 *((__STRING2_COPY_ARR3 *) __dest) = \
287 ((__STRING2_COPY_ARR3) { { (src)[0], (src)[1], \
291 *((__STRING2_COPY_ARR4 *) __dest) = \
292 ((__STRING2_COPY_ARR4) { { (src)[0], (src)[1], \
293 (src)[2], '\0' } }); \
296 *((__STRING2_COPY_ARR5 *) __dest) = \
297 ((__STRING2_COPY_ARR5) { { (src)[0], (src)[1], \
298 (src)[2], (src)[3], \
302 *((__STRING2_COPY_ARR6 *) __dest) = \
303 ((__STRING2_COPY_ARR6) { { (src)[0], (src)[1], \
304 (src)[2], (src)[3], \
305 (src)[4], '\0' } }); \
308 *((__STRING2_COPY_ARR7 *) __dest) = \
309 ((__STRING2_COPY_ARR7) { { (src)[0], (src)[1], \
310 (src)[2], (src)[3], \
311 (src)[4], (src)[5], \
315 *((__STRING2_COPY_ARR8 *) __dest) = \
316 ((__STRING2_COPY_ARR8) { { (src)[0], (src)[1], \
317 (src)[2], (src)[3], \
318 (src)[4], (src)[5], \
319 (src)[6], '\0' } }); \
322 (char *) (__dest + ((srclen) - 1)); }))
328 /* Copy no more than N characters of SRC to DEST. */
329 #ifndef _HAVE_STRING_ARCH_strncpy
330 # if defined _HAVE_STRING_ARCH_memset && defined _HAVE_STRING_ARCH_mempcpy
331 # define strncpy(dest, src, n) \
332 (__extension__ ({ char *__dest = (dest); \
333 __builtin_constant_p (src) && __builtin_constant_p (n) \
334 ? (strlen (src) + 1 >= ((size_t) (n)) \
335 ? (char *) memcpy (__dest, src, n) \
336 : (memset (__mempcpy (__dest, src, strlen (src)), \
337 '\0', n - strlen (src)), \
339 : strncpy (__dest, src, n); }))
341 # define strncpy(dest, src, n) \
342 (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \
343 ? (strlen (src) + 1 >= ((size_t) (n)) \
344 ? (char *) memcpy (dest, src, n) \
345 : strncpy (dest, src, n)) \
346 : strncpy (dest, src, n)))
351 /* Append no more than N characters from SRC onto DEST. */
352 #ifndef _HAVE_STRING_ARCH_strncat
353 # ifdef _HAVE_STRING_ARCH_strchr
354 # define strncat(dest, src, n) \
355 (__extension__ ({ char *__dest = (dest); \
356 __builtin_constant_p (src) && __builtin_constant_p (n) \
357 ? (strlen (src) < ((size_t) (n)) \
358 ? strcat (__dest, src) \
359 : (memcpy (strchr (__dest, '\0'), src, n), __dest)) \
360 : strncat (dest, src, n); }))
362 # define strncat(dest, src, n) \
363 (__extension__ (__builtin_constant_p (src) && __builtin_constant_p (n) \
364 ? (strlen (src) < ((size_t) (n)) \
365 ? strcat (dest, src) \
366 : strncat (dest, src, n)) \
367 : strncat (dest, src, n)))
372 /* Compare characters of S1 and S2. */
373 #ifndef _HAVE_STRING_ARCH_strcmp
374 # define strcmp(s1, s2) \
375 (__extension__ (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
376 && (!__string2_1bptr_p (s1) || strlen (s1) >= 4) \
377 && (!__string2_1bptr_p (s2) || strlen (s2) >= 4) \
378 ? memcmp (s1, s2, (strlen (s1) < strlen (s2) \
379 ? strlen (s1) : strlen (s2)) + 1) \
380 : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
381 && __string2_1bptr_p (s2) && strlen (s1) < 4 \
382 ? (__builtin_constant_p (s2) \
383 ? __strcmp_cc (s1, s2, strlen (s1)) \
384 : __strcmp_cg (s1, s2, strlen (s1))) \
385 : (__builtin_constant_p (s2) && __string2_1bptr_p (s1) \
386 && __string2_1bptr_p (s2) && strlen (s2) < 4 \
387 ? (__builtin_constant_p (s1) \
388 ? __strcmp_cc (s1, s2, strlen (s2)) \
389 : __strcmp_gc (s1, s2, strlen (s2))) \
390 : strcmp (s1, s2)))))
392 # define __strcmp_cc(s1, s2, l) \
393 (__extension__ ({ register int __result = ((unsigned char) (s1)[0] \
394 - (unsigned char) (s2)[0]); \
395 if (l > 0 && __result == 0) \
397 __result = ((unsigned char) (s1)[1] \
398 - (unsigned char) (s2)[1]); \
399 if (l > 1 && __result == 0) \
401 __result = ((unsigned char) (s1)[2] \
402 - (unsigned char) (s2)[2]); \
403 if (l > 2 && __result == 0) \
404 __result = ((unsigned char) (s1)[3] \
405 - (unsigned char) (s2)[3]); \
410 # define __strcmp_cg(s1, s2, l1) \
411 (__extension__ ({ __const unsigned char *__s2 = (unsigned char *) (s2); \
412 register int __result = (unsigned char) (s1)[0] - __s2[0];\
413 if (l1 > 0 && __result == 0) \
415 __result = (unsigned char) (s1)[1] - __s2[1]; \
416 if (l1 > 1 && __result == 0) \
418 __result = (unsigned char) (s1)[2] - __s2[2]; \
419 if (l1 > 2 && __result == 0) \
420 __result = (unsigned char) (s1)[3] - __s2[3]; \
425 # define __strcmp_gc(s1, s2, l2) \
426 (__extension__ ({ __const unsigned char *__s1 = (unsigned char *) (s1); \
427 register int __result = __s1[0] - (unsigned char) (s2)[0];\
428 if (l2 > 0 && __result == 0) \
430 __result = __s1[1] - (unsigned char) (s2)[1]; \
431 if (l2 > 1 && __result == 0) \
433 __result = __s1[2] - (unsigned char) (s2)[2]; \
434 if (l2 > 2 && __result == 0) \
435 __result = __s1[3] - (unsigned char) (s2)[3]; \
442 /* Compare N characters of S1 and S2. */
443 #ifndef _HAVE_STRING_ARCH_strncmp
444 # define strncmp(s1, s2, n) \
445 (__extension__ (__builtin_constant_p (s1) && strlen (s1) < ((size_t) (n)) \
447 : (__builtin_constant_p (s2) && strlen (s2) < ((size_t) (n))\
449 : strncmp (s1, s2, n))))
453 /* Return the length of the initial segment of S which
454 consists entirely of characters not in REJECT. */
455 #ifndef _HAVE_STRING_ARCH_strcspn
456 # define strcspn(s, reject) \
457 (__extension__ (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
458 ? ((reject)[0] == '\0' \
460 : ((reject)[1] == '\0' \
461 ? __strcspn_c1 (s, (reject)[0]) \
462 : strcspn (s, reject))) \
463 : strcspn (s, reject)))
465 __STRING_INLINE
size_t __strcspn_c1 (__const
char *__s
, char __reject
);
466 __STRING_INLINE
size_t
467 __strcspn_c1 (__const
char *__s
, char __reject
)
469 register size_t __result
= 0;
470 while (__s
[__result
] != '\0' && __s
[__result
] != __reject
)
477 /* Return the length of the initial segment of S which
478 consists entirely of characters in ACCEPT. */
479 #ifndef _HAVE_STRING_ARCH_strspn
480 # define strspn(s, accept) \
481 (__extension__ (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
482 ? ((accept)[0] == '\0' \
484 : ((accept)[1] == '\0' \
485 ? __strspn_c1 (s, (accept)[0]) \
486 : strspn (s, accept))) \
487 : strspn (s, accept)))
489 __STRING_INLINE
size_t __strspn_c1 (__const
char *__s
, char __accept
);
490 __STRING_INLINE
size_t
491 __strspn_c1 (__const
char *__s
, char __accept
)
493 register size_t __result
= 0;
494 /* Please note that __accept never can be '\0'. */
495 while (__s
[__result
] == __accept
)
502 /* Find the first occurrence in S of any character in ACCEPT. */
503 #ifndef _HAVE_STRING_ARCH_strpbrk
504 # define strpbrk(s, accept) \
505 (__extension__ (__builtin_constant_p (accept) && __string2_1bptr_p (accept) \
506 ? ((accept)[0] == '\0' \
508 : ((accept)[1] == '\0' \
509 ? strchr (s, (accept)[0]) \
510 : strpbrk (s, accept))) \
511 : strpbrk (s, accept)))
515 /* Find the first occurrence of NEEDLE in HAYSTACK. */
516 #ifndef _HAVE_STRING_ARCH_strstr
517 # define strstr(haystack, needle) \
518 (__extension__ (__builtin_constant_p (needle) && __string2_1bptr_p (needle) \
519 ? ((needle)[0] == '\0' \
521 : ((needle)[1] == '\0' \
522 ? strchr (haystack, (needle)[0]) \
523 : strstr (haystack, needle))) \
524 : strstr (haystack, needle)))
529 # ifndef _HAVE_STRING_ARCH_strnlen
530 __STRING_INLINE
size_t strnlen (__const
char *__string
, size_t __maxlen
);
531 __STRING_INLINE
size_t
532 strnlen (__const
char *__string
, size_t __maxlen
)
534 __const
char *__end
= (__const
char *) memchr (__string
, '\0', __maxlen
);
535 return __end
? __end
- __string
: __maxlen
;
542 # ifndef _HAVE_STRING_ARCH_strsep
544 # define strsep(s, reject) \
545 (__extension__ (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
546 ? ((reject)[0] != '\0' && (reject)[1] == '\0' \
547 ? __strsep_1c (s, (reject)[0]) \
548 : __strsep_g (s, reject)) \
549 : __strsep_g (s, reject)))
551 __STRING_INLINE
char *__strsep_1c (char **__s
, char __reject
);
552 __STRING_INLINE
char *
553 __strsep_1c (char **__s
, char __reject
)
555 register char *__retval
= *__s
;
556 if (__retval
== NULL
|| *__retval
== '\0')
558 while (*__retval
== __reject
)
560 if ((*__s
= strchr (__retval
, __reject
)) != NULL
)
565 __STRING_INLINE
char *__strsep_g (char **__s
, __const
char *__reject
);
566 __STRING_INLINE
char *
567 __strsep_g (char **__s
, __const
char *__reject
)
569 register char *__retval
= *__s
;
570 if (__retval
== NULL
|| *__retval
== '\0')
572 if ((*__s
= strpbrk (__retval
, __reject
)) != NULL
)
580 #undef __STRING_INLINE
582 #endif /* No string inlines. */