1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 3 * string function definitions for NOLIBC 4 * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu> 5 */ 6 7 #ifndef _NOLIBC_STRING_H 8 #define _NOLIBC_STRING_H 9 10 #include "std.h" 11 12 static void *malloc(size_t len); 13 14 /* 15 * As much as possible, please keep functions alphabetically sorted. 16 */ 17 18 static __attribute__((unused)) 19 int memcmp(const void *s1, const void *s2, size_t n) 20 { 21 size_t ofs = 0; 22 char c1 = 0; 23 24 while (ofs < n && !(c1 = ((char *)s1)[ofs] - ((char *)s2)[ofs])) { 25 ofs++; 26 } 27 return c1; 28 } 29 30 static __attribute__((unused)) 31 void *_nolibc_memcpy_up(void *dst, const void *src, size_t len) 32 { 33 size_t pos = 0; 34 35 while (pos < len) { 36 ((char *)dst)[pos] = ((const char *)src)[pos]; 37 pos++; 38 } 39 return dst; 40 } 41 42 static __attribute__((unused)) 43 void *_nolibc_memcpy_down(void *dst, const void *src, size_t len) 44 { 45 while (len) { 46 len--; 47 ((char *)dst)[len] = ((const char *)src)[len]; 48 } 49 return dst; 50 } 51 52 /* might be ignored by the compiler without -ffreestanding, then found as 53 * missing. 54 */ 55 __attribute__((weak,unused,section(".text.nolibc_memmove"))) 56 void *memmove(void *dst, const void *src, size_t len) 57 { 58 size_t dir, pos; 59 60 pos = len; 61 dir = -1; 62 63 if (dst < src) { 64 pos = -1; 65 dir = 1; 66 } 67 68 while (len) { 69 pos += dir; 70 ((char *)dst)[pos] = ((const char *)src)[pos]; 71 len--; 72 } 73 return dst; 74 } 75 76 /* must be exported, as it's used by libgcc on ARM */ 77 __attribute__((weak,unused,section(".text.nolibc_memcpy"))) 78 void *memcpy(void *dst, const void *src, size_t len) 79 { 80 return _nolibc_memcpy_up(dst, src, len); 81 } 82 83 /* might be ignored by the compiler without -ffreestanding, then found as 84 * missing. 85 */ 86 __attribute__((weak,unused,section(".text.nolibc_memset"))) 87 void *memset(void *dst, int b, size_t len) 88 { 89 char *p = dst; 90 91 while (len--) 92 *(p++) = b; 93 return dst; 94 } 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. 129 */ 130 static __attribute__((unused)) 131 size_t nolibc_strlen(const char *str) 132 { 133 size_t len; 134 135 for (len = 0; str[len]; len++); 136 return len; 137 } 138 139 /* do not trust __builtin_constant_p() at -O0, as clang will emit a test and 140 * the two branches, then will rely on an external definition of strlen(). 141 */ 142 #if defined(__OPTIMIZE__) 143 #define strlen(str) ({ \ 144 __builtin_constant_p((str)) ? \ 145 __builtin_strlen((str)) : \ 146 nolibc_strlen((str)); \ 147 }) 148 #else 149 #define strlen(str) nolibc_strlen((str)) 150 #endif 151 152 static __attribute__((unused)) 153 size_t strnlen(const char *str, size_t maxlen) 154 { 155 size_t len; 156 157 for (len = 0; (len < maxlen) && str[len]; len++); 158 return len; 159 } 160 161 static __attribute__((unused)) 162 char *strdup(const char *str) 163 { 164 size_t len; 165 char *ret; 166 167 len = strlen(str); 168 ret = malloc(len + 1); 169 if (__builtin_expect(ret != NULL, 1)) 170 memcpy(ret, str, len + 1); 171 172 return ret; 173 } 174 175 static __attribute__((unused)) 176 char *strndup(const char *str, size_t maxlen) 177 { 178 size_t len; 179 char *ret; 180 181 len = strnlen(str, maxlen); 182 ret = malloc(len + 1); 183 if (__builtin_expect(ret != NULL, 1)) { 184 memcpy(ret, str, len); 185 ret[len] = '\0'; 186 } 187 188 return ret; 189 } 190 191 static __attribute__((unused)) 192 size_t strlcat(char *dst, const char *src, size_t size) 193 { 194 size_t len; 195 char c; 196 197 for (len = 0; dst[len]; len++) 198 ; 199 200 for (;;) { 201 c = *src; 202 if (len < size) 203 dst[len] = c; 204 if (!c) 205 break; 206 len++; 207 src++; 208 } 209 210 return len; 211 } 212 213 static __attribute__((unused)) 214 size_t strlcpy(char *dst, const char *src, size_t size) 215 { 216 size_t len; 217 char c; 218 219 for (len = 0;;) { 220 c = src[len]; 221 if (len < size) 222 dst[len] = c; 223 if (!c) 224 break; 225 len++; 226 } 227 return len; 228 } 229 230 static __attribute__((unused)) 231 char *strncat(char *dst, const char *src, size_t size) 232 { 233 char *orig = dst; 234 235 while (*dst) 236 dst++; 237 238 while (size && (*dst = *src)) { 239 src++; 240 dst++; 241 size--; 242 } 243 244 *dst = 0; 245 return orig; 246 } 247 248 static __attribute__((unused)) 249 int strncmp(const char *a, const char *b, size_t size) 250 { 251 unsigned int c; 252 int diff = 0; 253 254 while (size-- && 255 !(diff = (unsigned char)*a++ - (c = (unsigned char)*b++)) && c) 256 ; 257 258 return diff; 259 } 260 261 static __attribute__((unused)) 262 char *strncpy(char *dst, const char *src, size_t size) 263 { 264 size_t len; 265 266 for (len = 0; len < size; len++) 267 if ((dst[len] = *src)) 268 src++; 269 return dst; 270 } 271 272 static __attribute__((unused)) 273 char *strrchr(const char *s, int c) 274 { 275 const char *ret = NULL; 276 277 while (*s) { 278 if (*s == (char)c) 279 ret = s; 280 s++; 281 } 282 return (char *)ret; 283 } 284 285 #endif /* _NOLIBC_STRING_H */ 286