Annotation of embedaddon/curl/lib/strtoofft.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: #include <errno.h>
                     24: #include "curl_setup.h"
                     25: 
                     26: #include "strtoofft.h"
                     27: 
                     28: /*
                     29:  * NOTE:
                     30:  *
                     31:  * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
                     32:  * could use in case strtoll() doesn't exist...  See
                     33:  * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
                     34:  */
                     35: 
                     36: #if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
                     37: #  ifdef HAVE_STRTOLL
                     38: #    define strtooff strtoll
                     39: #  else
                     40: #    if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
                     41: #      if defined(_SAL_VERSION)
                     42:          _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
                     43:              _In_z_ const char *_String,
                     44:              _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
                     45: #      else
                     46:          _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
                     47:                                            char **_EndPtr, int _Radix);
                     48: #      endif
                     49: #      define strtooff _strtoi64
                     50: #    else
                     51: #      define PRIVATE_STRTOOFF 1
                     52: #    endif
                     53: #  endif
                     54: #else
                     55: #  define strtooff strtol
                     56: #endif
                     57: 
                     58: #ifdef PRIVATE_STRTOOFF
                     59: 
                     60: /* Range tests can be used for alphanum decoding if characters are consecutive,
                     61:    like in ASCII. Else an array is scanned. Determine this condition now. */
                     62: 
                     63: #if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
                     64: 
                     65: #define NO_RANGE_TEST
                     66: 
                     67: static const char valchars[] =
                     68:             "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
                     69: #endif
                     70: 
                     71: static int get_char(char c, int base);
                     72: 
                     73: /**
                     74:  * Custom version of the strtooff function.  This extracts a curl_off_t
                     75:  * value from the given input string and returns it.
                     76:  */
                     77: static curl_off_t strtooff(const char *nptr, char **endptr, int base)
                     78: {
                     79:   char *end;
                     80:   int is_negative = 0;
                     81:   int overflow;
                     82:   int i;
                     83:   curl_off_t value = 0;
                     84:   curl_off_t newval;
                     85: 
                     86:   /* Skip leading whitespace. */
                     87:   end = (char *)nptr;
                     88:   while(ISSPACE(end[0])) {
                     89:     end++;
                     90:   }
                     91: 
                     92:   /* Handle the sign, if any. */
                     93:   if(end[0] == '-') {
                     94:     is_negative = 1;
                     95:     end++;
                     96:   }
                     97:   else if(end[0] == '+') {
                     98:     end++;
                     99:   }
                    100:   else if(end[0] == '\0') {
                    101:     /* We had nothing but perhaps some whitespace -- there was no number. */
                    102:     if(endptr) {
                    103:       *endptr = end;
                    104:     }
                    105:     return 0;
                    106:   }
                    107: 
                    108:   /* Handle special beginnings, if present and allowed. */
                    109:   if(end[0] == '0' && end[1] == 'x') {
                    110:     if(base == 16 || base == 0) {
                    111:       end += 2;
                    112:       base = 16;
                    113:     }
                    114:   }
                    115:   else if(end[0] == '0') {
                    116:     if(base == 8 || base == 0) {
                    117:       end++;
                    118:       base = 8;
                    119:     }
                    120:   }
                    121: 
                    122:   /* Matching strtol, if the base is 0 and it doesn't look like
                    123:    * the number is octal or hex, we assume it's base 10.
                    124:    */
                    125:   if(base == 0) {
                    126:     base = 10;
                    127:   }
                    128: 
                    129:   /* Loop handling digits. */
                    130:   value = 0;
                    131:   overflow = 0;
                    132:   for(i = get_char(end[0], base);
                    133:       i != -1;
                    134:       end++, i = get_char(end[0], base)) {
                    135:     newval = base * value + i;
                    136:     if(newval < value) {
                    137:       /* We've overflowed. */
                    138:       overflow = 1;
                    139:       break;
                    140:     }
                    141:     else
                    142:       value = newval;
                    143:   }
                    144: 
                    145:   if(!overflow) {
                    146:     if(is_negative) {
                    147:       /* Fix the sign. */
                    148:       value *= -1;
                    149:     }
                    150:   }
                    151:   else {
                    152:     if(is_negative)
                    153:       value = CURL_OFF_T_MIN;
                    154:     else
                    155:       value = CURL_OFF_T_MAX;
                    156: 
                    157:     errno = ERANGE;
                    158:   }
                    159: 
                    160:   if(endptr)
                    161:     *endptr = end;
                    162: 
                    163:   return value;
                    164: }
                    165: 
                    166: /**
                    167:  * Returns the value of c in the given base, or -1 if c cannot
                    168:  * be interpreted properly in that base (i.e., is out of range,
                    169:  * is a null, etc.).
                    170:  *
                    171:  * @param c     the character to interpret according to base
                    172:  * @param base  the base in which to interpret c
                    173:  *
                    174:  * @return  the value of c in base, or -1 if c isn't in range
                    175:  */
                    176: static int get_char(char c, int base)
                    177: {
                    178: #ifndef NO_RANGE_TEST
                    179:   int value = -1;
                    180:   if(c <= '9' && c >= '0') {
                    181:     value = c - '0';
                    182:   }
                    183:   else if(c <= 'Z' && c >= 'A') {
                    184:     value = c - 'A' + 10;
                    185:   }
                    186:   else if(c <= 'z' && c >= 'a') {
                    187:     value = c - 'a' + 10;
                    188:   }
                    189: #else
                    190:   const char *cp;
                    191:   int value;
                    192: 
                    193:   cp = memchr(valchars, c, 10 + 26 + 26);
                    194: 
                    195:   if(!cp)
                    196:     return -1;
                    197: 
                    198:   value = cp - valchars;
                    199: 
                    200:   if(value >= 10 + 26)
                    201:     value -= 26;                /* Lowercase. */
                    202: #endif
                    203: 
                    204:   if(value >= base) {
                    205:     value = -1;
                    206:   }
                    207: 
                    208:   return value;
                    209: }
                    210: #endif  /* Only present if we need strtoll, but don't have it. */
                    211: 
                    212: /*
                    213:  * Parse a *positive* up to 64 bit number written in ascii.
                    214:  */
                    215: CURLofft curlx_strtoofft(const char *str, char **endp, int base,
                    216:                          curl_off_t *num)
                    217: {
                    218:   char *end;
                    219:   curl_off_t number;
                    220:   errno = 0;
                    221:   *num = 0; /* clear by default */
                    222: 
                    223:   while(*str && ISSPACE(*str))
                    224:     str++;
                    225:   if('-' == *str) {
                    226:     if(endp)
                    227:       *endp = (char *)str; /* didn't actually move */
                    228:     return CURL_OFFT_INVAL; /* nothing parsed */
                    229:   }
                    230:   number = strtooff(str, &end, base);
                    231:   if(endp)
                    232:     *endp = end;
                    233:   if(errno == ERANGE)
                    234:     /* overflow/underflow */
                    235:     return CURL_OFFT_FLOW;
                    236:   else if(str == end)
                    237:     /* nothing parsed */
                    238:     return CURL_OFFT_INVAL;
                    239: 
                    240:   *num = number;
                    241:   return CURL_OFFT_OK;
                    242: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>