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