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