This set of three packages: AppPkg, StdLib, StdLibPrivateInternalFiles; contains the implementation of libraries based upon non-UEFI standards such as ISO/IEC-9899, the library portion of the C Language Standard, POSIX, etc. AppPkg contains applications that make use of the standard libraries defined in the StdLib Package. StdLib contains header (include) files and the implementations of the standard libraries. StdLibPrivateInternalFiles contains files for the exclusive use of the library implementations in StdLib. These files should never be directly referenced from applications or other code. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11600 6f19259b-4bc3-4df7-8a09-765794883524
399 lines
12 KiB
C
399 lines
12 KiB
C
/** @file
|
|
Integer Numeric Conversion Functions.
|
|
|
|
The atoi, atol, and atoll functions convert the initial portion of the string
|
|
pointed to by nptr to int, long int, and long long int representation,
|
|
respectively. They are equivalent to:
|
|
- atoi: (int)strtol(nptr, (char **)NULL, 10)
|
|
- atol: strtol(nptr, (char **)NULL, 10)
|
|
- atoll: strtoll(nptr, (char **)NULL, 10)
|
|
|
|
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
|
This program and the accompanying materials are licensed and made available under
|
|
the terms and conditions of the BSD License that accompanies this distribution.
|
|
The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php.
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
**/
|
|
#include <Uefi.h>
|
|
#include <Library/BaseLib.h>
|
|
|
|
#include <LibConfig.h>
|
|
|
|
#include <ctype.h>
|
|
#include <errno.h>
|
|
#include <limits.h>
|
|
#include <stdlib.h>
|
|
|
|
/** The atoi function converts the initial portion of the string pointed to by
|
|
nptr to int representation. Except for the behavior on error, it is
|
|
equivalent to:
|
|
- (int)strtol(nptr, (char **)NULL, 10)
|
|
|
|
@return The atoi function returns the converted value.
|
|
**/
|
|
int
|
|
atoi(const char *nptr)
|
|
{
|
|
int Retval;
|
|
BOOLEAN Negative = FALSE;
|
|
|
|
while(isspace((const unsigned char)*nptr)) ++nptr; // Skip leading spaces
|
|
|
|
if(*nptr == '+') {
|
|
Negative = FALSE;
|
|
++nptr;
|
|
}
|
|
else if(*nptr == '-') {
|
|
Negative = TRUE;
|
|
++nptr;
|
|
}
|
|
Retval = (int)AsciiStrDecimalToUintn(nptr);
|
|
if(Negative) {
|
|
Retval = -Retval;
|
|
}
|
|
return Retval;
|
|
}
|
|
|
|
/** The atol function converts the initial portion of the string pointed to by
|
|
nptr to long int representation. Except for the behavior on error, it is
|
|
equivalent to:
|
|
- strtol(nptr, (char **)NULL, 10)
|
|
|
|
@return The atol function returns the converted value.
|
|
**/
|
|
long int
|
|
atol(const char *nptr)
|
|
{
|
|
long int Retval;
|
|
BOOLEAN Negative = FALSE;
|
|
|
|
while(isspace(*nptr)) ++nptr; // Skip leading spaces
|
|
|
|
if(*nptr == '+') {
|
|
Negative = FALSE;
|
|
++nptr;
|
|
}
|
|
else if(*nptr == '-') {
|
|
Negative = TRUE;
|
|
++nptr;
|
|
}
|
|
Retval = (long int)AsciiStrDecimalToUint64(nptr);
|
|
if(Negative) {
|
|
Retval = -Retval;
|
|
}
|
|
return Retval;
|
|
}
|
|
|
|
/** The atoll function converts the initial portion of the string pointed to by
|
|
nptr to long long int representation. Except for the behavior on error, it
|
|
is equivalent to:
|
|
- strtoll(nptr, (char **)NULL, 10)
|
|
|
|
@return The atoll function returns the converted value.
|
|
**/
|
|
long long int
|
|
atoll(const char *nptr)
|
|
{
|
|
long long int Retval;
|
|
BOOLEAN Negative = FALSE;
|
|
|
|
while(isspace(*nptr)) ++nptr; // Skip leading spaces
|
|
|
|
if(*nptr == '+') {
|
|
Negative = FALSE;
|
|
++nptr;
|
|
}
|
|
else if(*nptr == '-') {
|
|
Negative = TRUE;
|
|
++nptr;
|
|
}
|
|
Retval = (long long int)AsciiStrDecimalToUint64(nptr);
|
|
if(Negative) {
|
|
Retval = -Retval;
|
|
}
|
|
return Retval;
|
|
}
|
|
|
|
static int
|
|
Digit2Val( int c)
|
|
{
|
|
if(__isHexLetter(c)) { /* If c is one of [A-Fa-f]... */
|
|
c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
|
|
}
|
|
return c - '0'; // Value returned is between 0 and 35, inclusive.
|
|
}
|
|
|
|
/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
|
|
portion of the string pointed to by nptr to long int, long long int,
|
|
unsigned long int, and unsigned long long int representation, respectively.
|
|
First, they decompose the input string into three parts: an initial,
|
|
possibly empty, sequence of white-space characters (as specified by the
|
|
isspace function), a subject sequence resembling an integer represented in
|
|
some radix determined by the value of base, and a final string of one or
|
|
more unrecognized characters, including the terminating null character of
|
|
the input string. Then, they attempt to convert the subject sequence to an
|
|
integer, and return the result.
|
|
|
|
If the value of base is zero, the expected form of the subject sequence is
|
|
that of an integer constant, optionally preceded
|
|
by a plus or minus sign, but not including an integer suffix. If the value
|
|
of base is between 2 and 36 (inclusive), the expected form of the subject
|
|
sequence is a sequence of letters and digits representing an integer with
|
|
the radix specified by base, optionally preceded by a plus or minus sign,
|
|
but not including an integer suffix. The letters from a (or A) through z
|
|
(or Z) are ascribed the values 10 through 35; only letters and digits whose
|
|
ascribed values are less than that of base are permitted. If the value of
|
|
base is 16, the characters 0x or 0X may optionally precede the sequence of
|
|
letters and digits, following the sign if present.
|
|
|
|
The subject sequence is defined as the longest initial subsequence of the
|
|
input string, starting with the first non-white-space character, that is of
|
|
the expected form. The subject sequence contains no characters if the input
|
|
string is empty or consists entirely of white space, or if the first
|
|
non-white-space character is other than a sign or a permissible letter or digit.
|
|
|
|
If the subject sequence has the expected form and the value of base is
|
|
zero, the sequence of characters starting with the first digit is
|
|
interpreted as an integer constant. If the subject sequence has the
|
|
expected form and the value of base is between 2 and 36, it is used as the
|
|
base for conversion, ascribing to each letter its value as given above. If
|
|
the subject sequence begins with a minus sign, the value resulting from the
|
|
conversion is negated (in the return type). A pointer to the final string
|
|
is stored in the object pointed to by endptr, provided that endptr is
|
|
not a null pointer.
|
|
|
|
In other than the "C" locale, additional locale-specific subject sequence
|
|
forms may be accepted.
|
|
|
|
If the subject sequence is empty or does not have the expected form, no
|
|
conversion is performed; the value of nptr is stored in the object pointed
|
|
to by endptr, provided that endptr is not a null pointer.
|
|
|
|
@return The strtol, strtoll, strtoul, and strtoull functions return the
|
|
converted value, if any. If no conversion could be performed, zero
|
|
is returned. If the correct value is outside the range of
|
|
representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
|
|
ULONG_MAX, or ULLONG_MAX is returned (according to the return type
|
|
and sign of the value, if any), and the value of the macro ERANGE
|
|
is stored in errno.
|
|
**/
|
|
long
|
|
strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
|
|
{
|
|
long Result = 0;
|
|
long Previous;
|
|
int temp;
|
|
BOOLEAN Negative = FALSE;
|
|
|
|
if((base < 0) || (base == 1) || (base > 36)) {
|
|
*endptr = NULL;
|
|
return 0;
|
|
}
|
|
// Skip leading spaces.
|
|
while(isspace(*nptr)) ++nptr;
|
|
|
|
// Process Subject sequence: optional sign followed by digits.
|
|
if(*nptr == '+') {
|
|
Negative = FALSE;
|
|
++nptr;
|
|
}
|
|
else if(*nptr == '-') {
|
|
Negative = TRUE;
|
|
++nptr;
|
|
}
|
|
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
|
|
nptr += 2;
|
|
}
|
|
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
|
|
Previous = Result;
|
|
Result = (Result * base) + (long int)temp;
|
|
if( Result <= Previous) { // Detect Overflow
|
|
if(Negative) {
|
|
Result = LONG_MIN;
|
|
}
|
|
else {
|
|
Result = LONG_MAX;
|
|
}
|
|
Negative = FALSE;
|
|
errno = ERANGE;
|
|
break;
|
|
}
|
|
++nptr;
|
|
}
|
|
if(Negative) {
|
|
Result = -Result;
|
|
}
|
|
|
|
// Save pointer to final sequence
|
|
if( endptr != NULL) {
|
|
*endptr = (char *)nptr;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/** The strtoul function converts the initial portion of the string pointed to
|
|
by nptr to unsigned long int representation.
|
|
|
|
See the description for strtol for more information.
|
|
|
|
@return The strtoul function returns the converted value, if any. If no
|
|
conversion could be performed, zero is returned. If the correct
|
|
value is outside the range of representable values, ULONG_MAX is
|
|
returned and the value of the macro ERANGE is stored in errno.
|
|
**/
|
|
unsigned long
|
|
strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
|
|
{
|
|
unsigned long Result = 0;
|
|
unsigned long Previous;
|
|
int temp;
|
|
|
|
if((base < 0) || (base == 1) || (base > 36)) {
|
|
*endptr = NULL;
|
|
return 0;
|
|
}
|
|
// Skip leading spaces.
|
|
while(isspace(*nptr)) ++nptr;
|
|
|
|
// Process Subject sequence: optional + sign followed by digits.
|
|
if(*nptr == '+') {
|
|
++nptr;
|
|
}
|
|
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
|
|
nptr += 2;
|
|
}
|
|
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
|
|
Previous = Result;
|
|
Result = (Result * base) + (unsigned long)temp;
|
|
if( Result < Previous) { // If we overflowed
|
|
Result = ULONG_MAX;
|
|
errno = ERANGE;
|
|
break;
|
|
}
|
|
++nptr;
|
|
}
|
|
|
|
// Save pointer to final sequence
|
|
if( endptr != NULL) {
|
|
*endptr = (char *)nptr;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/** The strtoll function converts the initial portion of the string pointed to
|
|
by nptr to long long int representation.
|
|
|
|
See the description for strtol for more information.
|
|
|
|
@return The strtoll function returns the converted value, if any. If no
|
|
conversion could be performed, zero is returned. If the correct
|
|
value is outside the range of representable values, LLONG_MIN or
|
|
LLONG_MAX is returned (according to the sign of the value, if any),
|
|
and the value of the macro ERANGE is stored in errno.
|
|
**/
|
|
long long
|
|
strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
|
|
{
|
|
long long Result = 0;
|
|
long long Previous;
|
|
int temp;
|
|
BOOLEAN Negative = FALSE;
|
|
|
|
if((base < 0) || (base == 1) || (base > 36)) {
|
|
*endptr = NULL;
|
|
return 0;
|
|
}
|
|
// Skip leading spaces.
|
|
while(isspace(*nptr)) ++nptr;
|
|
|
|
// Process Subject sequence: optional sign followed by digits.
|
|
if(*nptr == '+') {
|
|
Negative = FALSE;
|
|
++nptr;
|
|
}
|
|
else if(*nptr == '-') {
|
|
Negative = TRUE;
|
|
++nptr;
|
|
}
|
|
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
|
|
nptr += 2;
|
|
}
|
|
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
|
|
Previous = Result;
|
|
Result = (Result * base) + (long long int)temp;
|
|
if( Result <= Previous) { // Detect Overflow
|
|
if(Negative) {
|
|
Result = LLONG_MIN;
|
|
}
|
|
else {
|
|
Result = LLONG_MAX;
|
|
}
|
|
Negative = FALSE;
|
|
errno = ERANGE;
|
|
break;
|
|
}
|
|
++nptr;
|
|
}
|
|
if(Negative) {
|
|
Result = -Result;
|
|
}
|
|
|
|
// Save pointer to final sequence
|
|
if( endptr != NULL) {
|
|
*endptr = (char *)nptr;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/** The strtoull function converts the initial portion of the string pointed to
|
|
by nptr to unsigned long long int representation.
|
|
|
|
See the description for strtol for more information.
|
|
|
|
@return The strtoull function returns the converted value, if any. If no
|
|
conversion could be performed, zero is returned. If the correct
|
|
value is outside the range of representable values, ULLONG_MAX is
|
|
returned and the value of the macro ERANGE is stored in errno.
|
|
**/
|
|
unsigned long long
|
|
strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
|
|
{
|
|
unsigned long long Result = 0;
|
|
unsigned long long Previous;
|
|
int temp;
|
|
|
|
if((base < 0) || (base == 1) || (base > 36)) {
|
|
*endptr = NULL;
|
|
return 0;
|
|
}
|
|
// Skip leading spaces.
|
|
while(isspace(*nptr)) ++nptr;
|
|
|
|
// Process Subject sequence: optional + sign followed by digits.
|
|
if(*nptr == '+') {
|
|
++nptr;
|
|
}
|
|
if( (base == 16) && (*nptr == '0') && (toupper(nptr[1]) == 'X')) {
|
|
nptr += 2;
|
|
}
|
|
while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
|
|
Previous = Result;
|
|
Result = (Result * base) + (unsigned long long)temp;
|
|
if( Result < Previous) { // If we overflowed
|
|
Result = ULLONG_MAX;
|
|
errno = ERANGE;
|
|
break;
|
|
}
|
|
++nptr;
|
|
}
|
|
|
|
// Save pointer to final sequence
|
|
if( endptr != NULL) {
|
|
*endptr = (char *)nptr;
|
|
}
|
|
return Result;
|
|
}
|