bn_mp_read_radix.c 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #include "tommath_private.h"
  2. #ifdef BN_MP_READ_RADIX_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis */
  4. /* SPDX-License-Identifier: Unlicense */
  5. #define MP_TOUPPER(c) ((((c) >= 'a') && ((c) <= 'z')) ? (((c) + 'A') - 'a') : (c))
  6. /* read a string [ASCII] in a given radix */
  7. mp_err mp_read_radix(mp_int *a, const char *str, int radix)
  8. {
  9. mp_err err;
  10. int y;
  11. mp_sign neg;
  12. unsigned pos;
  13. char ch;
  14. /* zero the digit bignum */
  15. mp_zero(a);
  16. /* make sure the radix is ok */
  17. if ((radix < 2) || (radix > 64)) {
  18. return MP_VAL;
  19. }
  20. /* if the leading digit is a
  21. * minus set the sign to negative.
  22. */
  23. if (*str == '-') {
  24. ++str;
  25. neg = MP_NEG;
  26. } else {
  27. neg = MP_ZPOS;
  28. }
  29. /* set the integer to the default of zero */
  30. mp_zero(a);
  31. /* process each digit of the string */
  32. while (*str != '\0') {
  33. /* if the radix <= 36 the conversion is case insensitive
  34. * this allows numbers like 1AB and 1ab to represent the same value
  35. * [e.g. in hex]
  36. */
  37. ch = (radix <= 36) ? (char)MP_TOUPPER((int)*str) : *str;
  38. pos = (unsigned)(ch - '(');
  39. if (mp_s_rmap_reverse_sz < pos) {
  40. break;
  41. }
  42. y = (int)mp_s_rmap_reverse[pos];
  43. /* if the char was found in the map
  44. * and is less than the given radix add it
  45. * to the number, otherwise exit the loop.
  46. */
  47. if ((y == 0xff) || (y >= radix)) {
  48. break;
  49. }
  50. if ((err = mp_mul_d(a, (mp_digit)radix, a)) != MP_OKAY) {
  51. return err;
  52. }
  53. if ((err = mp_add_d(a, (mp_digit)y, a)) != MP_OKAY) {
  54. return err;
  55. }
  56. ++str;
  57. }
  58. /* if an illegal character was found, fail. */
  59. if (!((*str == '\0') || (*str == '\r') || (*str == '\n'))) {
  60. mp_zero(a);
  61. return MP_VAL;
  62. }
  63. /* set the sign only if a != 0 */
  64. if (!MP_IS_ZERO(a)) {
  65. a->sign = neg;
  66. }
  67. return MP_OKAY;
  68. }
  69. #endif