summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoman Smrž <roman.smrz@seznam.cz>2021-01-31 21:13:19 +0100
committerRoman Smrž <roman.smrz@seznam.cz>2021-01-31 21:13:19 +0100
commitc63b1a4591a0a54d3ccd449573f408739ea29af2 (patch)
tree2527ffb477e8b4395ede48383402d77ecd4e2b5b
parentfc368248316aebeb756bdd8b85d3f819eddc49d1 (diff)
Storage: hexadecimal encoding of binary record items
-rw-r--r--src/base64.h107
-rw-r--r--src/storage.cpp21
2 files changed, 16 insertions, 112 deletions
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);