string.h (4964B)
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 12static void *malloc(size_t len); 13 14/* 15 * As much as possible, please keep functions alphabetically sorted. 16 */ 17 18static __attribute__((unused)) 19int 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 30static __attribute__((unused)) 31void *_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 42static __attribute__((unused)) 43void *_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"))) 56void *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"))) 78void *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"))) 87void *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 96static __attribute__((unused)) 97char *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 107static __attribute__((unused)) 108int 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 118static __attribute__((unused)) 119char *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 */ 130static __attribute__((unused)) 131size_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 152static __attribute__((unused)) 153size_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 161static __attribute__((unused)) 162char *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 175static __attribute__((unused)) 176char *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 191static __attribute__((unused)) 192size_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 213static __attribute__((unused)) 214size_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 230static __attribute__((unused)) 231char *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 248static __attribute__((unused)) 249int 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 261static __attribute__((unused)) 262char *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 272static __attribute__((unused)) 273char *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 */