]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/StdLib/NumericInt.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / LibC / StdLib / NumericInt.c
CommitLineData
2aa62f2b 1/** @file\r
2 Integer Numeric Conversion Functions.\r
3\r
4 The atoi, atol, and atoll functions convert the initial portion of the string\r
5 pointed to by nptr to int, long int, and long long int representation,\r
6 respectively. They are equivalent to:\r
7 - atoi: (int)strtol(nptr, (char **)NULL, 10)\r
8 - atol: strtol(nptr, (char **)NULL, 10)\r
9 - atoll: strtoll(nptr, (char **)NULL, 10)\r
10\r
d7ce7006 11 Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r
2aa62f2b 12 This program and the accompanying materials are licensed and made available under\r
13 the terms and conditions of the BSD License that accompanies this distribution.\r
14 The full text of the license may be found at\r
15 http://opensource.org/licenses/bsd-license.php.\r
16\r
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
19**/\r
20#include <Uefi.h>\r
21#include <Library/BaseLib.h>\r
22\r
23#include <LibConfig.h>\r
24\r
25#include <ctype.h>\r
26#include <errno.h>\r
27#include <limits.h>\r
28#include <stdlib.h>\r
29\r
30/** The atoi function converts the initial portion of the string pointed to by\r
31 nptr to int representation. Except for the behavior on error, it is\r
32 equivalent to:\r
33 - (int)strtol(nptr, (char **)NULL, 10)\r
34\r
35 @return The atoi function returns the converted value.\r
36**/\r
37int\r
38atoi(const char *nptr)\r
39{\r
40 int Retval;\r
41 BOOLEAN Negative = FALSE;\r
42\r
43 while(isspace((const unsigned char)*nptr)) ++nptr; // Skip leading spaces\r
44\r
45 if(*nptr == '+') {\r
46 Negative = FALSE;\r
47 ++nptr;\r
48 }\r
49 else if(*nptr == '-') {\r
50 Negative = TRUE;\r
51 ++nptr;\r
52 }\r
53 Retval = (int)AsciiStrDecimalToUintn(nptr);\r
54 if(Negative) {\r
55 Retval = -Retval;\r
56 }\r
57 return Retval;\r
58}\r
59\r
60/** The atol function converts the initial portion of the string pointed to by\r
61 nptr to long int representation. Except for the behavior on error, it is\r
62 equivalent to:\r
63 - strtol(nptr, (char **)NULL, 10)\r
64\r
65 @return The atol function returns the converted value.\r
66**/\r
67long int\r
68atol(const char *nptr)\r
69{\r
70 long int Retval;\r
71 BOOLEAN Negative = FALSE;\r
72\r
73 while(isspace(*nptr)) ++nptr; // Skip leading spaces\r
74\r
75 if(*nptr == '+') {\r
76 Negative = FALSE;\r
77 ++nptr;\r
78 }\r
79 else if(*nptr == '-') {\r
80 Negative = TRUE;\r
81 ++nptr;\r
82 }\r
83 Retval = (long int)AsciiStrDecimalToUint64(nptr);\r
84 if(Negative) {\r
85 Retval = -Retval;\r
86 }\r
87 return Retval;\r
88}\r
89\r
90/** The atoll function converts the initial portion of the string pointed to by\r
91 nptr to long long int representation. Except for the behavior on error, it\r
92 is equivalent to:\r
93 - strtoll(nptr, (char **)NULL, 10)\r
94\r
95 @return The atoll function returns the converted value.\r
96**/\r
97long long int\r
98atoll(const char *nptr)\r
99{\r
100 long long int Retval;\r
101 BOOLEAN Negative = FALSE;\r
102\r
103 while(isspace(*nptr)) ++nptr; // Skip leading spaces\r
104\r
105 if(*nptr == '+') {\r
106 Negative = FALSE;\r
107 ++nptr;\r
108 }\r
109 else if(*nptr == '-') {\r
110 Negative = TRUE;\r
111 ++nptr;\r
112 }\r
113 Retval = (long long int)AsciiStrDecimalToUint64(nptr);\r
114 if(Negative) {\r
115 Retval = -Retval;\r
116 }\r
117 return Retval;\r
118}\r
119\r
120static int\r
121Digit2Val( int c)\r
122{\r
d7ce7006 123 if(isalpha(c)) { /* If c is one of [A-Za-z]... */\r
2aa62f2b 124 c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)\r
125 }\r
126 return c - '0'; // Value returned is between 0 and 35, inclusive.\r
127}\r
128\r
129/** The strtol, strtoll, strtoul, and strtoull functions convert the initial\r
130 portion of the string pointed to by nptr to long int, long long int,\r
131 unsigned long int, and unsigned long long int representation, respectively.\r
132 First, they decompose the input string into three parts: an initial,\r
133 possibly empty, sequence of white-space characters (as specified by the\r
134 isspace function), a subject sequence resembling an integer represented in\r
135 some radix determined by the value of base, and a final string of one or\r
136 more unrecognized characters, including the terminating null character of\r
137 the input string. Then, they attempt to convert the subject sequence to an\r
138 integer, and return the result.\r
139\r
140 If the value of base is zero, the expected form of the subject sequence is\r
141 that of an integer constant, optionally preceded\r
142 by a plus or minus sign, but not including an integer suffix. If the value\r
143 of base is between 2 and 36 (inclusive), the expected form of the subject\r
144 sequence is a sequence of letters and digits representing an integer with\r
145 the radix specified by base, optionally preceded by a plus or minus sign,\r
146 but not including an integer suffix. The letters from a (or A) through z\r
147 (or Z) are ascribed the values 10 through 35; only letters and digits whose\r
148 ascribed values are less than that of base are permitted. If the value of\r
149 base is 16, the characters 0x or 0X may optionally precede the sequence of\r
150 letters and digits, following the sign if present.\r
151\r
152 The subject sequence is defined as the longest initial subsequence of the\r
153 input string, starting with the first non-white-space character, that is of\r
154 the expected form. The subject sequence contains no characters if the input\r
155 string is empty or consists entirely of white space, or if the first\r
156 non-white-space character is other than a sign or a permissible letter or digit.\r
157\r
158 If the subject sequence has the expected form and the value of base is\r
159 zero, the sequence of characters starting with the first digit is\r
160 interpreted as an integer constant. If the subject sequence has the\r
161 expected form and the value of base is between 2 and 36, it is used as the\r
162 base for conversion, ascribing to each letter its value as given above. If\r
163 the subject sequence begins with a minus sign, the value resulting from the\r
164 conversion is negated (in the return type). A pointer to the final string\r
165 is stored in the object pointed to by endptr, provided that endptr is\r
166 not a null pointer.\r
167\r
168 In other than the "C" locale, additional locale-specific subject sequence\r
169 forms may be accepted.\r
170\r
171 If the subject sequence is empty or does not have the expected form, no\r
172 conversion is performed; the value of nptr is stored in the object pointed\r
173 to by endptr, provided that endptr is not a null pointer.\r
174\r
175 @return The strtol, strtoll, strtoul, and strtoull functions return the\r
176 converted value, if any. If no conversion could be performed, zero\r
177 is returned. If the correct value is outside the range of\r
178 representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,\r
179 ULONG_MAX, or ULLONG_MAX is returned (according to the return type\r
180 and sign of the value, if any), and the value of the macro ERANGE\r
181 is stored in errno.\r
182**/\r
183long\r
184strtol(const char * __restrict nptr, char ** __restrict endptr, int base)\r
185{\r
d7ce7006 186 const char *pEnd;\r
2aa62f2b 187 long Result = 0;\r
188 long Previous;\r
189 int temp;\r
190 BOOLEAN Negative = FALSE;\r
191\r
d7ce7006 192 pEnd = nptr;\r
193\r
2aa62f2b 194 if((base < 0) || (base == 1) || (base > 36)) {\r
d7ce7006 195 if(endptr != NULL) {\r
2aa62f2b 196 *endptr = NULL;\r
d7ce7006 197 }\r
2aa62f2b 198 return 0;\r
199 }\r
200 // Skip leading spaces.\r
201 while(isspace(*nptr)) ++nptr;\r
202\r
203 // Process Subject sequence: optional sign followed by digits.\r
204 if(*nptr == '+') {\r
205 Negative = FALSE;\r
206 ++nptr;\r
207 }\r
208 else if(*nptr == '-') {\r
209 Negative = TRUE;\r
210 ++nptr;\r
211 }\r
d7ce7006 212\r
213 if(*nptr == '0') { /* Might be Octal or Hex */\r
214 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */\r
215 if((base == 0) || (base == 16)) {\r
216 nptr += 2; /* Skip the "0X" */\r
217 base = 16; /* In case base was 0 */\r
218 }\r
219 }\r
220 else { /* Looks like Octal */\r
221 if((base == 0) || (base == 8)) {\r
222 ++nptr; /* Skip the leading "0" */\r
223 base = 8; /* In case base was 0 */\r
224 }\r
225 }\r
226 }\r
227 if(base == 0) { /* If still zero then must be decimal */\r
228 base = 10;\r
229 }\r
230 if(*nptr == '0') {\r
231 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */\r
232 pEnd = nptr;\r
2aa62f2b 233 }\r
d7ce7006 234\r
2aa62f2b 235 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
236 Previous = Result;\r
237 Result = (Result * base) + (long int)temp;\r
238 if( Result <= Previous) { // Detect Overflow\r
239 if(Negative) {\r
240 Result = LONG_MIN;\r
241 }\r
242 else {\r
243 Result = LONG_MAX;\r
244 }\r
245 Negative = FALSE;\r
246 errno = ERANGE;\r
247 break;\r
248 }\r
d7ce7006 249 pEnd = ++nptr;\r
2aa62f2b 250 }\r
251 if(Negative) {\r
252 Result = -Result;\r
253 }\r
254\r
255 // Save pointer to final sequence\r
d7ce7006 256 if(endptr != NULL) {\r
257 *endptr = (char *)pEnd;\r
2aa62f2b 258 }\r
259 return Result;\r
260}\r
261\r
262/** The strtoul function converts the initial portion of the string pointed to\r
263 by nptr to unsigned long int representation.\r
264\r
265 See the description for strtol for more information.\r
266\r
267 @return The strtoul function returns the converted value, if any. If no\r
268 conversion could be performed, zero is returned. If the correct\r
269 value is outside the range of representable values, ULONG_MAX is\r
270 returned and the value of the macro ERANGE is stored in errno.\r
271**/\r
272unsigned long\r
273strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)\r
274{\r
d7ce7006 275 const char *pEnd;\r
2aa62f2b 276 unsigned long Result = 0;\r
277 unsigned long Previous;\r
278 int temp;\r
279\r
d7ce7006 280 pEnd = nptr;\r
281\r
2aa62f2b 282 if((base < 0) || (base == 1) || (base > 36)) {\r
d7ce7006 283 if(endptr != NULL) {\r
2aa62f2b 284 *endptr = NULL;\r
d7ce7006 285 }\r
2aa62f2b 286 return 0;\r
287 }\r
288 // Skip leading spaces.\r
289 while(isspace(*nptr)) ++nptr;\r
290\r
291 // Process Subject sequence: optional + sign followed by digits.\r
292 if(*nptr == '+') {\r
293 ++nptr;\r
294 }\r
d7ce7006 295\r
296 if(*nptr == '0') { /* Might be Octal or Hex */\r
297 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */\r
298 if((base == 0) || (base == 16)) {\r
299 nptr += 2; /* Skip the "0X" */\r
300 base = 16; /* In case base was 0 */\r
301 }\r
302 }\r
303 else { /* Looks like Octal */\r
304 if((base == 0) || (base == 8)) {\r
305 ++nptr; /* Skip the leading "0" */\r
306 base = 8; /* In case base was 0 */\r
307 }\r
308 }\r
309 }\r
310 if(base == 0) { /* If still zero then must be decimal */\r
311 base = 10;\r
312 }\r
313 if(*nptr == '0') {\r
314 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */\r
315 pEnd = nptr;\r
2aa62f2b 316 }\r
d7ce7006 317\r
2aa62f2b 318 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
319 Previous = Result;\r
320 Result = (Result * base) + (unsigned long)temp;\r
321 if( Result < Previous) { // If we overflowed\r
322 Result = ULONG_MAX;\r
323 errno = ERANGE;\r
324 break;\r
325 }\r
d7ce7006 326 pEnd = ++nptr;\r
2aa62f2b 327 }\r
328\r
329 // Save pointer to final sequence\r
d7ce7006 330 if(endptr != NULL) {\r
331 *endptr = (char *)pEnd;\r
2aa62f2b 332 }\r
333 return Result;\r
334}\r
335\r
336/** The strtoll function converts the initial portion of the string pointed to\r
337 by nptr to long long int representation.\r
338\r
339 See the description for strtol for more information.\r
340\r
341 @return The strtoll function returns the converted value, if any. If no\r
342 conversion could be performed, zero is returned. If the correct\r
343 value is outside the range of representable values, LLONG_MIN or\r
344 LLONG_MAX is returned (according to the sign of the value, if any),\r
345 and the value of the macro ERANGE is stored in errno.\r
346**/\r
347long long\r
348strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)\r
349{\r
d7ce7006 350 const char *pEnd;\r
2aa62f2b 351 long long Result = 0;\r
352 long long Previous;\r
353 int temp;\r
354 BOOLEAN Negative = FALSE;\r
355\r
d7ce7006 356 pEnd = nptr;\r
357\r
2aa62f2b 358 if((base < 0) || (base == 1) || (base > 36)) {\r
d7ce7006 359 if(endptr != NULL) {\r
2aa62f2b 360 *endptr = NULL;\r
d7ce7006 361 }\r
2aa62f2b 362 return 0;\r
363 }\r
364 // Skip leading spaces.\r
365 while(isspace(*nptr)) ++nptr;\r
366\r
367 // Process Subject sequence: optional sign followed by digits.\r
368 if(*nptr == '+') {\r
369 Negative = FALSE;\r
370 ++nptr;\r
371 }\r
372 else if(*nptr == '-') {\r
373 Negative = TRUE;\r
374 ++nptr;\r
375 }\r
d7ce7006 376\r
377 if(*nptr == '0') { /* Might be Octal or Hex */\r
378 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */\r
379 if((base == 0) || (base == 16)) {\r
380 nptr += 2; /* Skip the "0X" */\r
381 base = 16; /* In case base was 0 */\r
382 }\r
383 }\r
384 else { /* Looks like Octal */\r
385 if((base == 0) || (base == 8)) {\r
386 ++nptr; /* Skip the leading "0" */\r
387 base = 8; /* In case base was 0 */\r
388 }\r
389 }\r
390 }\r
391 if(base == 0) { /* If still zero then must be decimal */\r
392 base = 10;\r
393 }\r
394 if(*nptr == '0') {\r
395 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */\r
396 pEnd = nptr;\r
2aa62f2b 397 }\r
d7ce7006 398\r
2aa62f2b 399 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
400 Previous = Result;\r
401 Result = (Result * base) + (long long int)temp;\r
402 if( Result <= Previous) { // Detect Overflow\r
403 if(Negative) {\r
404 Result = LLONG_MIN;\r
405 }\r
406 else {\r
407 Result = LLONG_MAX;\r
408 }\r
409 Negative = FALSE;\r
410 errno = ERANGE;\r
411 break;\r
412 }\r
d7ce7006 413 pEnd = ++nptr;\r
2aa62f2b 414 }\r
415 if(Negative) {\r
416 Result = -Result;\r
417 }\r
418\r
419 // Save pointer to final sequence\r
d7ce7006 420 if(endptr != NULL) {\r
421 *endptr = (char *)pEnd;\r
2aa62f2b 422 }\r
423 return Result;\r
424}\r
425\r
426/** The strtoull function converts the initial portion of the string pointed to\r
427 by nptr to unsigned long long int representation.\r
428\r
429 See the description for strtol for more information.\r
430\r
431 @return The strtoull function returns the converted value, if any. If no\r
432 conversion could be performed, zero is returned. If the correct\r
433 value is outside the range of representable values, ULLONG_MAX is\r
434 returned and the value of the macro ERANGE is stored in errno.\r
435**/\r
436unsigned long long\r
437strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)\r
438{\r
d7ce7006 439 const char *pEnd;\r
2aa62f2b 440 unsigned long long Result = 0;\r
441 unsigned long long Previous;\r
442 int temp;\r
443\r
d7ce7006 444 pEnd = nptr;\r
445\r
2aa62f2b 446 if((base < 0) || (base == 1) || (base > 36)) {\r
d7ce7006 447 if(endptr != NULL) {\r
2aa62f2b 448 *endptr = NULL;\r
d7ce7006 449 }\r
2aa62f2b 450 return 0;\r
451 }\r
452 // Skip leading spaces.\r
453 while(isspace(*nptr)) ++nptr;\r
454\r
455 // Process Subject sequence: optional + sign followed by digits.\r
456 if(*nptr == '+') {\r
457 ++nptr;\r
458 }\r
d7ce7006 459\r
460 if(*nptr == '0') { /* Might be Octal or Hex */\r
461 if(toupper(nptr[1]) == 'X') { /* Looks like Hex */\r
462 if((base == 0) || (base == 16)) {\r
463 nptr += 2; /* Skip the "0X" */\r
464 base = 16; /* In case base was 0 */\r
465 }\r
466 }\r
467 else { /* Looks like Octal */\r
468 if((base == 0) || (base == 8)) {\r
469 ++nptr; /* Skip the leading "0" */\r
470 base = 8; /* In case base was 0 */\r
471 }\r
472 }\r
473 }\r
474 if(base == 0) { /* If still zero then must be decimal */\r
475 base = 10;\r
476 }\r
477 if(*nptr == '0') {\r
478 for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */\r
479 pEnd = nptr;\r
2aa62f2b 480 }\r
d7ce7006 481\r
2aa62f2b 482 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
483 Previous = Result;\r
484 Result = (Result * base) + (unsigned long long)temp;\r
485 if( Result < Previous) { // If we overflowed\r
486 Result = ULLONG_MAX;\r
487 errno = ERANGE;\r
488 break;\r
489 }\r
d7ce7006 490 pEnd = ++nptr;\r
2aa62f2b 491 }\r
492\r
493 // Save pointer to final sequence\r
d7ce7006 494 if(endptr != NULL) {\r
495 *endptr = (char *)pEnd;\r
2aa62f2b 496 }\r
497 return Result;\r
498}\r