Annotation of embedaddon/curl/lib/strtoofft.c, revision 1.1
1.1 ! misho 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>