CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
encoding.cpp
Go to the documentation of this file.
1
9#include "string/encoding.h"
10
11#if defined(__clang__)
12#pragma clang diagnostic push
13#pragma clang diagnostic ignored "-Wdeprecated" // Clang: warning: 'codecvt' is deprecated
14#endif
15
16#include <algorithm>
17#include <cassert>
18#include <codecvt>
19#include <locale>
20#include <vector>
21
22namespace CppCommon {
23
24std::string Encoding::ToUTF8(std::wstring_view wstr)
25{
26#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
27 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
28 return convert.to_bytes((char16_t*)wstr.data(), (char16_t*)wstr.data() + wstr.size());
29#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
30 std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
31 return convert.to_bytes(wstr.data(), wstr.data() + wstr.size());
32#elif defined(_WIN32) || defined(_WIN64)
33 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
34 return convert.to_bytes(wstr.data(), wstr.data() + wstr.size());
35#endif
36}
37
38std::wstring Encoding::FromUTF8(std::string_view str)
39{
40#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__MINGW64__)
41 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
42 auto tmp = convert.from_bytes(str.data(), str.data() + str.size());
43 return std::wstring(tmp.data(), tmp.data() + tmp.size());
44#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
45 std::wstring_convert<std::codecvt_utf8<wchar_t>> convert;
46 return convert.from_bytes(str.data(), str.data() + str.size());
47#elif defined(_WIN32) || defined(_WIN64)
48 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> convert;
49 return convert.from_bytes(str.data(), str.data() + str.size());
50#endif
51}
52
53std::u16string Encoding::UTF8toUTF16(std::string_view str)
54{
55#if defined(_MSC_VER)
56 std::wstring_convert<std::codecvt_utf8_utf16<uint16_t>, uint16_t> convert;
57 auto tmp = convert.from_bytes(str.data(), str.data() + str.size());
58 return std::u16string(tmp.data(), tmp.data() + tmp.size());
59#else
60 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
61 return convert.from_bytes(str.data(), str.data() + str.size());
62#endif
63}
64
65std::u32string Encoding::UTF8toUTF32(std::string_view str)
66{
67#if defined(_MSC_VER)
68 std::wstring_convert<std::codecvt_utf8<uint32_t>, uint32_t> convert;
69 auto tmp = convert.from_bytes(str.data(), str.data() + str.size());
70 return std::u32string(tmp.data(), tmp.data() + tmp.size());
71#else
72 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
73 return convert.from_bytes(str.data(), str.data() + str.size());
74#endif
75}
76
77std::string Encoding::UTF16toUTF8(std::u16string_view str)
78{
79#if defined(_MSC_VER)
80 std::wstring_convert<std::codecvt_utf8_utf16<uint16_t>, uint16_t> convert;
81 return convert.to_bytes((uint16_t*)str.data(), (uint16_t*)str.data() + str.size());
82#else
83 std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
84 return convert.to_bytes(str.data(), str.data() + str.size());
85#endif
86}
87
88std::u32string Encoding::UTF16toUTF32(std::u16string_view str)
89{
90 std::string bytes;
91 bytes.reserve(str.size() * 2);
92
93 for (const char16_t ch : str)
94 {
95 bytes.push_back((uint8_t)(ch / 256));
96 bytes.push_back((uint8_t)(ch % 256));
97 }
98
99#if defined(_MSC_VER)
100 std::wstring_convert<std::codecvt_utf16<uint32_t>, uint32_t> convert;
101 auto tmp = convert.from_bytes(bytes);
102 return std::u32string(tmp.data(), tmp.data() + tmp.size());
103#else
104 std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
105 return convert.from_bytes(bytes);
106#endif
107}
108
109std::string Encoding::UTF32toUTF8(std::u32string_view str)
110{
111#if defined(_MSC_VER)
112 std::wstring_convert<std::codecvt_utf8<uint32_t>, uint32_t> convert;
113 return convert.to_bytes((uint32_t*)str.data(), (uint32_t*)str.data() + str.size());
114#else
115 std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
116 return convert.to_bytes(str.data(), str.data() + str.size());
117#endif
118}
119
120std::u16string Encoding::UTF32toUTF16(std::u32string_view str)
121{
122#if defined(_MSC_VER)
123 std::wstring_convert<std::codecvt_utf16<uint32_t>, uint32_t> convert;
124 std::string bytes = convert.to_bytes((uint32_t*)str.data(), (uint32_t*)str.data() + str.size());
125#else
126 std::wstring_convert<std::codecvt_utf16<char32_t>, char32_t> convert;
127 std::string bytes = convert.to_bytes(str.data(), str.data() + str.size());
128#endif
129
130 std::u16string result;
131 result.reserve(bytes.size() / 2);
132
133 for (size_t i = 0; i < bytes.size(); i += 2)
134 result.push_back((char16_t)((uint8_t)(bytes[i]) * 256 + (uint8_t)(bytes[i + 1])));
135
136 return result;
137}
138
139std::string Encoding::Base16Encode(std::string_view str)
140{
141 const char base16[] = "0123456789ABCDEF";
142
143 size_t ilength = str.length();
144 size_t olength = ilength * 2;
145
146 std::string result;
147 result.resize(olength, 0);
148
149 for (size_t i = 0, j = 0; i < ilength;)
150 {
151 uint8_t ch = (uint8_t)str[i++];
152
153 result[j++] = base16[(ch & 0xF0) >> 4];
154 result[j++] = base16[(ch & 0x0F) >> 0];
155 }
156
157 return result;
158}
159
160std::string Encoding::Base16Decode(std::string_view str)
161{
162 static const unsigned char base16[128] =
163 {
164 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
165 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
166 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
167 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
168 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
169 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
170 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
171 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
172 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF,
173 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
174 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
175 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
176 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF,
177 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
178 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
179 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
180 };
181
182 size_t ilength = str.length();
183
184 assert(((ilength % 2) == 0) && "Invalid Base16 sting!");
185 if ((ilength % 2) != 0)
186 return "";
187
188 size_t olength = ilength / 2;
189
190 std::string result;
191 result.resize(olength, 0);
192
193 for (size_t i = 0, j = 0; i < ilength;)
194 {
195 uint8_t a = (uint8_t)str[i++];
196 uint8_t b = (uint8_t)str[i++];
197
198 // Validate ASCII
199 assert(((a < 0x80) && (b < 0x80)) && "Invalid Base16 content!");
200 if ((a >= 0x80) || (b >= 0x80))
201 return "";
202
203 // Convert ASCII to Base16
204 a = base16[a];
205 b = base16[b];
206
207 result[j++] = ((a << 4) | b);
208 }
209
210 return result;
211}
212
213std::string Encoding::Base32Encode(std::string_view str)
214{
215 const char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567=";
216
217 size_t ilength = str.length();
218 size_t olength = ((ilength / 5) * 8) + ((ilength % 5) ? 8 : 0);
219
220 std::string result;
221 result.resize(olength, 0);
222
223 for (size_t i = 0, j = 0; i < ilength;)
224 {
225 size_t block = ((ilength - i) < 5 ? (ilength - i) : 5);
226 uint8_t n1, n2, n3, n4, n5, n6, n7, n8;
227 n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = 0;
228
229 switch (block)
230 {
231 case 5:
232 n8 = (((uint8_t)str[i + 4] & 0x1F) >> 0);
233 n7 = (((uint8_t)str[i + 4] & 0xE0) >> 5);
234 case 4:
235 n7 |= (((uint8_t)str[i + 3] & 0x03) << 3);
236 n6 = (((uint8_t)str[i + 3] & 0x7C) >> 2);
237 n5 = (((uint8_t)str[i + 3] & 0x80) >> 7);
238 case 3:
239 n5 |= (((uint8_t)str[i + 2] & 0x0F) << 1);
240 n4 = (((uint8_t)str[i + 2] & 0xF0) >> 4);
241 case 2:
242 n4 |= (((uint8_t)str[i + 1] & 0x01) << 4);
243 n3 = (((uint8_t)str[i + 1] & 0x3E) >> 1);
244 n2 = (((uint8_t)str[i + 1] & 0xC0) >> 6);
245 case 1:
246 n2 |= (((uint8_t)str[i + 0] & 0x07) << 2);
247 n1 = (((uint8_t)str[i + 0] & 0xF8) >> 3);
248 break;
249 default:
250 assert(false && "Invalid Base32 operation!");
251 }
252 i += block;
253
254 // Validate
255 assert((n1 <= 31) && "Invalid Base32 n1 value!");
256 assert((n2 <= 31) && "Invalid Base32 n2 value!" );
257 assert((n3 <= 31) && "Invalid Base32 n3 value!" );
258 assert((n4 <= 31) && "Invalid Base32 n4 value!" );
259 assert((n5 <= 31) && "Invalid Base32 n5 value!" );
260 assert((n6 <= 31) && "Invalid Base32 n6 value!" );
261 assert((n7 <= 31) && "Invalid Base32 n7 value!" );
262 assert((n8 <= 31) && "Invalid Base32 n8 value!" );
263
264 // Padding
265 switch (block)
266 {
267 case 1: n3 = n4 = 32;
268 case 2: n5 = 32;
269 case 3: n6 = n7 = 32;
270 case 4: n8 = 32;
271 case 5:
272 break;
273 default:
274 assert(false && "Invalid Base32 operation!");
275 }
276
277 // 8 outputs
278 result[j++] = base32[n1];
279 result[j++] = base32[n2];
280 result[j++] = base32[n3];
281 result[j++] = base32[n4];
282 result[j++] = base32[n5];
283 result[j++] = base32[n6];
284 result[j++] = base32[n7];
285 result[j++] = base32[n8];
286 }
287
288 return result;
289}
290
291std::string Encoding::Base32Decode(std::string_view str)
292{
293 static const unsigned char base32[128] =
294 {
295 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
296 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
297 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
298 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
299 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
300 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
301 0xFF, 0xFF, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
302 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0xFF, 0xFF,
303 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
304 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
305 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
306 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
307 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
308 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
309 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
310 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
311 };
312
313 size_t ilength = str.length();
314
315 assert(((ilength % 8) == 0) && "Invalid Base32 sting!");
316 if ((ilength % 8) != 0)
317 return "";
318
319 size_t olength = (ilength / 8) * 5;
320
321 std::string result;
322 result.resize(olength, 0);
323
324 for (size_t i = 0, j = 0; i < ilength;)
325 {
326 // 8 inputs
327 uint8_t n1 = (uint8_t)str[i++];
328 uint8_t n2 = (uint8_t)str[i++];
329 uint8_t n3 = (uint8_t)str[i++];
330 uint8_t n4 = (uint8_t)str[i++];
331 uint8_t n5 = (uint8_t)str[i++];
332 uint8_t n6 = (uint8_t)str[i++];
333 uint8_t n7 = (uint8_t)str[i++];
334 uint8_t n8 = (uint8_t)str[i++];
335
336 // Validate ASCII
337 assert(((n1 < 0x80) && (n2 < 0x80) && (n3 < 0x80) && (n4 < 0x80) && (n5 < 0x80) && (n6 < 0x80) && (n7 < 0x80) && (n8 < 0x80)) && "Invalid Base32 content!");
338 if ((n1 >= 0x80) || (n2 >= 0x80) || (n3 >= 0x80) || (n4 >= 0x80) || (n5 >= 0x80) || (n6 >= 0x80) || (n7 >= 0x80) || (n8 >= 0x80))
339 return "";
340
341 // Convert ASCII to Base32
342 n1 = base32[n1];
343 n2 = base32[n2];
344 n3 = base32[n3];
345 n4 = base32[n4];
346 n5 = base32[n5];
347 n6 = base32[n6];
348 n7 = base32[n7];
349 n8 = base32[n8];
350
351 // Validate Base32
352 assert(((n1 <= 31) && (n2 <= 31)) && "Invalid Base32 content!");
353 if ((n1 > 31) || (n2 > 31))
354 return "";
355
356 // The following can be padding
357 assert(((n3 <= 32) && (n4 <= 32) && (n5 <= 32) && (n6 <= 32) && (n7 <= 32) && (n8 <= 32)) && "Invalid Base32 content!");
358 if ((n3 > 32) || (n4 > 32) || (n5 > 32) || (n6 > 32) || (n7 > 32) || (n8 > 32))
359 return "";
360
361 // 5 outputs
362 result[j++] = ((n1 & 0x1f) << 3) | ((n2 & 0x1c) >> 2);
363 result[j++] = ((n2 & 0x03) << 6) | ((n3 & 0x1f) << 1) | ((n4 & 0x10) >> 4);
364 result[j++] = ((n4 & 0x0f) << 4) | ((n5 & 0x1e) >> 1);
365 result[j++] = ((n5 & 0x01) << 7) | ((n6 & 0x1f) << 2) | ((n7 & 0x18) >> 3);
366 result[j++] = ((n7 & 0x07) << 5) | ((n8 & 0x1f));
367
368 // Padding
369 if (n8 == 32)
370 {
371 result.resize(result.size() - 1);
372 assert((((n7 == 32) && (n6 == 32)) || (n7 != 32)) && "Invalid Base32 content!");
373 if (n6 == 32)
374 {
375 result.resize(result.size() - 1);
376 if (n5 == 32)
377 {
378 result.resize(result.size() - 1);
379 assert((((n4 == 32) && (n3 == 32)) || (n4 != 32)) && "Invalid Base32 content!");
380 if (n3 == 32)
381 {
382 result.resize(result.size() - 1);
383 }
384 }
385 }
386 }
387 }
388
389 return result;
390}
391
392std::string Encoding::Base64Encode(std::string_view str)
393{
394 const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
395 const size_t mods[] = { 0, 2, 1 };
396
397 size_t ilength = str.length();
398 size_t olength = 4 * ((ilength + 2) / 3);
399
400 std::string result;
401 result.resize(olength, 0);
402
403 for (size_t i = 0, j = 0; i < ilength;)
404 {
405 uint32_t octet_a = i < ilength ? (uint8_t)str[i++] : 0;
406 uint32_t octet_b = i < ilength ? (uint8_t)str[i++] : 0;
407 uint32_t octet_c = i < ilength ? (uint8_t)str[i++] : 0;
408
409 uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
410
411 result[j++] = base64[(triple >> 3 * 6) & 0x3F];
412 result[j++] = base64[(triple >> 2 * 6) & 0x3F];
413 result[j++] = base64[(triple >> 1 * 6) & 0x3F];
414 result[j++] = base64[(triple >> 0 * 6) & 0x3F];
415 }
416
417 for (size_t i = 0; i < mods[ilength % 3]; ++i)
418 result[result.size() - 1 - i] = '=';
419
420 return result;
421}
422
423std::string Encoding::Base64Decode(std::string_view str)
424{
425 static const unsigned char base64[256] =
426 {
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
428 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x3f,
430 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
432 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
433 0x00, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
434 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
438 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
439 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
442 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
443 };
444
445 size_t ilength = str.length();
446
447 if (ilength % 4 != 0)
448 return "";
449
450 size_t olength = ilength / 4 * 3;
451
452 if (str[ilength - 1] == '=') olength--;
453 if (str[ilength - 2] == '=') olength--;
454
455 std::string result;
456 result.resize(olength, 0);
457
458 for (size_t i = 0, j = 0; i < ilength;)
459 {
460 uint32_t sextet_a = str[i] == '=' ? 0 & i++ : base64[(uint8_t)str[i++]];
461 uint32_t sextet_b = str[i] == '=' ? 0 & i++ : base64[(uint8_t)str[i++]];
462 uint32_t sextet_c = str[i] == '=' ? 0 & i++ : base64[(uint8_t)str[i++]];
463 uint32_t sextet_d = str[i] == '=' ? 0 & i++ : base64[(uint8_t)str[i++]];
464
465 uint32_t triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
466
467 if (j < olength) result[j++] = (triple >> 2 * 8) & 0xFF;
468 if (j < olength) result[j++] = (triple >> 1 * 8) & 0xFF;
469 if (j < olength) result[j++] = (triple >> 0 * 8) & 0xFF;
470
471 }
472
473 return result;
474}
475
476std::string Encoding::URLEncode(std::string_view str)
477{
478 std::string result;
479 result.reserve(str.size());
480
481 for (char ch : str)
482 {
483 if (isalnum(ch) || (ch == '-') || (ch == '.') || (ch == '/') || (ch == '_') || (ch == '~'))
484 result.push_back(ch);
485 else if (ch == ' ')
486 result.push_back('+');
487 else
488 {
489 const char hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
490 result.push_back('%');
491 result.push_back(hex[(ch >> 4) & 0x0F]);
492 result.push_back(hex[(ch >> 0) & 0x0F]);
493 }
494 }
495
496 return result;
497}
498
499std::string Encoding::URLDecode(std::string_view str)
500{
501 std::string result;
502 result.reserve(str.size());
503
504 for (size_t i = 0; i < str.size(); ++i)
505 {
506 char ch = str[i];
507 if (ch == '%')
508 {
509 const char hex[] = "0123456789ABCDEF";
510
511 if (++i == str.size())
512 {
513 result.push_back('?');
514 break;
515 }
516
517 int hi = (int)(std::find(hex, hex + 16, toupper(str[i])) - hex);
518
519 if (++i == str.size())
520 {
521 result.push_back('?');
522 break;
523 }
524
525 int lo = (int)(std::find(hex, hex + 16, toupper(str[i])) - hex);
526
527 if ((hi >= 16) || (lo >= 16))
528 {
529 result.push_back('?');
530 break;
531 }
532
533 result.push_back((char)((hi << 4) + lo));
534 }
535 else if (ch == '+')
536 result.push_back(' ');
537 else
538 result.push_back(ch);
539 }
540
541 return result;
542}
543
544} // namespace CppCommon
545
546#if defined(__clang__)
547#pragma clang diagnostic pop
548#endif
static std::wstring FromUTF8(std::string_view str)
Convert UTF-8 encoded string to system wide-string.
Definition encoding.cpp:38
static std::string ToUTF8(std::wstring_view wstr)
Convert system wide-string to UTF-8 encoded string.
Definition encoding.cpp:24
static std::u32string UTF16toUTF32(std::u16string_view str)
Convert UTF-16 encoded string to UTF-32 encoded string.
Definition encoding.cpp:88
static std::u32string UTF8toUTF32(std::string_view str)
Convert UTF-8 encoded string to UTF-32 encoded string.
Definition encoding.cpp:65
static std::string Base16Decode(std::string_view str)
Base16 decode string.
Definition encoding.cpp:160
static std::string Base16Encode(std::string_view str)
Base16 encode string.
Definition encoding.cpp:139
static std::string Base64Decode(std::string_view str)
Base64 decode string.
Definition encoding.cpp:423
static std::string Base64Encode(std::string_view str)
Base64 encode string.
Definition encoding.cpp:392
static std::string URLDecode(std::string_view str)
URL decode string.
Definition encoding.cpp:499
static std::u16string UTF32toUTF16(std::u32string_view str)
Convert UTF-32 encoded string to UTF-16 encoded string.
Definition encoding.cpp:120
static std::string UTF16toUTF8(std::u16string_view str)
Convert UTF-16 encoded string to UTF-8 encoded string.
Definition encoding.cpp:77
static std::u16string UTF8toUTF16(std::string_view str)
Convert UTF-8 encoded string to UTF-16 encoded string.
Definition encoding.cpp:53
static std::string UTF32toUTF8(std::u32string_view str)
Convert UTF-32 encoded string to UTF-8 encoded string.
Definition encoding.cpp:109
static std::string URLEncode(std::string_view str)
URL encode string.
Definition encoding.cpp:476
static std::string Base32Decode(std::string_view str)
Base32 decode string.
Definition encoding.cpp:291
static std::string Base32Encode(std::string_view str)
Base32 encode string.
Definition encoding.cpp:213
Encoding utilities definition.
C++ Common project definitions.