10template <
typename chartype>
11simdutf_warn_unused simdutf_constexpr23
result slow_base64_to_binary_safe_impl(
12 const chartype *input,
size_t length,
char *output,
size_t &outlen,
13 base64_options options,
14 last_chunk_handling_options last_chunk_options)
noexcept {
15 const bool ignore_garbage = (options & base64_default_accept_garbage) != 0;
16 auto ri = simdutf::scalar::base64::find_end(input, length, options);
17 size_t equallocation = ri.equallocation;
18 size_t equalsigns = ri.equalsigns;
20 size_t full_input_length = ri.full_input_length;
21 (void)full_input_length;
24 if (!ignore_garbage && equalsigns > 0) {
25 return {INVALID_BASE64_CHARACTER, equallocation};
42 full_result r = scalar::base64::base64_tail_decode_safe(
43 output, outlen, input, length, equalsigns, options, last_chunk_options);
44 r = scalar::base64::patch_tail_result(r, 0, 0, equallocation,
45 full_input_length, last_chunk_options);
46 outlen = r.output_count;
47 if (!is_partial(last_chunk_options) && r.error == error_code::SUCCESS &&
50 if ((outlen % 3 == 0) || ((outlen % 3) + 1 + equalsigns != 4)) {
51 r.error = error_code::INVALID_BASE64_CHARACTER;
54 return {r.error, r.input_count};
58template <
typename chartype>
59simdutf_warn_unused simdutf_constexpr23
result base64_to_binary_safe_impl(
60 const chartype *input,
size_t length,
char *output,
size_t &outlen,
61 base64_options options,
62 last_chunk_handling_options last_chunk_handling_options,
63 bool decode_up_to_bad_char)
noexcept {
64 static_assert(std::is_same<chartype, char>::value ||
65 std::is_same<chartype, char16_t>::value,
66 "Only char and char16_t are supported.");
67 size_t remaining_input_length = length;
68 size_t remaining_output_length = outlen;
69 size_t input_position = 0;
70 size_t output_position = 0;
73 size_t safe_input = detail::min(
74 remaining_input_length,
76 bool done_with_partial = (safe_input == remaining_input_length);
79#if SIMDUTF_CPLUSPLUS23
81 r = scalar::base64::base64_to_binary_details_impl(
82 input + input_position, safe_input, output + output_position, options,
84 ? last_chunk_handling_options
85 : simdutf::last_chunk_handling_options::only_full_chunks);
90 input + input_position, safe_input, output + output_position, options,
92 ? last_chunk_handling_options
93 : simdutf::last_chunk_handling_options::only_full_chunks);
95 simdutf_log_assert(r.input_count <= safe_input,
96 "You should not read more than safe_input");
97 simdutf_log_assert(r.output_count <= remaining_output_length,
98 "You should not write more than remaining_output_length");
100 input_position += r.input_count;
101 output_position += r.output_count;
102 remaining_input_length -= r.input_count;
103 remaining_output_length -= r.output_count;
104 if (r.error != simdutf::error_code::SUCCESS) {
106 if (decode_up_to_bad_char &&
107 r.error == error_code::INVALID_BASE64_CHARACTER) {
108 return slow_base64_to_binary_safe_impl(
109 input, length, output, outlen, options, last_chunk_handling_options);
111 outlen = output_position;
112 return {r.error, input_position};
115 if (done_with_partial) {
117 outlen = output_position;
118 return {simdutf::error_code::SUCCESS, input_position};
122 r = simdutf::scalar::base64::base64_to_binary_details_safe_impl(
123 input + input_position, remaining_input_length, output + output_position,
124 remaining_output_length, options, last_chunk_handling_options);
125 input_position += r.input_count;
126 output_position += r.output_count;
127 remaining_input_length -= r.input_count;
128 remaining_output_length -= r.output_count;
130 if (r.error != simdutf::error_code::SUCCESS) {
132 if (decode_up_to_bad_char &&
133 r.error == error_code::INVALID_BASE64_CHARACTER) {
134 return slow_base64_to_binary_safe_impl(
135 input, length, output, outlen, options, last_chunk_handling_options);
137 outlen = output_position;
138 return {r.error, input_position};
140 if (input_position < length) {
150 while (input_position > 0 &&
155 outlen = output_position;
156 return {simdutf::error_code::SUCCESS, input_position};