5#ifndef ADA_URL_SEARCH_PARAMS_INL_H
6#define ADA_URL_SEARCH_PARAMS_INL_H
22template <
typename T, ada::url_search_params_iter_type Type>
25inline void url_search_params::reset(std::string_view input) {
30inline void url_search_params::initialize(std::string_view input) {
31 if (!input.empty() && input.front() ==
'?') {
32 input.remove_prefix(1);
35 auto process_key_value = [&](
const std::string_view current) {
36 auto equal = current.find(
'=');
38 if (equal == std::string_view::npos) {
39 std::string name(current);
40 std::ranges::replace(name,
'+',
' ');
41 params.emplace_back(unicode::percent_decode(name, name.find(
'%')),
"");
43 std::string name(current.substr(0, equal));
44 std::string value(current.substr(equal + 1));
46 std::ranges::replace(name,
'+',
' ');
47 std::ranges::replace(value,
'+',
' ');
49 params.emplace_back(unicode::percent_decode(name, name.find(
'%')),
50 unicode::percent_decode(value, value.find(
'%')));
54 while (!input.empty()) {
55 auto ampersand_index = input.find(
'&');
57 if (ampersand_index == std::string_view::npos) {
59 process_key_value(input);
62 }
else if (ampersand_index != 0) {
63 process_key_value(input.substr(0, ampersand_index));
66 input.remove_prefix(ampersand_index + 1);
71 const std::string_view value) {
72 params.emplace_back(key, value);
78 const std::string_view key) {
79 auto entry = std::ranges::find_if(
80 params, [&key](
const auto ¶m) {
return param.first == key; });
82 if (entry == params.end()) {
90 const std::string_view key) {
91 std::vector<std::string> out{};
93 for (
auto ¶m : params) {
94 if (param.first == key) {
95 out.emplace_back(param.second);
103 auto entry = std::ranges::find_if(
104 params, [&key](
const auto ¶m) {
return param.first == key; });
105 return entry != params.end();
109 std::string_view value)
noexcept {
110 auto entry = std::ranges::find_if(params, [&key, &value](
const auto ¶m) {
111 return param.first == key && param.second == value;
113 return entry != params.end();
119 for (
size_t i = 0; i < params.size(); i++) {
120 auto key = ada::unicode::percent_encode(params[i].first, character_set);
121 auto value = ada::unicode::percent_encode(params[i].second, character_set);
124 std::ranges::replace(key,
' ',
'+');
125 std::ranges::replace(value,
' ',
'+');
138 const std::string_view value) {
139 const auto find = [&key](
const auto ¶m) {
return param.first == key; };
141 auto it = std::ranges::find_if(params, find);
143 if (it == params.end()) {
144 params.emplace_back(key, value);
147 params.erase(std::remove_if(std::next(it), params.end(), find),
153 std::erase_if(params,
154 [&key](
const auto ¶m) {
return param.first == key; });
158 const std::string_view value) {
159 std::erase_if(params, [&key, &value](
const auto ¶m) {
160 return param.first == key && param.second == value;
166 std::ranges::stable_sort(params, [](
const key_value_pair &lhs,
167 const key_value_pair &rhs) {
169 uint32_t low_surrogate1 = 0, low_surrogate2 = 0;
170 while ((i < lhs.first.size() || low_surrogate1 != 0) &&
171 (j < rhs.first.size() || low_surrogate2 != 0)) {
172 uint32_t codePoint1 = 0, codePoint2 = 0;
174 if (low_surrogate1 != 0) {
175 codePoint1 = low_surrogate1;
178 uint8_t c1 = uint8_t(lhs.first[i]);
182 }
else if (c1 <= 0xDF) {
183 codePoint1 = ((c1 & 0x1F) << 6) | (uint8_t(lhs.first[i + 1]) & 0x3F);
185 }
else if (c1 <= 0xEF) {
186 codePoint1 = ((c1 & 0x0F) << 12) |
187 ((uint8_t(lhs.first[i + 1]) & 0x3F) << 6) |
188 (uint8_t(lhs.first[i + 2]) & 0x3F);
191 codePoint1 = ((c1 & 0x07) << 18) |
192 ((uint8_t(lhs.first[i + 1]) & 0x3F) << 12) |
193 ((uint8_t(lhs.first[i + 2]) & 0x3F) << 6) |
194 (uint8_t(lhs.first[i + 3]) & 0x3F);
197 codePoint1 -= 0x10000;
198 uint16_t high_surrogate = uint16_t(0xD800 + (codePoint1 >> 10));
199 low_surrogate1 = uint16_t(0xDC00 + (codePoint1 & 0x3FF));
200 codePoint1 = high_surrogate;
204 if (low_surrogate2 != 0) {
205 codePoint2 = low_surrogate2;
208 uint8_t c2 = uint8_t(rhs.first[j]);
212 }
else if (c2 <= 0xDF) {
213 codePoint2 = ((c2 & 0x1F) << 6) | (uint8_t(rhs.first[j + 1]) & 0x3F);
215 }
else if (c2 <= 0xEF) {
216 codePoint2 = ((c2 & 0x0F) << 12) |
217 ((uint8_t(rhs.first[j + 1]) & 0x3F) << 6) |
218 (uint8_t(rhs.first[j + 2]) & 0x3F);
221 codePoint2 = ((c2 & 0x07) << 18) |
222 ((uint8_t(rhs.first[j + 1]) & 0x3F) << 12) |
223 ((uint8_t(rhs.first[j + 2]) & 0x3F) << 6) |
224 (uint8_t(rhs.first[j + 3]) & 0x3F);
226 codePoint2 -= 0x10000;
227 uint16_t high_surrogate = uint16_t(0xD800 + (codePoint2 >> 10));
228 low_surrogate2 = uint16_t(0xDC00 + (codePoint2 & 0x3FF));
229 codePoint2 = high_surrogate;
233 if (codePoint1 != codePoint2) {
234 return (codePoint1 < codePoint2);
237 return (j < rhs.first.size() || low_surrogate2 != 0);
259template <
typename T, url_search_params_iter_type Type>
261 return pos < params.params.size();
269 return params.params[pos++].first;
277 return params.params[pos++].second;
281inline std::optional<key_value_view_pair>
286 return params.params[pos++];
Definitions of the character sets used by unicode functions.
constexpr uint8_t WWW_FORM_URLENCODED_PERCENT_ENCODE[32]
url_search_params_iter< std::string_view, url_search_params_iter_type::VALUES > url_search_params_values_iter
url_search_params_iter< key_value_view_pair, url_search_params_iter_type::ENTRIES > url_search_params_entries_iter
url_search_params_iter< std::string_view, url_search_params_iter_type::KEYS > url_search_params_keys_iter
std::optional< std::string_view > next()
void set(std::string_view key, std::string_view value)
std::vector< std::string > get_all(std::string_view key)
void remove(std::string_view key)
url_search_params_entries_iter get_entries()
std::string to_string() const
url_search_params_keys_iter get_keys()
size_t size() const noexcept
void append(std::string_view key, std::string_view value)
url_search_params_values_iter get_values()
std::optional< std::string_view > get(std::string_view key)
bool has(std::string_view key) noexcept
Definitions for all unicode specific functions.
Declaration for the URL Search Params.