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