Mercurial > hg > piper-cpp
comparison json/base-n/include/basen.hpp @ 38:eb004c1b9579
Update base-n code from https://github.com/azawadzki/base-n
author | Chris Cannam <c.cannam@qmul.ac.uk> |
---|---|
date | Mon, 22 Aug 2016 17:16:11 +0100 |
parents | 6e8607ebad03 |
children |
comparison
equal
deleted
inserted
replaced
37:f8332b1acfc2 | 38:eb004c1b9579 |
---|---|
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; | |
56 | |
55 namespace { | 57 namespace { |
56 | 58 |
57 char extract_partial_bits(char value, unsigned int start_bit, unsigned int bits_count) | 59 char extract_partial_bits(char value, unsigned int start_bit, unsigned int bits_count) |
58 { | 60 { |
59 assert(start_bit + bits_count < 8); | 61 assert(start_bit + bits_count < 8); |
62 // shift extracted bits to the beginning of the byte | |
60 char t1 = value >> (8 - bits_count - start_bit); | 63 char t1 = value >> (8 - bits_count - start_bit); |
61 char t2 = t1 & ~(-1 << bits_count); | 64 // mask out bits on the left |
65 char t2 = t1 & ~(-1U << bits_count); | |
62 return t2; | 66 return t2; |
63 } | 67 } |
64 | 68 |
65 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, unsigned int start_bit, unsigned int bits_count) |
66 { | 70 { |
67 assert(start_bit + bits_count < 16); | 71 assert(start_bit + bits_count < 16); |
68 int bits_count_in_previous = 8 - start_bit; | 72 int bits_count_in_previous = 8 - start_bit; |
69 int bits_count_in_next = bits_count - bits_count_in_previous; | 73 int bits_count_in_next = bits_count - bits_count_in_previous; |
70 char t1 = previous << bits_count_in_next; | 74 char t1 = previous << bits_count_in_next; |
71 char t2 = next >> (8 - bits_count_in_next) & ~(-1 << bits_count_in_next) ; | 75 char t2 = next >> (8 - bits_count_in_next) & ~(-1U << bits_count_in_next) ; |
72 return (t1 | t2) & ~(-1 << bits_count); | 76 return (t1 | t2) & ~(-1U << bits_count); |
73 } | 77 } |
74 | 78 |
75 } | 79 } |
76 | 80 |
77 struct b16_conversion_traits | 81 struct b16_conversion_traits |
93 if (c >= '0' && c <= '9') { | 97 if (c >= '0' && c <= '9') { |
94 return c - '0'; | 98 return c - '0'; |
95 } else if (c >= 'A' && c <= 'F') { | 99 } else if (c >= 'A' && c <= 'F') { |
96 return c - 'A' + 10; | 100 return c - 'A' + 10; |
97 } | 101 } |
98 return -1; | 102 return ERROR; |
99 } | 103 } |
100 }; | 104 }; |
101 | 105 |
102 struct b32_conversion_traits | 106 struct b32_conversion_traits |
103 { | 107 { |
118 if (c >= 'A' && c <= 'Z') { | 122 if (c >= 'A' && c <= 'Z') { |
119 return c - 'A'; | 123 return c - 'A'; |
120 } else if (c >= '2' && c <= '7') { | 124 } else if (c >= '2' && c <= '7') { |
121 return c - '2' + 26; | 125 return c - '2' + 26; |
122 } | 126 } |
123 return -1; | 127 return ERROR; |
124 } | 128 } |
125 }; | 129 }; |
126 | 130 |
127 struct b64_conversion_traits | 131 struct b64_conversion_traits |
128 { | 132 { |
150 } else if (c == '+') { | 154 } else if (c == '+') { |
151 return c - '+' + alph_len * 2 + 10; | 155 return c - '+' + alph_len * 2 + 10; |
152 } else if (c == '/') { | 156 } else if (c == '/') { |
153 return c - '/' + alph_len * 2 + 11; | 157 return c - '/' + alph_len * 2 + 11; |
154 } | 158 } |
155 return -1; | 159 return ERROR; |
156 } | 160 } |
157 }; | 161 }; |
158 | 162 |
159 template<class ConversionTraits, class Iter1, class Iter2> | 163 template<class ConversionTraits, class Iter1, class Iter2> |
160 void decode(Iter1 start, Iter1 end, Iter2 out) | 164 void decode(Iter1 start, Iter1 end, Iter2 out) |
167 if (std::isspace(*iter)) { | 171 if (std::isspace(*iter)) { |
168 ++iter; | 172 ++iter; |
169 continue; | 173 continue; |
170 } | 174 } |
171 char value = ConversionTraits::decode(*iter); | 175 char value = ConversionTraits::decode(*iter); |
172 if (value == -1) { | 176 if (value == ERROR) { |
173 // malformed data, but let's go on... | 177 // malformed data, but let's go on... |
174 ++iter; | 178 ++iter; |
175 continue; | 179 continue; |
176 } | 180 } |
177 unsigned int bits_in_current_byte = std::min<int>(output_current_bit + ConversionTraits::group_length(), 8) - output_current_bit; | 181 unsigned int bits_in_current_byte = std::min<int>(output_current_bit + ConversionTraits::group_length(), 8) - output_current_bit; |
184 *out++ = buffer; | 188 *out++ = buffer; |
185 buffer = 0; | 189 buffer = 0; |
186 output_current_bit = 0; | 190 output_current_bit = 0; |
187 } | 191 } |
188 } else { | 192 } else { |
189 // the value span across current and next byte | 193 // the value spans across the current and the next byte |
190 int bits_in_next_byte = ConversionTraits::group_length() - bits_in_current_byte; | 194 int bits_in_next_byte = ConversionTraits::group_length() - bits_in_current_byte; |
191 // fill current byte and flush it to our output | 195 // fill the current byte and flush it to our output |
192 buffer |= value >> bits_in_next_byte; | 196 buffer |= value >> bits_in_next_byte; |
193 *out++ = buffer; | 197 *out++ = buffer; |
194 buffer = 0; | 198 buffer = 0; |
195 // 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 |
196 // during next iterations | 200 // during next iterations |