• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 19012754211

02 Nov 2025 01:10PM UTC coverage: 90.677% (+0.006%) from 90.671%
19012754211

push

github

web-flow
Merge pull request #5137 from randombit/jack/clang-tidy-includes

Remove various unused includes flagged by clang-tidy misc-include-cleaner

100457 of 110786 relevant lines covered (90.68%)

12189873.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.43
/src/lib/codec/base64/base64.cpp
1
/*
2
* Base64 Encoding and Decoding
3
* (C) 2010,2015,2020 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/base64.h>
9

10
#include <botan/exceptn.h>
11
#include <botan/internal/charset.h>
12
#include <botan/internal/codec_base.h>
13
#include <botan/internal/fmt.h>
14
#include <botan/internal/int_utils.h>
15
#include <botan/internal/loadstor.h>
16
#include <botan/internal/rounding.h>
17

18
namespace Botan {
19

20
namespace {
21

22
class Base64 final {
23
   public:
24
      static std::string name() noexcept { return "base64"; }
14✔
25

26
      static constexpr size_t encoding_bytes_in() noexcept { return m_encoding_bytes_in; }
27

28
      static constexpr size_t encoding_bytes_out() noexcept { return m_encoding_bytes_out; }
29

30
      static constexpr size_t decoding_bytes_in() noexcept { return m_encoding_bytes_out; }
31

32
      static constexpr size_t decoding_bytes_out() noexcept { return m_encoding_bytes_in; }
33

34
      static constexpr size_t bits_consumed() noexcept { return m_encoding_bits; }
35

36
      static constexpr size_t remaining_bits_before_padding() noexcept { return m_remaining_bits_before_padding; }
37

38
      static constexpr size_t encode_max_output(size_t input_length) {
2,510✔
39
         return (round_up(input_length, m_encoding_bytes_in) / m_encoding_bytes_in) * m_encoding_bytes_out;
2,510✔
40
      }
41

42
      static constexpr size_t decode_max_output(size_t input_length) {
32,706✔
43
         return (round_up(input_length, m_encoding_bytes_out) * m_encoding_bytes_in) / m_encoding_bytes_out;
32,687✔
44
      }
45

46
      static void encode(char out[4], const uint8_t in[3]) noexcept;
47

48
      static uint8_t lookup_binary_value(char input) noexcept;
49

50
      static bool check_bad_char(uint8_t bin, char input, bool ignore_ws);
51

52
      static void decode(uint8_t* out_ptr, const uint8_t decode_buf[4]) {
5,443,841✔
53
         out_ptr[0] = (decode_buf[0] << 2) | (decode_buf[1] >> 4);
5,443,841✔
54
         out_ptr[1] = (decode_buf[1] << 4) | (decode_buf[2] >> 2);
5,443,841✔
55
         out_ptr[2] = (decode_buf[2] << 6) | decode_buf[3];
5,443,841✔
56
      }
57

58
      static size_t bytes_to_remove(size_t final_truncate) { return final_truncate; }
59

60
   private:
61
      static constexpr size_t m_encoding_bits = 6;
62
      static constexpr size_t m_remaining_bits_before_padding = 8;
63

64
      static constexpr size_t m_encoding_bytes_in = 3;
65
      static constexpr size_t m_encoding_bytes_out = 4;
66
};
67

68
uint32_t lookup_base64_chars(uint32_t x32) {
2,181,473✔
69
   /*
70
   * The basic insight of this approach is that our goal is computing
71
   * f(x) = y where x is in [0,63) and y is the correct base64 encoding.
72
   *
73
   * Instead of doing this directly, we compute
74
   * offset(x) such that f(x) = x + offset(x)
75
   *
76
   * This is described in
77
   * http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html#improved-version
78
   *
79
   * Here we do a SWAR (simd within a register) implementation of Wojciech's lookup_version2_swar
80
   */
81

82
   uint32_t r = x32 + 0x41414141;
2,181,473✔
83

84
   r += (~swar_lt<uint32_t>(x32, 0x1A1A1A1A)) & 0x06060606;
2,181,473✔
85
   r -= (~swar_lt<uint32_t>(x32, 0x34343434)) & 0x4B4B4B4B;
2,181,473✔
86
   r -= (~swar_lt<uint32_t>(x32, 0x3E3E3E3E)) & 0x0F0F0F0F;
2,181,473✔
87
   r += (~swar_lt<uint32_t>(x32, 0x3F3F3F3F)) & 0x03030303;
2,181,473✔
88

89
   return r;
2,181,473✔
90
}
91

92
//static
93
void Base64::encode(char out[4], const uint8_t in[3]) noexcept {
2,181,473✔
94
   const uint32_t b0 = (in[0] & 0xFC) >> 2;
2,181,473✔
95
   const uint32_t b1 = ((in[0] & 0x03) << 4) | (in[1] >> 4);
2,181,473✔
96
   const uint32_t b2 = ((in[1] & 0x0F) << 2) | (in[2] >> 6);
2,181,473✔
97
   const uint32_t b3 = in[2] & 0x3F;
2,181,473✔
98

99
   const uint32_t z = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
2,181,473✔
100

101
   const uint32_t b64 = lookup_base64_chars(z);
2,181,473✔
102

103
   out[0] = static_cast<char>(get_byte<0>(b64));
2,181,473✔
104
   out[1] = static_cast<char>(get_byte<1>(b64));
2,181,473✔
105
   out[2] = static_cast<char>(get_byte<2>(b64));
2,181,473✔
106
   out[3] = static_cast<char>(get_byte<3>(b64));
2,181,473✔
107
}
2,181,473✔
108

