1 /* 2 * libc string functions 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU Library General Public License version 2. 6 */ 7 8 #include "libcflat.h" 9 #include "ctype.h" 10 #include "stdlib.h" 11 #include "linux/compiler.h" 12 13 size_t strlen(const char *buf) 14 { 15 size_t len = 0; 16 17 while (*buf++) 18 ++len; 19 return len; 20 } 21 22 size_t strnlen(const char *buf, size_t maxlen) 23 { 24 const char *sc; 25 26 for (sc = buf; maxlen-- && *sc != '\0'; ++sc) 27 /* nothing */ ; 28 return sc - buf; 29 } 30 31 char *strcat(char *dest, const char *src) 32 { 33 char *p = dest; 34 35 while (*p) 36 ++p; 37 while ((*p++ = *src++) != 0) 38 ; 39 return dest; 40 } 41 42 char *strcpy(char *dest, const char *src) 43 { 44 *dest = 0; 45 return strcat(dest, src); 46 } 47 48 int strncmp(const char *a, const char *b, size_t n) 49 { 50 for (; n--; ++a, ++b) 51 if (*a != *b || *a == '\0') 52 return *a - *b; 53 54 return 0; 55 } 56 57 int strncasecmp(const char *a, const char *b, size_t n) 58 { 59 for (; n--; ++a, ++b) 60 if (tolower(*a) != tolower(*b) || *a == '\0') 61 return tolower(*a) - tolower(*b); 62 63 return 0; 64 } 65 66 int strcmp(const char *a, const char *b) 67 { 68 return strncmp(a, b, SIZE_MAX); 69 } 70 71 int strcasecmp(const char *a, const char *b) 72 { 73 return strncasecmp(a, b, SIZE_MAX); 74 } 75 76 char *strchr(const char *s, int c) 77 { 78 while (*s != (char)c) 79 if (*s++ == '\0') 80 return NULL; 81 return (char *)s; 82 } 83 84 char *strrchr(const char *s, int c) 85 { 86 const char *last = NULL; 87 do { 88 if (*s == (char)c) 89 last = s; 90 } while (*s++); 91 return (char *)last; 92 } 93 94 char *strchrnul(const char *s, int c) 95 { 96 while (*s && *s != (char)c) 97 s++; 98 return (char *)s; 99 } 100 101 char *strstr(const char *s1, const char *s2) 102 { 103 size_t l1, l2; 104 105 l2 = strlen(s2); 106 if (!l2) 107 return (char *)s1; 108 l1 = strlen(s1); 109 while (l1 >= l2) { 110 l1--; 111 if (!memcmp(s1, s2, l2)) 112 return (char *)s1; 113 s1++; 114 } 115 return NULL; 116 } 117 118 void *memset(void *s, int c, size_t n) 119 { 120 size_t i; 121 char *a = s; 122 123 for (i = 0; i < n; ++i) 124 a[i] = c; 125 126 return s; 127 } 128 129 void *memcpy(void *dest, const void *src, size_t n) 130 { 131 size_t i; 132 char *a = dest; 133 const char *b = src; 134 135 for (i = 0; i < n; ++i) 136 a[i] = b[i]; 137 138 return dest; 139 } 140 141 int memcmp(const void *s1, const void *s2, size_t n) 142 { 143 const unsigned char *a = s1, *b = s2; 144 int ret = 0; 145 146 while (n--) { 147 ret = *a - *b; 148 if (ret) 149 break; 150 ++a, ++b; 151 } 152 return ret; 153 } 154 155 void *memmove(void *dest, const void *src, size_t n) 156 { 157 const unsigned char *s = src; 158 unsigned char *d = dest; 159 160 if (d <= s) { 161 while (n--) 162 *d++ = *s++; 163 } else { 164 d += n, s += n; 165 while (n--) 166 *--d = *--s; 167 } 168 return dest; 169 } 170 171 void *memchr(const void *s, int c, size_t n) 172 { 173 const unsigned char *str = s, chr = (unsigned char)c; 174 175 while (n--) 176 if (*str++ == chr) 177 return (void *)(str - 1); 178 return NULL; 179 } 180 181 static unsigned long long __strtoll(const char *nptr, char **endptr, 182 int base, bool is_signed, bool is_longlong) 183 { 184 unsigned long long ull = 0; 185 const char *s = nptr; 186 int neg, c; 187 188 assert(base == 0 || (base >= 2 && base <= 36)); 189 190 while (isspace(*s)) 191 s++; 192 193 if (*s == '-') { 194 neg = 1; 195 s++; 196 } else { 197 neg = 0; 198 if (*s == '+') 199 s++; 200 } 201 202 if (base == 0 || base == 16) { 203 if (*s == '0') { 204 s++; 205 if (*s == 'x' || *s == 'X') { 206 s++; 207 base = 16; 208 } else if (base == 0) 209 base = 8; 210 } else if (base == 0) 211 base = 10; 212 } 213 214 while (*s) { 215 if (*s >= '0' && *s < '0' + base && *s <= '9') 216 c = *s - '0'; 217 else if (*s >= 'a' && *s < 'a' + base - 10) 218 c = *s - 'a' + 10; 219 else if (*s >= 'A' && *s < 'A' + base - 10) 220 c = *s - 'A' + 10; 221 else 222 break; 223 224 if (!is_longlong) { 225 if (is_signed) { 226 long sl = (long)ull; 227 assert(!check_mul_overflow(sl, base)); 228 assert(!check_add_overflow(sl * base, c)); 229 } else { 230 unsigned long ul = (unsigned long)ull; 231 assert(!check_mul_overflow(ul, base)); 232 assert(!check_add_overflow(ul * base, c)); 233 } 234 } else { 235 if (is_signed) { 236 long long sll = (long long)ull; 237 assert(!check_mul_overflow(sll, base)); 238 assert(!check_add_overflow(sll * base, c)); 239 } else { 240 assert(!check_mul_overflow(ull, base)); 241 assert(!check_add_overflow(ull * base, c)); 242 } 243 } 244 245 ull = ull * base + c; 246 s++; 247 } 248 249 if (neg) 250 ull = -ull; 251 252 if (endptr) 253 *endptr = (char *)s; 254 255 return ull; 256 } 257 258 long int strtol(const char *nptr, char **endptr, int base) 259 { 260 return __strtoll(nptr, endptr, base, true, false); 261 } 262 263 unsigned long int strtoul(const char *nptr, char **endptr, int base) 264 { 265 return __strtoll(nptr, endptr, base, false, false); 266 } 267 268 long long int strtoll(const char *nptr, char **endptr, int base) 269 { 270 return __strtoll(nptr, endptr, base, true, true); 271 } 272 273 unsigned long long int strtoull(const char *nptr, char **endptr, int base) 274 { 275 return __strtoll(nptr, endptr, base, false, true); 276 } 277 278 long atol(const char *ptr) 279 { 280 return strtol(ptr, NULL, 10); 281 } 282 283 extern char **environ; 284 285 char *getenv(const char *name) 286 { 287 char **envp = environ, *delim; 288 int len; 289 290 while (*envp) { 291 delim = strchr(*envp, '='); 292 assert(delim); 293 len = delim - *envp; 294 if (memcmp(name, *envp, len) == 0 && !name[len]) 295 return delim + 1; 296 ++envp; 297 } 298 return NULL; 299 } 300 301 /* Very simple glob matching. Allows '*' at beginning and end of pattern. */ 302 bool simple_glob(const char *text, const char *pattern) 303 { 304 bool star_start = false; 305 bool star_end = false; 306 size_t n = strlen(pattern); 307 char copy[n + 1]; 308 309 if (pattern[0] == '*') { 310 pattern += 1; 311 n -= 1; 312 star_start = true; 313 } 314 315 strcpy(copy, pattern); 316 317 if (n > 0 && pattern[n - 1] == '*') { 318 n -= 1; 319 copy[n] = '\0'; 320 star_end = true; 321 } 322 323 if (star_start && star_end) 324 return strstr(text, copy); 325 326 if (star_end) 327 return strstr(text, copy) == text; 328 329 if (star_start) { 330 size_t text_len = strlen(text); 331 const char *suffix; 332 333 if (n > text_len) 334 return false; 335 suffix = text + text_len - n; 336 return !strcmp(suffix, copy); 337 } 338 339 return !strcmp(text, copy); 340 } 341