K-HHC
C++ Header-only Library for Hexahexacontadecimal Encoding/Decoding
Loading...
Searching...
No Matches
hhc.hpp
Go to the documentation of this file.
1#ifndef hhc_HPP
2#define hhc_HPP
3#include <cstdint>
4#include <array>
5#include <stdexcept>
6#include "hhc_constants.hpp"
7#include "hhc_assert.hpp"
8#include <string>
9
10namespace hhc {
11
20 constexpr void hhc_32bit_encode_padded(uint32_t input, char* output_string) {
21 HHC_ASSERT(output_string != nullptr);
22
23 for (uint32_t pos = HHC_32BIT_ENCODED_LENGTH; pos > 0; --pos) {
24 const uint32_t index = input % BASE;
25 input /= BASE;
26 output_string[pos - 1] = ALPHABET[index];
27
28 }
29 }
30
37 constexpr void hhc_unpad_string(char* output_string) {
38 HHC_ASSERT(output_string != nullptr);
39
40 const char* first_significant = output_string;
41 while (*first_significant == ALPHABET[0]) {
42 ++first_significant;
43 }
44
45 // All characters were padding: the value is zero, whose canonical
46 // unpadded encoding is a single padding character
47 if (*first_significant == '\0') {
48 if (first_significant != output_string) {
49 output_string[0] = ALPHABET[0];
50 output_string[1] = '\0';
51 }
52 return;
53 }
54
55 // Move the significant characters (including null terminator) to the
56 // start. Destination never overtakes source, so a forward copy is safe.
57 char* dst = output_string;
58 while ((*dst++ = *first_significant++) != '\0') {
59 }
60 }
61
70 constexpr void hhc_32bit_encode_unpadded(uint32_t input, char* output_string) {
71 HHC_ASSERT(output_string != nullptr);
72 hhc_32bit_encode_padded(input, output_string);
73 hhc_unpad_string(output_string);
74 }
75
84 constexpr uint32_t hhc_32bit_decode_unsafe(const char* input_string) {
85 HHC_ASSERT(input_string != nullptr);
86 uint32_t output = 0;
87 for (std::size_t pos = 0; pos < HHC_32BIT_ENCODED_LENGTH; ++pos) {
88 const auto c = static_cast<unsigned char>(input_string[pos]);
89 output = output * BASE + INVERSE_ALPHABET[c];
90 }
91 return output;
92 }
93
94
103 constexpr void hhc_64bit_encode_padded(uint64_t input, char* output_string) {
104 HHC_ASSERT(output_string != nullptr);
105 for (uint32_t pos = HHC_64BIT_ENCODED_LENGTH; pos > 0; --pos) {
106 const uint32_t index = input % BASE;
107 input /= BASE;
108 output_string[pos - 1] = ALPHABET[index];
109 }
110 }
111
120 constexpr void hhc_64bit_encode_unpadded(uint64_t input, char* output_string) {
121 HHC_ASSERT(output_string != nullptr);
122 hhc_64bit_encode_padded(input, output_string);
123 hhc_unpad_string(output_string);
124 }
125
134 constexpr uint64_t hhc_64bit_decode_unsafe(const char* input_string) {
135 HHC_ASSERT(input_string != nullptr);
136 uint64_t output = 0;
137 for (std::size_t pos = 0; pos < HHC_64BIT_ENCODED_LENGTH; ++pos) {
138 const auto c = static_cast<unsigned char>(input_string[pos]);
139 output = output * BASE + INVERSE_ALPHABET[c];
140 }
141 return output;
142 }
143
152 constexpr std::size_t hhc_validate_string(const char* input_string) {
153 HHC_ASSERT(input_string != nullptr);
154 if (*input_string == '\0') {
155 return 0;
156 }
157 const char* const start = input_string;
158 while (*input_string != '\0') {
159 const auto c = static_cast<unsigned char>(*input_string++);
161 return 0;
162 }
163 }
164 return input_string - start;
165 }
166
173 constexpr bool hhc_bounds_check(const char* input_string, const char* max_string) {
174 HHC_ASSERT(input_string != nullptr);
175 HHC_ASSERT(max_string != nullptr);
176 while (*max_string != '\0') {
177 const auto current = static_cast<unsigned char>(*input_string);
178 const auto maximum = static_cast<unsigned char>(*max_string);
179 if (current < maximum) {
180 return true;
181 }
182 if (current > maximum) {
183 return false;
184 }
185 ++input_string;
186 ++max_string;
187 }
188 return true;
189 }
190
198 constexpr uint32_t hhc_32bit_decode(const char* input_string) {
199 if (input_string == nullptr) {
200 throw std::invalid_argument("Invalid HHC string (nullptr)");
201 }
202
203 const std::size_t length = hhc_validate_string(input_string);
204 if (length == 0 || length > HHC_32BIT_ENCODED_LENGTH) {
205 throw std::invalid_argument("Invalid HHC string (length " + std::to_string(length) + ")");
206 }
207
208 // If the string is not padded, pad it (no bounds check needed - shorter strings are always valid)
209 if (length < HHC_32BIT_ENCODED_LENGTH) {
210 char padded_string[HHC_32BIT_STRING_LENGTH] = {}; // Zero-init also null-terminates
211 const std::size_t padding = HHC_32BIT_ENCODED_LENGTH - length;
212
213 for (std::size_t i = 0; i < padding; ++i) {
214 padded_string[i] = ALPHABET[0];
215 }
216 for (std::size_t i = 0; i < length; ++i) {
217 padded_string[padding + i] = input_string[i];
218 }
219
220 return hhc_32bit_decode_unsafe(padded_string);
221 }
222
223 // Check bounds on the already-padded string
225 throw std::out_of_range("HHC string exceeds 32-bit bounds");
226 }
227
228 return hhc_32bit_decode_unsafe(input_string); // Already padded
229 }
230
238 constexpr uint64_t hhc_64bit_decode(const char* input_string) {
239 if (input_string == nullptr) {
240 throw std::invalid_argument("Invalid HHC string (nullptr)");
241 }
242
243 const std::size_t length = hhc_validate_string(input_string);
244 if (length == 0 || length > HHC_64BIT_ENCODED_LENGTH) {
245 throw std::invalid_argument("Invalid HHC string (length " + std::to_string(length) + ")");
246 }
247
248 // If the string is not padded, pad it (no bounds check needed - shorter strings are always valid)
249 if (length < HHC_64BIT_ENCODED_LENGTH) {
250 char padded_string[HHC_64BIT_STRING_LENGTH] = {}; // Zero-init also null-terminates
251 const std::size_t padding = HHC_64BIT_ENCODED_LENGTH - length;
252
253 for (std::size_t i = 0; i < padding; ++i) {
254 padded_string[i] = ALPHABET[0];
255 }
256 for (std::size_t i = 0; i < length; ++i) {
257 padded_string[padding + i] = input_string[i];
258 }
259
260 return hhc_64bit_decode_unsafe(padded_string);
261 }
262
263 // Check bounds on the already-padded string
265 throw std::out_of_range("HHC string exceeds 64-bit bounds");
266 }
267
268 return hhc_64bit_decode_unsafe(input_string); // Already padded
269 }
270} // namespace hhc
271
272#endif // hhc_HPP
#define HHC_ASSERT(expr)
HHC assertion macro.
Definition hhc_assert.hpp:210
Definition hhc.hpp:10
constexpr auto HHC_64BIT_ENCODED_MAX_STRING
Definition hhc_constants.hpp:47
constexpr size_t HHC_64BIT_STRING_LENGTH
Definition hhc_constants.hpp:43
constexpr size_t HHC_32BIT_ENCODED_LENGTH
Definition hhc_constants.hpp:44
constexpr uint32_t hhc_32bit_decode_unsafe(const char *input_string)
Decode a 32-bit integer from a 6-character string.
Definition hhc.hpp:84
constexpr uint64_t hhc_64bit_decode_unsafe(const char *input_string)
Decode a 64-bit integer from a 11-character string.
Definition hhc.hpp:134
constexpr void hhc_unpad_string(char *output_string)
Unpad a string by removing the leading '-' padding characters and moving the significant content to t...
Definition hhc.hpp:37
constexpr auto HHC_32BIT_ENCODED_MAX_STRING
Definition hhc_constants.hpp:46
constexpr void hhc_64bit_encode_unpadded(uint64_t input, char *output_string)
Encode a 64-bit integer into a 11-character string without padding.
Definition hhc.hpp:120
constexpr size_t HHC_32BIT_STRING_LENGTH
Definition hhc_constants.hpp:42
constexpr uint8_t HHC_INVALID_CHAR
Definition hhc_constants.hpp:20
constexpr uint32_t hhc_32bit_decode(const char *input_string)
Decode a 32-bit integer from a 6-character string.
Definition hhc.hpp:198
constexpr std::size_t hhc_validate_string(const char *input_string)
Validate a string to ensure it is a valid HHC string.
Definition hhc.hpp:152
constexpr void hhc_64bit_encode_padded(uint64_t input, char *output_string)
Encode a 64-bit integer into a 11-character string.
Definition hhc.hpp:103
constexpr std::array< char, BASE > ALPHABET
Definition hhc_constants.hpp:10
constexpr void hhc_32bit_encode_unpadded(uint32_t input, char *output_string)
Encode a 32-bit integer into a 6-character string without padding.
Definition hhc.hpp:70
constexpr size_t HHC_64BIT_ENCODED_LENGTH
Definition hhc_constants.hpp:45
constexpr auto INVERSE_ALPHABET
Definition hhc_constants.hpp:39
constexpr void hhc_32bit_encode_padded(uint32_t input, char *output_string)
Encode a 32-bit integer into a 6-character string.
Definition hhc.hpp:20
constexpr uint32_t BASE
Definition hhc_constants.hpp:9
constexpr uint64_t hhc_64bit_decode(const char *input_string)
Decode a 64-bit integer from a 11-character string.
Definition hhc.hpp:238
constexpr bool hhc_bounds_check(const char *input_string, const char *max_string)
Check if a string is within the bounds of a maximum string.
Definition hhc.hpp:173