kit

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

stdlib.c (6611B)


      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)) size_t memalignment(const void* p) {
    182   __UINTPTR_TYPE__ v = (__UINTPTR_TYPE__)p;
    183   if (v == 0) return 0;
    184   return (size_t)(v & (0u - v));
    185 }
    186 
    187 typedef __INTMAX_TYPE__ kit_intmax_t;
    188 typedef __UINTMAX_TYPE__ kit_uintmax_t;
    189 
    190 typedef struct {
    191   kit_intmax_t quot;
    192   kit_intmax_t rem;
    193 } imaxdiv_t;
    194 
    195 __attribute__((weak)) kit_intmax_t imaxabs(kit_intmax_t j) {
    196   return j < 0 ? -j : j;
    197 }
    198 
    199 __attribute__((weak)) imaxdiv_t imaxdiv(kit_intmax_t numer,
    200                                         kit_intmax_t denom) {
    201   imaxdiv_t r;
    202   r.quot = numer / denom;
    203   r.rem = numer % denom;
    204   return r;
    205 }
    206 
    207 __attribute__((weak)) kit_intmax_t strtoimax(const char* nptr, char** endptr,
    208                                              int base) {
    209   return (kit_intmax_t)strtoll(nptr, endptr, base);
    210 }
    211 
    212 __attribute__((weak)) kit_uintmax_t strtoumax(const char* nptr, char** endptr,
    213                                               int base) {
    214   return (kit_uintmax_t)strtoull(nptr, endptr, base);
    215 }
    216 
    217 __attribute__((weak)) int abs(int j) { return j < 0 ? -j : j; }
    218 __attribute__((weak)) long labs(long j) { return j < 0 ? -j : j; }
    219 __attribute__((weak)) long long llabs(long long j) { return j < 0 ? -j : j; }
    220 
    221 __attribute__((weak)) div_t div(int numer, int denom) {
    222   div_t r;
    223   r.quot = numer / denom;
    224   r.rem = numer % denom;
    225   return r;
    226 }
    227 
    228 __attribute__((weak)) ldiv_t ldiv(long numer, long denom) {
    229   ldiv_t r;
    230   r.quot = numer / denom;
    231   r.rem = numer % denom;
    232   return r;
    233 }
    234 
    235 __attribute__((weak)) lldiv_t lldiv(long long numer, long long denom) {
    236   lldiv_t r;
    237   r.quot = numer / denom;
    238   r.rem = numer % denom;
    239   return r;
    240 }
    241 
    242 __attribute__((weak)) void* bsearch(const void* key, const void* base,
    243                                     size_t nmemb, size_t size,
    244                                     int (*compar)(const void*, const void*)) {
    245   const unsigned char* b = (const unsigned char*)base;
    246   size_t low = 0;
    247   size_t high = nmemb;
    248 
    249   while (low < high) {
    250     size_t mid = low + (high - low) / 2;
    251     const void* elem = b + mid * size;
    252     int cmp = compar(key, elem);
    253     if (cmp < 0) {
    254       high = mid;
    255     } else if (cmp > 0) {
    256       low = mid + 1;
    257     } else {
    258       return (void*)elem;
    259     }
    260   }
    261   return NULL;
    262 }