Annotation of embedaddon/curl/lib/strtoofft.c, revision 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>