]> git.ipfire.org Git - thirdparty/glibc.git/blame - string/bits/string2.h
[BZ #19239] Issue deprecation warnings on macro expansion.
[thirdparty/glibc.git] / string / bits / string2.h
CommitLineData
9a0a462c 1/* Machine-independant string function optimizations.
f7a9f785 2 Copyright (C) 1997-2016 Free Software Foundation, Inc.
9a0a462c
UD
3 This file is part of the GNU C Library.
4 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
5
6 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
9a0a462c
UD
10
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
41bdb6e2 14 Lesser General Public License for more details.
9a0a462c 15
41bdb6e2 16 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
9a0a462c 19
61eb22d3
UD
20#ifndef _STRING_H
21# error "Never use <bits/string2.h> directly; include <string.h> instead."
22#endif
23
2bdd4ca6 24#ifndef __NO_STRING_INLINES
9a0a462c
UD
25
26/* Unlike the definitions in the header <bits/string.h> the
61952351
UD
27 definitions contained here are not optimized down to assembler
28 level. Those optimizations are not always a good idea since this
9a0a462c 29 means the code size increases a lot. Instead the definitions here
61952351
UD
30 optimize some functions in a way which do not dramatically
31 increase the code size and which do not use assembler. The main
4a691b06 32 trick is to use GCC's `__builtin_constant_p' function.
9a0a462c
UD
33
34 Every function XXX which has a defined version in
61eb22d3 35 <bits/string.h> must be accompanied by a symbol _HAVE_STRING_ARCH_XXX
9a0a462c
UD
36 to make sure we don't get redefinitions.
37
38 We must use here macros instead of inline functions since the
49c091e5 39 trick won't work with the latter. */
9a0a462c 40
9bbd7837
UD
41#ifndef __STRING_INLINE
42# ifdef __cplusplus
43# define __STRING_INLINE inline
44# else
b037a293 45# define __STRING_INLINE __extern_inline
9bbd7837 46# endif
9a0a462c
UD
47#endif
48
7ef90c15
UD
49/* Dereferencing a pointer arg to run sizeof on it fails for the void
50 pointer case, so we use this instead.
51 Note that __x is evaluated twice. */
52#define __string2_1bptr_p(__x) \
36ab45e1 53 ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
61eb22d3
UD
54
55/* Set N bytes of S to C. */
3dbfd811 56#if !defined _HAVE_STRING_ARCH_memset
155bc2a5 57# define __bzero(s, n) __builtin_memset (s, '\0', n)
61eb22d3 58#endif
9a0a462c 59
e7c5513d 60
482eec0d 61#ifndef _HAVE_STRING_ARCH_strchr
c1422e5b 62extern void *__rawmemchr (const void *__s, int __c);
4a691b06
UD
63# define strchr(s, c) \
64 (__extension__ (__builtin_constant_p (c) && !__builtin_constant_p (s) \
65 && (c) == '\0' \
66 ? (char *) __rawmemchr (s, c) \
67 : __builtin_strchr (s, c)))
482eec0d
UD
68#endif
69
70
9a0a462c
UD
71/* Copy SRC to DEST, returning pointer to final NUL byte. */
72#ifdef __USE_GNU
155bc2a5
WD
73# ifndef _HAVE_STRING_ARCH_stpcpy
74# define __stpcpy(dest, src) __builtin_stpcpy (dest, src)
9a0a462c
UD
75/* In glibc we use this function frequently but for namespace reasons
76 we have to use the name `__stpcpy'. */
155bc2a5
WD
77# define stpcpy(dest, src) __stpcpy (dest, src)
78# endif
9a0a462c
UD
79#endif
80
81
82/* Copy no more than N characters of SRC to DEST. */
83#ifndef _HAVE_STRING_ARCH_strncpy
155bc2a5 84# define strncpy(dest, src, n) __builtin_strncpy (dest, src, n)
9a0a462c
UD
85#endif
86
87
88/* Append no more than N characters from SRC onto DEST. */
89#ifndef _HAVE_STRING_ARCH_strncat
d3d99893 90# ifdef _USE_STRING_ARCH_strchr
9a0a462c 91# define strncat(dest, src, n) \
650425ce
UD
92 (__extension__ ({ char *__dest = (dest); \
93 __builtin_constant_p (src) && __builtin_constant_p (n) \
94 ? (strlen (src) < ((size_t) (n)) \
95 ? strcat (__dest, src) \
9c3b1ceb
UD
96 : (*((char *) __mempcpy (strchr (__dest, '\0'), \
97 src, n)) = '\0', __dest)) \
650425ce 98 : strncat (dest, src, n); }))
9a0a462c 99# else
155bc2a5 100# define strncat(dest, src, n) __builtin_strncat (dest, src, n)
9a0a462c
UD
101# endif
102#endif
103
104
650425ce
UD
105/* Compare characters of S1 and S2. */
106#ifndef _HAVE_STRING_ARCH_strcmp
155bc2a5 107# define strcmp(s1, s2) \
4a691b06
UD
108 __extension__ \
109 ({ size_t __s1_len, __s2_len; \
110 (__builtin_constant_p (s1) && __builtin_constant_p (s2) \
111 && (__s1_len = strlen (s1), __s2_len = strlen (s2), \
112 (!__string2_1bptr_p (s1) || __s1_len >= 4) \
113 && (!__string2_1bptr_p (s2) || __s2_len >= 4)) \
114 ? __builtin_strcmp (s1, s2) \
115 : (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
116 && (__s1_len = strlen (s1), __s1_len < 4) \
117 ? (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
118 ? __builtin_strcmp (s1, s2) \
119 : __strcmp_cg (s1, s2, __s1_len)) \
120 : (__builtin_constant_p (s2) && __string2_1bptr_p (s2) \
121 && (__s2_len = strlen (s2), __s2_len < 4) \
122 ? (__builtin_constant_p (s1) && __string2_1bptr_p (s1) \
123 ? __builtin_strcmp (s1, s2) \
155bc2a5
WD
124 : -__strcmp_cg (s2, s1, __s2_len)) \
125 : __builtin_strcmp (s1, s2)))); })
a5a0310d 126
650425ce 127# define __strcmp_cg(s1, s2, l1) \
a784e502
UD
128 (__extension__ ({ const unsigned char *__s2 = \
129 (const unsigned char *) (const char *) (s2); \
2e09a79a 130 int __result = \
a784e502 131 (((const unsigned char *) (const char *) (s1))[0] \
fab6d621 132 - __s2[0]); \
650425ce
UD
133 if (l1 > 0 && __result == 0) \
134 { \
a784e502
UD
135 __result = (((const unsigned char *) \
136 (const char *) (s1))[1] - __s2[1]); \
650425ce
UD
137 if (l1 > 1 && __result == 0) \
138 { \
a784e502
UD
139 __result = (((const unsigned char *) \
140 (const char *) (s1))[2] - __s2[2]); \
650425ce 141 if (l1 > 2 && __result == 0) \
a784e502
UD
142 __result = (((const unsigned char *) \
143 (const char *) (s1))[3] \
af6f3906 144 - __s2[3]); \
650425ce
UD
145 } \
146 } \
147 __result; }))
650425ce
UD
148#endif
149
150
9a0a462c
UD
151/* Compare N characters of S1 and S2. */
152#ifndef _HAVE_STRING_ARCH_strncmp
d30da2a8
UD
153# define strncmp(s1, s2, n) \
154 (__extension__ (__builtin_constant_p (n) \
155 && ((__builtin_constant_p (s1) \
156 && strlen (s1) < ((size_t) (n))) \
157 || (__builtin_constant_p (s2) \
158 && strlen (s2) < ((size_t) (n)))) \
159 ? strcmp (s1, s2) : strncmp (s1, s2, n)))
9a0a462c
UD
160#endif
161
162
163/* Return the length of the initial segment of S which
164 consists entirely of characters not in REJECT. */
d3496c9f 165#ifndef _HAVE_STRING_ARCH_strcspn
155bc2a5 166# define strcspn(s, reject) __builtin_strcspn (s, reject)
9a0a462c
UD
167#endif
168
169
170/* Return the length of the initial segment of S which
171 consists entirely of characters in ACCEPT. */
91f3b75f 172#ifndef _HAVE_STRING_ARCH_strspn
155bc2a5 173# define strspn(s, accept) __builtin_strspn (s, accept)
9a0a462c
UD
174#endif
175
176
177/* Find the first occurrence in S of any character in ACCEPT. */
282b71f0 178#ifndef _HAVE_STRING_ARCH_strpbrk
155bc2a5 179# define strpbrk(s, accept) __builtin_strpbrk (s, accept)
9a0a462c
UD
180#endif
181
182
61423e13
UD
183#if !defined _HAVE_STRING_ARCH_strtok_r || defined _FORCE_INLINES
184# ifndef _HAVE_STRING_ARCH_strtok_r
185# define __strtok_r(s, sep, nextp) \
6973fc01 186 (__extension__ (__builtin_constant_p (sep) && __string2_1bptr_p (sep) \
a784e502
UD
187 && ((const char *) (sep))[0] != '\0' \
188 && ((const char *) (sep))[1] == '\0' \
189 ? __strtok_r_1c (s, ((const char *) (sep))[0], nextp) \
7551a1e5 190 : __strtok_r (s, sep, nextp)))
61423e13 191# endif
6973fc01
UD
192
193__STRING_INLINE char *__strtok_r_1c (char *__s, char __sep, char **__nextp);
194__STRING_INLINE char *
195__strtok_r_1c (char *__s, char __sep, char **__nextp)
196{
197 char *__result;
198 if (__s == NULL)
199 __s = *__nextp;
200 while (*__s == __sep)
201 ++__s;
61423e13
UD
202 __result = NULL;
203 if (*__s != '\0')
6973fc01 204 {
61423e13 205 __result = __s++;
29215bbd
UD
206 while (*__s != '\0')
207 if (*__s++ == __sep)
208 {
209 __s[-1] = '\0';
210 break;
211 }
6973fc01 212 }
ebca8f73 213 *__nextp = __s;
6973fc01
UD
214 return __result;
215}
acd7f096 216# ifdef __USE_POSIX
61423e13 217# define strtok_r(s, sep, nextp) __strtok_r (s, sep, nextp)
6973fc01
UD
218# endif
219#endif
220
221
61423e13
UD
222#if !defined _HAVE_STRING_ARCH_strsep || defined _FORCE_INLINES
223# ifndef _HAVE_STRING_ARCH_strsep
b61345a1 224
a784e502 225extern char *__strsep_g (char **__stringp, const char *__delim);
61423e13 226# define __strsep(s, reject) \
36ab45e1
UD
227 __extension__ \
228 ({ char __r0, __r1, __r2; \
229 (__builtin_constant_p (reject) && __string2_1bptr_p (reject) \
a784e502
UD
230 && (__r0 = ((const char *) (reject))[0], \
231 ((const char *) (reject))[0] != '\0') \
232 ? ((__r1 = ((const char *) (reject))[1], \
233 ((const char *) (reject))[1] == '\0') \
36ab45e1 234 ? __strsep_1c (s, __r0) \
a784e502 235 : ((__r2 = ((const char *) (reject))[2], __r2 == '\0') \
36ab45e1 236 ? __strsep_2c (s, __r0, __r1) \
a784e502 237 : (((const char *) (reject))[3] == '\0' \
36ab45e1 238 ? __strsep_3c (s, __r0, __r1, __r2) \
b61345a1
UD
239 : __strsep_g (s, reject)))) \
240 : __strsep_g (s, reject)); })
61423e13 241# endif
61eb22d3
UD
242
243__STRING_INLINE char *__strsep_1c (char **__s, char __reject);
244__STRING_INLINE char *
245__strsep_1c (char **__s, char __reject)
246{
2e09a79a 247 char *__retval = *__s;
61423e13 248 if (__retval != NULL && (*__s = strchr (__retval, __reject)) != NULL)
61eb22d3 249 *(*__s)++ = '\0';
14c44e2e
UD
250 return __retval;
251}
252
253__STRING_INLINE char *__strsep_2c (char **__s, char __reject1, char __reject2);
254__STRING_INLINE char *
255__strsep_2c (char **__s, char __reject1, char __reject2)
256{
2e09a79a 257 char *__retval = *__s;
61423e13 258 if (__retval != NULL)
14c44e2e 259 {
2e09a79a 260 char *__cp = __retval;
61423e13 261 while (1)
14c44e2e 262 {
61423e13
UD
263 if (*__cp == '\0')
264 {
265 __cp = NULL;
266 break;
267 }
268 if (*__cp == __reject1 || *__cp == __reject2)
269 {
270 *__cp++ = '\0';
271 break;
272 }
273 ++__cp;
14c44e2e 274 }
61423e13 275 *__s = __cp;
14c44e2e
UD
276 }
277 return __retval;
278}
279
280__STRING_INLINE char *__strsep_3c (char **__s, char __reject1, char __reject2,
281 char __reject3);
282__STRING_INLINE char *
283__strsep_3c (char **__s, char __reject1, char __reject2, char __reject3)
284{
2e09a79a 285 char *__retval = *__s;
61423e13 286 if (__retval != NULL)
14c44e2e 287 {
2e09a79a 288 char *__cp = __retval;
61423e13 289 while (1)
14c44e2e 290 {
61423e13
UD
291 if (*__cp == '\0')
292 {
293 __cp = NULL;
294 break;
295 }
296 if (*__cp == __reject1 || *__cp == __reject2 || *__cp == __reject3)
297 {
298 *__cp++ = '\0';
299 break;
300 }
301 ++__cp;
14c44e2e 302 }
61423e13 303 *__s = __cp;
14c44e2e 304 }
650425ce 305 return __retval;
61eb22d3 306}
498afc54 307# ifdef __USE_MISC
61423e13 308# define strsep(s, reject) __strsep (s, reject)
31161268
UD
309# endif
310#endif
311
7ef90c15 312/* We need the memory allocation functions for inline strdup().
d2537a47 313 Referring to stdlib.h (even minimally) is not allowed
4a582094 314 in any of the tight standards compliant modes. */
6e2cc2c1 315#ifdef __USE_MISC
31161268 316
4a582094
UD
317# if !defined _HAVE_STRING_ARCH_strdup || !defined _HAVE_STRING_ARCH_strndup
318# define __need_malloc_and_calloc
319# include <stdlib.h>
320# endif
7ef90c15 321
4a582094 322# ifndef _HAVE_STRING_ARCH_strdup
31161268 323
a784e502 324extern char *__strdup (const char *__string) __THROW __attribute_malloc__;
4a582094 325# define __strdup(s) \
7551a1e5 326 (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \
a784e502 327 ? (((const char *) (s))[0] == '\0' \
a83b5649 328 ? (char *) calloc ((size_t) 1, (size_t) 1) \
7551a1e5
UD
329 : ({ size_t __len = strlen (s) + 1; \
330 char *__retval = (char *) malloc (__len); \
331 if (__retval != NULL) \
332 __retval = (char *) memcpy (__retval, s, __len); \
333 __retval; })) \
334 : __strdup (s)))
31161268 335
3d7c00e3 336# if defined __USE_XOPEN_EXTENDED || defined __USE_XOPEN2K8
4a582094
UD
337# define strdup(s) __strdup (s)
338# endif
61eb22d3 339# endif
61eb22d3 340
4a582094 341# ifndef _HAVE_STRING_ARCH_strndup
7551a1e5 342
a784e502 343extern char *__strndup (const char *__string, size_t __n)
160016c9 344 __THROW __attribute_malloc__;
4a582094 345# define __strndup(s, n) \
7551a1e5 346 (__extension__ (__builtin_constant_p (s) && __string2_1bptr_p (s) \
a784e502 347 ? (((const char *) (s))[0] == '\0' \
a83b5649 348 ? (char *) calloc ((size_t) 1, (size_t) 1) \
7551a1e5
UD
349 : ({ size_t __len = strlen (s) + 1; \
350 size_t __n = (n); \
351 char *__retval; \
352 if (__n < __len) \
fb4fb542 353 __len = __n + 1; \
7551a1e5
UD
354 __retval = (char *) malloc (__len); \
355 if (__retval != NULL) \
356 { \
357 __retval[__len - 1] = '\0'; \
358 __retval = (char *) memcpy (__retval, s, \
359 __len - 1); \
360 } \
361 __retval; })) \
61423e13 362 : __strndup (s, n)))
7551a1e5 363
3d7c00e3 364# ifdef __USE_XOPEN2K8
61423e13 365# define strndup(s, n) __strndup (s, n)
4a582094 366# endif
7551a1e5 367# endif
7551a1e5 368
4a582094 369#endif /* Use misc. or use GNU. */
7551a1e5 370
9bbd7837
UD
371#ifndef _FORCE_INLINES
372# undef __STRING_INLINE
373#endif
9a0a462c 374
61eb22d3 375#endif /* No string inlines. */