]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/LibC/StdLib/NumericInt.c
Standard Libraries for EDK II.
[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
11 Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
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
123 if(__isHexLetter(c)) { /* If c is one of [A-Fa-f]... */\r
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
186 long Result = 0;\r
187 long Previous;\r
188 int temp;\r
189 BOOLEAN Negative = FALSE;\r
190\r
191 if((base < 0) || (base == 1) || (base > 36)) {\r
192 *endptr = NULL;\r
193 return 0;\r
194 }\r
195 // Skip leading spaces.\r
196 while(isspace(*nptr)) ++nptr;\r
197\r
198 // Process Subject sequence: optional sign followed by digits.\r
199 if(*nptr == '+') {\r
200 Negative = FALSE;\r
201 ++nptr;\r
202 }\r
203 else if(*nptr == '-') {\r
204 Negative = TRUE;\r
205 ++nptr;\r
206 }\r
207 if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {\r
208 nptr += 2;\r
209 }\r
210 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
211 Previous = Result;\r
212 Result = (Result * base) + (long int)temp;\r
213 if( Result <= Previous) { // Detect Overflow\r
214 if(Negative) {\r
215 Result = LONG_MIN;\r
216 }\r
217 else {\r
218 Result = LONG_MAX;\r
219 }\r
220 Negative = FALSE;\r
221 errno = ERANGE;\r
222 break;\r
223 }\r
224 ++nptr;\r
225 }\r
226 if(Negative) {\r
227 Result = -Result;\r
228 }\r
229\r
230 // Save pointer to final sequence\r
231 if( endptr != NULL) {\r
232 *endptr = (char *)nptr;\r
233 }\r
234 return Result;\r
235}\r
236\r
237/** The strtoul function converts the initial portion of the string pointed to\r
238 by nptr to unsigned long int representation.\r
239\r
240 See the description for strtol for more information.\r
241\r
242 @return The strtoul function returns the converted value, if any. If no\r
243 conversion could be performed, zero is returned. If the correct\r
244 value is outside the range of representable values, ULONG_MAX is\r
245 returned and the value of the macro ERANGE is stored in errno.\r
246**/\r
247unsigned long\r
248strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)\r
249{\r
250 unsigned long Result = 0;\r
251 unsigned long Previous;\r
252 int temp;\r
253\r
254 if((base < 0) || (base == 1) || (base > 36)) {\r
255 *endptr = NULL;\r
256 return 0;\r
257 }\r
258 // Skip leading spaces.\r
259 while(isspace(*nptr)) ++nptr;\r
260\r
261 // Process Subject sequence: optional + sign followed by digits.\r
262 if(*nptr == '+') {\r
263 ++nptr;\r
264 }\r
265 if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {\r
266 nptr += 2;\r
267 }\r
268 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
269 Previous = Result;\r
270 Result = (Result * base) + (unsigned long)temp;\r
271 if( Result < Previous) { // If we overflowed\r
272 Result = ULONG_MAX;\r
273 errno = ERANGE;\r
274 break;\r
275 }\r
276 ++nptr;\r
277 }\r
278\r
279 // Save pointer to final sequence\r
280 if( endptr != NULL) {\r
281 *endptr = (char *)nptr;\r
282 }\r
283 return Result;\r
284}\r
285\r
286/** The strtoll function converts the initial portion of the string pointed to\r
287 by nptr to long long int representation.\r
288\r
289 See the description for strtol for more information.\r
290\r
291 @return The strtoll function returns the converted value, if any. If no\r
292 conversion could be performed, zero is returned. If the correct\r
293 value is outside the range of representable values, LLONG_MIN or\r
294 LLONG_MAX is returned (according to the sign of the value, if any),\r
295 and the value of the macro ERANGE is stored in errno.\r
296**/\r
297long long\r
298strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)\r
299{\r
300 long long Result = 0;\r
301 long long Previous;\r
302 int temp;\r
303 BOOLEAN Negative = FALSE;\r
304\r
305 if((base < 0) || (base == 1) || (base > 36)) {\r
306 *endptr = NULL;\r
307 return 0;\r
308 }\r
309 // Skip leading spaces.\r
310 while(isspace(*nptr)) ++nptr;\r
311\r
312 // Process Subject sequence: optional sign followed by digits.\r
313 if(*nptr == '+') {\r
314 Negative = FALSE;\r
315 ++nptr;\r
316 }\r
317 else if(*nptr == '-') {\r
318 Negative = TRUE;\r
319 ++nptr;\r
320 }\r
321 if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {\r
322 nptr += 2;\r
323 }\r
324 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
325 Previous = Result;\r
326 Result = (Result * base) + (long long int)temp;\r
327 if( Result <= Previous) { // Detect Overflow\r
328 if(Negative) {\r
329 Result = LLONG_MIN;\r
330 }\r
331 else {\r
332 Result = LLONG_MAX;\r
333 }\r
334 Negative = FALSE;\r
335 errno = ERANGE;\r
336 break;\r
337 }\r
338 ++nptr;\r
339 }\r
340 if(Negative) {\r
341 Result = -Result;\r
342 }\r
343\r
344 // Save pointer to final sequence\r
345 if( endptr != NULL) {\r
346 *endptr = (char *)nptr;\r
347 }\r
348 return Result;\r
349}\r
350\r
351/** The strtoull function converts the initial portion of the string pointed to\r
352 by nptr to unsigned long long int representation.\r
353\r
354 See the description for strtol for more information.\r
355\r
356 @return The strtoull function returns the converted value, if any. If no\r
357 conversion could be performed, zero is returned. If the correct\r
358 value is outside the range of representable values, ULLONG_MAX is\r
359 returned and the value of the macro ERANGE is stored in errno.\r
360**/\r
361unsigned long long\r
362strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)\r
363{\r
364 unsigned long long Result = 0;\r
365 unsigned long long Previous;\r
366 int temp;\r
367\r
368 if((base < 0) || (base == 1) || (base > 36)) {\r
369 *endptr = NULL;\r
370 return 0;\r
371 }\r
372 // Skip leading spaces.\r
373 while(isspace(*nptr)) ++nptr;\r
374\r
375 // Process Subject sequence: optional + sign followed by digits.\r
376 if(*nptr == '+') {\r
377 ++nptr;\r
378 }\r
379 if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {\r
380 nptr += 2;\r
381 }\r
382 while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {\r
383 Previous = Result;\r
384 Result = (Result * base) + (unsigned long long)temp;\r
385 if( Result < Previous) { // If we overflowed\r
386 Result = ULLONG_MAX;\r
387 errno = ERANGE;\r
388 break;\r
389 }\r
390 ++nptr;\r
391 }\r
392\r
393 // Save pointer to final sequence\r
394 if( endptr != NULL) {\r
395 *endptr = (char *)nptr;\r
396 }\r
397 return Result;\r
398}\r