mpfmt.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 int
  14. to64(mpint *b, char *buf, int len)
  15. {
  16. uint8_t *p;
  17. int n, rv;
  18. p = nil;
  19. n = mptobe(b, nil, 0, &p);
  20. if(n < 0)
  21. return -1;
  22. rv = enc64(buf, len, p, n);
  23. free(p);
  24. return rv;
  25. }
  26. static int
  27. to32(mpint *b, char *buf, int len)
  28. {
  29. uint8_t *p;
  30. int n, rv;
  31. // leave room for a multiple of 5 buffer size
  32. n = b->top*Dbytes + 5;
  33. p = malloc(n);
  34. if(p == nil)
  35. return -1;
  36. n = mptobe(b, p, n, nil);
  37. if(n < 0)
  38. return -1;
  39. // round up buffer size, enc32 only accepts a multiple of 5
  40. if(n%5)
  41. n += 5 - (n%5);
  42. rv = enc32(buf, len, p, n);
  43. free(p);
  44. return rv;
  45. }
  46. static char set16[] = "0123456789ABCDEF";
  47. static int
  48. to16(mpint *b, char *buf, int len)
  49. {
  50. mpdigit *p, x;
  51. int i, j;
  52. char *out, *eout;
  53. if(len < 1)
  54. return -1;
  55. out = buf;
  56. eout = buf+len;
  57. for(p = &b->p[b->top-1]; p >= b->p; p--){
  58. x = *p;
  59. for(i = Dbits-4; i >= 0; i -= 4){
  60. j = 0xf & (x>>i);
  61. if(j != 0 || out != buf){
  62. if(out >= eout)
  63. return -1;
  64. *out++ = set16[j];
  65. }
  66. }
  67. }
  68. if(out == buf)
  69. *out++ = '0';
  70. if(out >= eout)
  71. return -1;
  72. *out = 0;
  73. return 0;
  74. }
  75. static char*
  76. modbillion(int rem, uint32_t r, char *out, char *buf)
  77. {
  78. uint32_t rr;
  79. int i;
  80. for(i = 0; i < 9; i++){
  81. rr = r%10;
  82. r /= 10;
  83. if(out <= buf)
  84. return nil;
  85. *--out = '0' + rr;
  86. if(rem == 0 && r == 0)
  87. break;
  88. }
  89. return out;
  90. }
  91. static int
  92. to10(mpint *b, char *buf, int len)
  93. {
  94. mpint *d, *r, *billion;
  95. char *out;
  96. if(len < 1)
  97. return -1;
  98. d = mpcopy(b);
  99. r = mpnew(0);
  100. billion = uitomp(1000000000, nil);
  101. out = buf+len;
  102. *--out = 0;
  103. do {
  104. mpdiv(d, billion, d, r);
  105. out = modbillion(d->top, r->p[0], out, buf);
  106. if(out == nil)
  107. break;
  108. } while(d->top != 0);
  109. mpfree(d);
  110. mpfree(r);
  111. mpfree(billion);
  112. if(out == nil)
  113. return -1;
  114. len -= out-buf;
  115. if(out != buf)
  116. memmove(buf, out, len);
  117. return 0;
  118. }
  119. int
  120. mpfmt(Fmt *fmt)
  121. {
  122. mpint *b;
  123. char *p;
  124. b = va_arg(fmt->args, mpint*);
  125. if(b == nil)
  126. return fmtstrcpy(fmt, "*");
  127. p = mptoa(b, fmt->prec, nil, 0);
  128. fmt->flags &= ~FmtPrec;
  129. if(p == nil)
  130. return fmtstrcpy(fmt, "*");
  131. else{
  132. fmtstrcpy(fmt, p);
  133. free(p);
  134. return 0;
  135. }
  136. }
  137. char*
  138. mptoa(mpint *b, int base, char *buf, int len)
  139. {
  140. char *out;
  141. int rv, alloced;
  142. alloced = 0;
  143. if(buf == nil){
  144. len = ((b->top+1)*Dbits+2)/3 + 1;
  145. buf = malloc(len);
  146. if(buf == nil)
  147. return nil;
  148. alloced = 1;
  149. }
  150. if(len < 2)
  151. return nil;
  152. out = buf;
  153. if(b->sign < 0){
  154. *out++ = '-';
  155. len--;
  156. }
  157. switch(base){
  158. case 64:
  159. rv = to64(b, out, len);
  160. break;
  161. case 32:
  162. rv = to32(b, out, len);
  163. break;
  164. default:
  165. case 16:
  166. rv = to16(b, out, len);
  167. break;
  168. case 10:
  169. rv = to10(b, out, len);
  170. break;
  171. }
  172. if(rv < 0){
  173. if(alloced)
  174. free(buf);
  175. return nil;
  176. }
  177. return buf;
  178. }