@@ -70,38 +70,37 @@ BaseNEncoder::encode(const std::vector<uint8_t>& input) {
7070 return (encoded_output);
7171 }
7272
73- // Turn the input data into a "bit stream"
74- // / @todo Can we devise a bit-stream class that can iterate over the input
75- // / without copying it? The weakness here is inbits could be rather large
76- // / for long strings since it input size * 8 bytes.
77- bool inbits[input.size () * 8 ];
78- bool * inbit = &inbits[0 ];
79- for (auto b : input) {
80- for (auto i = 0 ; i < 8 ; i++) {
81- bool val = b & 0x80 ;
82- *inbit++ = val;
83- b <<= 1 ;
84- }
85- }
86-
87- // Now encode the bit stream.
73+ uint8_t cur_bit = 0x0 ;
8874 int cnt = 0 ;
8975 int digit_idx = 0 ;
90- auto inbit_end = inbit;
91- inbit = &inbits[0 ];
92- for (inbit = &inbits[0 ]; inbit != inbit_end; ++inbit) {
76+ int cur_byte = 0 ;
77+ auto bytes = input.begin ();
78+ while (1 ) {
79+ if (!cur_bit) {
80+ if (bytes == input.end ()) {
81+ break ;
82+ }
83+
84+ cur_byte = *bytes;
85+ cur_bit = 0x80 ;
86+ ++bytes;
87+ }
88+
9389 if (cnt < bits_per_digit_) {
94- // Shift the index one to accommodate next bit.
9590 digit_idx <<= 1 ;
9691 } else {
97- // Have a complete digit index, look it the digit and add it.
92+ // Have a complete digit index, look up digit and add it.
9893 encoded_output.push_back (bitsToDigit (digit_idx));
9994 digit_idx = 0 ;
10095 cnt = 0 ;
10196 }
10297
10398 // Add the current bit to the digit index.
104- digit_idx |= *inbit;
99+ if (cur_byte & cur_bit) {
100+ digit_idx |= 1 ;
101+ }
102+
103+ cur_bit >>= 1 ;
105104 ++cnt;
106105 }
107106
@@ -128,52 +127,84 @@ BaseNEncoder::encode(const std::vector<uint8_t>& input) {
128127void
129128BaseNEncoder::decode (const std::string& encoded_str, std::vector<uint8_t >& output) {
130129 output.clear ();
131- bool inbits[encoded_str.size () * bits_per_digit_];
132- bool * inbit = &inbits[0 ];
133130 size_t dig_cnt = 0 ;
134131 size_t pad_cnt = 0 ;
135132 size_t shift_bits = 8 - bits_per_digit_;
133+ uint8_t cur_byte = 0 ;
134+ size_t cur_bit_cnt = 0 ;
136135 for (const auto enc_digit : encoded_str) {
137136 if (pad_char_ && enc_digit == pad_char_) {
138137 pad_cnt++;
139138 continue ;
140139 }
141140
142- // translate the b64 digit to bits.
141+ // Translate the b64 digit to bits.
143142 uint8_t dig_bits = digitToBits (enc_digit);
144143
144+ // Skip whitespace.
145145 if (dig_bits == 0xee ) {
146- // skip whitespace
147146 continue ;
148147 }
149148
149+ // Error on invalid characters.
150150 if (dig_bits == 0xff ) {
151151 isc_throw (isc::BadValue, " attempt to decode a value not in "
152152 << algorithm_ << " char set" << " : " << encoded_str);
153153 }
154154
155+ // Error if pads are in the middle.
155156 if (pad_cnt) {
156157 isc_throw (isc::BadValue, " pad mixed with digits in "
157158 << algorithm_ << " : " << encoded_str);
158159 }
159160
161+ // Bump the valid character count.
160162 dig_cnt++;
163+
164+ // Shift off what we don't need.
161165 dig_bits <<= shift_bits;
166+
167+ // Add digit's decoded bits to current byte.
162168 for (auto i = 0 ; i < bits_per_digit_; ++i) {
163- *inbit++ = ((dig_bits & 0x80 ) == 0x80 );
169+ if (cur_bit_cnt < 8 ) {
170+ // Shift contents to make room for next gbit.
171+ cur_byte <<= 1 ;
172+ } else {
173+ // Add the completed byte to the output.
174+ output.push_back (cur_byte);
175+ cur_byte = 0 ;
176+ cur_bit_cnt = 0 ;
177+ }
178+
179+ // Add the next bit if its set.
180+ if (dig_bits & 0x80 ) {
181+ cur_byte |= 1 ;
182+ }
183+
184+ // Shift the decoded bits over.
164185 dig_bits <<= 1 ;
186+
187+ // Update the current byte bit count.
188+ ++cur_bit_cnt;
165189 }
166190 }
167191
192+ if (cur_bit_cnt == 8 ) {
193+ // Whole one left to add.
194+ output.push_back (cur_byte);
195+ } else if (cur_bit_cnt && cur_byte) {
196+ // Left over bits that are not zero.
197+ isc_throw (BadValue, " non-zero bits left over " << encoded_str);
198+ }
199+
168200 if (pad_char_) {
169- // Check for invalid number of pad characters.
201+ // Check for too many pad characters.
170202 if (pad_cnt > max_pad_) {
171203 isc_throw (isc::BadValue, " too many pad characters for "
172204 << algorithm_ << " : " << encoded_str);
173205 }
174206
175207 // Check for invalid number of pad characters.
176- // / @todo is this valid
177208 const size_t padbits = ((pad_cnt * bits_per_digit_) + 7 ) & ~7 ;
178209 if (padbits > bits_per_digit_ * (pad_cnt + 1 )) {
179210 isc_throw (isc::BadValue, " Invalid padding for "
@@ -186,32 +217,6 @@ BaseNEncoder::decode(const std::string& encoded_str, std::vector<uint8_t>& outpu
186217 isc_throw (isc::BadValue, " Incomplete input for "
187218 << algorithm_ << " : " << encoded_str);
188219 }
189-
190- int cnt = 0 ;
191- int digit_idx = 0 ;
192-
193- auto inbit_end = inbit;
194- inbit = &inbits[0 ];
195- for (inbit = &inbits[0 ]; inbit != inbit_end; ++inbit) {
196- if (cnt < 8 ) {
197- digit_idx <<= 1 ;
198- } else {
199- output.push_back (digit_idx);
200- digit_idx = 0 ;
201- cnt = 0 ;
202- }
203-
204- digit_idx |= *inbit;
205- ++cnt;
206- }
207-
208- if (cnt == 8 ) {
209- // Whole one left to add.
210- output.push_back (digit_idx);
211- } else if (cnt && digit_idx) {
212- // Left over bits that are not zero.
213- isc_throw (BadValue, " non-zero bits left over " << encoded_str);
214- }
215220}
216221
217222const char * Base64Encoder::DIGIT_SET = " ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -282,40 +287,41 @@ const std::vector<uint8_t> Base16Encoder::BITS_TABLE = {
282287
283288string
284289encodeBase64 (const vector<uint8_t >& binary) {
285- Base64Encoder encoder;
290+ static Base64Encoder encoder;
286291 return (encoder.encode (binary));
287292}
288293
289294void
290295decodeBase64 (const std::string& encoded_str, std::vector<uint8_t >& output) {
291- Base64Encoder encoder;
296+ static Base64Encoder encoder;
292297 encoder.decode (encoded_str, output);
293298}
294299
295300string
296301encodeBase32Hex (const vector<uint8_t >& binary) {
297- Base32HexEncoder encoder;
302+ static Base32HexEncoder encoder;
298303 return (encoder.encode (binary));
299304}
300305
301306void
302307decodeBase32Hex (const std::string& encoded_str, std::vector<uint8_t >& output) {
303- Base32HexEncoder encoder;
308+ static Base32HexEncoder encoder;
304309 encoder.decode (encoded_str, output);
305310}
306311
307312string
308313encodeHex (const vector<uint8_t >& binary) {
309- Base16Encoder encoder;
314+ static Base16Encoder encoder;
310315 return (encoder.encode (binary));
311316}
312317
313318void
314319decodeHex (const string& encoded_str, vector<uint8_t >& output) {
315- Base16Encoder encoder;
320+ static Base16Encoder encoder;
316321 encoder.decode (encoded_str, output);
317322}
318323
324+
319325} // namespace encode
320326} // namespace util
321327} // namespace isc
0 commit comments