encode/base: correct decode table indexing
This commit is contained in:
parent
d323197459
commit
d037e71bba
@ -200,47 +200,48 @@ namespace util::encode {
|
|||||||
if (src.size () % group_symbols)
|
if (src.size () % group_symbols)
|
||||||
throw std::invalid_argument ("base-encoded strings must be a proper multiple of 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);
|
auto cursor = std::cbegin (src);
|
||||||
for (size_t i = 0, last = std::size (src) / group_symbols - padded?1:0;
|
const int groups = std::size (src) / group_symbols;
|
||||||
i != last;
|
const bool padded = std::cend (src)[-1] == '=';
|
||||||
++i)
|
|
||||||
{
|
|
||||||
num = std::accumulate (
|
|
||||||
cursor, cursor + group_symbols,
|
|
||||||
uint_fast32_t {0},
|
|
||||||
[] (auto a, auto b) {
|
|
||||||
return a << symbol_bits | dec_v<Size>[static_cast<unsigned>(b)];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
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<Size>[unsigned(*cursor++)];
|
||||||
|
accum <<= symbol_bits;
|
||||||
|
accum |= symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cursor != std::end (src)) {
|
for (int j = group_bytes - 1; j >= 0; --j) {
|
||||||
auto last = std::find (cursor, std::cend (src), '=');
|
const uint8_t byte = accum >> (j*8);
|
||||||
num = std::accumulate (
|
*dst++ = byte;
|
||||||
cursor, last,
|
}
|
||||||
uint_fast32_t{0},
|
}
|
||||||
[] (auto a, auto b) {
|
|
||||||
return a << symbol_bits | dec_v<Size>[static_cast<unsigned> (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<Size>[unsigned(symbol)];
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
auto symbols = last - cursor;
|
|
||||||
auto bits = symbols * symbol_bits;
|
auto bits = symbols * symbol_bits;
|
||||||
auto shift = bits%8;
|
auto shift = bits%8;
|
||||||
num >>= shift;
|
accum >>= shift;
|
||||||
|
|
||||||
for (auto i = bits / 8; i; )
|
for (int j = bits / 8 - 1; j >= 0; --j) {
|
||||||
*dst++ = bytes[--i];
|
auto byte = (accum >> (j*8)) & 0xff;
|
||||||
|
*dst++ = byte;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst;
|
return dst;
|
||||||
|
@ -8,24 +8,39 @@
|
|||||||
static constexpr char input[] = "foobar";
|
static constexpr char input[] = "foobar";
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// test vectors from rfc4648
|
// test vectors from rfc4648
|
||||||
template <int Size>
|
template <int Size>
|
||||||
struct output { static const char *value[std::size (input)]; };
|
struct output { static const char *value[std::size (input)]; };
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
const char* output<64>::value[] = {
|
const char* output<64>::value[] = {
|
||||||
"", "Zg==", "Zm8=", "Zm9v", "Zm9vYg==", "Zm9vYmE=", "Zm9vYmFy",
|
"",
|
||||||
|
"Zg==",
|
||||||
|
"Zm8=",
|
||||||
|
"Zm9v",
|
||||||
|
"Zm9vYg==",
|
||||||
|
"Zm9vYmE=",
|
||||||
|
"Zm9vYmFy",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
const char* output<32>::value[] {
|
const char* output<32>::value[] {
|
||||||
"", "MY======", "MZXQ====", "MZXW6===", "MZXW6YQ=", "MZXW6YTB", "MZXW6YTBOI======"
|
"",
|
||||||
|
"MY======",
|
||||||
|
"MZXQ====",
|
||||||
|
"MZXW6===",
|
||||||
|
"MZXW6YQ=",
|
||||||
|
"MZXW6YTB",
|
||||||
|
"MZXW6YTBOI======"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
#if 0
|
#if 0
|
||||||
template <>
|
template <>
|
||||||
const char* output<32h>::value[] {
|
const char* output<32h>::value[] {
|
||||||
@ -37,7 +52,13 @@ const char* output<32h>::value[] {
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <>
|
template <>
|
||||||
const char *output<16>::value[] = {
|
const char *output<16>::value[] = {
|
||||||
"", "66", "666F", "666F6F", "666F6F62", "666F6F6261", "666F6F626172"
|
"",
|
||||||
|
"66",
|
||||||
|
"666F",
|
||||||
|
"666F6F",
|
||||||
|
"666F6F62",
|
||||||
|
"666F6F6261",
|
||||||
|
"666F6F626172"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user