From d037e71bba60f23faaf55fdecaa19278415c13de Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 17 Jan 2018 20:10:26 +1100 Subject: [PATCH] encode/base: correct decode table indexing --- encode/base.hpp | 65 ++++++++++++++++++++++---------------------- test/encode/base.cpp | 29 +++++++++++++++++--- 2 files changed, 58 insertions(+), 36 deletions(-) diff --git a/encode/base.hpp b/encode/base.hpp index d4aad0f9..3a1157e5 100644 --- a/encode/base.hpp +++ b/encode/base.hpp @@ -200,47 +200,48 @@ namespace util::encode { if (src.size () % group_symbols) throw std::invalid_argument ("base-encoded strings must be a proper multiple of symbols"); - union { - uint_fast32_t num; - uint8_t bytes[group_bytes]; - }; - - const bool padded = src.end ()[-1] == '='; auto cursor = std::cbegin (src); - for (size_t i = 0, last = std::size (src) / group_symbols - padded?1:0; - i != last; - ++i) - { - num = std::accumulate ( - cursor, cursor + group_symbols, - uint_fast32_t {0}, - [] (auto a, auto b) { - return a << symbol_bits | dec_v[static_cast(b)]; - } - ); + const int groups = std::size (src) / group_symbols; + const bool padded = std::cend (src)[-1] == '='; - cursor += group_symbols; + for (int i = 0; i < groups - (padded?1:0); ++i) { + uint64_t accum = 0; - dst = std::copy (std::crbegin (bytes), std::crend (bytes), dst); + for (int j = 0; j < group_symbols; ++j) { + auto symbol = dec_v[unsigned(*cursor++)]; + accum <<= symbol_bits; + accum |= symbol; + } + + for (int j = group_bytes - 1; j >= 0; --j) { + const uint8_t byte = accum >> (j*8); + *dst++ = byte; + } } - if (cursor != std::end (src)) { - auto last = std::find (cursor, std::cend (src), '='); - num = std::accumulate ( - cursor, last, - uint_fast32_t{0}, - [] (auto a, auto b) { - return a << symbol_bits | dec_v[static_cast (b)]; - } - ); + if (padded) { + uint64_t accum = 0; + int symbols = 0; + + for (int j = 0; j < group_symbols; ++j) { + auto symbol = *cursor++; + if (symbol == '=') + break; + + symbols++; + + accum <<= symbol_bits; + accum |= dec_v[unsigned(symbol)]; + } - auto symbols = last - cursor; auto bits = symbols * symbol_bits; auto shift = bits%8; - num >>= shift; + accum >>= shift; - for (auto i = bits / 8; i; ) - *dst++ = bytes[--i]; + for (int j = bits / 8 - 1; j >= 0; --j) { + auto byte = (accum >> (j*8)) & 0xff; + *dst++ = byte; + } } return dst; diff --git a/test/encode/base.cpp b/test/encode/base.cpp index 621da75b..0a6c9d61 100644 --- a/test/encode/base.cpp +++ b/test/encode/base.cpp @@ -8,24 +8,39 @@ static constexpr char input[] = "foobar"; -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// // test vectors from rfc4648 template struct output { static const char *value[std::size (input)]; }; + //----------------------------------------------------------------------------- template <> const char* output<64>::value[] = { - "", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy", + "", + "Zg==", + "Zm8=", + "Zm9v", + "Zm9vYg==", + "Zm9vYmE=", + "Zm9vYmFy", }; +//----------------------------------------------------------------------------- template <> const char* output<32>::value[] { - "", "MY======", "MZXQ====", "MZXW6===", "MZXW6YQ=", "MZXW6YTB", "MZXW6YTBOI======" + "", + "MY======", + "MZXQ====", + "MZXW6===", + "MZXW6YQ=", + "MZXW6YTB", + "MZXW6YTBOI======" }; +//----------------------------------------------------------------------------- #if 0 template <> const char* output<32h>::value[] { @@ -37,7 +52,13 @@ const char* output<32h>::value[] { //----------------------------------------------------------------------------- template <> const char *output<16>::value[] = { - "", "66", "666F", "666F6F", "666F6F62", "666F6F6261", "666F6F626172" + "", + "66", + "666F", + "666F6F", + "666F6F62", + "666F6F6261", + "666F6F626172" };