plugins/header_rewrite/matcher.cc (82 lines of code) (raw):

/* @file Implementation for creating all values. @section license License Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ #include <string> #include <algorithm> #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 { TSAssert(std::holds_alternative<swoc::IPRangeSet>(_data)); const auto &ranges = std::get<swoc::IPRangeSet>(_data); if (ranges.contains(swoc::IPAddr(addr))) { if (pi_dbg_ctl.on()) { char text[INET6_ADDRSTRLEN]; Dbg(pi_dbg_ctl, "Successfully found IP-range match on %s", getIP(addr, text)); } return true; } return false; }