| /* |
| 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. |
| */ |
| ////////////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // Implement the classes for the various types of hash keys we support. |
| // |
| #pragma once |
| |
| #include <string> |
| #include <sstream> |
| #include <stdexcept> |
| |
| #include "ts/ts.h" |
| |
| #include "regex_helper.h" |
| #include "lulu.h" |
| |
| // Possible operators that we support (at least partially) |
| enum MatcherOps { |
| MATCH_EQUAL, |
| MATCH_LESS_THEN, |
| MATCH_GREATER_THEN, |
| MATCH_REGULAR_EXPRESSION, |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // Base class for all Matchers (this is also the interface) |
| // |
| class Matcher |
| { |
| public: |
| explicit Matcher(const MatcherOps op) : _op(op) { TSDebug(PLUGIN_NAME_DBG, "Calling CTOR for Matcher"); } |
| virtual ~Matcher() { TSDebug(PLUGIN_NAME_DBG, "Calling DTOR for Matcher"); } |
| |
| // noncopyable |
| Matcher(const Matcher &) = delete; |
| void operator=(const Matcher &) = delete; |
| |
| protected: |
| const MatcherOps _op; |
| }; |
| |
| // Template class to match on various types of data |
| template <class T> class Matchers : public Matcher |
| { |
| public: |
| explicit Matchers<T>(const MatcherOps op) : Matcher(op), _data() {} |
| // Getters / setters |
| const T & |
| get() const |
| { |
| return _data; |
| }; |
| |
| void |
| setRegex(const std::string & /* data ATS_UNUSED */) |
| { |
| if (!helper.setRegexMatch(_data)) { |
| std::stringstream ss; |
| ss << _data; |
| TSError("[%s] Invalid regex: failed to precompile: %s", PLUGIN_NAME, ss.str().c_str()); |
| TSDebug(PLUGIN_NAME, "Invalid regex: failed to precompile: %s", ss.str().c_str()); |
| throw std::runtime_error("Malformed regex"); |
| } else { |
| TSDebug(PLUGIN_NAME, "Regex precompiled successfully"); |
| } |
| } |
| |
| void |
| setRegex(const unsigned int /* t ATS_UNUSED */) |
| { |
| return; |
| } |
| void |
| setRegex(const TSHttpStatus /* t ATS_UNUSED */) |
| { |
| return; |
| } |
| |
| void |
| set(const T &d) |
| { |
| _data = d; |
| if (_op == MATCH_REGULAR_EXPRESSION) { |
| setRegex(d); |
| } |
| } |
| |
| // Evaluate this matcher |
| bool |
| test(const T &t) const |
| { |
| switch (_op) { |
| case MATCH_EQUAL: |
| return test_eq(t); |
| break; |
| case MATCH_LESS_THEN: |
| return test_lt(t); |
| break; |
| case MATCH_GREATER_THEN: |
| return test_gt(t); |
| break; |
| case MATCH_REGULAR_EXPRESSION: |
| return test_reg(t); |
| break; |
| default: |
| // ToDo: error |
| break; |
| } |
| return false; |
| } |
| |
| private: |
| void |
| debug_helper(const T &t, const char *op, bool r) const |
| { |
| std::stringstream ss; |
| |
| ss << '"' << t << '"' << op << '"' << _data << '"' << " -> " << r; |
| TSDebug(PLUGIN_NAME, "\ttesting: %s", ss.str().c_str()); |
| } |
| |
| // For basic types |
| bool |
| test_eq(const T &t) const |
| { |
| bool r = (t == _data); |
| |
| if (TSIsDebugTagSet(PLUGIN_NAME)) { |
| debug_helper(t, " == ", r); |
| } |
| return r; |
| } |
| |
| bool |
| test_lt(const T &t) const |
| { |
| bool r = (t < _data); |
| |
| if (TSIsDebugTagSet(PLUGIN_NAME)) { |
| debug_helper(t, " < ", r); |
| } |
| return r; |
| } |
| |
| bool |
| test_gt(const T &t) const |
| { |
| bool r = t > _data; |
| |
| if (TSIsDebugTagSet(PLUGIN_NAME)) { |
| debug_helper(t, " > ", r); |
| } |
| return r; |
| } |
| |
| bool |
| test_reg(const unsigned int /* t ATS_UNUSED */) const |
| { |
| // Not supported |
| return false; |
| } |
| |
| bool |
| test_reg(const TSHttpStatus /* t ATS_UNUSED */) const |
| { |
| // Not supported |
| return false; |
| } |
| |
| bool |
| test_reg(const std::string &t) const |
| { |
| int ovector[OVECCOUNT]; |
| |
| TSDebug(PLUGIN_NAME, "Test regular expression %s : %s", _data.c_str(), t.c_str()); |
| if (helper.regexMatch(t.c_str(), t.length(), ovector) > 0) { |
| TSDebug(PLUGIN_NAME, "Successfully found regular expression match"); |
| return true; |
| } |
| return false; |
| } |
| |
| T _data; |
| regexHelper helper; |
| }; |