blob: 0e292c0df110063039c0e1a40ed0ed6bc5dd32b3 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/optimization_guide/url_pattern_with_wildcards.h"
#include "base/logging.h"
#include "base/macros.h"
namespace {
// Splits |url_pattern| by wildcard, and returns the split patterns.
std::vector<std::string> SplitURLPattern(const std::string& url_pattern) {
std::vector<std::string> split_subpatterns;
size_t search_start_pos = 0;
while (true) {
size_t next_wildcard_pos = url_pattern.find('*', search_start_pos);
if (next_wildcard_pos == std::string::npos) {
// Add rest of the |url_pattern|, and return.
split_subpatterns.push_back(url_pattern.substr(search_start_pos));
return split_subpatterns;
}
if (next_wildcard_pos == search_start_pos) {
// Skip empty subpatterns. This catches any explicit wildcards at the
// front and back, as well as repeated consecutive wildcards.
search_start_pos++;
continue;
}
// Add the subpattern from |search_start_pos| (inclusive) to
// |next_wildcard_pos| (not inclusive).
split_subpatterns.push_back(url_pattern.substr(
search_start_pos, next_wildcard_pos - search_start_pos));
search_start_pos = next_wildcard_pos + 1;
}
return split_subpatterns;
}
} // namespace
namespace optimization_guide {
URLPatternWithWildcards::URLPatternWithWildcards(const std::string& url_pattern)
: split_subpatterns_(SplitURLPattern(url_pattern)) {
DCHECK(!url_pattern.empty());
DCHECK(!split_subpatterns_.empty());
}
URLPatternWithWildcards::~URLPatternWithWildcards() = default;
bool URLPatternWithWildcards::Matches(const std::string& url_string) const {
// Determine if |url_string| matches |this| pattern. This determination is
// made by searching all the subpatterns in |split_subpatterns_| while
// traversing |url_string| . If all the subpatterns in |split_subpatterns_|
// are found in |url_string|, then it's a match.
// Note that each of the subpattern belonging in |split_subpatterns_| should
// be located in |url_string| after the location of the previous subpattern.
//
// Example: If |split_subpatterns_| is {"example.com", "foo"}, and
// |url_string| is example.com/pages/foo.jpg, then first "example.com" is
// searched in |url_string| beginning at index 0. Then, "foo" is searched in
// |url_string| beginning at index 10.
size_t search_start_pos = 0;
for (const auto& subpattern : split_subpatterns_) {
DCHECK_GE(url_string.length(), search_start_pos);
search_start_pos = url_string.find(subpattern, search_start_pos);
// |url_string| does not match |this| pattern.
if (search_start_pos == std::string::npos)
return false;
// Move the search position for next subpattern to be after where
// |subpattern| ends in |url_string|.
search_start_pos += subpattern.length();
}
return true;
}
} // namespace optimization_guide