]> git.ipfire.org Git - thirdparty/glibc.git/blob - string/string-inlines.c
Improve strtok and strtok_r performance. Instead of calling strpbrk which
[thirdparty/glibc.git] / string / string-inlines.c
1 /* Copyright (C) 1999-2016 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
17
18 /* <bits/string.h> and <bits/string2.h> declare some extern inline
19 functions. These functions are declared additionally here if
20 inlining is not possible. */
21
22 #undef __USE_STRING_INLINES
23 #define __USE_STRING_INLINES
24 #define _FORCE_INLINES
25 #define __STRING_INLINE /* empty */
26 #define __NO_INLINE__
27
28 #include <string.h>
29 #undef index
30 #undef rindex
31
32 #undef __NO_INLINE__
33 #include <bits/string.h>
34 #include <bits/string2.h>
35
36 #include "shlib-compat.h"
37
38 #if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_25)
39 /* The inline functions are not used from GLIBC 2.25 and forward, however
40 they are required to provide the symbols through string-inlines.c
41 (if inlining is not possible for compatibility reasons). */
42
43 char *
44 __old_strtok_r_1c (char *__s, char __sep, char **__nextp)
45 {
46 char *__result;
47 if (__s == NULL)
48 __s = *__nextp;
49 while (*__s == __sep)
50 ++__s;
51 __result = NULL;
52 if (*__s != '\0')
53 {
54 __result = __s++;
55 while (*__s != '\0')
56 if (*__s++ == __sep)
57 {
58 __s[-1] = '\0';
59 break;
60 }
61 }
62 *__nextp = __s;
63 return __result;
64 }
65 compat_symbol (libc, __old_strtok_r_1c, __strtok_r_1c, GLIBC_2_1_1);
66 #endif
67
68 #if SHLIB_COMPAT (libc, GLIBC_2_1_1, GLIBC_2_24)
69 /* The inline functions are not used from GLIBC 2.24 and forward, however
70 they are required to provide the symbols through string-inlines.c
71 (if inlining is not possible for compatibility reasons). */
72 size_t
73 __old_strcspn_c1 (const char *__s, int __reject)
74 {
75 size_t __result = 0;
76 while (__s[__result] != '\0' && __s[__result] != __reject)
77 ++__result;
78 return __result;
79 }
80 compat_symbol (libc, __old_strcspn_c1, __strcspn_c1, GLIBC_2_1_1);
81
82 size_t
83 __old_strcspn_c2 (const char *__s, int __reject1, int __reject2)
84 {
85 size_t __result = 0;
86 while (__s[__result] != '\0' && __s[__result] != __reject1
87 && __s[__result] != __reject2)
88 ++__result;
89 return __result;
90 }
91 compat_symbol (libc, __old_strcspn_c2, __strcspn_c2, GLIBC_2_1_1);
92
93 size_t
94 __old_strcspn_c3 (const char *__s, int __reject1, int __reject2,
95 int __reject3)
96 {
97 size_t __result = 0;
98 while (__s[__result] != '\0' && __s[__result] != __reject1
99 && __s[__result] != __reject2 && __s[__result] != __reject3)
100 ++__result;
101 return __result;
102 }
103 compat_symbol (libc, __old_strcspn_c3, __strcspn_c3, GLIBC_2_1_1);
104
105 size_t
106 __old_strspn_c1 (const char *__s, int __accept)
107 {
108 size_t __result = 0;
109 /* Please note that __accept never can be '\0'. */
110 while (__s[__result] == __accept)
111 ++__result;
112 return __result;
113 }
114 compat_symbol (libc, __old_strspn_c1, __strspn_c1, GLIBC_2_1_1);
115
116 size_t
117 __old_strspn_c2 (const char *__s, int __accept1, int __accept2)
118 {
119 size_t __result = 0;
120 /* Please note that __accept1 and __accept2 never can be '\0'. */
121 while (__s[__result] == __accept1 || __s[__result] == __accept2)
122 ++__result;
123 return __result;
124 }
125 compat_symbol (libc, __old_strspn_c2, __strspn_c2, GLIBC_2_1_1);
126
127 size_t
128 __old_strspn_c3 (const char *__s, int __accept1, int __accept2,
129 int __accept3)
130 {
131 size_t __result = 0;
132 /* Please note that __accept1 to __accept3 never can be '\0'. */
133 while (__s[__result] == __accept1 || __s[__result] == __accept2
134 || __s[__result] == __accept3)
135 ++__result;
136 return __result;
137 }
138 compat_symbol (libc, __old_strspn_c3, __strspn_c3, GLIBC_2_1_1);
139
140 char *
141 __old_strpbrk_c2 (const char *__s, int __accept1, int __accept2)
142 {
143 /* Please note that __accept1 and __accept2 never can be '\0'. */
144 while (*__s != '\0' && *__s != __accept1 && *__s != __accept2)
145 ++__s;
146 return *__s == '\0' ? NULL : (char *) (size_t) __s;
147 }
148 compat_symbol (libc, __old_strpbrk_c2, __strpbrk_c2, GLIBC_2_1_1);
149
150 char *
151 __old_strpbrk_c3 (const char *__s, int __accept1, int __accept2, int __accept3)
152 {
153 /* Please note that __accept1 to __accept3 never can be '\0'. */
154 while (*__s != '\0' && *__s != __accept1 && *__s != __accept2
155 && *__s != __accept3)
156 ++__s;
157 return *__s == '\0' ? NULL : (char *) (size_t) __s;
158 }
159 compat_symbol (libc, __old_strpbrk_c3, __strpbrk_c3, GLIBC_2_1_1);
160
161 /* These are a few types we need for the optimizations if we cannot
162 use unaligned memory accesses. */
163 # define __STRING2_COPY_TYPE(N) \
164 typedef struct { unsigned char __arr[N]; } \
165 __attribute__ ((__packed__)) __STRING2_COPY_ARR##N
166 __STRING2_COPY_TYPE (2);
167 __STRING2_COPY_TYPE (3);
168 __STRING2_COPY_TYPE (4);
169 __STRING2_COPY_TYPE (5);
170 __STRING2_COPY_TYPE (6);
171 __STRING2_COPY_TYPE (7);
172 __STRING2_COPY_TYPE (8);
173 # undef __STRING2_COPY_TYPE
174
175
176 # if _STRING_INLINE_unaligned
177 void *
178 __old_mempcpy_small (void *__dest1,
179 char __src0_1, char __src2_1, char __src4_1, char __src6_1,
180 __uint16_t __src0_2, __uint16_t __src4_2,
181 __uint32_t __src0_4, __uint32_t __src4_4,
182 size_t __srclen)
183 {
184 union {
185 __uint32_t __ui;
186 __uint16_t __usi;
187 unsigned char __uc;
188 unsigned char __c;
189 } *__u = __dest1;
190 switch ((unsigned int) __srclen)
191 {
192 case 1:
193 __u->__c = __src0_1;
194 __u = __extension__ ((void *) __u + 1);
195 break;
196 case 2:
197 __u->__usi = __src0_2;
198 __u = __extension__ ((void *) __u + 2);
199 break;
200 case 3:
201 __u->__usi = __src0_2;
202 __u = __extension__ ((void *) __u + 2);
203 __u->__c = __src2_1;
204 __u = __extension__ ((void *) __u + 1);
205 break;
206 case 4:
207 __u->__ui = __src0_4;
208 __u = __extension__ ((void *) __u + 4);
209 break;
210 case 5:
211 __u->__ui = __src0_4;
212 __u = __extension__ ((void *) __u + 4);
213 __u->__c = __src4_1;
214 __u = __extension__ ((void *) __u + 1);
215 break;
216 case 6:
217 __u->__ui = __src0_4;
218 __u = __extension__ ((void *) __u + 4);
219 __u->__usi = __src4_2;
220 __u = __extension__ ((void *) __u + 2);
221 break;
222 case 7:
223 __u->__ui = __src0_4;
224 __u = __extension__ ((void *) __u + 4);
225 __u->__usi = __src4_2;
226 __u = __extension__ ((void *) __u + 2);
227 __u->__c = __src6_1;
228 __u = __extension__ ((void *) __u + 1);
229 break;
230 case 8:
231 __u->__ui = __src0_4;
232 __u = __extension__ ((void *) __u + 4);
233 __u->__ui = __src4_4;
234 __u = __extension__ ((void *) __u + 4);
235 break;
236 }
237 return (void *) __u;
238 }
239
240 # else
241
242 void *
243 __old_mempcpy_small (void *__dest, char __src1,
244 __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
245 __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
246 __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
247 __STRING2_COPY_ARR8 __src8, size_t __srclen)
248 {
249 union {
250 char __c;
251 __STRING2_COPY_ARR2 __sca2;
252 __STRING2_COPY_ARR3 __sca3;
253 __STRING2_COPY_ARR4 __sca4;
254 __STRING2_COPY_ARR5 __sca5;
255 __STRING2_COPY_ARR6 __sca6;
256 __STRING2_COPY_ARR7 __sca7;
257 __STRING2_COPY_ARR8 __sca8;
258 } *__u = __dest;
259 switch ((unsigned int) __srclen)
260 {
261 case 1:
262 __u->__c = __src1;
263 break;
264 case 2:
265 __extension__ __u->__sca2 = __src2;
266 break;
267 case 3:
268 __extension__ __u->__sca3 = __src3;
269 break;
270 case 4:
271 __extension__ __u->__sca4 = __src4;
272 break;
273 case 5:
274 __extension__ __u->__sca5 = __src5;
275 break;
276 case 6:
277 __extension__ __u->__sca6 = __src6;
278 break;
279 case 7:
280 __extension__ __u->__sca7 = __src7;
281 break;
282 case 8:
283 __extension__ __u->__sca8 = __src8;
284 break;
285 }
286 return __extension__ ((void *) __u + __srclen);
287 }
288 # endif
289 compat_symbol (libc, __old_mempcpy_small, __mempcpy_small, GLIBC_2_1_1);
290
291 # if _STRING_INLINE_unaligned
292 char *
293 __old_strcpy_small (char *__dest,
294 __uint16_t __src0_2, __uint16_t __src4_2,
295 __uint32_t __src0_4, __uint32_t __src4_4,
296 size_t __srclen)
297 {
298 union {
299 __uint32_t __ui;
300 __uint16_t __usi;
301 unsigned char __uc;
302 } *__u = (void *) __dest;
303 switch ((unsigned int) __srclen)
304 {
305 case 1:
306 __u->__uc = '\0';
307 break;
308 case 2:
309 __u->__usi = __src0_2;
310 break;
311 case 3:
312 __u->__usi = __src0_2;
313 __u = __extension__ ((void *) __u + 2);
314 __u->__uc = '\0';
315 break;
316 case 4:
317 __u->__ui = __src0_4;
318 break;
319 case 5:
320 __u->__ui = __src0_4;
321 __u = __extension__ ((void *) __u + 4);
322 __u->__uc = '\0';
323 break;
324 case 6:
325 __u->__ui = __src0_4;
326 __u = __extension__ ((void *) __u + 4);
327 __u->__usi = __src4_2;
328 break;
329 case 7:
330 __u->__ui = __src0_4;
331 __u = __extension__ ((void *) __u + 4);
332 __u->__usi = __src4_2;
333 __u = __extension__ ((void *) __u + 2);
334 __u->__uc = '\0';
335 break;
336 case 8:
337 __u->__ui = __src0_4;
338 __u = __extension__ ((void *) __u + 4);
339 __u->__ui = __src4_4;
340 break;
341 }
342 return __dest;
343 }
344
345 # else
346
347 char *
348 __old_strcpy_small (char *__dest,
349 __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
350 __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
351 __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
352 __STRING2_COPY_ARR8 __src8, size_t __srclen)
353 {
354 union {
355 char __c;
356 __STRING2_COPY_ARR2 __sca2;
357 __STRING2_COPY_ARR3 __sca3;
358 __STRING2_COPY_ARR4 __sca4;
359 __STRING2_COPY_ARR5 __sca5;
360 __STRING2_COPY_ARR6 __sca6;
361 __STRING2_COPY_ARR7 __sca7;
362 __STRING2_COPY_ARR8 __sca8;
363 } *__u = (void *) __dest;
364 switch ((unsigned int) __srclen)
365 {
366 case 1:
367 __u->__c = '\0';
368 break;
369 case 2:
370 __extension__ __u->__sca2 = __src2;
371 break;
372 case 3:
373 __extension__ __u->__sca3 = __src3;
374 break;
375 case 4:
376 __extension__ __u->__sca4 = __src4;
377 break;
378 case 5:
379 __extension__ __u->__sca5 = __src5;
380 break;
381 case 6:
382 __extension__ __u->__sca6 = __src6;
383 break;
384 case 7:
385 __extension__ __u->__sca7 = __src7;
386 break;
387 case 8:
388 __extension__ __u->__sca8 = __src8;
389 break;
390 }
391 return __dest;
392 }
393 # endif
394 compat_symbol (libc, __old_strcpy_small, __strcpy_small, GLIBC_2_1_1);
395
396 # if _STRING_INLINE_unaligned
397 char *
398 __old_stpcpy_small (char *__dest,
399 __uint16_t __src0_2, __uint16_t __src4_2,
400 __uint32_t __src0_4, __uint32_t __src4_4,
401 size_t __srclen)
402 {
403 union {
404 unsigned int __ui;
405 unsigned short int __usi;
406 unsigned char __uc;
407 char __c;
408 } *__u = (void *) __dest;
409 switch ((unsigned int) __srclen)
410 {
411 case 1:
412 __u->__uc = '\0';
413 break;
414 case 2:
415 __u->__usi = __src0_2;
416 __u = __extension__ ((void *) __u + 1);
417 break;
418 case 3:
419 __u->__usi = __src0_2;
420 __u = __extension__ ((void *) __u + 2);
421 __u->__uc = '\0';
422 break;
423 case 4:
424 __u->__ui = __src0_4;
425 __u = __extension__ ((void *) __u + 3);
426 break;
427 case 5:
428 __u->__ui = __src0_4;
429 __u = __extension__ ((void *) __u + 4);
430 __u->__uc = '\0';
431 break;
432 case 6:
433 __u->__ui = __src0_4;
434 __u = __extension__ ((void *) __u + 4);
435 __u->__usi = __src4_2;
436 __u = __extension__ ((void *) __u + 1);
437 break;
438 case 7:
439 __u->__ui = __src0_4;
440 __u = __extension__ ((void *) __u + 4);
441 __u->__usi = __src4_2;
442 __u = __extension__ ((void *) __u + 2);
443 __u->__uc = '\0';
444 break;
445 case 8:
446 __u->__ui = __src0_4;
447 __u = __extension__ ((void *) __u + 4);
448 __u->__ui = __src4_4;
449 __u = __extension__ ((void *) __u + 3);
450 break;
451 }
452 return &__u->__c;
453 }
454
455 # else
456
457 char *
458 __old_stpcpy_small (char *__dest,
459 __STRING2_COPY_ARR2 __src2, __STRING2_COPY_ARR3 __src3,
460 __STRING2_COPY_ARR4 __src4, __STRING2_COPY_ARR5 __src5,
461 __STRING2_COPY_ARR6 __src6, __STRING2_COPY_ARR7 __src7,
462 __STRING2_COPY_ARR8 __src8, size_t __srclen)
463 {
464 union {
465 char __c;
466 __STRING2_COPY_ARR2 __sca2;
467 __STRING2_COPY_ARR3 __sca3;
468 __STRING2_COPY_ARR4 __sca4;
469 __STRING2_COPY_ARR5 __sca5;
470 __STRING2_COPY_ARR6 __sca6;
471 __STRING2_COPY_ARR7 __sca7;
472 __STRING2_COPY_ARR8 __sca8;
473 } *__u = (void *) __dest;
474 switch ((unsigned int) __srclen)
475 {
476 case 1:
477 __u->__c = '\0';
478 break;
479 case 2:
480 __extension__ __u->__sca2 = __src2;
481 break;
482 case 3:
483 __extension__ __u->__sca3 = __src3;
484 break;
485 case 4:
486 __extension__ __u->__sca4 = __src4;
487 break;
488 case 5:
489 __extension__ __u->__sca5 = __src5;
490 break;
491 case 6:
492 __extension__ __u->__sca6 = __src6;
493 break;
494 case 7:
495 __extension__ __u->__sca7 = __src7;
496 break;
497 case 8:
498 __extension__ __u->__sca8 = __src8;
499 break;
500 }
501 return __dest + __srclen - 1;
502 }
503 # endif
504 compat_symbol (libc, __old_stpcpy_small, __stpcpy_small, GLIBC_2_1_1);
505
506 #endif