Home | History | Annotate | Line # | Download | only in utilities
utstrsuppt.c revision 1.1
      1 /*******************************************************************************
      2  *
      3  * Module Name: utstrsuppt - Support functions for string-to-integer conversion
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #include "acpi.h"
     45 #include "accommon.h"
     46 
     47 #define _COMPONENT          ACPI_UTILITIES
     48         ACPI_MODULE_NAME    ("utstrsuppt")
     49 
     50 
     51 /* Local prototypes */
     52 
     53 static ACPI_STATUS
     54 AcpiUtInsertDigit (
     55     UINT64                  *AccumulatedValue,
     56     UINT32                  Base,
     57     int                     AsciiDigit);
     58 
     59 static ACPI_STATUS
     60 AcpiUtStrtoulMultiply64 (
     61     UINT64                  Multiplicand,
     62     UINT64                  Multiplier,
     63     UINT64                  *OutProduct);
     64 
     65 static ACPI_STATUS
     66 AcpiUtStrtoulAdd64 (
     67     UINT64                  Addend1,
     68     UINT64                  Addend2,
     69     UINT64                  *OutSum);
     70 
     71 
     72 /*******************************************************************************
     73  *
     74  * FUNCTION:    AcpiUtConvertOctalString
     75  *
     76  * PARAMETERS:  String                  - Null terminated input string
     77  *              ReturnValuePtr          - Where the converted value is returned
     78  *
     79  * RETURN:      Status and 64-bit converted integer
     80  *
     81  * DESCRIPTION: Performs a base 8 conversion of the input string to an
     82  *              integer value, either 32 or 64 bits.
     83  *
     84  * NOTE:        Maximum 64-bit unsigned octal value is 01777777777777777777777
     85  *              Maximum 32-bit unsigned octal value is 037777777777
     86  *
     87  ******************************************************************************/
     88 
     89 ACPI_STATUS
     90 AcpiUtConvertOctalString (
     91     char                    *String,
     92     UINT64                  *ReturnValuePtr)
     93 {
     94     UINT64                  AccumulatedValue = 0;
     95     ACPI_STATUS             Status = AE_OK;
     96 
     97 
     98     /* Convert each ASCII byte in the input string */
     99 
    100     while (*String)
    101     {
    102         /* Character must be ASCII 0-7, otherwise terminate with no error */
    103 
    104         if (!(ACPI_IS_OCTAL_DIGIT (*String)))
    105         {
    106             break;
    107         }
    108 
    109         /* Convert and insert this octal digit into the accumulator */
    110 
    111         Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String);
    112         if (ACPI_FAILURE (Status))
    113         {
    114             Status = AE_OCTAL_OVERFLOW;
    115             break;
    116         }
    117 
    118         String++;
    119     }
    120 
    121     /* Always return the value that has been accumulated */
    122 
    123     *ReturnValuePtr = AccumulatedValue;
    124     return (Status);
    125 }
    126 
    127 
    128 /*******************************************************************************
    129  *
    130  * FUNCTION:    AcpiUtConvertDecimalString
    131  *
    132  * PARAMETERS:  String                  - Null terminated input string
    133  *              ReturnValuePtr          - Where the converted value is returned
    134  *
    135  * RETURN:      Status and 64-bit converted integer
    136  *
    137  * DESCRIPTION: Performs a base 10 conversion of the input string to an
    138  *              integer value, either 32 or 64 bits.
    139  *
    140  * NOTE:        Maximum 64-bit unsigned decimal value is 18446744073709551615
    141  *              Maximum 32-bit unsigned decimal value is 4294967295
    142  *
    143  ******************************************************************************/
    144 
    145 ACPI_STATUS
    146 AcpiUtConvertDecimalString (
    147     char                    *String,
    148     UINT64                  *ReturnValuePtr)
    149 {
    150     UINT64                  AccumulatedValue = 0;
    151     ACPI_STATUS             Status = AE_OK;
    152 
    153 
    154     /* Convert each ASCII byte in the input string */
    155 
    156     while (*String)
    157     {
    158         /* Character must be ASCII 0-9, otherwise terminate with no error */
    159 
    160         if (!isdigit (*String))
    161         {
    162            break;
    163         }
    164 
    165         /* Convert and insert this decimal digit into the accumulator */
    166 
    167         Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String);
    168         if (ACPI_FAILURE (Status))
    169         {
    170             Status = AE_DECIMAL_OVERFLOW;
    171             break;
    172         }
    173 
    174         String++;
    175     }
    176 
    177     /* Always return the value that has been accumulated */
    178 
    179     *ReturnValuePtr = AccumulatedValue;
    180     return (Status);
    181 }
    182 
    183 
    184 /*******************************************************************************
    185  *
    186  * FUNCTION:    AcpiUtConvertHexString
    187  *
    188  * PARAMETERS:  String                  - Null terminated input string
    189  *              ReturnValuePtr          - Where the converted value is returned
    190  *
    191  * RETURN:      Status and 64-bit converted integer
    192  *
    193  * DESCRIPTION: Performs a base 16 conversion of the input string to an
    194  *              integer value, either 32 or 64 bits.
    195  *
    196  * NOTE:        Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
    197  *              Maximum 32-bit unsigned hex value is 0xFFFFFFFF
    198  *
    199  ******************************************************************************/
    200 
    201 ACPI_STATUS
    202 AcpiUtConvertHexString (
    203     char                    *String,
    204     UINT64                  *ReturnValuePtr)
    205 {
    206     UINT64                  AccumulatedValue = 0;
    207     ACPI_STATUS             Status = AE_OK;
    208 
    209 
    210     /* Convert each ASCII byte in the input string */
    211 
    212     while (*String)
    213     {
    214         /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */
    215 
    216         if (!isxdigit (*String))
    217         {
    218             break;
    219         }
    220 
    221         /* Convert and insert this hex digit into the accumulator */
    222 
    223         Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String);
    224         if (ACPI_FAILURE (Status))
    225         {
    226             Status = AE_HEX_OVERFLOW;
    227             break;
    228         }
    229 
    230         String++;
    231     }
    232 
    233     /* Always return the value that has been accumulated */
    234 
    235     *ReturnValuePtr = AccumulatedValue;
    236     return (Status);
    237 }
    238 
    239 
    240 /*******************************************************************************
    241  *
    242  * FUNCTION:    AcpiUtRemoveLeadingZeros
    243  *
    244  * PARAMETERS:  String                  - Pointer to input ASCII string
    245  *
    246  * RETURN:      Next character after any leading zeros. This character may be
    247  *              used by the caller to detect end-of-string.
    248  *
    249  * DESCRIPTION: Remove any leading zeros in the input string. Return the
    250  *              next character after the final ASCII zero to enable the caller
    251  *              to check for the end of the string (NULL terminator).
    252  *
    253  ******************************************************************************/
    254 
    255 char
    256 AcpiUtRemoveLeadingZeros (
    257     char                    **String)
    258 {
    259 
    260     while (**String == ACPI_ASCII_ZERO)
    261     {
    262         *String += 1;
    263     }
    264 
    265     return (**String);
    266 }
    267 
    268 
    269 /*******************************************************************************
    270  *
    271  * FUNCTION:    AcpiUtRemoveWhitespace
    272  *
    273  * PARAMETERS:  String                  - Pointer to input ASCII string
    274  *
    275  * RETURN:      Next character after any whitespace. This character may be
    276  *              used by the caller to detect end-of-string.
    277  *
    278  * DESCRIPTION: Remove any leading whitespace in the input string. Return the
    279  *              next character after the final ASCII zero to enable the caller
    280  *              to check for the end of the string (NULL terminator).
    281  *
    282  ******************************************************************************/
    283 
    284 char
    285 AcpiUtRemoveWhitespace (
    286     char                    **String)
    287 {
    288 
    289     while (isspace ((UINT8) **String))
    290     {
    291         *String += 1;
    292     }
    293 
    294     return (**String);
    295 }
    296 
    297 
    298 /*******************************************************************************
    299  *
    300  * FUNCTION:    AcpiUtDetectHexPrefix
    301  *
    302  * PARAMETERS:  String                  - Pointer to input ASCII string
    303  *
    304  * RETURN:      TRUE if a "0x" prefix was found at the start of the string
    305  *
    306  * DESCRIPTION: Detect and remove a hex "0x" prefix
    307  *
    308  ******************************************************************************/
    309 
    310 BOOLEAN
    311 AcpiUtDetectHexPrefix (
    312     char                    **String)
    313 {
    314 
    315     if ((**String == ACPI_ASCII_ZERO) &&
    316         (tolower ((int) *(*String + 1)) == 'x'))
    317     {
    318         *String += 2;        /* Go past the leading 0x */
    319         return (TRUE);
    320     }
    321 
    322     return (FALSE);     /* Not a hex string */
    323 }
    324 
    325 
    326 /*******************************************************************************
    327  *
    328  * FUNCTION:    AcpiUtDetectOctalPrefix
    329  *
    330  * PARAMETERS:  String                  - Pointer to input ASCII string
    331  *
    332  * RETURN:      True if an octal "0" prefix was found at the start of the
    333  *              string
    334  *
    335  * DESCRIPTION: Detect and remove an octal prefix (zero)
    336  *
    337  ******************************************************************************/
    338 
    339 BOOLEAN
    340 AcpiUtDetectOctalPrefix (
    341     char                    **String)
    342 {
    343 
    344     if (**String == ACPI_ASCII_ZERO)
    345     {
    346         *String += 1;       /* Go past the leading 0 */
    347         return (TRUE);
    348     }
    349 
    350     return (FALSE);     /* Not an octal string */
    351 }
    352 
    353 
    354 /*******************************************************************************
    355  *
    356  * FUNCTION:    AcpiUtInsertDigit
    357  *
    358  * PARAMETERS:  AccumulatedValue        - Current value of the integer value
    359  *                                        accumulator. The new value is
    360  *                                        returned here.
    361  *              Base                    - Radix, either 8/10/16
    362  *              AsciiDigit              - ASCII single digit to be inserted
    363  *
    364  * RETURN:      Status and result of the convert/insert operation. The only
    365  *              possible returned exception code is numeric overflow of
    366  *              either the multiply or add conversion operations.
    367  *
    368  * DESCRIPTION: Generic conversion and insertion function for all bases:
    369  *
    370  *              1) Multiply the current accumulated/converted value by the
    371  *              base in order to make room for the new character.
    372  *
    373  *              2) Convert the new character to binary and add it to the
    374  *              current accumulated value.
    375  *
    376  *              Note: The only possible exception indicates an integer
    377  *              overflow (AE_NUMERIC_OVERFLOW)
    378  *
    379  ******************************************************************************/
    380 
    381 static ACPI_STATUS
    382 AcpiUtInsertDigit (
    383     UINT64                  *AccumulatedValue,
    384     UINT32                  Base,
    385     int                     AsciiDigit)
    386 {
    387     ACPI_STATUS             Status;
    388     UINT64                  Product;
    389 
    390 
    391      /* Make room in the accumulated value for the incoming digit */
    392 
    393     Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product);
    394     if (ACPI_FAILURE (Status))
    395     {
    396         return (Status);
    397     }
    398 
    399     /* Add in the new digit, and store the sum to the accumulated value */
    400 
    401     Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit),
    402         AccumulatedValue);
    403 
    404     return (Status);
    405 }
    406 
    407 
    408 /*******************************************************************************
    409  *
    410  * FUNCTION:    AcpiUtStrtoulMultiply64
    411  *
    412  * PARAMETERS:  Multiplicand            - Current accumulated converted integer
    413  *              Multiplier              - Base/Radix
    414  *              OutProduct              - Where the product is returned
    415  *
    416  * RETURN:      Status and 64-bit product
    417  *
    418  * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
    419  *              well as 32-bit overflow if necessary (if the current global
    420  *              integer width is 32).
    421  *
    422  ******************************************************************************/
    423 
    424 static ACPI_STATUS
    425 AcpiUtStrtoulMultiply64 (
    426     UINT64                  Multiplicand,
    427     UINT64                  Multiplier,
    428     UINT64                  *OutProduct)
    429 {
    430     UINT64                  Product;
    431 
    432 
    433     /* Exit if either operand is zero */
    434 
    435     *OutProduct = 0;
    436     if (!Multiplicand || !Multiplier)
    437     {
    438         return (AE_OK);
    439     }
    440 
    441     /* Check for 64-bit overflow before the actual multiplication */
    442 
    443     if (Multiplicand > (ACPI_UINT64_MAX / Multiplier))
    444     {
    445         return (AE_NUMERIC_OVERFLOW);
    446     }
    447 
    448     Product = Multiplicand * Multiplier;
    449 
    450     /* Check for 32-bit overflow if necessary */
    451 
    452     if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX))
    453     {
    454         return (AE_NUMERIC_OVERFLOW);
    455     }
    456 
    457     *OutProduct = Product;
    458     return (AE_OK);
    459 }
    460 
    461 
    462 /*******************************************************************************
    463  *
    464  * FUNCTION:    AcpiUtStrtoulAdd64
    465  *
    466  * PARAMETERS:  Addend1                 - Current accumulated converted integer
    467  *              Addend2                 - New hex value/char
    468  *              OutSum                  - Where sum is returned (Accumulator)
    469  *
    470  * RETURN:      Status and 64-bit sum
    471  *
    472  * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
    473  *              well as 32-bit overflow if necessary (if the current global
    474  *              integer width is 32).
    475  *
    476  ******************************************************************************/
    477 
    478 static ACPI_STATUS
    479 AcpiUtStrtoulAdd64 (
    480     UINT64                  Addend1,
    481     UINT64                  Addend2,
    482     UINT64                  *OutSum)
    483 {
    484     UINT64                  Sum;
    485 
    486 
    487     /* Check for 64-bit overflow before the actual addition */
    488 
    489     if ((Addend1 > 0) && (Addend2 > (ACPI_UINT64_MAX - Addend1)))
    490     {
    491         return (AE_NUMERIC_OVERFLOW);
    492     }
    493 
    494     Sum = Addend1 + Addend2;
    495 
    496     /* Check for 32-bit overflow if necessary */
    497 
    498     if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX))
    499     {
    500         return (AE_NUMERIC_OVERFLOW);
    501     }
    502 
    503     *OutSum = Sum;
    504     return (AE_OK);
    505 }
    506