File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / strtoofft.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (5 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>