strtoofft.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 
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 
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  while(str && *str && ISSPACE(*str))
223  str++;
224  if('-' == *str) {
225  if(endp)
226  *endp = (char *)str; /* didn't actually move */
227  return CURL_OFFT_INVAL; /* nothing parsed */
228  }
229  number = strtooff(str, &end, base);
230  if(endp)
231  *endp = end;
232  if(errno == ERANGE)
233  /* overflow/underflow */
234  return CURL_OFFT_FLOW;
235  else if(str == end)
236  /* nothing parsed */
237  return CURL_OFFT_INVAL;
238 
239  *num = number;
240  return CURL_OFFT_OK;
241 }
auto base
#define __cdecl
Definition: web_server.c:58
unsigned int i
Definition: unit1303.c:79
const char * str
Definition: unit1398.c:33
#define strtooff
Definition: strtoofft.c:55
CURLofft curlx_strtoofft(const char *str, char **endp, int base, curl_off_t *num)
Definition: strtoofft.c:215
#define CURL_OFF_T_MIN
Definition: strtoofft.h:49
CURL_TYPEOF_CURL_OFF_T curl_off_t
Definition: system.h:420
CURLofft
Definition: strtoofft.h:51
#define ISSPACE(x)
#define CURL_OFF_T_MAX
Definition: strtoofft.h:47
UNITTEST_START int * value
Definition: unit1602.c:51


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16