Line data Source code
1 : #include "base_enc.h"
2 : #include <stdint.h>
3 :
4 : static const int8_t b58digits_map[] = {
5 : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
6 : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
7 : -1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
8 : -1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
9 : -1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
10 : 22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
11 : -1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
12 : 47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
13 : };
14 :
15 : typedef ulong b58_maxint_t;
16 : typedef uint b58_almostmaxint_t;
17 0 : #define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8)
18 : static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1);
19 :
20 : int
21 0 : b58tobin(void * bin, ulong * binszp, const char *b58, ulong b58sz) {
22 0 : ulong binsz = *binszp;
23 0 : const unsigned char *b58u = (void*)b58;
24 0 : unsigned char *binu = bin;
25 0 : ulong outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t);
26 0 : b58_almostmaxint_t outi[outisz];
27 0 : b58_maxint_t t;
28 0 : b58_almostmaxint_t c;
29 0 : ulong i, j;
30 0 : uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t);
31 0 : b58_almostmaxint_t zeromask = ( bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0 );
32 0 : unsigned zerocount = 0;
33 :
34 0 : memset( outi, 0, sizeof(b58_almostmaxint_t)*outisz );
35 :
36 : // Leading zeros, just count
37 0 : for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
38 0 : ++zerocount;
39 :
40 0 : for ( ; i < b58sz; ++i) {
41 0 : if (b58u[i] & 0x80)
42 : // High-bit set on invalid digit
43 0 : return 1;
44 0 : if (b58digits_map[b58u[i]] == -1)
45 : // Invalid base58 digit
46 0 : return 1;
47 0 : c = (unsigned)b58digits_map[b58u[i]];
48 0 : for (j = outisz; j--; ) {
49 0 : t = ((b58_maxint_t)outi[j]) * 58 + c;
50 0 : c = (unsigned)(t >> b58_almostmaxint_bits);
51 0 : outi[j] = (unsigned)(t & b58_almostmaxint_mask);
52 0 : }
53 0 : if (c)
54 : // Output number too big (carry to the next int32)
55 0 : return 1;
56 0 : if (outi[0] & zeromask)
57 : // Output number too big (last int32 filled too far)
58 0 : return 1;
59 0 : }
60 :
61 0 : j = 0;
62 0 : if (bytesleft) {
63 0 : for (i = bytesleft; i > 0; --i) {
64 0 : *(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff;
65 0 : }
66 0 : ++j;
67 0 : }
68 :
69 0 : for (; j < outisz; ++j) {
70 0 : for (i = sizeof(*outi); i > 0; --i) {
71 0 : *(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff;
72 0 : }
73 0 : }
74 :
75 : // Count canonical base58 byte count
76 0 : binu = bin;
77 0 : for (i = 0; i < binsz; ++i) {
78 0 : if (binu[i])
79 0 : break;
80 0 : --*binszp;
81 0 : }
82 0 : *binszp += zerocount;
83 :
84 0 : return 0;
85 0 : }
|