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