Refactor b58tobin to be more easily reconfigured for using different integer sizes
This commit is contained in:
49
base58.c
49
base58.c
@@ -32,24 +32,31 @@ static const int8_t b58digits_map[] = {
|
|||||||
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
|
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef uint64_t b58_maxint_t;
|
||||||
|
typedef uint32_t b58_almostmaxint_t;
|
||||||
|
#define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8)
|
||||||
|
static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1);
|
||||||
|
|
||||||
bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
||||||
{
|
{
|
||||||
size_t binsz = *binszp;
|
size_t binsz = *binszp;
|
||||||
const unsigned char *b58u = (void*)b58;
|
const unsigned char *b58u = (void*)b58;
|
||||||
unsigned char *binu = bin;
|
unsigned char *binu = bin;
|
||||||
size_t outisz = (binsz + 3) / 4;
|
size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t);
|
||||||
uint32_t outi[outisz];
|
b58_almostmaxint_t outi[outisz];
|
||||||
uint64_t t;
|
b58_maxint_t t;
|
||||||
uint32_t c;
|
b58_almostmaxint_t c;
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
uint8_t bytesleft = binsz % 4;
|
uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t);
|
||||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0;
|
||||||
unsigned zerocount = 0;
|
unsigned zerocount = 0;
|
||||||
|
|
||||||
if (!b58sz)
|
if (!b58sz)
|
||||||
b58sz = strlen(b58);
|
b58sz = strlen(b58);
|
||||||
|
|
||||||
memset(outi, 0, outisz * sizeof(*outi));
|
for (i = 0; i < outisz; ++i) {
|
||||||
|
outi[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Leading zeros, just count
|
// Leading zeros, just count
|
||||||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
|
for (i = 0; i < b58sz && b58u[i] == '1'; ++i)
|
||||||
@@ -66,9 +73,9 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
|||||||
c = (unsigned)b58digits_map[b58u[i]];
|
c = (unsigned)b58digits_map[b58u[i]];
|
||||||
for (j = outisz; j--; )
|
for (j = outisz; j--; )
|
||||||
{
|
{
|
||||||
t = ((uint64_t)outi[j]) * 58 + c;
|
t = ((b58_maxint_t)outi[j]) * 58 + c;
|
||||||
c = (t & 0x3f00000000) >> 32;
|
c = t >> b58_almostmaxint_bits;
|
||||||
outi[j] = t & 0xffffffff;
|
outi[j] = t & b58_almostmaxint_mask;
|
||||||
}
|
}
|
||||||
if (c)
|
if (c)
|
||||||
// Output number too big (carry to the next int32)
|
// Output number too big (carry to the next int32)
|
||||||
@@ -79,24 +86,18 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
switch (bytesleft) {
|
if (bytesleft) {
|
||||||
case 3:
|
for (i = bytesleft; i > 0; --i) {
|
||||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
*(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff;
|
||||||
case 2:
|
}
|
||||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
++j;
|
||||||
case 1:
|
|
||||||
*(binu++) = (outi[0] & 0xff);
|
|
||||||
++j;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (; j < outisz; ++j)
|
for (; j < outisz; ++j)
|
||||||
{
|
{
|
||||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
for (i = sizeof(*outi); i > 0; --i) {
|
||||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
*(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff;
|
||||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
}
|
||||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count canonical base58 byte count
|
// Count canonical base58 byte count
|
||||||
|
|||||||
Reference in New Issue
Block a user