blob: 03288741240f577c7318e7b8b6171d3e2bb05697 [file] [log] [blame]
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/base/url_search_params_view.h"
#include <algorithm>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/containers/to_vector.h"
#include "net/base/url_unescape_iterator.h"
#include "net/base/url_util.h"
#include "url/gurl.h"
namespace net {
namespace {
std::string Unescape(std::string_view view) {
const auto unescaped_range = MakeUrlUnescapeRange(view);
std::string decoded(std::ranges::begin(unescaped_range),
std::ranges::end(unescaped_range));
return decoded;
}
} // namespace
UrlSearchParamsView::UrlSearchParamsView(const GURL& url) {
for (auto it = QueryIterator(url); !it.IsAtEnd(); it.Advance()) {
// Keys are actively unescaped and copied during construction. Values are
// not copied, and are lazily unescaped on use.
params_.emplace_back(Unescape(it.GetKey()), it.GetValue());
}
}
UrlSearchParamsView::~UrlSearchParamsView() = default;
bool UrlSearchParamsView::operator==(const UrlSearchParamsView& other) const =
default;
void UrlSearchParamsView::Sort() {
if (params_.size() <= 1u) {
// No sort needed, so avoid doing any work.
return;
}
// Note: the standard specifies sorting by UTF-16 code unit. Here we are
// sorting by UTF-8 code unit, which will give a different order in some edge
// cases, but because we only care about normalizing the order, and not the
// actual order itself, it doesn't matter.
std::ranges::stable_sort(params_, std::less<>(), &KeyValue::unescaped_key);
}
void UrlSearchParamsView::DeleteAllWithNames(
const base::flat_set<std::string>& names) {
absl::erase_if(params_, [&names](const KeyValue& key_value) {
return names.contains(key_value.unescaped_key);
});
}
void UrlSearchParamsView::DeleteAllExceptWithNames(
const base::flat_set<std::string>& names) {
absl::erase_if(params_, [&names](const KeyValue& key_value) {
return !names.contains(key_value.unescaped_key);
});
}
std::vector<std::pair<std::string, std::string>>
UrlSearchParamsView::GetDecodedParamsForTesting() const {
return base::ToVector(params_, [](const KeyValue& key_value) {
return std::pair(key_value.unescaped_key,
Unescape(key_value.escaped_value));
});
}
bool UrlSearchParamsView::KeyValue::operator==(const KeyValue& other) const {
return unescaped_key == other.unescaped_key &&
EqualsAfterUrlDecoding(escaped_value, other.escaped_value);
}
} // namespace net