From c63b1a4591a0a54d3ccd449573f408739ea29af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roman=20Smr=C5=BE?= <roman.smrz@seznam.cz> Date: Sun, 31 Jan 2021 21:13:19 +0100 Subject: Storage: hexadecimal encoding of binary record items --- src/base64.h | 107 -------------------------------------------------------- src/storage.cpp | 21 ++++++++--- 2 files changed, 16 insertions(+), 112 deletions(-) delete mode 100644 src/base64.h diff --git a/src/base64.h b/src/base64.h deleted file mode 100644 index 324a5dd..0000000 --- a/src/base64.h +++ /dev/null @@ -1,107 +0,0 @@ -#pragma once - -#include <cstdint> -#include <stdexcept> -#include <string> -#include <vector> - -namespace { namespace base64 { - - const static char encodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - const static char padCharacter = '='; - - std::string encode(const std::vector<uint8_t> & input) - { - std::string encoded; - encoded.reserve(((input.size()/3) + (input.size() % 3 > 0)) * 4); - uint32_t temp; - auto cursor = input.begin(); - for (size_t i = 0; i < input.size() / 3; i++) - { - temp = (*cursor++) << 16; // Convert to big endian - temp += (*cursor++) << 8; - temp += (*cursor++); - encoded.append(1, encodeLookup[(temp & 0x00FC0000) >> 18]); - encoded.append(1, encodeLookup[(temp & 0x0003F000) >> 12]); - encoded.append(1, encodeLookup[(temp & 0x00000FC0) >> 6 ]); - encoded.append(1, encodeLookup[(temp & 0x0000003F) ]); - } - switch (input.size() % 3) - { - case 1: - temp = (*cursor++) << 16; // Convert to big endian - encoded.append(1, encodeLookup[(temp & 0x00FC0000) >> 18]); - encoded.append(1, encodeLookup[(temp & 0x0003F000) >> 12]); - encoded.append(2, padCharacter); - break; - case 2: - temp = (*cursor++) << 16; // Convert to big endian - temp += (*cursor++) << 8; - encoded.append(1, encodeLookup[(temp & 0x00FC0000) >> 18]); - encoded.append(1, encodeLookup[(temp & 0x0003F000) >> 12]); - encoded.append(1, encodeLookup[(temp & 0x00000FC0) >> 6 ]); - encoded.append(1, padCharacter); - break; - } - return encoded; - } - - std::vector<uint8_t> decode(const std::string & input) - { - if (input.length() % 4) // Sanity check - throw std::runtime_error("Non-Valid base64!"); - - size_t padding = 0; - if (input.length()) { - if (input[input.length() - 1] == padCharacter) - padding++; - if (input[input.length() - 2] == padCharacter) - padding++; - } - - // Setup a vector to hold the result - std::vector<uint8_t> decoded; - decoded.reserve(((input.length()/4)*3) - padding); - uint32_t temp = 0; // Holds decoded quanta - auto cursor = input.begin(); - while (cursor < input.end()) - { - for (size_t quantumPosition = 0; quantumPosition < 4; quantumPosition++) - { - temp <<= 6; - if (*cursor >= 0x41 && *cursor <= 0x5A) // This area will need tweaking if - temp |= *cursor - 0x41; // you are using an alternate alphabet - else if (*cursor >= 0x61 && *cursor <= 0x7A) - temp |= *cursor - 0x47; - else if (*cursor >= 0x30 && *cursor <= 0x39) - temp |= *cursor + 0x04; - else if (*cursor == 0x2B) - temp |= 0x3E; // change to 0x2D for URL alphabet - else if (*cursor == 0x2F) - temp |= 0x3F; // change to 0x5F for URL alphabet - else if (*cursor == padCharacter) // pad - { - switch (input.end() - cursor) - { - case 1: //One pad character - decoded.push_back((temp >> 16) & 0x000000FF); - decoded.push_back((temp >> 8 ) & 0x000000FF); - return decoded; - case 2: //Two pad characters - decoded.push_back((temp >> 10) & 0x000000FF); - return decoded; - default: - throw std::runtime_error("Invalid Padding in Base 64!"); - } - } else - throw std::runtime_error("Non-Valid Character in Base 64!"); - cursor++; - } - decoded.push_back((temp >> 16) & 0x000000FF); - decoded.push_back((temp >> 8 ) & 0x000000FF); - decoded.push_back((temp ) & 0x000000FF); - } - return decoded; - } - -} } diff --git a/src/storage.cpp b/src/storage.cpp index 6e2f118..4cfa08d 100644 --- a/src/storage.cpp +++ b/src/storage.cpp @@ -1,5 +1,4 @@ #include "storage.h" -#include "base64.h" #include <charconv> #include <chrono> @@ -1018,9 +1017,17 @@ optional<RecordT<S>> RecordT<S>::decode(const S & st, } else if (type == "t") items->emplace_back(name, value); - else if (type == "b") - items->emplace_back(name, base64::decode(value)); - else if (type == "d") + else if (type == "b") { + if (value.size() % 2) + return nullopt; + vector<uint8_t> binary(value.size() / 2, 0); + + for (size_t i = 0; i < binary.size(); i++) + std::from_chars(value.data() + 2 * i, + value.data() + 2 * i + 2, + binary[i], 16); + items->emplace_back(name, std::move(binary)); + } else if (type == "d") items->emplace_back(name, ZonedTime(value)); else if (type == "u") items->emplace_back(name, UUID(value)); @@ -1100,7 +1107,11 @@ vector<uint8_t> RecordT<S>::encodeInner() const value = *x; } else if (auto x = item.asBinary()) { type = "b"; - value = base64::encode(*x); + value.resize(x->size() * 2, '0'); + for (size_t i = 0; i < x->size(); i++) + std::to_chars(value.data() + 2 * i + ((*x)[i] < 0x10), + value.data() + 2 * i + 2, + (*x)[i], 16); } else if (auto x = item.asDate()) { type = "d"; value = string(*x); -- cgit v1.2.3