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