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