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

randombit / botan / 14540090049

18 Apr 2025 06:45PM UTC coverage: 91.314% (+0.005%) from 91.309%
14540090049

Pull #4832

github

web-flow
Merge 76c608e15 into 7f66c45b3
Pull Request #4832: Replace std::vector with std::array in codec_base to avoid allocations

95529 of 104616 relevant lines covered (91.31%)

13134050.08 hits per line

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

98.7
/src/lib/utils/codec_base.h
1
/*
2
* Base Encoding and Decoding
3
* (C) 2018 Erwan Chaussy
4
* (C) 2018 Jack Lloyd
5
*
6
* Botan is released under the Simplified BSD License (see license.txt)
7
*/
8

9
#ifndef BOTAN_BASE_CODEC_H_
10
#define BOTAN_BASE_CODEC_H_
11

12
#include <botan/exceptn.h>
13
#include <botan/mem_ops.h>
14
#include <array>
15
#include <string>
16
#include <type_traits>
17

18
namespace Botan {
19

20
/**
21
* Perform encoding using the base provided
22
* @param base object giving access to the encodings specifications
23
* @param output an array of at least base.encode_max_output bytes
24
* @param input is some binary data
25
* @param input_length length of input in bytes
26
* @param input_consumed is an output parameter which says how many
27
*        bytes of input were actually consumed. If less than
28
*        input_length, then the range input[consumed:length]
29
*        should be passed in later along with more input.
30
* @param final_inputs true iff this is the last input, in which case
31
         padding chars will be applied if needed
32
* @return number of bytes written to output
33
*/
34
template <class Base>
35
size_t base_encode(
2,533✔
36
   Base&& base, char output[], const uint8_t input[], size_t input_length, size_t& input_consumed, bool final_inputs) {
37
   input_consumed = 0;
2,533✔
38

39
   constexpr size_t encoding_bytes_in = std::remove_reference_t<Base>::encoding_bytes_in();
2,533✔
40
   constexpr size_t encoding_bytes_out = std::remove_reference_t<Base>::encoding_bytes_out();
2,533✔
41

42
   size_t input_remaining = input_length;
2,533✔
43
   size_t output_produced = 0;
2,533✔
44

45
   while(input_remaining >= encoding_bytes_in) {
2,181,666✔
46
      base.encode(output + output_produced, input + input_consumed);
2,179,133✔
47

48
      input_consumed += encoding_bytes_in;
2,179,133✔
49
      output_produced += encoding_bytes_out;
2,179,133✔
50
      input_remaining -= encoding_bytes_in;
2,179,133✔
51
   }
52

53
   if(final_inputs && input_remaining) {
2,533✔
54
      std::array<uint8_t, encoding_bytes_in> remainder{};
2,139✔
55
      for(size_t i = 0; i != input_remaining; ++i) {
5,376✔
56
         remainder[i] = input[input_consumed + i];
3,237✔
57
      }
58

59
      base.encode(output + output_produced, remainder.data());
2,139✔
60

61
      const size_t bits_consumed = base.bits_consumed();
2,139✔
62
      const size_t remaining_bits_before_padding = base.remaining_bits_before_padding();
2,139✔
63

64
      size_t empty_bits = 8 * (encoding_bytes_in - input_remaining);
2,139✔
65
      size_t index = output_produced + encoding_bytes_out - 1;
2,139✔
66
      while(empty_bits >= remaining_bits_before_padding) {
5,376✔
67
         output[index--] = '=';
3,237✔
68
         empty_bits -= bits_consumed;
3,237✔
69
      }
70

71
      input_consumed += input_remaining;
2,139✔
72
      output_produced += encoding_bytes_out;
2,139✔
73
   }
74

75
   return output_produced;
2,533✔
76
}
77

78
template <typename Base>
79
std::string base_encode_to_string(Base&& base, const uint8_t input[], size_t input_length) {
2,527✔
80
   const size_t output_length = base.encode_max_output(input_length);
2,527✔
81
   std::string output(output_length, 0);
2,527✔
82

83
   size_t consumed = 0;
2,527✔
84
   size_t produced = 0;
2,527✔
85

86
   if(output_length > 0) {
2,527✔
87
      produced = base_encode(base, &output.front(), input, input_length, consumed, true);
2,525✔
88
   }
89

90
   BOTAN_ASSERT_EQUAL(consumed, input_length, "Consumed the entire input");
2,527✔
91
   BOTAN_ASSERT_EQUAL(produced, output.size(), "Produced expected size");
2,527✔
92

93
   return output;
2,527✔
94
}
×
95

96
/**
97
* Perform decoding using the base provided
98
* @param base object giving access to the encodings specifications
99
* @param output an array of at least Base::decode_max_output bytes
100
* @param input some base input
101
* @param input_length length of input in bytes
102
* @param input_consumed is an output parameter which says how many
103
*        bytes of input were actually consumed. If less than
104
*        input_length, then the range input[consumed:length]
105
*        should be passed in later along with more input.
106
* @param final_inputs true iff this is the last input, in which case
107
         padding is allowed
108
* @param ignore_ws ignore whitespace on input; if false, throw an
109
                   exception if whitespace is encountered
110
* @return number of bytes written to output
111
*/
112
template <typename Base>
113
size_t base_decode(Base&& base,
16,437✔
114
                   uint8_t output[],
115
                   const char input[],
116
                   size_t input_length,
117
                   size_t& input_consumed,
118
                   bool final_inputs,
119
                   bool ignore_ws = true) {
120
   constexpr size_t decoding_bytes_in = std::remove_reference_t<Base>::decoding_bytes_in();
16,437✔
121
   constexpr size_t decoding_bytes_out = std::remove_reference_t<Base>::decoding_bytes_out();
16,437✔
122

123
   uint8_t* out_ptr = output;
16,437✔
124
   std::array<uint8_t, decoding_bytes_in> decode_buf{};
16,437✔
125
   size_t decode_buf_pos = 0;
16,437✔
126
   size_t final_truncate = 0;
16,437✔
127

128
   clear_mem(output, base.decode_max_output(input_length));
16,437✔
129

130
   for(size_t i = 0; i != input_length; ++i) {
22,129,321✔
131
      const uint8_t bin = base.lookup_binary_value(input[i]);
22,112,960✔
132

133
      // This call might throw Invalid_Argument
134
      if(base.check_bad_char(bin, input[i], ignore_ws)) {
22,112,960✔
135
         decode_buf[decode_buf_pos] = bin;
21,748,496✔
136
         ++decode_buf_pos;
21,748,496✔
137
      }
138

139
      /*
140
      * If we're at the end of the input, pad with 0s and truncate
141
      */
142
      if(final_inputs && (i == input_length - 1)) {
22,112,884✔
143
         if(decode_buf_pos) {
16,346✔
144
            for(size_t j = decode_buf_pos; j < decoding_bytes_in; ++j) {
28,287✔
145
               decode_buf[j] = 0;
16,286✔
146
            }
147

148
            final_truncate = decoding_bytes_in - decode_buf_pos;
12,001✔
149
            decode_buf_pos = decoding_bytes_in;
150
         }
151
      }
152

153
      if(decode_buf_pos == decoding_bytes_in) {
22,096,538✔
154
         base.decode(out_ptr, decode_buf.data());
5,441,084✔
155

156
         out_ptr += decoding_bytes_out;
5,441,084✔
157
         decode_buf_pos = 0;
5,441,084✔
158
         input_consumed = i + 1;
5,441,084✔
159
      }
160
   }
161

162
   while(input_consumed < input_length && base.lookup_binary_value(input[input_consumed]) == 0x80) {
21,658✔
163
      ++input_consumed;
5,297✔
164
   }
165

166
   size_t written = (out_ptr - output) - base.bytes_to_remove(final_truncate);
16,361✔
167

168
   return written;
16,361✔
169
}
170

171
template <typename Base>
172
size_t base_decode_full(Base&& base, uint8_t output[], const char input[], size_t input_length, bool ignore_ws) {
16,435✔
173
   size_t consumed = 0;
16,435✔
174
   const size_t written = base_decode(base, output, input, input_length, consumed, true, ignore_ws);
16,435✔
175

176
   if(consumed != input_length) {
16,359✔
177
      throw Invalid_Argument(base.name() + " decoding failed, input did not have full bytes");
56✔
178
   }
179

180
   return written;
16,345✔
181
}
182

183
template <typename Vector, typename Base>
184
Vector base_decode_to_vec(Base&& base, const char input[], size_t input_length, bool ignore_ws) {
16,418✔
185
   const size_t output_length = base.decode_max_output(input_length);
16,418✔
186
   Vector bin(output_length);
16,418✔
187

188
   const size_t written = base_decode_full(base, bin.data(), input, input_length, ignore_ws);
16,418✔
189

190
   bin.resize(written);
16,328✔
191
   return bin;
16,328✔
192
}
90✔
193

194
}  // namespace Botan
195

196
#endif
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