15ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/***************************************************************************
25ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                                  _   _ ____  _
35ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *  Project                     ___| | | |  _ \| |
45ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             / __| | | | |_) | |
55ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                            | (__| |_| |  _ <| |___
65ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *                             \___|\___/|_| \_\_____|
75ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
8e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET * Copyright (C) 1998 - 2011, 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
125ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * are also available at http://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
23e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET#include "curl_setup.h"
24e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET
255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#include "strtoofft.h"
265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/*
285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * NOTE:
295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * In the ISO C standard (IEEE Std 1003.1), there is a strtoimax() function we
315ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * could use in case strtoll() doesn't exist...  See
325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * http://www.opengroup.org/onlinepubs/009695399/functions/strtoimax.html
335ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifdef NEED_CURL_STRTOLL
365ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/* Range tests can be used for alphanum decoding if characters are consecutive,
385ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   like in ASCII. Else an array is scanned. Determine this condition now. */
395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#if('9' - '0') != 9 || ('Z' - 'A') != 25 || ('z' - 'a') != 25
415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#define NO_RANGE_TEST
435ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic const char valchars[] =
455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic int get_char(char c, int base);
495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/**
515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Emulated version of the strtoll function.  This extracts a long long
525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * value from the given input string and returns it.
535ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsencurl_off_t
555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsencurlx_strtoll(const char *nptr, char **endptr, int base)
565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
575ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  char *end;
585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int is_negative = 0;
595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int overflow;
605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int i;
615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  curl_off_t value = 0;
625ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  curl_off_t newval;
635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Skip leading whitespace. */
655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  end = (char *)nptr;
665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  while(ISSPACE(end[0])) {
675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Handle the sign, if any. */
715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(end[0] == '-') {
725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    is_negative = 1;
735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
745ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '+') {
765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    end++;
775ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '\0') {
795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    /* We had nothing but perhaps some whitespace -- there was no number. */
805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(endptr) {
815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      *endptr = end;
825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return 0;
845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Handle special beginnings, if present and allowed. */
875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(end[0] == '0' && end[1] == 'x') {
885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(base == 16 || base == 0) {
895ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      end += 2;
905ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      base = 16;
915ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
925ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
935ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(end[0] == '0') {
945ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(base == 8 || base == 0) {
955ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      end++;
965ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      base = 8;
975ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
985ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
995ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1005ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Matching strtol, if the base is 0 and it doesn't look like
1015ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   * the number is octal or hex, we assume it's base 10.
1025ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen   */
1035ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(base == 0) {
1045ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    base = 10;
1055ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1065ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1075ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  /* Loop handling digits. */
1085ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  value = 0;
1095ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  overflow = 0;
110e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET  for(i = get_char(end[0], base);
111e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      i != -1;
112e6cd738ed3716c02557fb3a47515244e949ade39Bertrand SIMONNET      end++, i = get_char(end[0], base)) {
1135ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    newval = base * value + i;
1145ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(newval < value) {
1155ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      /* We've overflowed. */
1165ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      overflow = 1;
1175ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      break;
1185ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1195ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    else
1205ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      value = newval;
1215ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1225ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1235ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(!overflow) {
1245ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(is_negative) {
1255ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      /* Fix the sign. */
1265ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen      value *= -1;
1275ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    }
1285ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1295ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else {
1305ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    if(is_negative)
1319bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      value = CURL_OFF_T_MIN;
1325ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    else
1339bd90e6e25f1e55f50201c87a1b5837de7e5b64aLucas Eckels      value = CURL_OFF_T_MAX;
1345ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1355ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    SET_ERRNO(ERANGE);
1365ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1375ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1385ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(endptr)
1395ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    *endptr = end;
1405ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1415ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return value;
1425ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
1435ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1445ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen/**
1455ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * Returns the value of c in the given base, or -1 if c cannot
1465ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * be interpreted properly in that base (i.e., is out of range,
1475ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * is a null, etc.).
1485ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1495ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @param c     the character to interpret according to base
1505ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @param base  the base in which to interpret c
1515ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen *
1525ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen * @return  the value of c in base, or -1 if c isn't in range
1535ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen */
1545ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsenstatic int get_char(char c, int base)
1555ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen{
1565ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#ifndef NO_RANGE_TEST
1575ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int value = -1;
1585ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(c <= '9' && c >= '0') {
1595ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - '0';
1605ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1615ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(c <= 'Z' && c >= 'A') {
1625ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - 'A' + 10;
1635ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1645ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  else if(c <= 'z' && c >= 'a') {
1655ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = c - 'a' + 10;
1665ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1675ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#else
1685ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  const char * cp;
1695ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  int value;
1705ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1715ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  cp = memchr(valchars, c, 10 + 26 + 26);
1725ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1735ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(!cp)
1745ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    return -1;
1755ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1765ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  value = cp - valchars;
1775ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1785ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(value >= 10 + 26)
1795ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value -= 26;                /* Lowercase. */
1805ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif
1815ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1825ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  if(value >= base) {
1835ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen    value = -1;
1845ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  }
1855ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen
1865ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen  return value;
1875ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen}
1885ab5018bf8f0e39957d264f33c3eeddd958ed5d8Kristian Monsen#endif  /* Only present if we need strtoll, but don't have it. */
189