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