1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
3 * string function definitions for NOLIBC
4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
7 #ifndef _NOLIBC_STRING_H
8 #define _NOLIBC_STRING_H
13 static void *malloc(size_t len
);
16 * As much as possible, please keep functions alphabetically sorted.
19 static __attribute__((unused
))
20 int memcmp(const void *s1
, const void *s2
, size_t n
)
25 while (ofs
< n
&& !(c1
= ((unsigned char *)s1
)[ofs
] - ((unsigned char *)s2
)[ofs
])) {
31 #ifndef NOLIBC_ARCH_HAS_MEMMOVE
32 /* might be ignored by the compiler without -ffreestanding, then found as
35 __attribute__((weak
,unused
,section(".text.nolibc_memmove")))
36 void *memmove(void *dst
, const void *src
, size_t len
)
50 ((char *)dst
)[pos
] = ((const char *)src
)[pos
];
55 #endif /* #ifndef NOLIBC_ARCH_HAS_MEMMOVE */
57 #ifndef NOLIBC_ARCH_HAS_MEMCPY
58 /* must be exported, as it's used by libgcc on ARM */
59 __attribute__((weak
,unused
,section(".text.nolibc_memcpy")))
60 void *memcpy(void *dst
, const void *src
, size_t len
)
65 ((char *)dst
)[pos
] = ((const char *)src
)[pos
];
70 #endif /* #ifndef NOLIBC_ARCH_HAS_MEMCPY */
72 #ifndef NOLIBC_ARCH_HAS_MEMSET
73 /* might be ignored by the compiler without -ffreestanding, then found as
76 __attribute__((weak
,unused
,section(".text.nolibc_memset")))
77 void *memset(void *dst
, int b
, size_t len
)
82 /* prevent gcc from recognizing memset() here */
88 #endif /* #ifndef NOLIBC_ARCH_HAS_MEMSET */
90 static __attribute__((unused
))
91 char *strchr(const char *s
, int c
)
101 static __attribute__((unused
))
102 int strcmp(const char *a
, const char *b
)
107 while (!(diff
= (unsigned char)*a
++ - (c
= (unsigned char)*b
++)) && c
)
112 static __attribute__((unused
))
113 char *strcpy(char *dst
, const char *src
)
117 while ((*dst
++ = *src
++));
121 /* this function is only used with arguments that are not constants or when
122 * it's not known because optimizations are disabled. Note that gcc 12
123 * recognizes an strlen() pattern and replaces it with a jump to strlen(),
124 * thus itself, hence the asm() statement below that's meant to disable this
125 * confusing practice.
127 __attribute__((weak
,unused
,section(".text.nolibc_strlen")))
128 size_t strlen(const char *str
)
132 for (len
= 0; str
[len
]; len
++)
137 /* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
138 * the two branches, then will rely on an external definition of strlen().
140 #if defined(__OPTIMIZE__)
141 #define nolibc_strlen(x) strlen(x)
142 #define strlen(str) ({ \
143 __builtin_constant_p((str)) ? \
144 __builtin_strlen((str)) : \
145 nolibc_strlen((str)); \
149 static __attribute__((unused
))
150 size_t strnlen(const char *str
, size_t maxlen
)
154 for (len
= 0; (len
< maxlen
) && str
[len
]; len
++);
158 static __attribute__((unused
))
159 char *strdup(const char *str
)
165 ret
= malloc(len
+ 1);
166 if (__builtin_expect(ret
!= NULL
, 1))
167 memcpy(ret
, str
, len
+ 1);
172 static __attribute__((unused
))
173 char *strndup(const char *str
, size_t maxlen
)
178 len
= strnlen(str
, maxlen
);
179 ret
= malloc(len
+ 1);
180 if (__builtin_expect(ret
!= NULL
, 1)) {
181 memcpy(ret
, str
, len
);
188 static __attribute__((unused
))
189 size_t strlcat(char *dst
, const char *src
, size_t size
)
191 size_t len
= strnlen(dst
, size
);
194 * We want len < size-1. But as size is unsigned and can wrap
195 * around, we use len + 1 instead.
197 while (len
+ 1 < size
) {
214 static __attribute__((unused
))
215 size_t strlcpy(char *dst
, const char *src
, size_t size
)
219 for (len
= 0; len
< size
; len
++) {
233 static __attribute__((unused
))
234 char *strncat(char *dst
, const char *src
, size_t size
)
241 while (size
&& (*dst
= *src
)) {
251 static __attribute__((unused
))
252 int strncmp(const char *a
, const char *b
, size_t size
)
258 !(diff
= (unsigned char)*a
++ - (c
= (unsigned char)*b
++)) && c
)
264 static __attribute__((unused
))
265 char *strncpy(char *dst
, const char *src
, size_t size
)
269 for (len
= 0; len
< size
; len
++)
270 if ((dst
[len
] = *src
))
275 static __attribute__((unused
))
276 char *strrchr(const char *s
, int c
)
278 const char *ret
= NULL
;
288 /* make sure to include all global symbols */
291 #endif /* _NOLIBC_STRING_H */