ReactOS  0.4.15-dev-5109-g2469ce2
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 - 2021, 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 MERCHANTABILITY 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  /*
103  * Character must be ASCII 0-7, otherwise:
104  * 1) Runtime: terminate with no error, per the ACPI spec
105  * 2) Compiler: return an error
106  */
107  if (!(ACPI_IS_OCTAL_DIGIT (*String)))
108  {
109 #ifdef ACPI_ASL_COMPILER
111 #endif
112  break;
113  }
114 
115  /* Convert and insert this octal digit into the accumulator */
116 
117  Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String);
118  if (ACPI_FAILURE (Status))
119  {
121  break;
122  }
123 
124  String++;
125  }
126 
127  /* Always return the value that has been accumulated */
128 
129  *ReturnValuePtr = AccumulatedValue;
130  return (Status);
131 }
132 
133 
134 /*******************************************************************************
135  *
136  * FUNCTION: AcpiUtConvertDecimalString
137  *
138  * PARAMETERS: String - Null terminated input string
139  * ReturnValuePtr - Where the converted value is returned
140  *
141  * RETURN: Status and 64-bit converted integer
142  *
143  * DESCRIPTION: Performs a base 10 conversion of the input string to an
144  * integer value, either 32 or 64 bits.
145  *
146  * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615
147  * Maximum 32-bit unsigned decimal value is 4294967295
148  *
149  ******************************************************************************/
150 
153  char *String,
154  UINT64 *ReturnValuePtr)
155 {
156  UINT64 AccumulatedValue = 0;
158 
159 
160  /* Convert each ASCII byte in the input string */
161 
162  while (*String)
163  {
164  /*
165  * Character must be ASCII 0-9, otherwise:
166  * 1) Runtime: terminate with no error, per the ACPI spec
167  * 2) Compiler: return an error
168  */
169  if (!isdigit ((int) *String))
170  {
171 #ifdef ACPI_ASL_COMPILER
173 #endif
174  break;
175  }
176 
177  /* Convert and insert this decimal digit into the accumulator */
178 
179  Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String);
180  if (ACPI_FAILURE (Status))
181  {
183  break;
184  }
185 
186  String++;
187  }
188 
189  /* Always return the value that has been accumulated */
190 
191  *ReturnValuePtr = AccumulatedValue;
192  return (Status);
193 }
194 
195 
196 /*******************************************************************************
197  *
198  * FUNCTION: AcpiUtConvertHexString
199  *
200  * PARAMETERS: String - Null terminated input string
201  * ReturnValuePtr - Where the converted value is returned
202  *
203  * RETURN: Status and 64-bit converted integer
204  *
205  * DESCRIPTION: Performs a base 16 conversion of the input string to an
206  * integer value, either 32 or 64 bits.
207  *
208  * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
209  * Maximum 32-bit unsigned hex value is 0xFFFFFFFF
210  *
211  ******************************************************************************/
212 
215  char *String,
216  UINT64 *ReturnValuePtr)
217 {
218  UINT64 AccumulatedValue = 0;
220 
221 
222  /* Convert each ASCII byte in the input string */
223 
224  while (*String)
225  {
226  /*
227  * Character must be ASCII A-F, a-f, or 0-9, otherwise:
228  * 1) Runtime: terminate with no error, per the ACPI spec
229  * 2) Compiler: return an error
230  */
231  if (!isxdigit ((int) *String))
232  {
233 #ifdef ACPI_ASL_COMPILER
235 #endif
236  break;
237  }
238 
239  /* Convert and insert this hex digit into the accumulator */
240 
241  Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String);
242  if (ACPI_FAILURE (Status))
243  {
245  break;
246  }
247 
248  String++;
249  }
250 
251  /* Always return the value that has been accumulated */
252 
253  *ReturnValuePtr = AccumulatedValue;
254  return (Status);
255 }
256 
257 
258 /*******************************************************************************
259  *
260  * FUNCTION: AcpiUtRemoveLeadingZeros
261  *
262  * PARAMETERS: String - Pointer to input ASCII string
263  *
264  * RETURN: Next character after any leading zeros. This character may be
265  * used by the caller to detect end-of-string.
266  *
267  * DESCRIPTION: Remove any leading zeros in the input string. Return the
268  * next character after the final ASCII zero to enable the caller
269  * to check for the end of the string (NULL terminator).
270  *
271  ******************************************************************************/
272 
273 char
275  char **String)
276 {
277 
278  while (**String == ACPI_ASCII_ZERO)
279  {
280  *String += 1;
281  }
282 
283  return (**String);
284 }
285 
286 
287 /*******************************************************************************
288  *
289  * FUNCTION: AcpiUtRemoveWhitespace
290  *
291  * PARAMETERS: String - Pointer to input ASCII string
292  *
293  * RETURN: Next character after any whitespace. This character may be
294  * used by the caller to detect end-of-string.
295  *
296  * DESCRIPTION: Remove any leading whitespace in the input string. Return the
297  * next character after the final ASCII zero to enable the caller
298  * to check for the end of the string (NULL terminator).
299  *
300  ******************************************************************************/
301 
302 char
304  char **String)
305 {
306 
307  while (isspace ((UINT8) **String))
308  {
309  *String += 1;
310  }
311 
312  return (**String);
313 }
314 
315 
316 /*******************************************************************************
317  *
318  * FUNCTION: AcpiUtDetectHexPrefix
319  *
320  * PARAMETERS: String - Pointer to input ASCII string
321  *
322  * RETURN: TRUE if a "0x" prefix was found at the start of the string
323  *
324  * DESCRIPTION: Detect and remove a hex "0x" prefix
325  *
326  ******************************************************************************/
327 
328 BOOLEAN
330  char **String)
331 {
332  char *InitialPosition = *String;
333 
335  if (*String != InitialPosition)
336  {
337  return (TRUE); /* String is past leading 0x */
338  }
339 
340  return (FALSE); /* Not a hex string */
341 }
342 
343 
344 /*******************************************************************************
345  *
346  * FUNCTION: AcpiUtRemoveHexPrefix
347  *
348  * PARAMETERS: String - Pointer to input ASCII string
349  *
350  * RETURN: none
351  *
352  * DESCRIPTION: Remove a hex "0x" prefix
353  *
354  ******************************************************************************/
355 
356 void
358  char **String)
359 {
360  if ((**String == ACPI_ASCII_ZERO) &&
361  (tolower ((int) *(*String + 1)) == 'x'))
362  {
363  *String += 2; /* Go past the leading 0x */
364  }
365 }
366 
367 
368 /*******************************************************************************
369  *
370  * FUNCTION: AcpiUtDetectOctalPrefix
371  *
372  * PARAMETERS: String - Pointer to input ASCII string
373  *
374  * RETURN: True if an octal "0" prefix was found at the start of the
375  * string
376  *
377  * DESCRIPTION: Detect and remove an octal prefix (zero)
378  *
379  ******************************************************************************/
380 
381 BOOLEAN
383  char **String)
384 {
385 
386  if (**String == ACPI_ASCII_ZERO)
387  {
388  *String += 1; /* Go past the leading 0 */
389  return (TRUE);
390  }
391 
392  return (FALSE); /* Not an octal string */
393 }
394 
395 
396 /*******************************************************************************
397  *
398  * FUNCTION: AcpiUtInsertDigit
399  *
400  * PARAMETERS: AccumulatedValue - Current value of the integer value
401  * accumulator. The new value is
402  * returned here.
403  * Base - Radix, either 8/10/16
404  * AsciiDigit - ASCII single digit to be inserted
405  *
406  * RETURN: Status and result of the convert/insert operation. The only
407  * possible returned exception code is numeric overflow of
408  * either the multiply or add conversion operations.
409  *
410  * DESCRIPTION: Generic conversion and insertion function for all bases:
411  *
412  * 1) Multiply the current accumulated/converted value by the
413  * base in order to make room for the new character.
414  *
415  * 2) Convert the new character to binary and add it to the
416  * current accumulated value.
417  *
418  * Note: The only possible exception indicates an integer
419  * overflow (AE_NUMERIC_OVERFLOW)
420  *
421  ******************************************************************************/
422 
423 static ACPI_STATUS
425  UINT64 *AccumulatedValue,
426  UINT32 Base,
427  int AsciiDigit)
428 {
430  UINT64 Product;
431 
432 
433  /* Make room in the accumulated value for the incoming digit */
434 
435  Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product);
436  if (ACPI_FAILURE (Status))
437  {
438  return (Status);
439  }
440 
441  /* Add in the new digit, and store the sum to the accumulated value */
442 
443  Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit),
444  AccumulatedValue);
445 
446  return (Status);
447 }
448 
449 
450 /*******************************************************************************
451  *
452  * FUNCTION: AcpiUtStrtoulMultiply64
453  *
454  * PARAMETERS: Multiplicand - Current accumulated converted integer
455  * Base - Base/Radix
456  * OutProduct - Where the product is returned
457  *
458  * RETURN: Status and 64-bit product
459  *
460  * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
461  * well as 32-bit overflow if necessary (if the current global
462  * integer width is 32).
463  *
464  ******************************************************************************/
465 
466 static ACPI_STATUS
468  UINT64 Multiplicand,
469  UINT32 Base,
470  UINT64 *OutProduct)
471 {
472  UINT64 Product;
473  UINT64 Quotient;
474 
475 
476  /* Exit if either operand is zero */
477 
478  *OutProduct = 0;
479  if (!Multiplicand || !Base)
480  {
481  return (AE_OK);
482  }
483 
484  /*
485  * Check for 64-bit overflow before the actual multiplication.
486  *
487  * Notes: 64-bit division is often not supported on 32-bit platforms
488  * (it requires a library function), Therefore ACPICA has a local
489  * 64-bit divide function. Also, Multiplier is currently only used
490  * as the radix (8/10/16), to the 64/32 divide will always work.
491  */
493  if (Multiplicand > Quotient)
494  {
495  return (AE_NUMERIC_OVERFLOW);
496  }
497 
498  Product = Multiplicand * Base;
499 
500  /* Check for 32-bit overflow if necessary */
501 
502  if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX))
503  {
504  return (AE_NUMERIC_OVERFLOW);
505  }
506 
507  *OutProduct = Product;
508  return (AE_OK);
509 }
510 
511 
512 /*******************************************************************************
513  *
514  * FUNCTION: AcpiUtStrtoulAdd64
515  *
516  * PARAMETERS: Addend1 - Current accumulated converted integer
517  * Digit - New hex value/char
518  * OutSum - Where sum is returned (Accumulator)
519  *
520  * RETURN: Status and 64-bit sum
521  *
522  * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
523  * well as 32-bit overflow if necessary (if the current global
524  * integer width is 32).
525  *
526  ******************************************************************************/
527 
528 static ACPI_STATUS
530  UINT64 Addend1,
531  UINT32 Digit,
532  UINT64 *OutSum)
533 {
534  UINT64 Sum;
535 
536 
537  /* Check for 64-bit overflow before the actual addition */
538 
539  if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1)))
540  {
541  return (AE_NUMERIC_OVERFLOW);
542  }
543 
544  Sum = Addend1 + Digit;
545 
546  /* Check for 32-bit overflow if necessary */
547 
548  if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX))
549  {
550  return (AE_NUMERIC_OVERFLOW);
551  }
552 
553  *OutSum = Sum;
554  return (AE_OK);
555 }
#define isspace(c)
Definition: acclib.h:69
UINT8 AcpiUtAsciiCharToHex(int HexChar)
Definition: uthex.c:135
#define AE_OCTAL_OVERFLOW
Definition: acexcep.h:142
#define TRUE
Definition: types.h:120
ACPI_STATUS AcpiUtConvertHexString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:214
#define AE_BAD_DECIMAL_CONSTANT
Definition: acexcep.h:157
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2413
char AcpiUtRemoveLeadingZeros(char **String)
Definition: utstrsuppt.c:274
#define AE_DECIMAL_OVERFLOW
Definition: acexcep.h:141
void AcpiUtRemoveHexPrefix(char **String)
Definition: utstrsuppt.c:357
BOOLEAN AcpiUtDetectHexPrefix(char **String)
Definition: utstrsuppt.c:329
#define AE_BAD_HEX_CONSTANT
Definition: acexcep.h:155
static ACPI_STATUS AcpiUtStrtoulMultiply64(UINT64 Multiplicand, UINT32 Base, UINT64 *OutProduct)
Definition: utstrsuppt.c:467
UINT32 ACPI_STATUS
Definition: actypes.h:460
char AcpiUtRemoveWhitespace(char **String)
Definition: utstrsuppt.c:303
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_NUMERIC_OVERFLOW
Definition: acexcep.h:139
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2430
#define FALSE
Definition: types.h:117
unsigned int UINT32
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
unsigned char BOOLEAN
#define isdigit(c)
Definition: acclib.h:68
BOOLEAN AcpiUtDetectOctalPrefix(char **String)
Definition: utstrsuppt.c:382
Status
Definition: gdiplustypes.h:24
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
#define AE_BAD_OCTAL_CONSTANT
Definition: acexcep.h:156
#define NULL
Definition: types.h:112
#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:529
static ACPI_STATUS AcpiUtInsertDigit(UINT64 *AccumulatedValue, UINT32 Base, int AsciiDigit)
Definition: utstrsuppt.c:424
unsigned long long UINT64
ACPI_STATUS AcpiUtConvertDecimalString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:152
unsigned char UINT8
int tolower(int c)
Definition: utclib.c:902
#define AE_OK
Definition: acexcep.h:97