ReactOS 0.4.15-dev-8408-g466a198
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 - 2022, 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
53static ACPI_STATUS
55 UINT64 *AccumulatedValue,
57 int AsciiDigit);
58
59static ACPI_STATUS
61 UINT64 Multiplicand,
63 UINT64 *OutProduct);
64
65static 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
273char
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
302char
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
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
356void
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
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
423static 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
466static 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
528static 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}
unsigned char BOOLEAN
unsigned long long UINT64
unsigned char UINT8
unsigned int UINT32
#define isspace(c)
Definition: acclib.h:69
#define isdigit(c)
Definition: acclib.h:68
#define isxdigit(c)
Definition: acclib.h:70
int tolower(int c)
Definition: utclib.c:902
#define AE_BAD_HEX_CONSTANT
Definition: acexcep.h:155
#define AE_BAD_OCTAL_CONSTANT
Definition: acexcep.h:156
#define ACPI_FAILURE(a)
Definition: acexcep.h:95
#define AE_NUMERIC_OVERFLOW
Definition: acexcep.h:139
#define AE_DECIMAL_OVERFLOW
Definition: acexcep.h:141
#define AE_BAD_DECIMAL_CONSTANT
Definition: acexcep.h:157
#define AE_OCTAL_OVERFLOW
Definition: acexcep.h:142
#define AE_HEX_OVERFLOW
Definition: acexcep.h:140
#define AE_OK
Definition: acexcep.h:97
#define ACPI_ASCII_ZERO
Definition: aclocal.h:1356
#define ACPI_IS_OCTAL_DIGIT(d)
Definition: acmacros.h:501
#define ACPI_MODULE_NAME(Name)
Definition: acoutput.h:216
#define ACPI_UINT64_MAX
Definition: actypes.h:67
UINT32 ACPI_STATUS
Definition: actypes.h:460
#define ACPI_UINT32_MAX
Definition: actypes.h:66
UINT8 AcpiUtAsciiCharToHex(int HexChar)
Definition: uthex.c:135
ACPI_STATUS AcpiUtShortDivide(UINT64 InDividend, UINT32 Divisor, UINT64 *OutQuotient, UINT32 *OutRemainder)
Definition: utmath.c:337
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
Status
Definition: gdiplustypes.h:25
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2451
char AcpiUtRemoveLeadingZeros(char **String)
Definition: utstrsuppt.c:274
char AcpiUtRemoveWhitespace(char **String)
Definition: utstrsuppt.c:303
ACPI_STATUS AcpiUtConvertHexString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:214
static ACPI_STATUS AcpiUtStrtoulAdd64(UINT64 Addend1, UINT32 Digit, UINT64 *OutSum)
Definition: utstrsuppt.c:529
BOOLEAN AcpiUtDetectOctalPrefix(char **String)
Definition: utstrsuppt.c:382
ACPI_STATUS AcpiUtConvertOctalString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:90
static ACPI_STATUS AcpiUtInsertDigit(UINT64 *AccumulatedValue, UINT32 Base, int AsciiDigit)
Definition: utstrsuppt.c:424
void AcpiUtRemoveHexPrefix(char **String)
Definition: utstrsuppt.c:357
ACPI_STATUS AcpiUtConvertDecimalString(char *String, UINT64 *ReturnValuePtr)
Definition: utstrsuppt.c:152
static ACPI_STATUS AcpiUtStrtoulMultiply64(UINT64 Multiplicand, UINT32 Base, UINT64 *OutProduct)
Definition: utstrsuppt.c:467
BOOLEAN AcpiUtDetectHexPrefix(char **String)
Definition: utstrsuppt.c:329
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2433