Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/include/nolibc/string.h
26288 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
static __attribute__((unused))
97
char *strchr(const char *s, int c)
98
{
99
while (*s) {
100
if (*s == (char)c)
101
return (char *)s;
102
s++;
103
}
104
return NULL;
105
}
106
107
static __attribute__((unused))
108
int strcmp(const char *a, const char *b)
109
{
110
unsigned int c;
111
int diff;
112
113
while (!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
114
;
115
return diff;
116
}
117
118
static __attribute__((unused))
119
char *strcpy(char *dst, const char *src)
120
{
121
char *ret = dst;
122
123
while ((*dst++ = *src++));
124
return ret;
125
}
126
127
/* this function is only used with arguments that are not constants or when
128
* it's not known because optimizations are disabled. Note that gcc 12
129
* recognizes an strlen() pattern and replaces it with a jump to strlen(),
130
* thus itself, hence the asm() statement below that's meant to disable this
131
* confusing practice.
132
*/
133
size_t strlen(const char *str);
134
__attribute__((weak,unused,section(".text.nolibc_strlen")))
135
size_t strlen(const char *str)
136
{
137
size_t len;
138
139
for (len = 0; str[len]; len++)
140
__asm__("");
141
return len;
142
}
143
144
/* do not trust __builtin_constant_p() at -O0, as clang will emit a test and
145
* the two branches, then will rely on an external definition of strlen().
146
*/
147
#if defined(__OPTIMIZE__)
148
#define nolibc_strlen(x) strlen(x)
149
#define strlen(str) ({ \
150
__builtin_constant_p((str)) ? \
151
__builtin_strlen((str)) : \
152
nolibc_strlen((str)); \
153
})
154
#endif
155
156
static __attribute__((unused))
157
size_t strnlen(const char *str, size_t maxlen)
158
{
159
size_t len;
160
161
for (len = 0; (len < maxlen) && str[len]; len++);
162
return len;
163
}
164
165
static __attribute__((unused))
166
char *strdup(const char *str)
167
{
168
size_t len;
169
char *ret;
170
171
len = strlen(str);
172
ret = malloc(len + 1);
173
if (__builtin_expect(ret != NULL, 1))
174
memcpy(ret, str, len + 1);
175
176
return ret;
177
}
178
179
static __attribute__((unused))
180
char *strndup(const char *str, size_t maxlen)
181
{
182
size_t len;
183
char *ret;
184
185
len = strnlen(str, maxlen);
186
ret = malloc(len + 1);
187
if (__builtin_expect(ret != NULL, 1)) {
188
memcpy(ret, str, len);
189
ret[len] = '\0';
190
}
191
192
return ret;
193
}
194
195
static __attribute__((unused))
196
size_t strlcat(char *dst, const char *src, size_t size)
197
{
198
size_t len = strnlen(dst, size);
199
200
/*
201
* We want len < size-1. But as size is unsigned and can wrap
202
* around, we use len + 1 instead.
203
*/
204
while (len + 1 < size) {
205
dst[len] = *src;
206
if (*src == '\0')
207
break;
208
len++;
209
src++;
210
}
211
212
if (len < size)
213
dst[len] = '\0';
214
215
while (*src++)
216
len++;
217
218
return len;
219
}
220
221
static __attribute__((unused))
222
size_t strlcpy(char *dst, const char *src, size_t size)
223
{
224
size_t len;
225
226
for (len = 0; len < size; len++) {
227
dst[len] = src[len];
228
if (!dst[len])
229
return len;
230
}
231
if (size)
232
dst[size-1] = '\0';
233
234
while (src[len])
235
len++;
236
237
return len;
238
}
239
240
static __attribute__((unused))
241
char *strncat(char *dst, const char *src, size_t size)
242
{
243
char *orig = dst;
244
245
while (*dst)
246
dst++;
247
248
while (size && (*dst = *src)) {
249
src++;
250
dst++;
251
size--;
252
}
253
254
*dst = 0;
255
return orig;
256
}
257
258
static __attribute__((unused))
259
int strncmp(const char *a, const char *b, size_t size)
260
{
261
unsigned int c;
262
int diff = 0;
263
264
while (size-- &&
265
!(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c)
266
;
267
268
return diff;
269
}
270
271
static __attribute__((unused))
272
char *strncpy(char *dst, const char *src, size_t size)
273
{
274
size_t len;
275
276
for (len = 0; len < size; len++)
277
if ((dst[len] = *src))
278
src++;
279
return dst;
280
}
281
282
static __attribute__((unused))
283
char *strrchr(const char *s, int c)
284
{
285
const char *ret = NULL;
286
287
while (*s) {
288
if (*s == (char)c)
289
ret = s;
290
s++;
291
}
292
return (char *)ret;
293
}
294
295
static __attribute__((unused))
296
char *strstr(const char *haystack, const char *needle)
297
{
298
size_t len_haystack, len_needle;
299
300
len_needle = strlen(needle);
301
if (!len_needle)
302
return NULL;
303
304
len_haystack = strlen(haystack);
305
while (len_haystack >= len_needle) {
306
if (!memcmp(haystack, needle, len_needle))
307
return (char *)haystack;
308
haystack++;
309
len_haystack--;
310
}
311
312
return NULL;
313
}
314
315
static __attribute__((unused))
316
int tolower(int c)
317
{
318
if (c >= 'A' && c <= 'Z')
319
return c - 'A' + 'a';
320
return c;
321
}
322
323
static __attribute__((unused))
324
int toupper(int c)
325
{
326
if (c >= 'a' && c <= 'z')
327
return c - 'a' + 'A';
328
return c;
329
}
330
331
#endif /* _NOLIBC_STRING_H */
332
333