Line data Source code
1 : /**
2 : Copyright (c) 2016-2022 Roman Katuntsev <sbkarr@stappler.org>
3 : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
4 :
5 : Permission is hereby granted, free of charge, to any person obtaining a copy
6 : of this software and associated documentation files (the "Software"), to deal
7 : in the Software without restriction, including without limitation the rights
8 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 : copies of the Software, and to permit persons to whom the Software is
10 : furnished to do so, subject to the following conditions:
11 :
12 : The above copyright notice and this permission notice shall be included in
13 : all copies or substantial portions of the Software.
14 :
15 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 : THE SOFTWARE.
22 : **/
23 :
24 : #include "SPString.h"
25 :
26 : namespace STAPPLER_VERSIONIZED stappler::base64 {
27 :
28 : using Reader = BytesViewNetwork;
29 :
30 : // Mapping from 6 bit pattern to ASCII character.
31 : static const char * base64EncodeLookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
32 :
33 : // Definition for "masked-out" areas of the base64DecodeLookup mapping
34 : #define xx 65
35 :
36 : static unsigned char base64DecodeLookup[256] = {
37 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
38 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
39 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, 62, xx, 63,
40 : 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
41 : xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
42 : 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, 63,
43 : xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
44 : 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
45 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
46 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
47 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
48 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
49 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
50 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
51 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
52 : xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
53 : };
54 :
55 : // Fundamental sizes of the binary and base64 encode/decode units in bytes
56 : constexpr int BinaryUnit = 3;
57 : constexpr int Base64Unit = 4;
58 :
59 5225 : size_t encodeSize(size_t l) { return ((l / BinaryUnit) + ((l % BinaryUnit) ? 1 : 0)) * Base64Unit; }
60 300 : size_t decodeSize(size_t l) { return ((l+Base64Unit-1) / Base64Unit) * BinaryUnit; }
61 :
62 : template <typename Callback>
63 1150 : static void make_encode(const CoderSource &data, const Callback &cb) {
64 1150 : Reader inputBuffer(data.data(), data.size());
65 1150 : auto length = inputBuffer.size();
66 :
67 1150 : size_t i = 0;
68 131704 : for (; i + BinaryUnit - 1 < length; i += BinaryUnit) {
69 : // Inner loop: turn 48 bytes into 64 base64 characters
70 130554 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
71 130554 : cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
72 130554 : cb(base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) | ((inputBuffer[i + 2] & 0xC0) >> 6)]);
73 130554 : cb(base64EncodeLookup[inputBuffer[i + 2] & 0x3F]);
74 : }
75 :
76 1150 : if (i + 1 < length) {
77 : // Handle the single '=' case
78 494 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
79 494 : cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
80 494 : cb(base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]);
81 494 : cb('=');
82 656 : } else if (i < length) {
83 : // Handle the double '=' case
84 259 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
85 259 : cb(base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]);
86 259 : cb('=');
87 259 : cb('=');
88 : }
89 1150 : }
90 :
91 : template <typename Callback>
92 3050 : static void make_decode(const CoderSource &data, const Callback &cb) {
93 3050 : StringView inputBuffer((char *)data.data(), data.size());
94 3050 : auto length = inputBuffer.size();
95 :
96 3050 : size_t i = 0;
97 222456 : while (i < length) {
98 : // Accumulate 4 valid characters (ignore everything else)
99 : unsigned char accumulated[Base64Unit];
100 219406 : size_t accumulateIndex = 0;
101 884709 : while (i < length) {
102 882475 : unsigned char decode = base64DecodeLookup[(unsigned char)inputBuffer[i++]];
103 882475 : if (decode != xx) {
104 874397 : accumulated[accumulateIndex] = decode;
105 874397 : accumulateIndex++;
106 874397 : if (accumulateIndex == Base64Unit) {
107 217172 : break;
108 : }
109 : }
110 : }
111 :
112 219406 : if(accumulateIndex >= 2)
113 219381 : cb((accumulated[0] << 2) | (accumulated[1] >> 4));
114 219406 : if(accumulateIndex >= 3)
115 218463 : cb((accumulated[1] << 4) | (accumulated[2] >> 2));
116 219406 : if(accumulateIndex >= 4)
117 217172 : cb((accumulated[2] << 6) | accumulated[3]);
118 : }
119 3050 : }
120 :
121 : #undef xx
122 :
123 125 : typename memory::PoolInterface::StringType __encode_pool(const CoderSource &source) {
124 125 : typename memory::PoolInterface::StringType output;
125 125 : output.reserve(encodeSize(source.size()));
126 125 : make_encode(source, [&] (const char &c) {
127 2500 : output.push_back(c);
128 2500 : });
129 125 : return output;
130 0 : }
131 500 : typename memory::StandartInterface::StringType __encode_std(const CoderSource &source) {
132 500 : typename memory::StandartInterface::StringType output;
133 500 : output.reserve(encodeSize(source.size()));
134 500 : make_encode(source, [&] (const char &c) {
135 234300 : output.push_back(c);
136 234300 : });
137 500 : return output;
138 0 : }
139 :
140 : template <>
141 125 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
142 125 : return __encode_pool(source);
143 : }
144 :
145 : template <>
146 500 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
147 500 : return __encode_std(source);
148 : }
149 :
150 25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
151 25 : make_encode(source, [&] (const char &c) {
152 600 : stream << c;
153 600 : });
154 25 : }
155 :
156 450 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
157 450 : make_encode(source, cb);
158 450 : }
159 :
160 50 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
161 50 : size_t accum = 0;
162 50 : if (bsize < encodeSize(source.size())) {
163 25 : make_encode(source, [&] (const char &c) {
164 600 : if (accum < bsize) {
165 250 : buf[accum++] = c;
166 : }
167 600 : });
168 : } else {
169 25 : make_encode(source, [&] (const char &c) {
170 600 : buf[accum++] = c;
171 600 : });
172 : }
173 50 : return accum;
174 : }
175 :
176 1125 : typename memory::PoolInterface::BytesType __decode_pool(const CoderSource &source) {
177 1125 : typename memory::PoolInterface::BytesType output;
178 1125 : output.reserve(encodeSize(source.size()));
179 1125 : make_decode(source, [&] (const uint8_t &c) {
180 33150 : output.emplace_back(c);
181 33150 : });
182 1125 : return output;
183 0 : }
184 1575 : typename memory::StandartInterface::BytesType __decode_std(const CoderSource &source) {
185 1575 : typename memory::StandartInterface::BytesType output;
186 1575 : output.reserve(encodeSize(source.size()));
187 1575 : make_decode(source, [&] (const uint8_t &c) {
188 541491 : output.emplace_back(c);
189 541491 : });
190 1575 : return output;
191 0 : }
192 50 : void decode(std::basic_ostream<char> &stream, const CoderSource &source) {
193 50 : make_decode(source, [&] (const uint8_t &c) {
194 800 : stream << char(c);
195 800 : });
196 50 : }
197 :
198 200 : void decode(const Callback<void(uint8_t)> &cb, const CoderSource &source) {
199 200 : make_decode(source, cb);
200 200 : }
201 :
202 100 : size_t decode(uint8_t *buf, size_t bsize, const CoderSource &source) {
203 100 : size_t accum = 0;
204 100 : if (bsize < decodeSize(source.size())) {
205 50 : make_decode(source, [&] (const uint8_t &c) {
206 800 : if (accum < bsize) {
207 500 : buf[accum++] = c;
208 : }
209 800 : });
210 : } else {
211 50 : make_decode(source, [&] (const uint8_t &c) {
212 800 : buf[accum++] = c;
213 800 : });
214 : }
215 100 : return accum;
216 : }
217 :
218 : }
219 :
220 : namespace STAPPLER_VERSIONIZED stappler::base64url {
221 :
222 : using Reader = BytesViewNetwork;
223 :
224 : // Mapping from 6 bit pattern to ASCII character.
225 : static const char * base64EncodeLookup = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
226 :
227 : // Fundamental sizes of the binary and base64 encode/decode units in bytes
228 : constexpr int BinaryUnit = 3;
229 : constexpr int Base64Unit = 4;
230 :
231 : template <typename Callback>
232 6775 : static void make_encode(const CoderSource &data, const Callback &cb) {
233 6775 : Reader inputBuffer(data.data(), data.size());
234 6775 : auto length = inputBuffer.size();
235 :
236 6775 : size_t i = 0;
237 60730 : for (; i + BinaryUnit - 1 < length; i += BinaryUnit) {
238 : // Inner loop: turn 48 bytes into 64 base64 characters
239 53955 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
240 53955 : cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
241 53955 : cb(base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2) | ((inputBuffer[i + 2] & 0xC0) >> 6)]);
242 53955 : cb(base64EncodeLookup[inputBuffer[i + 2] & 0x3F]);
243 : }
244 :
245 6775 : if (i + 1 < length) {
246 : // Handle the single '=' case
247 541 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
248 541 : cb(base64EncodeLookup[((inputBuffer[i] & 0x03) << 4) | ((inputBuffer[i + 1] & 0xF0) >> 4)]);
249 541 : cb(base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2]);
250 6234 : } else if (i < length) {
251 : // Handle the double '=' case
252 879 : cb(base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2]);
253 879 : cb(base64EncodeLookup[(inputBuffer[i] & 0x03) << 4]);
254 : }
255 6775 : }
256 :
257 675 : typename memory::PoolInterface::StringType __encode_pool(const CoderSource &source) {
258 675 : typename memory::PoolInterface::StringType output;
259 675 : output.reserve(encodeSize(source.size()));
260 675 : make_encode(source, [&] (const char &c) {
261 21825 : output.push_back(c);
262 21825 : });
263 675 : return output;
264 0 : }
265 1125 : typename memory::StandartInterface::StringType __encode_std(const CoderSource &source) {
266 1125 : typename memory::StandartInterface::StringType output;
267 1125 : output.reserve(encodeSize(source.size()));
268 1125 : make_encode(source, [&] (const char &c) {
269 117751 : output.push_back(c);
270 117751 : });
271 1125 : return output;
272 0 : }
273 :
274 : template <>
275 675 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
276 675 : return __encode_pool(source);
277 : }
278 :
279 : template <>
280 1125 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
281 1125 : return __encode_std(source);
282 : }
283 :
284 25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
285 25 : make_encode(source, [&] (const char &c) {
286 550 : stream << c;
287 550 : });
288 25 : }
289 :
290 4900 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
291 4900 : make_encode(source, cb);
292 4900 : }
293 :
294 50 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
295 50 : size_t accum = 0;
296 50 : if (bsize < encodeSize(source.size())) {
297 25 : make_encode(source, [&] (const char &c) {
298 550 : if (accum < bsize) {
299 250 : buf[accum++] = c;
300 : }
301 550 : });
302 : } else {
303 25 : make_encode(source, [&] (const char &c) {
304 550 : buf[accum++] = c;
305 550 : });
306 : }
307 50 : return accum;
308 : }
309 :
310 : }
311 :
312 : namespace STAPPLER_VERSIONIZED stappler::base16 {
313 :
314 : using Reader = BytesViewNetwork;
315 :
316 : static const char* s_hexTable_lower[256] = {
317 : "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f", "10", "11",
318 : "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f", "20", "21", "22", "23",
319 : "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f", "30", "31", "32", "33", "34", "35",
320 : "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f", "40", "41", "42", "43", "44", "45", "46", "47",
321 : "48", "49", "4a", "4b", "4c", "4d", "4e", "4f", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
322 : "5a", "5b", "5c", "5d", "5e", "5f", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b",
323 : "6c", "6d", "6e", "6f", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d",
324 : "7e", "7f", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
325 : "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f", "a0", "a1",
326 : "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af", "b0", "b1", "b2", "b3",
327 : "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf", "c0", "c1", "c2", "c3", "c4", "c5",
328 : "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
329 : "d8", "d9", "da", "db", "dc", "dd", "de", "df", "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
330 : "ea", "eb", "ec", "ed", "ee", "ef", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb",
331 : "fc", "fd", "fe", "ff"
332 : };
333 :
334 : static const char* s_hexTable_upper[256] = {
335 : "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11",
336 : "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23",
337 : "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35",
338 : "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47",
339 : "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
340 : "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B",
341 : "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D",
342 : "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
343 : "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1",
344 : "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3",
345 : "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5",
346 : "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
347 : "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9",
348 : "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB",
349 : "FC", "FD", "FE", "FF"
350 : };
351 :
352 : static uint8_t s_decTable[256] = {
353 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
354 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0,
355 : 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
356 : 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
357 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
358 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
359 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
360 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
361 : };
362 :
363 25 : size_t encodeSize(size_t length) { return length * 2; }
364 25 : size_t decodeSize(size_t length) { return length / 2; }
365 :
366 100 : const char *charToHex(const char &c, bool upper) {
367 100 : return upper ? s_hexTable_upper[reinterpret_cast<const uint8_t &>(c)] : s_hexTable_lower[reinterpret_cast<const uint8_t &>(c)];
368 : }
369 :
370 3250 : uint8_t hexToChar(const char &c) {
371 3250 : return s_decTable[reinterpret_cast<const uint8_t &>(c)];
372 : }
373 :
374 1625 : uint8_t hexToChar(const char &c, const char &d) {
375 1625 : return (hexToChar(c) << 4) | hexToChar(d);
376 : }
377 :
378 :
379 : template <>
380 25 : auto encode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::StringType {
381 25 : Reader inputBuffer(source.data(), source.size());
382 25 : const auto length = inputBuffer.size();
383 :
384 25 : memory::PoolInterface::StringType output; output.resize(length * 2);
385 225 : for (size_t i = 0; i < length; ++i) {
386 200 : memcpy(output.data() + i * 2, s_hexTable_lower[inputBuffer[i]], 2);
387 : }
388 50 : return output;
389 0 : }
390 :
391 : template <>
392 177 : auto encode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::StringType {
393 177 : Reader inputBuffer(source.data(), source.size());
394 177 : const auto length = inputBuffer.size();
395 :
396 177 : memory::StandartInterface::StringType output; output.reserve(length * 2);
397 5047 : for (size_t i = 0; i < length; ++i) {
398 4870 : output.append(s_hexTable_lower[inputBuffer[i]], 2);
399 : }
400 :
401 354 : return output;
402 0 : }
403 :
404 25 : void encode(std::basic_ostream<char> &stream, const CoderSource &source) {
405 25 : const auto length = source.size();
406 425 : for (size_t i = 0; i < length; ++i) {
407 400 : stream << s_hexTable_lower[source[i]];
408 : }
409 25 : }
410 25 : void encode(const Callback<void(char)> &cb, const CoderSource &source) {
411 25 : const auto length = source.size();
412 425 : for (size_t i = 0; i < length; ++i) {
413 400 : auto &t = s_hexTable_lower[source[i]];
414 400 : cb(t[0]);
415 400 : cb(t[1]);
416 : }
417 25 : }
418 17337 : size_t encode(char *buf, size_t bsize, const CoderSource &source) {
419 17337 : Reader inputBuffer(source.data(), source.size());
420 17334 : const auto length = inputBuffer.size();
421 :
422 17334 : size_t bytes = 0;
423 156194 : for (size_t i = 0; i < length; ++i) {
424 138871 : if (bytes + 2 <= bsize) {
425 138871 : memcpy(buf + i * 2, s_hexTable_lower[inputBuffer[i]], 2);
426 138860 : bytes += 2;
427 : } else {
428 0 : break;
429 : }
430 : }
431 17323 : return bytes;
432 : }
433 :
434 : template <>
435 25 : auto decode<memory::PoolInterface>(const CoderSource &source) -> typename memory::PoolInterface::BytesType {
436 25 : const auto length = source.size();
437 25 : memory::PoolInterface::BytesType outputBuffer; outputBuffer.reserve(length / 2);
438 425 : for (size_t i = 0; i < length; i += 2) {
439 400 : outputBuffer.push_back(
440 400 : (s_decTable[source[i]] << 4)
441 400 : | s_decTable[source[i + 1]]);
442 : }
443 25 : return outputBuffer;
444 0 : }
445 :
446 : template <>
447 1175 : auto decode<memory::StandartInterface>(const CoderSource &source) -> typename memory::StandartInterface::BytesType {
448 1175 : const auto length = source.size();
449 1175 : memory::StandartInterface::BytesType outputBuffer; outputBuffer.reserve(length / 2);
450 61400 : for (size_t i = 0; i < length; i += 2) {
451 60225 : outputBuffer.push_back(
452 60225 : (s_decTable[source[i]] << 4)
453 60225 : | s_decTable[source[i + 1]]);
454 : }
455 1175 : return outputBuffer;
456 0 : }
457 :
458 25 : void decode(std::basic_ostream<char> &stream, const CoderSource &source) {
459 25 : const auto length = source.size();
460 :
461 425 : for (size_t i = 0; i < length; i += 2) {
462 : stream << char(
463 400 : (s_decTable[source[i]] << 4)
464 400 : | s_decTable[source[i + 1]]);
465 : }
466 25 : }
467 25 : void decode(const Callback<void(uint8_t)> &cb, const CoderSource &source) {
468 25 : const auto length = source.size();
469 :
470 425 : for (size_t i = 0; i < length; i += 2) {
471 400 : cb(uint8_t(
472 400 : (s_decTable[source[i]] << 4)
473 400 : | s_decTable[source[i + 1]]));
474 : }
475 25 : }
476 25 : size_t decode(uint8_t *buf, size_t bsize, const CoderSource &source) {
477 25 : const auto length = source.size();
478 :
479 25 : size_t bytes = 0;
480 425 : for (size_t i = 0; i < length; i += 2) {
481 400 : if (bytes + 1 <= bsize) {
482 400 : buf[bytes] = uint8_t(
483 400 : (s_decTable[source[i]] << 4)
484 400 : | s_decTable[source[i + 1]]);
485 400 : ++ bytes;
486 : } else {
487 0 : break;
488 : }
489 : }
490 25 : return bytes;
491 : }
492 :
493 : }
|