utstrsuppt.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /*******************************************************************************
  2. *
  3. * Module Name: utstrsuppt - string-to-integer conversion support functions
  4. *
  5. ******************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2017, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #include <acpi/acpi.h>
  43. #include "accommon.h"
  44. #define _COMPONENT ACPI_UTILITIES
  45. ACPI_MODULE_NAME("utstrsuppt")
  46. /* Local prototypes */
  47. static acpi_status
  48. acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit);
  49. static acpi_status
  50. acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product);
  51. static acpi_status
  52. acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum);
  53. /*******************************************************************************
  54. *
  55. * FUNCTION: acpi_ut_convert_octal_string
  56. *
  57. * PARAMETERS: string - Null terminated input string
  58. * return_value_ptr - Where the converted value is returned
  59. *
  60. * RETURN: Status and 64-bit converted integer
  61. *
  62. * DESCRIPTION: Performs a base 8 conversion of the input string to an
  63. * integer value, either 32 or 64 bits.
  64. *
  65. * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777
  66. * Maximum 32-bit unsigned octal value is 037777777777
  67. *
  68. ******************************************************************************/
  69. acpi_status acpi_ut_convert_octal_string(char *string, u64 *return_value_ptr)
  70. {
  71. u64 accumulated_value = 0;
  72. acpi_status status = AE_OK;
  73. /* Convert each ASCII byte in the input string */
  74. while (*string) {
  75. /* Must be ASCII 0-7, otherwise terminate with no error */
  76. if (!(ACPI_IS_OCTAL_DIGIT(*string))) {
  77. break;
  78. }
  79. /* Convert and insert this octal digit into the accumulator */
  80. status = acpi_ut_insert_digit(&accumulated_value, 8, *string);
  81. if (ACPI_FAILURE(status)) {
  82. status = AE_OCTAL_OVERFLOW;
  83. break;
  84. }
  85. string++;
  86. }
  87. /* Always return the value that has been accumulated */
  88. *return_value_ptr = accumulated_value;
  89. return (status);
  90. }
  91. /*******************************************************************************
  92. *
  93. * FUNCTION: acpi_ut_convert_decimal_string
  94. *
  95. * PARAMETERS: string - Null terminated input string
  96. * return_value_ptr - Where the converted value is returned
  97. *
  98. * RETURN: Status and 64-bit converted integer
  99. *
  100. * DESCRIPTION: Performs a base 10 conversion of the input string to an
  101. * integer value, either 32 or 64 bits.
  102. *
  103. * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615
  104. * Maximum 32-bit unsigned decimal value is 4294967295
  105. *
  106. ******************************************************************************/
  107. acpi_status acpi_ut_convert_decimal_string(char *string, u64 *return_value_ptr)
  108. {
  109. u64 accumulated_value = 0;
  110. acpi_status status = AE_OK;
  111. /* Convert each ASCII byte in the input string */
  112. while (*string) {
  113. /* Must be ASCII 0-9, otherwise terminate with no error */
  114. if (!isdigit(*string)) {
  115. break;
  116. }
  117. /* Convert and insert this decimal digit into the accumulator */
  118. status = acpi_ut_insert_digit(&accumulated_value, 10, *string);
  119. if (ACPI_FAILURE(status)) {
  120. status = AE_DECIMAL_OVERFLOW;
  121. break;
  122. }
  123. string++;
  124. }
  125. /* Always return the value that has been accumulated */
  126. *return_value_ptr = accumulated_value;
  127. return (status);
  128. }
  129. /*******************************************************************************
  130. *
  131. * FUNCTION: acpi_ut_convert_hex_string
  132. *
  133. * PARAMETERS: string - Null terminated input string
  134. * return_value_ptr - Where the converted value is returned
  135. *
  136. * RETURN: Status and 64-bit converted integer
  137. *
  138. * DESCRIPTION: Performs a base 16 conversion of the input string to an
  139. * integer value, either 32 or 64 bits.
  140. *
  141. * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF
  142. * Maximum 32-bit unsigned hex value is 0xFFFFFFFF
  143. *
  144. ******************************************************************************/
  145. acpi_status acpi_ut_convert_hex_string(char *string, u64 *return_value_ptr)
  146. {
  147. u64 accumulated_value = 0;
  148. acpi_status status = AE_OK;
  149. /* Convert each ASCII byte in the input string */
  150. while (*string) {
  151. /* Must be ASCII A-F, a-f, or 0-9, otherwise terminate with no error */
  152. if (!isxdigit(*string)) {
  153. break;
  154. }
  155. /* Convert and insert this hex digit into the accumulator */
  156. status = acpi_ut_insert_digit(&accumulated_value, 16, *string);
  157. if (ACPI_FAILURE(status)) {
  158. status = AE_HEX_OVERFLOW;
  159. break;
  160. }
  161. string++;
  162. }
  163. /* Always return the value that has been accumulated */
  164. *return_value_ptr = accumulated_value;
  165. return (status);
  166. }
  167. /*******************************************************************************
  168. *
  169. * FUNCTION: acpi_ut_remove_leading_zeros
  170. *
  171. * PARAMETERS: string - Pointer to input ASCII string
  172. *
  173. * RETURN: Next character after the leading zeros. This behavior may be
  174. * Used by the caller to detect end-of-string.
  175. *
  176. * DESCRIPTION: Remove all leading zeros in the input string. Return the
  177. * next character after the final zero to check for the end
  178. * of the string (NULL terminator).
  179. *
  180. ******************************************************************************/
  181. char acpi_ut_remove_leading_zeros(char **string)
  182. {
  183. /* Skip all leading zeros */
  184. while (**string == ACPI_ASCII_ZERO) {
  185. *string += 1;
  186. }
  187. return (**string);
  188. }
  189. /*******************************************************************************
  190. *
  191. * FUNCTION: acpi_ut_detect_hex_prefix
  192. *
  193. * PARAMETERS: string - Pointer to input ASCII string
  194. *
  195. * RETURN: TRUE if a 0x prefix was found
  196. *
  197. * DESCRIPTION: Detect and remove a hex 0x prefix
  198. *
  199. ******************************************************************************/
  200. u8 acpi_ut_detect_hex_prefix(char **string)
  201. {
  202. if ((**string == ACPI_ASCII_ZERO) &&
  203. (tolower((int)*(*string + 1)) == 'x')) {
  204. *string += 2; /* Go past the leading 0x */
  205. return (TRUE);
  206. }
  207. return (FALSE); /* Not a hex string */
  208. }
  209. /*******************************************************************************
  210. *
  211. * FUNCTION: acpi_ut_detect_octal_prefix
  212. *
  213. * PARAMETERS: string - Pointer to input ASCII string
  214. *
  215. * RETURN: True if an octal 0 prefix was found
  216. *
  217. * DESCRIPTION: Detect and remove an octal prefix (zero)
  218. *
  219. ******************************************************************************/
  220. u8 acpi_ut_detect_octal_prefix(char **string)
  221. {
  222. if (**string == ACPI_ASCII_ZERO) {
  223. *string += 1; /* Go past the leading 0 */
  224. return (TRUE);
  225. }
  226. return (FALSE); /* Not an octal string */
  227. }
  228. /*******************************************************************************
  229. *
  230. * FUNCTION: acpi_ut_insert_digit
  231. *
  232. * PARAMETERS: accumulated_value - Current value of the integer value
  233. * accumulator. The New value is
  234. * returned here.
  235. * base - Radix, either 8/10/16 supported
  236. * ascii_digit - ASCII single digit to be inserted
  237. *
  238. * RETURN: Status and result of convert/insert operation. The only
  239. * exception is numeric overflow of either the multiply or the
  240. * add operations.
  241. *
  242. * DESCRIPTION: Generic conversion and insertion function for all bases:
  243. *
  244. * 1) Multiply the current accumulated converted value by the
  245. * base in order to make room for the new character.
  246. *
  247. * 2) Add the current accumulated/converted value the new
  248. * character (after the character has been converted to a binary
  249. * value).
  250. *
  251. * Note: The only possible exception indicates an integer
  252. * overflow (AE_NUMERIC_OVERFLOW)
  253. *
  254. ******************************************************************************/
  255. static acpi_status
  256. acpi_ut_insert_digit(u64 *accumulated_value, u32 base, int ascii_digit)
  257. {
  258. acpi_status status;
  259. u64 product;
  260. /* Make room in the accumulated value for the incoming digit */
  261. status = acpi_ut_strtoul_multiply64(*accumulated_value, base, &product);
  262. if (ACPI_FAILURE(status)) {
  263. return (status);
  264. }
  265. /* Add in the new digit, and store to the caller's accumulated value */
  266. status =
  267. acpi_ut_strtoul_add64(product,
  268. acpi_ut_ascii_char_to_hex(ascii_digit),
  269. accumulated_value);
  270. if (ACPI_FAILURE(status)) {
  271. return (status);
  272. }
  273. return (AE_OK);
  274. }
  275. /*******************************************************************************
  276. *
  277. * FUNCTION: acpi_ut_strtoul_multiply64
  278. *
  279. * PARAMETERS: multiplicand - Current accumulated converted integer
  280. * multiplier - Base/Radix
  281. * out_product - Where the product is returned
  282. *
  283. * RETURN: Status and 64-bit product
  284. *
  285. * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as
  286. * well as 32-bit overflow if necessary (if the current global
  287. * integer width is 32).
  288. *
  289. ******************************************************************************/
  290. static acpi_status
  291. acpi_ut_strtoul_multiply64(u64 multiplicand, u64 multiplier, u64 *out_product)
  292. {
  293. u64 val;
  294. /* Exit if either operand is zero */
  295. *out_product = 0;
  296. if (!multiplicand || !multiplier) {
  297. return (AE_OK);
  298. }
  299. /* Check for 64-bit overflow before the actual multiplication */
  300. acpi_ut_short_divide(ACPI_UINT64_MAX, (u32)multiplier, &val, NULL);
  301. if (multiplicand > val) {
  302. return (AE_NUMERIC_OVERFLOW);
  303. }
  304. val = multiplicand * multiplier;
  305. /* Check for 32-bit overflow if necessary */
  306. if ((acpi_gbl_integer_bit_width == 32) && (val > ACPI_UINT32_MAX)) {
  307. return (AE_NUMERIC_OVERFLOW);
  308. }
  309. *out_product = val;
  310. return (AE_OK);
  311. }
  312. /*******************************************************************************
  313. *
  314. * FUNCTION: acpi_ut_strtoul_add64
  315. *
  316. * PARAMETERS: addend1 - Current accumulated converted integer
  317. * addend2 - New hex value/char
  318. * out_sum - Where sum is returned (Accumulator)
  319. *
  320. * RETURN: Status and 64-bit sum
  321. *
  322. * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as
  323. * well as 32-bit overflow if necessary (if the current global
  324. * integer width is 32).
  325. *
  326. ******************************************************************************/
  327. static acpi_status acpi_ut_strtoul_add64(u64 addend1, u64 addend2, u64 *out_sum)
  328. {
  329. u64 sum;
  330. /* Check for 64-bit overflow before the actual addition */
  331. if ((addend1 > 0) && (addend2 > (ACPI_UINT64_MAX - addend1))) {
  332. return (AE_NUMERIC_OVERFLOW);
  333. }
  334. sum = addend1 + addend2;
  335. /* Check for 32-bit overflow if necessary */
  336. if ((acpi_gbl_integer_bit_width == 32) && (sum > ACPI_UINT32_MAX)) {
  337. return (AE_NUMERIC_OVERFLOW);
  338. }
  339. *out_sum = sum;
  340. return (AE_OK);
  341. }