Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 0 additions & 80 deletions plugins/header_rewrite/matcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,86 +26,6 @@

#include "matcher.h"

static bool
match_with_modifiers(std::string_view rhs, std::string_view lhs, CondModifiers mods)
{
// Case-aware equality
static auto equals = [](std::string_view a, std::string_view b, CondModifiers mods) -> bool {
if (has_modifier(mods, CondModifiers::MOD_NOCASE)) {
return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](char c1, char c2) {
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2));
});
}
return a == b;
};

// Case-aware substring search
static auto contains = [](std::string_view haystack, std::string_view needle, CondModifiers mods) -> bool {
if (!has_modifier(mods, CondModifiers::MOD_NOCASE)) {
return haystack.find(needle) != std::string_view::npos;
}
auto it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) {
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2));
});
return it != haystack.end();
};

if (has_modifier(mods, CondModifiers::MOD_EXT)) {
auto dot = rhs.rfind('.');
return dot != std::string_view::npos && dot + 1 < rhs.size() && equals(rhs.substr(dot + 1), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_SUF)) {
return rhs.size() >= lhs.size() && equals(rhs.substr(rhs.size() - lhs.size()), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_PRE)) {
return rhs.size() >= lhs.size() && equals(rhs.substr(0, lhs.size()), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_MID)) {
return contains(rhs, lhs, mods);
}

return equals(rhs, lhs, mods);
}

// Special case for strings, to allow for insensitive case comparisons for std::string matchers.
template <>
bool
Matchers<std::string>::test_eq(const std::string &t) const
{
std::string_view lhs = std::get<std::string>(_data);
std::string_view rhs = t;
bool result = match_with_modifiers(rhs, lhs, _mods);

if (pi_dbg_ctl.on()) {
debug_helper(t, " == ", result);
}

return result;
}

template <>
bool
Matchers<std::string>::test_set(const std::string &t) const
{
TSAssert(std::holds_alternative<std::set<std::string>>(_data));
std::string_view rhs = t;

for (const auto &entry : std::get<std::set<std::string>>(_data)) {
if (match_with_modifiers(rhs, entry, _mods)) {
if (pi_dbg_ctl.on()) {
debug_helper(t, " ∈ ", true);
}
return true;
}
}

debug_helper(t, " ∈ ", false);
return false;
}

template <>
bool
Matchers<const sockaddr *>::test(const sockaddr *const &addr, const Resources & /* Not used */) const
Expand Down
80 changes: 80 additions & 0 deletions plugins/header_rewrite/matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,83 @@ template <class T> class Matchers : public Matcher
std::variant<T, std::set<T>, swoc::IPRangeSet, regexHelper> _data;
CondModifiers _mods = CondModifiers::NONE;
};

static bool
match_with_modifiers(std::string_view rhs, std::string_view lhs, CondModifiers mods)
{
// Case-aware equality
static auto equals = [](std::string_view a, std::string_view b, CondModifiers mods) -> bool {
if (has_modifier(mods, CondModifiers::MOD_NOCASE)) {
return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin(), [](char c1, char c2) {
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2));
});
}
return a == b;
};

// Case-aware substring search
static auto contains = [](std::string_view haystack, std::string_view needle, CondModifiers mods) -> bool {
if (!has_modifier(mods, CondModifiers::MOD_NOCASE)) {
return haystack.find(needle) != std::string_view::npos;
}
auto it = std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) {
return std::tolower(static_cast<unsigned char>(c1)) == std::tolower(static_cast<unsigned char>(c2));
});
return it != haystack.end();
};

if (has_modifier(mods, CondModifiers::MOD_EXT)) {
auto dot = rhs.rfind('.');
return dot != std::string_view::npos && dot + 1 < rhs.size() && equals(rhs.substr(dot + 1), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_SUF)) {
return rhs.size() >= lhs.size() && equals(rhs.substr(rhs.size() - lhs.size()), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_PRE)) {
return rhs.size() >= lhs.size() && equals(rhs.substr(0, lhs.size()), lhs, mods);
}

if (has_modifier(mods, CondModifiers::MOD_MID)) {
return contains(rhs, lhs, mods);
}

return equals(rhs, lhs, mods);
}

// Special case for strings, to allow for insensitive case comparisons for std::string matchers.
template <>
inline bool
Matchers<std::string>::test_eq(const std::string &t) const
{
std::string_view lhs = std::get<std::string>(_data);
std::string_view rhs = t;
bool result = match_with_modifiers(rhs, lhs, _mods);

if (pi_dbg_ctl.on()) {
debug_helper(t, " == ", result);
}

return result;
}

template <>
inline bool
Matchers<std::string>::test_set(const std::string &t) const
{
TSAssert(std::holds_alternative<std::set<std::string>>(_data));
std::string_view rhs = t;

for (const auto &entry : std::get<std::set<std::string>>(_data)) {
if (match_with_modifiers(rhs, entry, _mods)) {
if (pi_dbg_ctl.on()) {
debug_helper(t, " ∈ ", true);
}
return true;
}
}

debug_helper(t, " ∈ ", false);
return false;
}