kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

stdlib.c (5621B)


      1 //===-- stdlib.c - kit freestanding stdlib primitives -------------------===//
      2 //
      3 // SPDX-License-Identifier: 0BSD
      4 //===----------------------------------------------------------------------===//
      5 
      6 #include <stddef.h>
      7 
      8 typedef struct {
      9   int quot;
     10   int rem;
     11 } div_t;
     12 
     13 typedef struct {
     14   long quot;
     15   long rem;
     16 } ldiv_t;
     17 
     18 typedef struct {
     19   long long quot;
     20   long long rem;
     21 } lldiv_t;
     22 
     23 static int kit_isspace(char c) { return c == ' ' || (c >= '\t' && c <= '\r'); }
     24 
     25 static int kit_digit_value(char c) {
     26   if (c >= '0' && c <= '9') return c - '0';
     27   if (c >= 'a' && c <= 'z') return c - 'a' + 10;
     28   if (c >= 'A' && c <= 'Z') return c - 'A' + 10;
     29   return -1;
     30 }
     31 
     32 static int kit_match_ci(const char* s, const char* word) {
     33   while (*word != '\0') {
     34     char a = *s++;
     35     char b = *word++;
     36     if (a >= 'A' && a <= 'Z') a = (char)(a - 'A' + 'a');
     37     if (a != b) return 0;
     38   }
     39   return 1;
     40 }
     41 
     42 __attribute__((weak)) unsigned long long strtoull(const char* nptr,
     43                                                   char** endptr, int base) {
     44   const char* s = nptr;
     45   int neg = 0;
     46   unsigned long long value = 0;
     47   int any = 0;
     48 
     49   while (kit_isspace(*s)) s++;
     50   if (*s == '+' || *s == '-') neg = *s++ == '-';
     51 
     52   if ((base == 0 || base == 16) && s[0] == '0' &&
     53       (s[1] == 'x' || s[1] == 'X')) {
     54     int d = kit_digit_value(s[2]);
     55     if (d >= 0 && d < 16) {
     56       s += 2;
     57       base = 16;
     58     }
     59   }
     60   if (base == 0) base = (*s == '0') ? 8 : 10;
     61   if (base < 2 || base > 36) {
     62     if (endptr) *endptr = (char*)nptr;
     63     return 0;
     64   }
     65 
     66   for (;;) {
     67     int d = kit_digit_value(*s);
     68     if (d < 0 || d >= base) break;
     69     value = value * (unsigned)base + (unsigned)d;
     70     s++;
     71     any = 1;
     72   }
     73 
     74   if (endptr) *endptr = (char*)(any ? s : nptr);
     75   return neg ? 0 - value : value;
     76 }
     77 
     78 __attribute__((weak)) unsigned long strtoul(const char* nptr, char** endptr,
     79                                             int base) {
     80   return (unsigned long)strtoull(nptr, endptr, base);
     81 }
     82 
     83 __attribute__((weak)) long long strtoll(const char* nptr, char** endptr,
     84                                         int base) {
     85   return (long long)strtoull(nptr, endptr, base);
     86 }
     87 
     88 __attribute__((weak)) long strtol(const char* nptr, char** endptr, int base) {
     89   return (long)strtoull(nptr, endptr, base);
     90 }
     91 
     92 __attribute__((weak)) long long atoll(const char* nptr) {
     93   return strtoll(nptr, NULL, 10);
     94 }
     95 __attribute__((weak)) long atol(const char* nptr) {
     96   return strtol(nptr, NULL, 10);
     97 }
     98 __attribute__((weak)) int atoi(const char* nptr) {
     99   return (int)strtol(nptr, NULL, 10);
    100 }
    101 
    102 static long double kit_strtold_impl(const char* nptr, char** endptr) {
    103   const char* s = nptr;
    104   int neg = 0;
    105   int any = 0;
    106   long double value = 0.0L;
    107 
    108   while (kit_isspace(*s)) s++;
    109   if (*s == '+' || *s == '-') neg = *s++ == '-';
    110 
    111   if (kit_match_ci(s, "infinity")) {
    112     if (endptr) *endptr = (char*)(s + 8);
    113     return neg ? -(1.0L / 0.0L) : (1.0L / 0.0L);
    114   }
    115   if (kit_match_ci(s, "inf")) {
    116     if (endptr) *endptr = (char*)(s + 3);
    117     return neg ? -(1.0L / 0.0L) : (1.0L / 0.0L);
    118   }
    119   if (kit_match_ci(s, "nan")) {
    120     if (endptr) *endptr = (char*)(s + 3);
    121     return 0.0L / 0.0L;
    122   }
    123 
    124   while (*s >= '0' && *s <= '9') {
    125     value = value * 10.0L + (long double)(*s - '0');
    126     s++;
    127     any = 1;
    128   }
    129 
    130   if (*s == '.') {
    131     long double place = 0.1L;
    132     s++;
    133     while (*s >= '0' && *s <= '9') {
    134       value += (long double)(*s - '0') * place;
    135       place *= 0.1L;
    136       s++;
    137       any = 1;
    138     }
    139   }
    140 
    141   if (!any) {
    142     if (endptr) *endptr = (char*)nptr;
    143     return 0.0L;
    144   }
    145 
    146   if (*s == 'e' || *s == 'E') {
    147     const char* exp_start = s;
    148     int exp_neg = 0;
    149     int exp_any = 0;
    150     int exp = 0;
    151     s++;
    152     if (*s == '+' || *s == '-') exp_neg = *s++ == '-';
    153     while (*s >= '0' && *s <= '9') {
    154       exp = exp * 10 + (*s - '0');
    155       s++;
    156       exp_any = 1;
    157     }
    158     if (exp_any) {
    159       while (exp-- > 0) value = exp_neg ? value / 10.0L : value * 10.0L;
    160     } else {
    161       s = exp_start;
    162     }
    163   }
    164 
    165   if (endptr) *endptr = (char*)s;
    166   return neg ? -value : value;
    167 }
    168 
    169 __attribute__((weak)) long double strtold(const char* nptr, char** endptr) {
    170   return kit_strtold_impl(nptr, endptr);
    171 }
    172 
    173 __attribute__((weak)) double strtod(const char* nptr, char** endptr) {
    174   return (double)kit_strtold_impl(nptr, endptr);
    175 }
    176 
    177 __attribute__((weak)) float strtof(const char* nptr, char** endptr) {
    178   return (float)kit_strtold_impl(nptr, endptr);
    179 }
    180 
    181 __attribute__((weak)) int abs(int j) { return j < 0 ? -j : j; }
    182 __attribute__((weak)) long labs(long j) { return j < 0 ? -j : j; }
    183 __attribute__((weak)) long long llabs(long long j) { return j < 0 ? -j : j; }
    184 
    185 __attribute__((weak)) div_t div(int numer, int denom) {
    186   div_t r;
    187   r.quot = numer / denom;
    188   r.rem = numer % denom;
    189   return r;
    190 }
    191 
    192 __attribute__((weak)) ldiv_t ldiv(long numer, long denom) {
    193   ldiv_t r;
    194   r.quot = numer / denom;
    195   r.rem = numer % denom;
    196   return r;
    197 }
    198 
    199 __attribute__((weak)) lldiv_t lldiv(long long numer, long long denom) {
    200   lldiv_t r;
    201   r.quot = numer / denom;
    202   r.rem = numer % denom;
    203   return r;
    204 }
    205 
    206 __attribute__((weak)) void* bsearch(const void* key, const void* base,
    207                                     size_t nmemb, size_t size,
    208                                     int (*compar)(const void*, const void*)) {
    209   const unsigned char* b = (const unsigned char*)base;
    210   size_t low = 0;
    211   size_t high = nmemb;
    212 
    213   while (low < high) {
    214     size_t mid = low + (high - low) / 2;
    215     const void* elem = b + mid * size;
    216     int cmp = compar(key, elem);
    217     if (cmp < 0) {
    218       high = mid;
    219     } else if (cmp > 0) {
    220       low = mid + 1;
    221     } else {
    222       return (void*)elem;
    223     }
    224   }
    225   return NULL;
    226 }