15ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/***************************************************************************
25ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                                  _   _ ____  _
35ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *  Project                     ___| | | |  _ \| |
45ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             / __| | | | |_) | |
55ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                            | (__| |_| |  _ <| |___
65ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             \___|\___/|_| \_\_____|
75ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
8486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
95ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * This software is licensed as described in the file COPYING, which
115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * you should have received as part of this distribution. The terms
128f1a214b8a21b66f33454790dfba97ae2f818289Alex Deymo * are also available at https://curl.haxx.se/docs/copyright.html.
135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * You may opt to use, copy, modify, merge, publish, distribute and/or sell
155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * copies of the Software, and permit persons to whom the Software is
165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * furnished to do so, under the terms of the COPYING file.
175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * KIND, either express or implied.
205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen ***************************************************************************/
225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
23486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#include <errno.h>
24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h"
25e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "strtoofft.h"
275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * NOTE:
305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * could use in case strtoll() doesn't exist...  See
3382be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes * https://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
36486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#if (SIZEOF_CURL_OFF_T > SIZEOF_LONG)
37486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#  ifdef HAVE_STRTOLL
38486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#    define strtooff strtoll
39486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#  else
40486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#    if defined(_MSC_VER) && (_MSC_VER >= 1300) && (_INTEGRAL_MAX_BITS >= 64)
41486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#      if defined(_SAL_VERSION)
42486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo         _Check_return_ _CRTIMP __int64 __cdecl _strtoi64(
43486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo             _In_z_ const char *_String,
44486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo             _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix);
45486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#      else
46486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo         _CRTIMP __int64 __cdecl _strtoi64(const char *_String,
47486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo                                           char **_EndPtr, int _Radix);
48486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#      endif
49486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#      define strtooff _strtoi64
50486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#    else
51486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#      define PRIVATE_STRTOOFF 1
52486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#    endif
53486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#  endif
54486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#else
55486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#  define strtooff strtol
56486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#endif
57486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo
58486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo#ifdef PRIVATE_STRTOOFF
595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/* Range tests can be used for alphanum decoding if characters are consecutive,
615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   like in ASCII. Else an array is scanned. Determine this condition now. */
625ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define NO_RANGE_TEST
665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic const char valchars[] =
685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic int get_char(char c, int base);
725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/**
74486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo * Custom version of the strtooff function.  This extracts a curl_off_t
755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * value from the given input string and returns it.
765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
77486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymostatic curl_off_t strtooff(const char *nptr, char **endptr, int base)
785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char *end;
805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int is_negative = 0;
815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int overflow;
825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int i;
835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  curl_off_t value = 0;
845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  curl_off_t newval;
855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Skip leading whitespace. */
875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  end = (char *)nptr;
885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  while(ISSPACE(end[0])) {
895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
905ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Handle the sign, if any. */
935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(end[0] == '-') {
945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    is_negative = 1;
955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '+') {
985ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1005ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '\0') {
1015ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    /* We had nothing but perhaps some whitespace -- there was no number. */
1025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(endptr) {
1035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      *endptr = end;
1045ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1055ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return 0;
1065ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1075ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1085ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Handle special beginnings, if present and allowed. */
1095ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(end[0] == '0' && end[1] == 'x') {
1105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(base == 16 || base == 0) {
1115ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      end += 2;
1125ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      base = 16;
1135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '0') {
1165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(base == 8 || base == 0) {
1175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      end++;
1185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      base = 8;
1195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Matching strtol, if the base is 0 and it doesn't look like
1235ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * the number is octal or hex, we assume it's base 10.
1245ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
1255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(base == 0) {
1265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    base = 10;
1275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Loop handling digits. */
1305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  value = 0;
1315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  overflow = 0;
132e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  for(i = get_char(end[0], base);
133e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      i != -1;
134e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      end++, i = get_char(end[0], base)) {
1355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    newval = base * value + i;
1365ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(newval < value) {
1375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      /* We've overflowed. */
1385ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      overflow = 1;
1395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      break;
1405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    else
1425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      value = newval;
1435ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(!overflow) {
1465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(is_negative) {
1475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      /* Fix the sign. */
1485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      value *= -1;
1495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else {
1525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(is_negative)
1539bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      value = CURL_OFF_T_MIN;
1545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    else
1559bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      value = CURL_OFF_T_MAX;
1565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
15782be86df6ec7baa34d6169c053fd1dfe56fa858eElliott Hughes    errno = ERANGE;
1585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(endptr)
1615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    *endptr = end;
1625ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return value;
1645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
1655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/**
1675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Returns the value of c in the given base, or -1 if c cannot
1685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * be interpreted properly in that base (i.e., is out of range,
1695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * is a null, etc.).
1705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @param c     the character to interpret according to base
1725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @param base  the base in which to interpret c
1735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1745ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @return  the value of c in base, or -1 if c isn't in range
1755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
1765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic int get_char(char c, int base)
1775ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
1785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifndef NO_RANGE_TEST
1795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int value = -1;
1805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(c <= '9' && c >= '0') {
1815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - '0';
1825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(c <= 'Z' && c >= 'A') {
1845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - 'A' + 10;
1855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(c <= 'z' && c >= 'a') {
1875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - 'a' + 10;
1885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#else
190cee0338be80bb81b15101686d6f60864455f1e6eElliott Hughes  const char *cp;
1915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int value;
1925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  cp = memchr(valchars, c, 10 + 26 + 26);
1945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(!cp)
1965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return -1;
1975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1985ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  value = cp - valchars;
1995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
2005ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(value >= 10 + 26)
2015ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value -= 26;                /* Lowercase. */
2025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
2035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
2045ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(value >= base) {
2055ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = -1;
2065ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
2075ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
2085ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return value;
2095ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
2105ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif  /* Only present if we need strtoll, but don't have it. */
211486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo
212486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo/*
213486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo * Parse a *positive* up to 64 bit number written in ascii.
214486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo */
215486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex DeymoCURLofft curlx_strtoofft(const char *str, char **endp, int base,
216486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo                         curl_off_t *num)
217486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo{
218486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  char *end;
219486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  curl_off_t number;
220486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  errno = 0;
221486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  *num = 0; /* clear by default */
222486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo
223486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  DEBUGASSERT(str);
224486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo
225486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  while(*str && ISSPACE(*str))
226486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    str++;
227486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  if('-' == *str) {
228486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    if(endp)
229486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo      *endp = (char *)str; /* didn't actually move */
230486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    return CURL_OFFT_INVAL; /* nothing parsed */
231486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  }
232486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  number = strtooff(str, &end, base);
233486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  if(endp)
234486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    *endp = end;
235486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  if(errno == ERANGE)
236486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    /* overflow/underflow */
237486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    return CURL_OFFT_FLOW;
238486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  else if(str == end)
239486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    /* nothing parsed */
240486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo    return CURL_OFFT_INVAL;
241486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo
242486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  *num = number;
243486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo  return CURL_OFFT_OK;
244486467e11b5904b3e04adc2f5fdb96fcfe65da84Alex Deymo}
245