From 8a924964758020a930e254d1fa2b8d24f0067f3a Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Wed, 23 Mar 2016 09:12:05 +0000 Subject: [PATCH] Refactor b58tobin to be more easily reconfigured for using different integer sizes --- base58.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/base58.c b/base58.c index 33566e0..71e687f 100644 --- a/base58.c +++ b/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); - ++j; - default: - break; + if (bytesleft) { + for (i = bytesleft; i > 0; --i) { + *(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff; + } + ++j; } 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