9#ifndef BOTAN_BASE_CODEC_H_
10#define BOTAN_BASE_CODEC_H_
12#include <botan/secmem.h>
13#include <botan/exceptn.h>
36 const uint8_t input[],
38 size_t& input_consumed,
43 const size_t encoding_bytes_in = base.encoding_bytes_in();
44 const size_t encoding_bytes_out = base.encoding_bytes_out();
46 size_t input_remaining = input_length;
47 size_t output_produced = 0;
49 while(input_remaining >= encoding_bytes_in)
51 base.encode(output + output_produced, input + input_consumed);
53 input_consumed += encoding_bytes_in;
54 output_produced += encoding_bytes_out;
55 input_remaining -= encoding_bytes_in;
58 if(final_inputs && input_remaining)
60 std::vector<uint8_t> remainder(encoding_bytes_in, 0);
61 for(
size_t i = 0; i != input_remaining; ++i)
62 { remainder[i] = input[input_consumed + i]; }
64 base.encode(output + output_produced, remainder.data());
66 const size_t bits_consumed = base.bits_consumed();
67 const size_t remaining_bits_before_padding = base.remaining_bits_before_padding();
69 size_t empty_bits = 8 * (encoding_bytes_in - input_remaining);
70 size_t index = output_produced + encoding_bytes_out - 1;
71 while(empty_bits >= remaining_bits_before_padding)
73 output[index--] =
'=';
74 empty_bits -= bits_consumed;
77 input_consumed += input_remaining;
78 output_produced += encoding_bytes_out;
81 return output_produced;
85template <
typename Base>
88 const size_t output_length = base.encode_max_output(input_length);
89 std::string output(output_length, 0);
123template <
typename Base>
128 size_t& input_consumed,
130 bool ignore_ws =
true)
132 const size_t decoding_bytes_in = base.decoding_bytes_in();
133 const size_t decoding_bytes_out = base.decoding_bytes_out();
135 uint8_t* out_ptr = output;
136 std::vector<uint8_t> decode_buf(decoding_bytes_in, 0);
137 size_t decode_buf_pos = 0;
138 size_t final_truncate = 0;
140 clear_mem(output, base.decode_max_output(input_length));
142 for(
size_t i = 0; i != input_length; ++i)
144 const uint8_t bin = base.lookup_binary_value(input[i]);
146 if(base.check_bad_char(bin, input[i], ignore_ws))
148 decode_buf[decode_buf_pos] = bin;
155 if(final_inputs && (i == input_length - 1))
159 for(
size_t j = decode_buf_pos; j < decoding_bytes_in; ++j)
160 { decode_buf[j] = 0; }
162 final_truncate = decoding_bytes_in - decode_buf_pos;
163 decode_buf_pos = decoding_bytes_in;
167 if(decode_buf_pos == decoding_bytes_in)
169 base.decode(out_ptr, decode_buf.data());
171 out_ptr += decoding_bytes_out;
173 input_consumed = i+1;
177 while(input_consumed < input_length &&
178 base.lookup_binary_value(input[input_consumed]) == 0x80)
183 size_t written = (out_ptr - output) - base.bytes_to_remove(final_truncate);
188template<
typename Base>
189size_t base_decode_full(Base&& base, uint8_t output[],
const char input[],
size_t input_length,
bool ignore_ws)
192 const size_t written =
base_decode(base, output, input, input_length, consumed,
true, ignore_ws);
194 if(consumed != input_length)
196 throw Invalid_Argument(base.name() +
" decoding failed, input did not have full bytes");
202template<
typename Vector,
typename Base>
208 const size_t output_length = base.decode_max_output(input_length);
209 Vector bin(output_length);
211 const size_t written =
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Vector base_decode_to_vec(Base &&base, const char input[], size_t input_length, bool ignore_ws)
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)
std::string base_encode_to_string(Base &&base, const uint8_t input[], size_t input_length)
constexpr void clear_mem(T *ptr, size_t n)
size_t base_decode_full(Base &&base, uint8_t output[], const char input[], size_t input_length, bool ignore_ws)