Mercurial > hg > piper-cpp
comparison ext/base-n/include/basen.hpp @ 258:048ab927a952
Update base-n code from upstream
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Fri, 09 Mar 2018 09:09:20 +0000 |
parents | bf8e3e7dd7de |
children |
comparison
equal
deleted
inserted
replaced
257:944e699a4068 | 258:048ab927a952 |
---|---|
50 void decode_b64(Iter1 start, Iter1 end, Iter2 out); | 50 void decode_b64(Iter1 start, Iter1 end, Iter2 out); |
51 | 51 |
52 namespace impl | 52 namespace impl |
53 { | 53 { |
54 | 54 |
55 const int ERROR = -1; | 55 const int Error = -1; |
56 | 56 |
57 namespace { | 57 namespace { |
58 | 58 |
59 char extract_partial_bits(char value, unsigned int start_bit, unsigned int bits_count) | 59 char extract_partial_bits(char value, size_t start_bit, size_t bits_count) |
60 { | 60 { |
61 assert(start_bit + bits_count < 8); | 61 assert(start_bit + bits_count < 8); |
62 // shift extracted bits to the beginning of the byte | 62 // shift extracted bits to the beginning of the byte |
63 char t1 = value >> (8 - bits_count - start_bit); | 63 char t1 = value >> (8 - bits_count - start_bit); |
64 // mask out bits on the left | 64 // mask out bits on the left |
65 char t2 = t1 & ~(-1U << bits_count); | 65 char t2 = t1 & ~(0xff << bits_count); |
66 return t2; | 66 return t2; |
67 } | 67 } |
68 | 68 |
69 char extract_overlapping_bits(char previous, char next, unsigned int start_bit, unsigned int bits_count) | 69 char extract_overlapping_bits(char previous, char next, size_t start_bit, size_t bits_count) |
70 { | 70 { |
71 assert(start_bit + bits_count < 16); | 71 assert(start_bit + bits_count < 16); |
72 int bits_count_in_previous = 8 - start_bit; | 72 size_t bits_count_in_previous = 8 - start_bit; |
73 int bits_count_in_next = bits_count - bits_count_in_previous; | 73 size_t bits_count_in_next = bits_count - bits_count_in_previous; |
74 char t1 = previous << bits_count_in_next; | 74 char t1 = previous << bits_count_in_next; |
75 char t2 = next >> (8 - bits_count_in_next) & ~(-1U << bits_count_in_next) ; | 75 char t2 = next >> (8 - bits_count_in_next) & ~(0xff << bits_count_in_next) ; |
76 return (t1 | t2) & ~(-1U << bits_count); | 76 return (t1 | t2) & ~(0xff << bits_count); |
77 } | 77 } |
78 | 78 |
79 } | 79 } |
80 | 80 |
81 struct b16_conversion_traits | 81 struct b16_conversion_traits |
97 if (c >= '0' && c <= '9') { | 97 if (c >= '0' && c <= '9') { |
98 return c - '0'; | 98 return c - '0'; |
99 } else if (c >= 'A' && c <= 'F') { | 99 } else if (c >= 'A' && c <= 'F') { |
100 return c - 'A' + 10; | 100 return c - 'A' + 10; |
101 } | 101 } |
102 return ERROR; | 102 return Error; |
103 } | 103 } |
104 }; | 104 }; |
105 | 105 |
106 struct b32_conversion_traits | 106 struct b32_conversion_traits |
107 { | 107 { |
122 if (c >= 'A' && c <= 'Z') { | 122 if (c >= 'A' && c <= 'Z') { |
123 return c - 'A'; | 123 return c - 'A'; |
124 } else if (c >= '2' && c <= '7') { | 124 } else if (c >= '2' && c <= '7') { |
125 return c - '2' + 26; | 125 return c - '2' + 26; |
126 } | 126 } |
127 return ERROR; | 127 return Error; |
128 } | 128 } |
129 }; | 129 }; |
130 | 130 |
131 struct b64_conversion_traits | 131 struct b64_conversion_traits |
132 { | 132 { |
154 } else if (c == '+') { | 154 } else if (c == '+') { |
155 return c - '+' + alph_len * 2 + 10; | 155 return c - '+' + alph_len * 2 + 10; |
156 } else if (c == '/') { | 156 } else if (c == '/') { |
157 return c - '/' + alph_len * 2 + 11; | 157 return c - '/' + alph_len * 2 + 11; |
158 } | 158 } |
159 return ERROR; | 159 return Error; |
160 } | 160 } |
161 }; | 161 }; |
162 | 162 |
163 template<class ConversionTraits, class Iter1, class Iter2> | 163 template<class ConversionTraits, class Iter1, class Iter2> |
164 void decode(Iter1 start, Iter1 end, Iter2 out) | 164 void decode(Iter1 start, Iter1 end, Iter2 out) |
165 { | 165 { |
166 Iter1 iter = start; | 166 Iter1 iter = start; |
167 int output_current_bit = 0; | 167 size_t output_current_bit = 0; |
168 char buffer = 0; | 168 char buffer = 0; |
169 | 169 |
170 while (iter != end) { | 170 while (iter != end) { |
171 if (std::isspace(*iter)) { | 171 if (std::isspace(*iter)) { |
172 ++iter; | 172 ++iter; |
173 continue; | 173 continue; |
174 } | 174 } |
175 char value = ConversionTraits::decode(*iter); | 175 char value = ConversionTraits::decode(*iter); |
176 if (value == ERROR) { | 176 if (value == Error) { |
177 // malformed data, but let's go on... | 177 // malformed data, but let's go on... |
178 ++iter; | 178 ++iter; |
179 continue; | 179 continue; |
180 } | 180 } |
181 unsigned int bits_in_current_byte = std::min<int>(output_current_bit + ConversionTraits::group_length(), 8) - output_current_bit; | 181 size_t bits_in_current_byte = std::min<size_t>(output_current_bit + ConversionTraits::group_length(), 8) - output_current_bit; |
182 if (bits_in_current_byte == ConversionTraits::group_length()) { | 182 if (bits_in_current_byte == ConversionTraits::group_length()) { |
183 // the value fits within current byte, so we can extract it directly | 183 // the value fits within current byte, so we can extract it directly |
184 buffer |= value << (8 - output_current_bit - ConversionTraits::group_length()); | 184 buffer |= value << (8 - output_current_bit - ConversionTraits::group_length()); |
185 output_current_bit += ConversionTraits::group_length(); | 185 output_current_bit += ConversionTraits::group_length(); |
186 // check if we filled up current byte completely; in such case we flush output and continue | 186 // check if we filled up current byte completely; in such case we flush output and continue |
189 buffer = 0; | 189 buffer = 0; |
190 output_current_bit = 0; | 190 output_current_bit = 0; |
191 } | 191 } |
192 } else { | 192 } else { |
193 // the value spans across the current and the next byte | 193 // the value spans across the current and the next byte |
194 int bits_in_next_byte = ConversionTraits::group_length() - bits_in_current_byte; | 194 size_t bits_in_next_byte = ConversionTraits::group_length() - bits_in_current_byte; |
195 // fill the current byte and flush it to our output | 195 // fill the current byte and flush it to our output |
196 buffer |= value >> bits_in_next_byte; | 196 buffer |= value >> bits_in_next_byte; |
197 *out++ = buffer; | 197 *out++ = buffer; |
198 buffer = 0; | 198 buffer = 0; |
199 // save the remainder of our value in the buffer; it will be flushed | 199 // save the remainder of our value in the buffer; it will be flushed |
207 | 207 |
208 template<class ConversionTraits, class Iter1, class Iter2> | 208 template<class ConversionTraits, class Iter1, class Iter2> |
209 void encode(Iter1 start, Iter1 end, Iter2 out) | 209 void encode(Iter1 start, Iter1 end, Iter2 out) |
210 { | 210 { |
211 Iter1 iter = start; | 211 Iter1 iter = start; |
212 int start_bit = 0; | 212 size_t start_bit = 0; |
213 bool has_backlog = false; | 213 bool has_backlog = false; |
214 char backlog = 0; | 214 char backlog = 0; |
215 | 215 |
216 while (has_backlog || iter != end) { | 216 while (has_backlog || iter != end) { |
217 if (!has_backlog) { | 217 if (!has_backlog) { |
285 } | 285 } |
286 | 286 |
287 } // bn | 287 } // bn |
288 | 288 |
289 #endif // BASEN_HPP | 289 #endif // BASEN_HPP |
290 |