Home | History | Annotate | Download | only in bionic
      1 /*
      2  * Copyright (c) 1992 The Regents of the University of California.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. Neither the name of the University nor the names of its contributors
     14  *    may be used to endorse or promote products derived from this software
     15  *    without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include <errno.h>
     31 #include <inttypes.h>
     32 #include <limits.h>
     33 #include <stdlib.h>
     34 
     35 #include <private/bionic_ctype.h>
     36 
     37 template <typename T, T Min, T Max> T StrToI(const char* nptr, char** endptr, int base) {
     38   // Ensure that base is between 2 and 36 inclusive, or the special value of 0.
     39   if (base < 0 || base == 1 || base > 36) {
     40     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
     41     errno = EINVAL;
     42     return 0;
     43   }
     44 
     45   // Skip white space and pick up leading +/- sign if any.
     46   // If base is 0, allow 0x for hex and 0 for octal, else
     47   // assume decimal; if base is already 16, allow 0x.
     48   const char* s = nptr;
     49   int c;
     50   do {
     51     c = *s++;
     52   } while (IsSpace(c));
     53   int neg;
     54   if (c == '-') {
     55     neg = 1;
     56     c = *s++;
     57   } else {
     58     neg = 0;
     59     if (c == '+') c = *s++;
     60   }
     61   if ((base == 0 || base == 16) && c == '0' &&
     62       (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
     63     c = s[1];
     64     s += 2;
     65     base = 16;
     66   }
     67   if (base == 0) base = (c == '0') ? 8 : 10;
     68 
     69   // We always work in the negative space because the most negative value has a
     70   // larger magnitude than the most positive value.
     71   T cutoff = Min / base;
     72   int cutlim = -(Min % base);
     73   // Non-zero if any digits consumed; negative to indicate overflow/underflow.
     74   int any = 0;
     75   T acc = 0;
     76   for (; ; c = *s++) {
     77     if (IsDigit(c)) {
     78       c -= '0';
     79     } else if (IsAlpha(c)) {
     80       c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
     81     } else {
     82       break;
     83     }
     84     if (c >= base) break;
     85     if (any < 0) continue;
     86     if (acc < cutoff || (acc == cutoff && c > cutlim)) {
     87       any = -1;
     88       acc = Min;
     89       errno = ERANGE;
     90     } else {
     91       any = 1;
     92       acc *= base;
     93       acc -= c;
     94     }
     95   }
     96   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
     97   if (!neg) {
     98     if (acc == Min) {
     99       errno = ERANGE;
    100       acc = Max;
    101     } else {
    102       acc = -acc;
    103     }
    104   }
    105   return acc;
    106 }
    107 
    108 template <typename T, T Max> T StrToU(const char* nptr, char** endptr, int base) {
    109   if (base < 0 || base == 1 || base > 36) {
    110     if (endptr != nullptr) *endptr = const_cast<char*>(nptr);
    111     errno = EINVAL;
    112     return 0;
    113   }
    114 
    115   const char* s = nptr;
    116   int c;
    117   do {
    118     c = *s++;
    119   } while (IsSpace(c));
    120   int neg;
    121   if (c == '-') {
    122     neg = 1;
    123     c = *s++;
    124   } else {
    125     neg = 0;
    126     if (c == '+') c = *s++;
    127   }
    128   if ((base == 0 || base == 16) && c == '0' &&
    129       (*s == 'x' || *s == 'X') && IsXDigit(s[1])) {
    130     c = s[1];
    131     s += 2;
    132     base = 16;
    133   }
    134   if (base == 0) base = (c == '0') ? 8 : 10;
    135 
    136   T cutoff = Max / static_cast<T>(base);
    137   int cutlim = Max % static_cast<T>(base);
    138   T acc = 0;
    139   int any = 0;
    140   for (; ; c = *s++) {
    141     if (IsDigit(c)) {
    142       c -= '0';
    143     } else if (IsAlpha(c)) {
    144       c -= IsUpper(c) ? 'A' - 10 : 'a' - 10;
    145     } else {
    146       break;
    147     }
    148     if (c >= base) break;
    149     if (any < 0) continue;
    150     if (acc > cutoff || (acc == cutoff && c > cutlim)) {
    151       any = -1;
    152       acc = Max;
    153       errno = ERANGE;
    154     } else {
    155       any = 1;
    156       acc *= base;
    157       acc += c;
    158     }
    159   }
    160   if (neg && any > 0) acc = -acc;
    161   if (endptr != nullptr) *endptr = const_cast<char*>(any ? s - 1 : nptr);
    162   return acc;
    163 }
    164 
    165 int atoi(const char* s) {
    166   return strtol(s, nullptr, 10);
    167 }
    168 
    169 long atol(const char* s) {
    170   return strtol(s, nullptr, 10);
    171 }
    172 
    173 long long atoll(const char* s) {
    174   return strtoll(s, nullptr, 10);
    175 }
    176 
    177 intmax_t strtoimax(const char* s, char** end, int base) {
    178   return StrToI<intmax_t, INTMAX_MIN, INTMAX_MAX>(s, end, base);
    179 }
    180 
    181 long strtol(const char* s, char** end, int base) {
    182   return StrToI<long, LONG_MIN, LONG_MAX>(s, end, base);
    183 }
    184 
    185 long long strtoll(const char* s, char** end, int base) {
    186   return StrToI<long long, LLONG_MIN, LLONG_MAX>(s, end, base);
    187 }
    188 
    189 // Public API since L, but not in any header.
    190 extern "C" long long strtoq(const char* s, char** end, int base) {
    191   return strtoll(s, end, base);
    192 }
    193 
    194 unsigned long strtoul(const char* s, char** end, int base) {
    195   return StrToU<unsigned long, ULONG_MAX>(s, end, base);
    196 }
    197 
    198 unsigned long long strtoull(const char* s, char** end, int base) {
    199   return StrToU<unsigned long long, ULLONG_MAX>(s, end, base);
    200 }
    201 
    202 uintmax_t strtoumax(const char* s, char** end, int base) {
    203   return StrToU<uintmax_t, UINTMAX_MAX>(s, end, base);
    204 }
    205 
    206 // Public API since L, but not in any header.
    207 extern "C" unsigned long long strtouq(const char* s, char** end, int base) {
    208   return strtoull(s, end, base);
    209 }
    210