Refactor b58tobin to be more easily reconfigured for using different integer sizes
This commit is contained in:
47
base58.c
47
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,
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
size_t binsz = *binszp;
|
||||
const unsigned char *b58u = (void*)b58;
|
||||
unsigned char *binu = bin;
|
||||
size_t outisz = (binsz + 3) / 4;
|
||||
uint32_t outi[outisz];
|
||||
uint64_t t;
|
||||
uint32_t c;
|
||||
size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t outi[outisz];
|
||||
b58_maxint_t t;
|
||||
b58_almostmaxint_t c;
|
||||
size_t i, j;
|
||||
uint8_t bytesleft = binsz % 4;
|
||||
uint32_t zeromask = bytesleft ? (0xffffffff << (bytesleft * 8)) : 0;
|
||||
uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t);
|
||||
b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0;
|
||||
unsigned zerocount = 0;
|
||||
|
||||
if (!b58sz)
|
||||
b58sz = strlen(b58);
|
||||
|
||||
memset(outi, 0, outisz * sizeof(*outi));
|
||||
for (i = 0; i < outisz; ++i) {
|
||||
outi[i] = 0;
|
||||
}
|
||||
|
||||
// Leading zeros, just count
|
||||
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]];
|
||||
for (j = outisz; j--; )
|
||||
{
|
||||
t = ((uint64_t)outi[j]) * 58 + c;
|
||||
c = (t & 0x3f00000000) >> 32;
|
||||
outi[j] = t & 0xffffffff;
|
||||
t = ((b58_maxint_t)outi[j]) * 58 + c;
|
||||
c = t >> b58_almostmaxint_bits;
|
||||
outi[j] = t & b58_almostmaxint_mask;
|
||||
}
|
||||
if (c)
|
||||
// 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;
|
||||
switch (bytesleft) {
|
||||
case 3:
|
||||
*(binu++) = (outi[0] & 0xff0000) >> 16;
|
||||
case 2:
|
||||
*(binu++) = (outi[0] & 0xff00) >> 8;
|
||||
case 1:
|
||||
*(binu++) = (outi[0] & 0xff);
|
||||
if (bytesleft) {
|
||||
for (i = bytesleft; i > 0; --i) {
|
||||
*(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
++j;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (; j < outisz; ++j)
|
||||
{
|
||||
*(binu++) = (outi[j] >> 0x18) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0x10) & 0xff;
|
||||
*(binu++) = (outi[j] >> 8) & 0xff;
|
||||
*(binu++) = (outi[j] >> 0) & 0xff;
|
||||
for (i = sizeof(*outi); i > 0; --i) {
|
||||
*(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
// Count canonical base58 byte count
|
||||
|
||||
Reference in New Issue
Block a user