Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/string.h
49256 views
1
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
2
/*
3
* string function definitions for NOLIBC
4
* Copyright (C) 2017-2021 Willy Tarreau <[email protected]>
5
*/
6
7
/* make sure to include all global symbols */
8
#include "nolibc.h"
9
10
#ifndef _NOLIBC_STRING_H
11
#define _NOLIBC_STRING_H
12
13
#include "arch.h"
14
#include "std.h"
15
16
static void *malloc(size_t len);
17
18
/*
19
* As much as possible, please keep functions alphabetically sorted.
20
*/
21
22
static __attribute__((unused))
23
int memcmp(const void *s1, const void *s2, size_t n)
24
{
25
size_t ofs = 0;
26
int c1 = 0;
27
28
while (ofs < n && !(c1 = ((unsigned char *)s1)[ofs] - ((unsigned char *)s2)[ofs])) {
29
ofs++;
30
}
31
return c1;
32
}
33
34
#ifndef NOLIBC_ARCH_HAS_MEMMOVE
35
/* might be ignored by the compiler without -ffreestanding, then found as
36
* missing.
37
*/
38
void *memmove(void *dst, const void *src, size_t len);
39
__attribute__((weak,unused,section(".text.nolibc_memmove")))
40
void *memmove(void *dst, const void *src, size_t len)
41
{
42
size_t dir, pos;
43
44
pos = len;
45
dir = -1;
46
47
if (dst < src) {
48
pos = -1;
49
dir = 1;
50
}
51
52
while (len) {
53
pos += dir;
54
((char *)dst)[pos] = ((const char *)src)[pos];
55
len--;
56
}
57
return dst;
58
}
59
#endif /* #ifndef NOLIBC_ARCH_HAS_MEMMOVE */
60
61
#ifndef NOLIBC_ARCH_HAS_MEMCPY
62
/* must be exported, as it's used by libgcc on ARM */
63
void *memcpy(void *dst, const void *src, size_t len);
64
__attribute__((weak,unused,section(".text.nolibc_memcpy")))
65
void *memcpy(void *dst, const void *src, size_t len)
66
{
67
size_t pos = 0;
68
69
while (pos < len) {
70
((char *)dst)[pos] = ((const char *)src)[pos];
71
pos++;
72
}
73
return dst;
74
}
75
#endif /* #ifndef NOLIBC_ARCH_HAS_MEMCPY */
76
77
#ifndef NOLIBC_ARCH_HAS_MEMSET
78
/* might be ignored by the compiler without -ffreestanding, then found as
79
* missing.
80
*/
81
void *memset(void *dst, int b, size_t len);
82
__attribute__((weak,unused,section(".text.nolibc_memset")))
83
void *memset(void *dst, int b, size_t len)
84
{
85
char *p = dst;
86
87
while (len--) {
88
/* prevent gcc from recognizing memset() here */
89
__asm__ volatile("");
90
*(p++) = b;
91
}
92
return dst;
93
}
94
#endif /* #ifndef NOLIBC_ARCH_HAS_MEMSET */
95
96
#ifndef NOLIBC_ARCH_HAS_MEMCHR
97
static __attribute__((unused))
98
void *memchr(const void *s, int c, size_t len)
99
{
100
char *p = (char *)s;
101
102
while (len--) {
103
if (*p == (char)c)
104
return p;
105
p++;
106
}
107
return NULL;
108
}
109
#endif /* #ifndef NOLIBC_ARCH_HAS_MEMCHR */
110
111
static __attribute__((unused))
112
char *strchr(const char *s, int c)
113
{
114
while (*s) {
115
if (*s == (char)c)
116
return (char *)s;
117
s++;
118
}
119
return NULL;
120
}
121
122
static __attribute__((unused))
123
int strcmp(const char *a, const char *b)
124
{
125
unsigned int c;
126
int diff;
127
128
while (!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
129
;
130
return diff;
131
}
132
133
static __attribute__((unused))
134
char *strcpy(char *dst, const char *src)
135
{
136
char *ret = dst;
137
138
while ((*dst++ = *src++));
139
return ret;
140
}
141
142
/* this function is only used with arguments that are not constants or when
143
* it's not known because optimizations are disabled. Note that gcc 12
144
* recognizes an strlen() pattern and replaces it with a jump to strlen(),
145
* thus itself, hence the asm() statement below that's meant to disable this
146
* confusing practice.
147
*/
148
size_t strlen(const char *str);
149
__attribute__((weak,unused,section(".text.nolibc_strlen")))
150
size_t strlen(const char *str)
151
{
152
size_t len;
153
154
for (len = 0; str[len]; len++)
155
__asm__("");
156
return len;
157
}
158
159
/* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
160
* the two branches, then will rely on an external definition of strlen().
161
*/
162
#if defined(__OPTIMIZE__)
163
#define nolibc_strlen(x) strlen(x)
164
#define strlen(str) ({ \
165
__builtin_constant_p((str)) ? \
166
__builtin_strlen((str)) : \
167
nolibc_strlen((str)); \
168
})
169
#endif
170
171
static __attribute__((unused))
172
size_t strnlen(const char *str, size_t maxlen)
173
{
174
size_t len;
175
176
for (len = 0; (len < maxlen) && str[len]; len++);
177
return len;
178
}
179
180
static __attribute__((unused))
181
char *strdup(const char *str)
182
{
183
size_t len;
184
char *ret;
185
186
len = strlen(str);
187
ret = malloc(len + 1);
188
if (__builtin_expect(ret != NULL, 1))
189
memcpy(ret, str, len + 1);
190
191
return ret;
192
}
193
194
static __attribute__((unused))
195
char *strndup(const char *str, size_t maxlen)
196
{
197
size_t len;
198
char *ret;
199
200
len = strnlen(str, maxlen);
201
ret = malloc(len + 1);
202
if (__builtin_expect(ret != NULL, 1)) {
203
memcpy(ret, str, len);
204
ret[len] = '\0';
205
}
206
207
return ret;
208
}
209
210
static __attribute__((unused))
211
size_t strlcat(char *dst, const char *src, size_t size)
212
{
213
size_t len = strnlen(dst, size);
214
215
/*
216
* We want len < size-1. But as size is unsigned and can wrap
217
* around, we use len + 1 instead.
218
*/
219
while (len + 1 < size) {
220
dst[len] = *src;
221
if (*src == '\0')
222
break;
223
len++;
224
src++;
225
}
226
227
if (len < size)
228
dst[len] = '\0';
229
230
while (*src++)
231
len++;
232
233
return len;
234
}
235
236
static __attribute__((unused))
237
size_t strlcpy(char *dst, const char *src, size_t size)
238
{
239
size_t len;
240
241
for (len = 0; len < size; len++) {
242
dst[len] = src[len];
243
if (!dst[len])
244
return len;
245
}
246
if (size)
247
dst[size-1] = '\0';
248
249
while (src[len])
250
len++;
251
252
return len;
253
}
254
255
static __attribute__((unused))
256
char *strncat(char *dst, const char *src, size_t size)
257
{
258
char *orig = dst;
259
260
while (*dst)
261
dst++;
262
263
while (size && (*dst = *src)) {
264
src++;
265
dst++;
266
size--;
267
}
268
269
*dst = 0;
270
return orig;
271
}
272
273
static __attribute__((unused))
274
int strncmp(const char *a, const char *b, size_t size)
275
{
276
unsigned int c;
277
int diff = 0;
278
279
while (size-- &&
280
!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
281
;
282
283
return diff;
284
}
285
286
static __attribute__((unused))
287
char *strncpy(char *dst, const char *src, size_t size)
288
{
289
size_t len;
290
291
for (len = 0; len < size; len++)
292
if ((dst[len] = *src))
293
src++;
294
return dst;
295
}
296
297
static __attribute__((unused))
298
char *strrchr(const char *s, int c)
299
{
300
const char *ret = NULL;
301
302
while (*s) {
303
if (*s == (char)c)
304
ret = s;
305
s++;
306
}
307
return (char *)ret;
308
}
309
310
static __attribute__((unused))
311
char *strstr(const char *haystack, const char *needle)
312
{
313
size_t len_haystack, len_needle;
314
315
len_needle = strlen(needle);
316
if (!len_needle)
317
return NULL;
318
319
len_haystack = strlen(haystack);
320
while (len_haystack >= len_needle) {
321
if (!memcmp(haystack, needle, len_needle))
322
return (char *)haystack;
323
haystack++;
324
len_haystack--;
325
}
326
327
return NULL;
328
}
329
330
static __attribute__((unused))
331
int tolower(int c)
332
{
333
if (c >= 'A' && c <= 'Z')
334
return c - 'A' + 'a';
335
return c;
336
}
337
338
static __attribute__((unused))
339
int toupper(int c)
340
{
341
if (c >= 'a' && c <= 'z')
342
return c - 'a' + 'A';
343
return c;
344
}
345
346
#endif /* _NOLIBC_STRING_H */
347
348