strtomp.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "os.h"
  10. #include <mp.h>
  11. #include <libsec.h>
  12. #include "dat.h"
  13. static struct {
  14. int inited;
  15. uint8_t t64[256];
  16. uint8_t t32[256];
  17. uint8_t t16[256];
  18. uint8_t t10[256];
  19. } tab;
  20. enum {
  21. INVAL= 255
  22. };
  23. static char set64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  24. static char set32[] = "23456789abcdefghijkmnpqrstuvwxyz";
  25. static char set16[] = "0123456789ABCDEF0123456789abcdef";
  26. static char set10[] = "0123456789";
  27. static void
  28. init(void)
  29. {
  30. char *p;
  31. memset(tab.t64, INVAL, sizeof(tab.t64));
  32. memset(tab.t32, INVAL, sizeof(tab.t32));
  33. memset(tab.t16, INVAL, sizeof(tab.t16));
  34. memset(tab.t10, INVAL, sizeof(tab.t10));
  35. for(p = set64; *p; p++)
  36. tab.t64[(uint8_t)*p] = p-set64;
  37. for(p = set32; *p; p++)
  38. tab.t32[(uint8_t)*p] = p-set32;
  39. for(p = set16; *p; p++)
  40. tab.t16[(uint8_t)*p] = (p-set16)%16;
  41. for(p = set10; *p; p++)
  42. tab.t10[(uint8_t)*p] = (p-set10);
  43. tab.inited = 1;
  44. }
  45. static char*
  46. from16(char *a, mpint *b)
  47. {
  48. char *p, *next;
  49. int i;
  50. mpdigit x;
  51. b->top = 0;
  52. for(p = a; *p; p++)
  53. if(tab.t16[*(uint8_t*)p] == INVAL)
  54. break;
  55. mpbits(b, (p-a)*4);
  56. b->top = 0;
  57. next = p;
  58. while(p > a){
  59. x = 0;
  60. for(i = 0; i < Dbits; i += 4){
  61. if(p <= a)
  62. break;
  63. x |= tab.t16[*(uint8_t*)--p]<<i;
  64. }
  65. b->p[b->top++] = x;
  66. }
  67. return next;
  68. }
  69. static uint32_t mppow10[] = {
  70. 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
  71. };
  72. static char*
  73. from10(char *a, mpint *b)
  74. {
  75. uint32_t x, y;
  76. mpint *pow, *r;
  77. int i;
  78. pow = mpnew(0);
  79. r = mpnew(0);
  80. b->top = 0;
  81. for(;;){
  82. // do a billion at a time in native arithmetic
  83. x = 0;
  84. for(i = 0; i < 9; i++){
  85. y = tab.t10[*(uint8_t*)a];
  86. if(y == INVAL)
  87. break;
  88. a++;
  89. x *= 10;
  90. x += y;
  91. }
  92. if(i == 0)
  93. break;
  94. // accumulate into mpint
  95. uitomp(mppow10[i], pow);
  96. uitomp(x, r);
  97. mpmul(b, pow, b);
  98. mpadd(b, r, b);
  99. if(i != 9)
  100. break;
  101. }
  102. mpfree(pow);
  103. mpfree(r);
  104. return a;
  105. }
  106. static char*
  107. from64(char *a, mpint *b)
  108. {
  109. char *buf = a;
  110. uint8_t *p;
  111. int n, m;
  112. for(; tab.t64[*(uint8_t*)a] != INVAL; a++)
  113. ;
  114. n = a-buf;
  115. mpbits(b, n*6);
  116. p = malloc(n);
  117. if(p == nil)
  118. return a;
  119. m = dec64(p, n, buf, n);
  120. betomp(p, m, b);
  121. free(p);
  122. return a;
  123. }
  124. static char*
  125. from32(char *a, mpint *b)
  126. {
  127. char *buf = a;
  128. uint8_t *p;
  129. int n, m;
  130. for(; tab.t64[*(uint8_t*)a] != INVAL; a++)
  131. ;
  132. n = a-buf;
  133. mpbits(b, n*5);
  134. p = malloc(n);
  135. if(p == nil)
  136. return buf;
  137. m = dec32(p, n, buf, n);
  138. if(m == -1)
  139. a = buf;
  140. else
  141. betomp(p, m, b);
  142. free(p);
  143. return a;
  144. }
  145. mpint*
  146. strtomp(char *a, char **pp, int base, mpint *b)
  147. {
  148. int sign;
  149. char *e;
  150. if(b == nil)
  151. b = mpnew(0);
  152. if(tab.inited == 0)
  153. init();
  154. while(*a==' ' || *a=='\t')
  155. a++;
  156. sign = 1;
  157. for(;; a++){
  158. switch(*a){
  159. case '-':
  160. sign *= -1;
  161. continue;
  162. }
  163. break;
  164. }
  165. switch(base){
  166. case 10:
  167. e = from10(a, b);
  168. break;
  169. default:
  170. case 16:
  171. e = from16(a, b);
  172. break;
  173. case 32:
  174. e = from32(a, b);
  175. break;
  176. case 64:
  177. e = from64(a, b);
  178. break;
  179. }
  180. // if no characters parsed, there wasn't a number to convert
  181. if(e == a)
  182. return nil;
  183. mpnorm(b);
  184. b->sign = sign;
  185. if(pp != nil)
  186. *pp = e;
  187. return b;
  188. }