// Copyright 2013-2016 Glyn Matthews. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef NETWORK_DETAIL_URI_PERCENT_ENCODE_INC #define NETWORK_DETAIL_URI_PERCENT_ENCODE_INC #include #include #include #include #include namespace network { namespace detail { inline optional percent_encode(std::string::const_iterator it) { try { char output = '\0'; detail::decode_char(it, &output); return output; } catch (percent_decoding_error &) { return optional(); } } template struct percent_encoded_to_upper { percent_encoded_to_upper() : count(0) {} void operator()(typename String::value_type &c) { if (c == '%') { count = 2; } else if (count > 0) { c = std::toupper(c, std::locale()); --count; } } unsigned count; }; template Iter decode_encoded_unreserved_chars(Iter first, Iter last) { // unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" // clang-format off const auto is_unreserved = [](char c) { return std::isalnum(c, std::locale()) || '-' == c || '.' == c || '_' == c || '~' == c; }; // clang-format on auto it = first, it2 = first; while (it != last) { if (*it == '%') { const auto sfirst = it; const auto opt_char = percent_encode(sfirst); if (opt_char && is_unreserved(*opt_char)) { *it2 = *opt_char; ++it; ++it; } else { *it2 = *it; } } else { *it2 = *it; } ++it; ++it2; } return it2; } } // namespace detail } // namespace network #endif // NETWORK_DETAIL_URI_PERCENT_ENCODE_INC