ReactOS  0.4.15-dev-499-g1f31905
utstrsuppt.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: utstrsuppt - Support functions for string-to-integer conversion
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2020, 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
55  UINT64 *AccumulatedValue,
56  UINT32 Base,
57  int AsciiDigit);
58 
59 static ACPI_STATUS
61  UINT64 Multiplicand,
62  UINT32 Base,
63  UINT64 *OutProduct);
64 
65 static ACPI_STATUS
67  UINT64 Addend1,
68  UINT32 Digit,
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 
91  char *String,
92  UINT64 *ReturnValuePtr)
93 {
94  UINT64 AccumulatedValue = 0;
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  {
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 
147  char *String,
148  UINT64 *ReturnValuePtr)
149 {
150  UINT64 AccumulatedValue = 0;
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  {
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 
203  char *String,
204  UINT64 *ReturnValuePtr)
205 {
206  UINT64 AccumulatedValue = 0;
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  {
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
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
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
312  char **String)
313 {
314  char *InitialPosition = *String;
315 
317  if (*String != InitialPosition)
318  {
319  return (TRUE); /* String is past leading 0x */
320  }
321 
322  return (FALSE); /* Not a hex string */
323 }
324 
325 
326 /*******************************************************************************
327  *
328  * FUNCTION: AcpiUtRemoveHexPrefix
329  *
330  * PARAMETERS: String - Pointer to input ASCII string
331  *
332  * RETURN: none
333  *
334  * DESCRIPTION: Remove a hex "0x" prefix
335  *
336  ******************************************************************************/
337 
338 void
340  char **String)
341 {
342  if ((**String == ACPI_ASCII_ZERO) &&
343  (tolower ((int) *(*String + 1)) == 'x'))
344  {
345  *String += 2; /* Go past the leading 0x */
346  }
347 }
348 
349 
350 /*******************************************************************************
351  *
352  * FUNCTION: AcpiUtDetectOctalPrefix
353  *
354  * PARAMETERS: String - Pointer to input ASCII string
355  *
356  * RETURN: True if an octal "0" prefix was found at the start of the
357  * string
358  *
359  * DESCRIPTION: Detect and remove an octal prefix (zero)
360  *
361  ******************************************************************************/
362 
363 BOOLEAN
365  char **String)
366 {
367 
368  if (**String == ACPI_ASCII_ZERO)
369  {
370  *String += 1; /* Go past the leading 0 */
371  return (TRUE);
372  }
373 
374  return (FALSE); /* Not an octal string */
375 }
376 
377 
378 /*******************************************************************************
379  *
380  * FUNCTION: AcpiUtInsertDigit
381  *
382  * PARAMETERS: AccumulatedValue - Current value of the integer value
383  * accumulator. The new value is
384  * returned here.
385  * Base - Radix, either 8/10/16
386  * AsciiDigit - ASCII single digit to be inserted
387  *
388  * RETURN: Status and result of the convert/insert operation. The only
389  * possible returned exception code is numeric overflow of
390  * either the multiply or add conversion operations.
391  *
392  * DESCRIPTION: Generic conversion and insertion function for all bases:
393  *
394  * 1) Multiply the current accumulated/converted value by the
395  * base in order to make room for the new character.
396  *
397  * 2) Convert the new character to binary and add it to the
398  * current accumulated value.
399  *
400  * Note: The only possible exception indicates an integer
401  * overflow (AE_NUMERIC_OVERFLOW)
402  *
403  ******************************************************************************/
404 
405 static ACPI_STATUS
407  UINT64 *AccumulatedValue,
408  UINT32 Base,
409  int AsciiDigit)
410 {
412  UINT64 Product;
413 
414 
415  /* Make room in the accumulated value for the incoming digit */
416 
417  Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product);
418  if (ACPI_FAILURE (Status))
419  {
420  return (Status);
421  }
422 
423  /* Add in the new digit, and store the sum to the accumulated value */
424 
425  Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit),
426  AccumulatedValue);
427 
428  return (Status);
429 }
430 
431 
432 /*******************************************************************************
433  *
434  * FUNCTION: AcpiUtStrtoulMultiply64
435  *
436  * PARAMETERS: Multiplicand - Current accumulated converted integer
437  * Base - Base/Radix
438  * OutProduct - Where the product is returned
439  *
440  * RETURN: Status and 64-bit product
441  *
442  * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
443  * well as 32-bit overflow if necessary (if the current global
444  * integer width is 32).
445  *
446  ******************************************************************************/
447 
448 static ACPI_STATUS
450  UINT64 Multiplicand,
451  UINT32 Base,
452  UINT64 *OutProduct)
453 {
454  UINT64 Product;
455  UINT64 Quotient;
456 
457 
458  /* Exit if either operand is zero */
459 
460  *OutProduct = 0;
461  if (!Multiplicand || !Base)
462  {
463  return (AE_OK);
464  }
465 
466  /*
467  * Check for 64-bit overflow before the actual multiplication.
468  *
469  * Notes: 64-bit division is often not supported on 32-bit platforms
470  * (it requires a library function), Therefore ACPICA has a local
471  * 64-bit divide function. Also, Multiplier is currently only used
472  * as the radix (8/10/16), to the 64/32 divide will always work.
473  */
475  if (Multiplicand > Quotient)
476  {
477  return (AE_NUMERIC_OVERFLOW);
478  }
479 
480  Product = Multiplicand * Base;
481 
482  /* Check for 32-bit overflow if necessary */
483 
484  if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX))
485  {
486  return (AE_NUMERIC_OVERFLOW);
487  }
488 
489  *OutProduct = Product;
490  return (AE_OK);
491 }
492 
493 
494 /*******************************************************************************
495  *
496  * FUNCTION: AcpiUtStrtoulAdd64
497  *
498  * PARAMETERS: Addend1 - Current accumulated converted integer
499  * Digit - New hex value/char
500  * OutSum - Where sum is returned (Accumulator)
501  *
502  * RETURN: Status and 64-bit sum
503  *
504  * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
505  * well as 32-bit overflow if necessary (if the current global
506  * integer width is 32).
507  *
508  ******************************************************************************/
509 
510 static ACPI_STATUS
512  UINT64 Addend1,
513  UINT32 Digit,
514  UINT64 *OutSum)
515 {
516  UINT64 Sum;
517 
518 
519  /* Check for 64-bit overflow before the actual addition */
520 
521  if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1)))
522  {
523  return (AE_NUMERIC_OVERFLOW);
524  }
525 
526  Sum = Addend1 + Digit;
527 
528  /* Check for 32-bit overflow if necessary */
529 
530  if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX))
531  {
532  return (AE_NUMERIC_OVERFLOW);
533  }
534 
535  *OutSum = Sum;
536  return (AE_OK);
537 }
#define isspace(c)
Definition: acclib.h:69
#define TRUE
Definition: types.h:120
UINT8 AcpiUtAsciiCharToHex(int HexChar)
Definition: uthex.c:135
#define AE_OCTAL_OVERFLOW
Definition: acexcep.h:142
ACPI_STATUS AcpiUtConvertHexString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:202
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2373
char AcpiUtRemoveLeadingZeros(char **String)
Definition: utstrsuppt.c:256
#define AE_DECIMAL_OVERFLOW
Definition: acexcep.h:141
void AcpiUtRemoveHexPrefix(char **String)
Definition: utstrsuppt.c:339
BOOLEAN AcpiUtDetectHexPrefix(char **String)
Definition: utstrsuppt.c:311
static WCHAR String[]
Definition: stringtable.c:55
static ACPI_STATUS AcpiUtStrtoulMultiply64(UINT64 Multiplicand, UINT32 Base, UINT64 *OutProduct)
Definition: utstrsuppt.c:449
UINT32 ACPI_STATUS
Definition: actypes.h:460
char AcpiUtRemoveWhitespace(char **String)
Definition: utstrsuppt.c:285
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_NUMERIC_OVERFLOW
Definition: acexcep.h:139
unsigned int UINT32
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define isdigit(c)
Definition: acclib.h:68
BOOLEAN AcpiUtDetectOctalPrefix(char **String)
Definition: utstrsuppt.c:364
ACPI_STATUS AcpiUtShortDivide(UINT64 InDividend, UINT32 Divisor, UINT64 *OutQuotient, UINT32 *OutRemainder)
Definition: utmath.c:337
#define AE_HEX_OVERFLOW
Definition: acexcep.h:140
#define ACPI_UINT32_MAX
Definition: actypes.h:66
#define ACPI_ASCII_ZERO
Definition: aclocal.h:1356
ACPI_STATUS AcpiUtConvertOctalString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:90
Status
Definition: gdiplustypes.h:24
#define ACPI_IS_OCTAL_DIGIT(d)
Definition: acmacros.h:501
#define isxdigit(c)
Definition: acclib.h:70
#define ACPI_UINT64_MAX
Definition: actypes.h:67
static ACPI_STATUS AcpiUtStrtoulAdd64(UINT64 Addend1, UINT32 Digit, UINT64 *OutSum)
Definition: utstrsuppt.c:511
static ACPI_STATUS AcpiUtInsertDigit(UINT64 *AccumulatedValue, UINT32 Base, int AsciiDigit)
Definition: utstrsuppt.c:406
unsigned long long UINT64
ACPI_STATUS AcpiUtConvertDecimalString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:146
unsigned char UINT8
int tolower(int c)
Definition: utclib.c:902
#define AE_OK
Definition: acexcep.h:97