| 2480 | } |
| 2481 | |
| 2482 | static void percent_decode(string_t& str) { |
| 2483 | typename string_t::iterator s2 = str.begin(), s3 = s2, s4 = s2; |
| 2484 | for (typename string_t::const_pointer s1 = str.c_str(), end = s1 + str.size(); s1 != end; ++s1, ++s2) |
| 2485 | if (traits::to_wchar(*s1) != L'%') |
| 2486 | *s2 = *s1; |
| 2487 | else { |
| 2488 | char_t d1 = *++s1; |
| 2489 | *s2 = char_t((hex_digit_value(d1) << 4) + hex_digit_value(*++s1)); |
| 2490 | } |
| 2491 | // Decode UTF-8 string in-place |
| 2492 | while (s3 != s2) { |
| 2493 | unsigned u = *s3; |
| 2494 | if (u < 0x80) |
| 2495 | ; |
| 2496 | else if ((u >> 5) == 6) { |
| 2497 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2498 | u = ((u & 0x1F) << 6) + (*s3 & 0x3F); |
| 2499 | } |
| 2500 | else if ((u >> 4) == 0xE) { |
| 2501 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2502 | u = ((u & 0xF) << 12) + ((*s3 & 0x3F) << 6); |
| 2503 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2504 | u += *s3 & 0x3F; |
| 2505 | } |
| 2506 | else if ((u >> 3) == 0x1E) { |
| 2507 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2508 | u = ((u & 7) << 18) + ((*s3 & 0x3F) << 12); |
| 2509 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2510 | u += (*s3 & 0x3F) << 6; |
| 2511 | if (++s3 == s2 || (*s3 & 0xC0) != 0x80) continue; |
| 2512 | u += *s3 & 0x3F; |
| 2513 | } |
| 2514 | else { |
| 2515 | ++s3; |
| 2516 | continue; |
| 2517 | } |
| 2518 | s4 = traits::from_utf32(u, s4); |
| 2519 | ++s3; |
| 2520 | } |
| 2521 | if (s4 != str.end()) str.resize(s4 - str.begin()); |
| 2522 | } |
| 2523 | |
| 2524 | static string_t right(const string_t& str, typename string_t::size_type n) { return str.substr(str.size() - n); } |
| 2525 | }; |