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