| 10 | #include <system_error> |
| 11 | |
| 12 | std::string UrlDecode(std::string_view url_encoded) |
| 13 | { |
| 14 | std::string res; |
| 15 | res.reserve(url_encoded.size()); |
| 16 | |
| 17 | for (size_t i = 0; i < url_encoded.size(); ++i) { |
| 18 | char c = url_encoded[i]; |
| 19 | // Special handling for percent which should be followed by two hex digits |
| 20 | // representing an octet values, see RFC 3986, Section 2.1 Percent-Encoding |
| 21 | if (c == '%' && i + 2 < url_encoded.size()) { |
| 22 | unsigned int decoded_value{0}; |
| 23 | auto [p, ec] = std::from_chars(url_encoded.data() + i + 1, url_encoded.data() + i + 3, decoded_value, 16); |
| 24 | |
| 25 | // Only if there is no error and the pointer is set to the end of |
| 26 | // the string, we can be sure both characters were valid hex |
| 27 | if (ec == std::errc{} && p == url_encoded.data() + i + 3) { |
| 28 | res += static_cast<char>(decoded_value); |
| 29 | // Next two characters are part of the percent encoding |
| 30 | i += 2; |
| 31 | continue; |
| 32 | } |
| 33 | // In case of invalid percent encoding, add the '%' and continue |
| 34 | } |
| 35 | res += c; |
| 36 | } |
| 37 | |
| 38 | return res; |
| 39 | } |
| 40 | |
| 41 | std::string UrlEncode(std::string_view str) |
| 42 | { |