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