109
//static
110
uint8_t Base64::lookup_binary_value(char input) noexcept {
22,128,789✔
111
   auto has_zero_byte = [](uint64_t v) { return ((v - 0x0101010101010101) & ~(v) & 0x8080808080808080); };
22,128,789✔
112

113
   // Assumes each byte is either 0x00 or 0x80
114
   auto index_of_first_set_byte = [](uint64_t v) {
22,128,789✔
115
      return ((((v - 1) & 0x0101010101010101) * 0x0101010101010101) >> 56) - 1;
22,128,789✔
116
   };
117

118
   constexpr uint64_t lo = 0x0101010101010101;
22,128,789✔
119

120
   const uint8_t x = static_cast<uint8_t>(input);
22,128,789✔
121

122
   const uint64_t x8 = x * lo;
22,128,789✔
123

124
   // Defines the valid ASCII ranges of base64, except the special chars (below)
125
   constexpr uint64_t val_l = make_uint64(0, 0, 0, 0, 0, 'A', 'a', '0');
22,128,789✔
126
   constexpr uint64_t val_u = make_uint64(0, 0, 0, 0, 0, 26, 26, 10);
22,128,789✔
127

128
   // If x is in one of the ranges return a mask. Otherwise we xor in at the
129
   // high word which will be our invalid marker
130
   auto v_mask = swar_in_range<uint64_t>(x8, val_l, val_u) ^ 0x80000000;
22,128,789✔
131

132
   // This is the offset added to x to get the value
133
   const uint64_t val_v = 0xbfb904 ^ (0xFF000000 - (x << 24));
22,128,789✔
134

135
   uint8_t z = x + static_cast<uint8_t>(val_v >> (8 * index_of_first_set_byte(v_mask)));
22,128,789✔
136

137
   // Valid base64 special characters, and some whitespace chars
138
   constexpr uint64_t specials_i = make_uint64(0, '+', '/', '=', ' ', '\n', '\t', '\r');
22,128,789✔
139

140
   const uint64_t specials_v = 0x3e3f8180808080 ^ (static_cast<uint64_t>(z) << 56);
22,128,789✔
141

142
   const uint64_t smask = has_zero_byte(x8 ^ specials_i) ^ 0x8000000000000000;
22,128,789✔
143

144
   return static_cast<uint8_t>(specials_v >> (8 * index_of_first_set_byte(smask)));
22,128,789✔
145
}
146

147
//static
148
bool Base64::check_bad_char(uint8_t bin, char input, bool ignore_ws) {
22,123,610✔
149
   if(bin <= 0x3F) {
22,123,610✔
150
      return true;
151
   } else if(!(bin == 0x81 || (bin == 0x80 && ignore_ws))) {
364,362✔
152
      throw Invalid_Argument(fmt("base64_decode: invalid character '{}'", format_char_for_display(input)));
76✔
153
   }
154
   return false;
155
}
156

157
}  // namespace
158

159
size_t base64_encode(char out[], const uint8_t in[], size_t input_length, size_t& input_consumed, bool final_inputs) {
8✔
160
   return base_encode(Base64(), out, in, input_length, input_consumed, final_inputs);
8✔
161
}
162

163
std::string base64_encode(const uint8_t input[], size_t input_length) {
2,510✔
164
   return base_encode_to_string(Base64(), input, input_length);
2,510✔
165
}
166

167
size_t base64_decode(
2✔
168
   uint8_t out[], const char in[], size_t input_length, size_t& input_consumed, bool final_inputs, bool ignore_ws) {
169
   return base_decode(Base64(), out, in, input_length, input_consumed, final_inputs, ignore_ws);
2✔
170
}
171

172
size_t base64_decode(uint8_t output[], const char input[], size_t input_length, bool ignore_ws) {
17✔
173
   return base_decode_full(Base64(), output, input, input_length, ignore_ws);
17✔
174
}
175

176
size_t base64_decode(uint8_t output[], std::string_view input, bool ignore_ws) {
17✔
177
   return base64_decode(output, input.data(), input.length(), ignore_ws);
17✔
178
}
179

180
size_t base64_decode(std::span<uint8_t> output, std::string_view input, bool ignore_ws) {
×
181
   if(output.size() < base64_decode_max_output(input.size())) {
×
182
      throw Invalid_Argument("base64_decode: output buffer is too short");
×
183
   }
184
   return base64_decode(output.data(), input.data(), input.length(), ignore_ws);
×
185
}
186

187
secure_vector<uint8_t> base64_decode(const char input[], size_t input_length, bool ignore_ws) {
16,334✔
188
   return base_decode_to_vec<secure_vector<uint8_t>>(Base64(), input, input_length, ignore_ws);
16,334✔
189
}
190

191
secure_vector<uint8_t> base64_decode(std::string_view input, bool ignore_ws) {
659✔
192
   return base64_decode(input.data(), input.size(), ignore_ws);
659✔
193
}
194

195
size_t base64_encode_max_output(size_t input_length) {
×
196
   return Base64::encode_max_output(input_length);
×
197
}
198

199
size_t base64_decode_max_output(size_t input_length) {
19✔
200
   return Base64::decode_max_output(input_length);
19✔
201
}
202

203
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc