strtomp.c 2.9 KB

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