diff options
| author | Roman Smrž <roman.smrz@seznam.cz> | 2021-01-31 21:13:19 +0100 | 
|---|---|---|
| committer | Roman Smrž <roman.smrz@seznam.cz> | 2021-01-31 21:13:19 +0100 | 
| commit | c63b1a4591a0a54d3ccd449573f408739ea29af2 (patch) | |
| tree | 2527ffb477e8b4395ede48383402d77ecd4e2b5b /src | |
| parent | fc368248316aebeb756bdd8b85d3f819eddc49d1 (diff) | |
Storage: hexadecimal encoding of binary record items
Diffstat (limited to 'src')
| -rw-r--r-- | src/base64.h | 107 | ||||
| -rw-r--r-- | src/storage.cpp | 21 | 
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); |