1#ifndef SIMDUTF_BASE64_IMPLEMENTATION_H
2#define SIMDUTF_BASE64_IMPLEMENTATION_H
8template <
typename chartype>
9simdutf_warn_unused simdutf_constexpr23 result slow_base64_to_binary_safe_impl(
10 const chartype *input,
size_t length,
char *output,
size_t &outlen,
11 base64_options options,
12 last_chunk_handling_options last_chunk_options)
noexcept {
13 const bool ignore_garbage = (options & base64_default_accept_garbage) != 0;
14 auto ri = simdutf::scalar::base64::find_end(input, length, options);
15 size_t equallocation = ri.equallocation;
16 size_t equalsigns = ri.equalsigns;
18 size_t full_input_length = ri.full_input_length;
19 (void)full_input_length;
22 if (!ignore_garbage && equalsigns > 0) {
23 return {INVALID_BASE64_CHARACTER, equallocation};
40 full_result r = scalar::base64::base64_tail_decode_safe(
41 output, outlen, input, length, equalsigns, options, last_chunk_options);
42 r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
43 full_input_length, last_chunk_options);
44 outlen = r.output_count;
45 if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
48 if ((outlen % 3 == 0) || ((outlen % 3) + 1 + equalsigns != 4)) {
49 r.error = error_code::INVALID_BASE64_CHARACTER;
52 return {r.error, r.input_count};
56template <
typename chartype>
57simdutf_warn_unused simdutf_constexpr23 result base64_to_binary_safe_impl(
58 const chartype *input,
size_t length,
char *output,
size_t &outlen,
59 base64_options options,
60 last_chunk_handling_options last_chunk_handling_options,
61 bool decode_up_to_bad_char)
noexcept {
62 static_assert(std::is_same<chartype, char>::value ||
63 std::is_same<chartype, char16_t>::value,
64 "Only char and char16_t are supported.");
65 size_t remaining_input_length = length;
66 size_t remaining_output_length = outlen;
67 size_t input_position = 0;
68 size_t output_position = 0;
71 size_t safe_input = (std::min)(
72 remaining_input_length,
73 base64_length_from_binary(remaining_output_length / 3 * 3, options));
74 bool done_with_partial = (safe_input == remaining_input_length);
77#if SIMDUTF_CPLUSPLUS23
79 r = scalar::base64::base64_to_binary_details_impl(
80 input + input_position, safe_input, output + output_position, options,
82 ? last_chunk_handling_options
83 : simdutf::last_chunk_handling_options::only_full_chunks);
87 r = get_active_implementation()->base64_to_binary_details(
88 input + input_position, safe_input, output + output_position, options,
90 ? last_chunk_handling_options
91 : simdutf::last_chunk_handling_options::only_full_chunks);
93 simdutf_log_assert(r.input_count <= safe_input,
94 "You should not read more than safe_input");
95 simdutf_log_assert(r.output_count <= remaining_output_length,
96 "You should not write more than remaining_output_length");
98 input_position += r.input_count;
99 output_position += r.output_count;
100 remaining_input_length -= r.input_count;
101 remaining_output_length -= r.output_count;
102 if (r.error != simdutf::error_code::SUCCESS) {
104 if (decode_up_to_bad_char &&
105 r.error == error_code::INVALID_BASE64_CHARACTER) {
106 return slow_base64_to_binary_safe_impl(
107 input, length, output, outlen, options, last_chunk_handling_options);
109 outlen = output_position;
110 return {r.error, input_position};
113 if (done_with_partial) {
115 outlen = output_position;
116 return {simdutf::error_code::SUCCESS, input_position};
120 r = simdutf::scalar::base64::base64_to_binary_details_safe_impl(
121 input + input_position, remaining_input_length, output + output_position,
122 remaining_output_length, options, last_chunk_handling_options);
123 input_position += r.input_count;
124 output_position += r.output_count;
125 remaining_input_length -= r.input_count;
126 remaining_output_length -= r.output_count;
128 if (r.error != simdutf::error_code::SUCCESS) {
130 if (decode_up_to_bad_char &&
131 r.error == error_code::INVALID_BASE64_CHARACTER) {
132 return slow_base64_to_binary_safe_impl(
133 input, length, output, outlen, options, last_chunk_handling_options);
135 outlen = output_position;
136 return {r.error, input_position};
138 if (input_position < length) {
148 while (input_position > 0 &&
149 base64_ignorable(input[input_position - 1], options)) {
153 outlen = output_position;
154 return {simdutf::error_code::SUCCESS, input_position};