/** @file A brief file description @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. */ /***************************************************************************** * * HostLookup.h - Interface to general purpose matcher * * ****************************************************************************/ #pragma once #include #include #include #include #include // HostLookup constants constexpr int HOST_TABLE_DEPTH = 3; // Controls the max number of levels in the logical tree constexpr int HOST_ARRAY_MAX = 8; // Sets the fixed array size class CharIndex; class HostArray; // The data in the HostMatcher tree is pointers to HostBranches. No duplicates keys permitted in the tree. To handle // multiple data items bound the same key, the HostBranch has the lead_indexs array which stores pointers (in the form // of array indexes) to HostLeaf structs // // There is HostLeaf struct for each data item put into the table // struct HostLeaf { /// Type of leaf. enum Type { LEAF_INVALID, HOST_PARTIAL, HOST_COMPLETE, DOMAIN_COMPLETE, DOMAIN_PARTIAL, }; Type type{LEAF_INVALID}; ///< Type of this leaf instance. std::string match; // Contains a copy of the match data bool isNot{false}; // used by any fasssst path ... void *opaque_data{nullptr}; // Data associated with this leaf HostLeaf() {} HostLeaf(std::string_view name, void *data) : opaque_data(data) { if (!name.empty() && name.front() == '!') { name.remove_prefix(1); isNot = true; } match.assign(name); } }; struct HostBranch { /// Branch type. enum Type { HOST_TERMINAL, HOST_HASH, HOST_INDEX, HOST_ARRAY, }; using HostTable = std::unordered_map; using LeafIndices = std::vector; /// Type of data in this branch. union Level { std::nullptr_t _nil; ///< HOST_TERMINAL HostTable *_table; ///< HOST_HASH CharIndex *_index; ///< HOST_INDEX HostArray *_array; ///< HOST_ARRAY void *_ptr; ///< As generic pointer. }; ~HostBranch(); int level_idx{0}; // what level in the tree. the root is level 0 Type type{HOST_TERMINAL}; // tells what kind of data structure is next_level is Level next_level{nullptr}; // opaque pointer to lookup structure LeafIndices leaf_indices; // HostLeaf indices. std::string key; }; // // End Host Lookup Helper types // struct HostLookupState { HostBranch *cur{nullptr}; int table_level{0}; int array_index{0}; std::string_view hostname; ///< Original host name. std::string_view hostname_stub; ///< Remaining host name to search. }; class HostLookup { public: using LeafArray = std::vector; using PrintFunc = std::function; HostLookup(std::string_view name); void NewEntry(std::string_view match_data, bool domain_record, void *opaque_data_in); void AllocateSpace(int num_entries); bool Match(std::string_view host); bool Match(std::string_view host, void **opaque_ptr); bool MatchFirst(std::string_view host, HostLookupState *s, void **opaque_ptr); bool MatchNext(HostLookupState *s, void **opaque_ptr); void Print(PrintFunc const &f) const; void Print() const; LeafArray * get_leaf_array() { return &leaf_array; } private: using HostTable = HostBranch::HostTable; using LeafIndices = HostBranch::LeafIndices; void TableInsert(std::string_view match_data, int index, bool domain_record); HostBranch *TableNewLevel(HostBranch *from, std::string_view level_data); HostBranch *InsertBranch(HostBranch *insert_in, std::string_view level_data); HostBranch *FindNextLevel(HostBranch *from, std::string_view level_data, bool bNotProcess = false); bool MatchArray(HostLookupState *s, void **opaque_ptr, LeafIndices &array, bool host_done); void PrintHostBranch(const HostBranch *hb, PrintFunc const &f) const; HostBranch root; // The top of the search tree LeafArray leaf_array; // array of all leaves in tree std::string matcher_name; // Used for Debug/Warning/Error messages };