36 Base&& base,
char output[],
const uint8_t input[],
size_t input_length,
size_t& input_consumed,
bool final_inputs) {
40 constexpr size_t encoding_bytes_in = std::remove_reference_t<Base>::encoding_bytes_in();
41 constexpr size_t encoding_bytes_out = std::remove_reference_t<Base>::encoding_bytes_out();
43 size_t input_remaining = input_length;
44 size_t output_produced = 0;
46 while(input_remaining >= encoding_bytes_in) {
47 base.encode(output + output_produced, input + input_consumed);
49 input_consumed += encoding_bytes_in;
50 output_produced += encoding_bytes_out;
51 input_remaining -= encoding_bytes_in;
54 if(final_inputs && input_remaining) {
55 std::array<uint8_t, encoding_bytes_in> remainder{};
56 for(
size_t i = 0; i != input_remaining; ++i) {
57 remainder[i] = input[input_consumed + i];
60 base.encode(output + output_produced, remainder.data());
62 const size_t bits_consumed = base.bits_consumed();
63 const size_t remaining_bits_before_padding = base.remaining_bits_before_padding();
65 size_t empty_bits = 8 * (encoding_bytes_in - input_remaining);
66 size_t index = output_produced + encoding_bytes_out - 1;
67 while(empty_bits >= remaining_bits_before_padding) {
68 output[index--] =
'=';
69 empty_bits -= bits_consumed;
72 input_consumed += input_remaining;
73 output_produced += encoding_bytes_out;
76 return output_produced;
81 const size_t output_length = base.encode_max_output(input_length);
82 std::string output(output_length, 0);
87 if(output_length > 0) {
88 produced =
base_encode(base, &output.front(), input, input_length, consumed,
true);
118 size_t& input_consumed,
120 bool ignore_ws =
true) {
122 constexpr size_t decoding_bytes_in = std::remove_reference_t<Base>::decoding_bytes_in();
123 constexpr size_t decoding_bytes_out = std::remove_reference_t<Base>::decoding_bytes_out();
126 std::array<uint8_t, decoding_bytes_in> decode_buf{};
127 size_t decode_buf_pos = 0;
128 size_t final_truncate = 0;
130 clear_mem(output, base.decode_max_output(input_length));
132 for(
size_t i = 0; i != input_length; ++i) {
133 const uint8_t bin = base.lookup_binary_value(input[i]);
136 if(base.check_bad_char(bin, input[i], ignore_ws)) {
137 decode_buf[decode_buf_pos] = bin;
144 if(final_inputs && (i == input_length - 1)) {
146 for(
size_t j = decode_buf_pos; j < decoding_bytes_in; ++j) {
150 final_truncate = decoding_bytes_in - decode_buf_pos;
151 decode_buf_pos = decoding_bytes_in;
155 if(decode_buf_pos == decoding_bytes_in) {
156 base.decode(
out_ptr, decode_buf.data());
160 input_consumed = i + 1;
164 while(input_consumed < input_length && base.lookup_binary_value(input[input_consumed]) == 0x80) {
168 size_t written = (
out_ptr - output) - base.bytes_to_remove(final_truncate);
174size_t base_decode_full(Base&& base, uint8_t output[],
const char input[],
size_t input_length,
bool ignore_ws) {
176 const size_t written =
base_decode(base, output, input, input_length, consumed,
true, ignore_ws);
178 if(consumed != input_length) {
179 throw Invalid_Argument(base.name() +
" decoding failed, input did not have full bytes");
size_t base_encode(Base &&base, char output[], const uint8_t input[], size_t input_length, size_t &input_consumed, bool final_inputs)
size_t base_decode(Base &&base, uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool final_inputs, bool ignore_ws=true)