From 88cea093c71331722ac935dabd0512d15c146726 Mon Sep 17 00:00:00 2001 From: Yaraslau Tamashevich Date: Thu, 11 Jan 2024 14:55:08 +0200 Subject: [PATCH] Move headers in unit module --- src/CoreVM/CoreVM.cppm | 140 +++---- src/CoreVM/TargetCodeGenerator.cpp | 2 +- src/CoreVM/ir/ConstantValue.cpp | 2 +- src/CoreVM/util.cppm | 543 +++++++++++++++++++++++++++- src/CoreVM/util/Cidr.cpp | 16 +- src/CoreVM/util/IPAddress.h | 274 -------------- src/CoreVM/util/PrefixTree-test.cpp | 3 +- src/CoreVM/util/PrefixTree.h | 103 ------ src/CoreVM/util/RegExp.cpp | 2 +- src/CoreVM/util/SuffixTree-test.cpp | 3 +- src/CoreVM/util/SuffixTree.h | 104 ------ src/CoreVM/util/unbox.h | 94 ----- src/CoreVM/vm/ConstantPool.cpp | 2 +- src/CoreVM/vm/Instruction.cpp | 2 +- src/CoreVM/vm/Runner.cpp | 3 +- 15 files changed, 621 insertions(+), 672 deletions(-) delete mode 100644 src/CoreVM/util/IPAddress.h delete mode 100644 src/CoreVM/util/PrefixTree.h delete mode 100644 src/CoreVM/util/SuffixTree.h delete mode 100644 src/CoreVM/util/unbox.h diff --git a/src/CoreVM/CoreVM.cppm b/src/CoreVM/CoreVM.cppm index 76be7ea..5910309 100644 --- a/src/CoreVM/CoreVM.cppm +++ b/src/CoreVM/CoreVM.cppm @@ -1,29 +1,38 @@ // SPDX-License-Identifier: Apache-2.0 module; -#include -#include -#include -#include +#include -#include -#include -#include +#include +#include +#include +#include +#include // memset() +#include // hash<> +#include +#include #include +#include #include +#include #include #include -#include -#include -#include + +#if defined(_WIN32) || defined(_WIN64) + #include + #include +#else + #include // ntohl(), htonl() + #include // in_addr, in6_addr +#endif export module CoreVM; export import :enums; -export import :util; +export import CoreVM.util; export namespace CoreVM::diagnostics { - class Report; +class Report; } export namespace CoreVM @@ -63,7 +72,6 @@ class MatchInstr; class RegExpGroupInstr; class CastInstr; - using Register = uint64_t; // vm using CoreNumber = int64_t; using CoreString = std::string; @@ -98,13 +106,11 @@ std::string disassemble(const Instruction* program, */ std::string disassemble(Instruction pc, size_t ip, size_t sp, const ConstantPool* cp); - std::string tos(LiteralType type); bool isArrayType(LiteralType type); LiteralType elementTypeOf(LiteralType type); - class InstructionVisitor { public: @@ -183,8 +189,6 @@ class InstructionVisitor virtual void visit(PInCidrInstr& instr) = 0; }; - - // {{{ array types class CoreArray { @@ -208,8 +212,6 @@ using CoreCidrArray = std::vector; // }}} - - struct FilePos { // {{{ FilePos(): FilePos { 1, 1, 0 } {} @@ -260,7 +262,6 @@ inline size_t operator-(const FilePos& a, const FilePos& b) } // }}} - // ExecutionEngine // VM class Runner @@ -424,8 +425,6 @@ class Runner std::list _stringGarbage; }; - - struct MatchCaseDef { //!< offset into the string pool (or regexp pool) of the associated program. @@ -447,7 +446,6 @@ class MatchDef std::vector cases; }; - class Match { public: @@ -466,7 +464,6 @@ class Match MatchDef _def; }; - /** * Provides a pool of constant that can be built dynamically during code * generation and accessed effeciently at runtime. @@ -518,8 +515,14 @@ class ConstantPool [[nodiscard]] const util::RegExp& getRegExp(size_t id) const { return _regularExpressions[id]; } [[nodiscard]] const std::vector& getIntArray(size_t id) const { return _intArrays[id]; } - [[nodiscard]] const std::vector& getStringArray(size_t id) const { return _stringArrays[id]; } - [[nodiscard]] const std::vector& getIPAddressArray(size_t id) const { return _ipaddrArrays[id]; } + [[nodiscard]] const std::vector& getStringArray(size_t id) const + { + return _stringArrays[id]; + } + [[nodiscard]] const std::vector& getIPAddressArray(size_t id) const + { + return _ipaddrArrays[id]; + } [[nodiscard]] const std::vector& getCidrArray(size_t id) const { return _cidrArrays[id]; } [[nodiscard]] const MatchDef& getMatchDef(size_t id) const { return _matchDefs[id]; } @@ -535,11 +538,20 @@ class ConstantPool } // bulk accessors - [[nodiscard]] const std::vector>& getModules() const { return _modules; } + [[nodiscard]] const std::vector>& getModules() const + { + return _modules; + } [[nodiscard]] const std::vector>& getHandlers() const { return _handlers; } [[nodiscard]] const std::vector& getMatchDefs() const { return _matchDefs; } - [[nodiscard]] const std::vector& getNativeHandlerSignatures() const { return _nativeHandlerSignatures; } - [[nodiscard]] const std::vector& getNativeFunctionSignatures() const { return _nativeFunctionSignatures; } + [[nodiscard]] const std::vector& getNativeHandlerSignatures() const + { + return _nativeHandlerSignatures; + } + [[nodiscard]] const std::vector& getNativeFunctionSignatures() const + { + return _nativeFunctionSignatures; + } void dump() const; @@ -565,7 +577,6 @@ class ConstantPool std::vector _nativeFunctionSignatures; }; - class Program { public: @@ -613,7 +624,6 @@ class Program std::vector _nativeFunctions; }; - class Handler { public: @@ -655,7 +665,6 @@ class Handler #endif }; - class Params { public: @@ -749,8 +758,6 @@ class Params std::vector _argv; }; - - enum class Attribute : unsigned { Experimental = 0x0001, // implementation is experimental, hence, parser can warn on use @@ -758,7 +765,6 @@ enum class Attribute : unsigned SideEffectFree = 0x0004, // implementation is side effect free }; - class Signature { private: @@ -796,9 +802,6 @@ class Signature LiteralType typeSignature(char ch); char signatureType(LiteralType t); - - - class NativeCallback { public: @@ -883,7 +886,6 @@ class NativeCallback void invoke(Params& args) const; }; - struct SourceLocation // {{{ { SourceLocation() = default; @@ -925,10 +927,8 @@ inline SourceLocation operator-(const SourceLocation& end, const SourceLocation& return SourceLocation(beg.filename, beg.begin, end.end); } - //!@} - class PassManager { public: @@ -966,7 +966,6 @@ class PassManager std::list> _handlerPasses; }; - /** * Defines an immutable IR value. */ @@ -1028,7 +1027,6 @@ class Value std::vector _uses; //! list of instructions that use this value. }; - class Constant: public Value { public: @@ -1066,8 +1064,6 @@ class ConstantArray: public Constant LiteralType makeArrayType(LiteralType elementType); }; - - class IRBuiltinFunction: public Constant { public: @@ -1083,14 +1079,11 @@ class IRBuiltinFunction: public Constant const NativeCallback& _native; }; - - - template class ConstantValue: public Constant { public: - ConstantValue(T value, const std::string& name = ""): Constant(Ty, name), _value(std::move(value)) {} + ConstantValue(T value, const std::string& name = ""): Constant(Ty, name), _value(std::move(value)) {} [[nodiscard]] T get() const { return _value; } @@ -1110,7 +1103,6 @@ using ConstantIP = ConstantValue; using ConstantCidr = ConstantValue; using ConstantRegExp = ConstantValue; - /** * Base class for native instructions. * @@ -1212,7 +1204,6 @@ class Instr: public Value std::vector _operands; }; - class NopInstr: public Instr { public: @@ -1671,7 +1662,6 @@ class IRBuiltinHandler: public Constant const NativeCallback& _native; }; - class IRProgram { public: @@ -1774,8 +1764,6 @@ class IRProgram friend class IRBuilder; }; - - class IRBuilder { private: @@ -2431,7 +2419,6 @@ inline const NativeCallback::DefaultValue& NativeCallback::getDefaultParamAt(siz } // }}} - using StackPointer = size_t; class TargetCodeGenerator: public InstructionVisitor @@ -2622,7 +2609,6 @@ class TargetCodeGenerator: public InstructionVisitor ConstantPool _cp; }; - /** Implements SMATCHEQ instruction. */ class MatchSame: public Match { @@ -2671,7 +2657,6 @@ class MatchRegEx: public Match std::vector> _map; }; - } // namespace CoreVM export namespace CoreVM::transform @@ -2701,7 +2686,6 @@ bool eliminateUnusedBlocks(IRHandler* handler); } // namespace CoreVM::transform - export namespace CoreVM::diagnostics { @@ -2891,8 +2875,6 @@ struct formatter: formatter } }; - - template <> struct formatter { @@ -2909,7 +2891,6 @@ struct formatter } }; - } // namespace fmt export @@ -2984,27 +2965,24 @@ export } }; - -template <> -struct fmt::formatter: fmt::formatter -{ - auto format(const CoreVM::FilePos& value, format_context& ctx) -> format_context::iterator + template <> + struct fmt::formatter: fmt::formatter { - return formatter::format(fmt::format("{}:{}", value.line, value.column), ctx); - } -}; + auto format(const CoreVM::FilePos& value, format_context& ctx) -> format_context::iterator + { + return formatter::format(fmt::format("{}:{}", value.line, value.column), ctx); + } + }; -template <> -struct fmt::formatter: fmt::formatter -{ - auto format(const CoreVM::SourceLocation& value, format_context& ctx) -> format_context::iterator + template <> + struct fmt::formatter: fmt::formatter { - if (!value.filename.empty()) - return formatter::format(fmt::format("{}:{}", value.filename, value.begin), ctx); - else - return formatter::format(fmt::format("{}", value.begin), ctx); - } -}; - - + auto format(const CoreVM::SourceLocation& value, format_context& ctx) -> format_context::iterator + { + if (!value.filename.empty()) + return formatter::format(fmt::format("{}:{}", value.filename, value.begin), ctx); + else + return formatter::format(fmt::format("{}", value.begin), ctx); + } + }; } diff --git a/src/CoreVM/TargetCodeGenerator.cpp b/src/CoreVM/TargetCodeGenerator.cpp index c0cd4dd..c853d5b 100644 --- a/src/CoreVM/TargetCodeGenerator.cpp +++ b/src/CoreVM/TargetCodeGenerator.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 module; #include -#include #include @@ -13,6 +12,7 @@ module; #include module CoreVM; +import CoreVM.util; namespace CoreVM { diff --git a/src/CoreVM/ir/ConstantValue.cpp b/src/CoreVM/ir/ConstantValue.cpp index 2fd0184..e62a84a 100644 --- a/src/CoreVM/ir/ConstantValue.cpp +++ b/src/CoreVM/ir/ConstantValue.cpp @@ -1,10 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 module; -#include #include module CoreVM; +import CoreVM.util; namespace CoreVM { diff --git a/src/CoreVM/util.cppm b/src/CoreVM/util.cppm index 64e5ded..d43b767 100644 --- a/src/CoreVM/util.cppm +++ b/src/CoreVM/util.cppm @@ -1,13 +1,514 @@ +// SPDX-License-Identifier: Apache-2.0 module; +#include + #include +#include +#include +#include // memset() +#include // hash<> +#include +#include #include -#include +#include + +#if defined(_WIN32) || defined(_WIN64) + #include + #include +#else + #include // ntohl(), htonl() + #include // in_addr, in6_addr +#endif -export module CoreVM:util; +#include +#include + +export module CoreVM.util; export namespace CoreVM::util { + +template +class UnboxedRange +{ + public: + using BoxedContainer = T; + using BoxedIterator = typename BoxedContainer::iterator; + using element_type = typename BoxedContainer::value_type::element_type; + + class iterator // NOLINT + { // {{{ + public: + using difference_type = typename BoxedContainer::iterator::difference_type; + using value_type = typename BoxedContainer::iterator::value_type::element_type; + using pointer = typename BoxedContainer::iterator::value_type::element_type*; + using reference = typename BoxedContainer::iterator::value_type::element_type&; + using iterator_category = typename BoxedContainer::iterator::iterator_category; + + explicit iterator(BoxedIterator boxed): _it(boxed) {} + + [[nodiscard]] const element_type& operator->() const { return **_it; } + [[nodiscard]] element_type& operator->() { return **_it; } + + [[nodiscard]] const element_type* operator*() const { return (*_it).get(); } + [[nodiscard]] element_type* operator*() { return (*_it).get(); } + + iterator& operator++() + { + ++_it; + return *this; + } + iterator& operator++(int) + { + ++_it; + return *this; + } + + [[nodiscard]] bool operator==(const iterator& other) const { return _it == other._it; } + [[nodiscard]] bool operator!=(const iterator& other) const { return _it != other._it; } + + private: + BoxedIterator _it; + }; // }}} + + UnboxedRange(BoxedIterator begin, BoxedIterator end): _begin(begin), _end(end) {} + explicit UnboxedRange(BoxedContainer& c): _begin(c.begin()), _end(c.end()) {} + + [[nodiscard]] iterator begin() const { return _begin; } + [[nodiscard]] iterator end() const { return _end; } + [[nodiscard]] size_t size() const + { + auto it = _begin; + size_t count = 0; + while (it != _end) + { + ++it; + ++count; + } + return count; + } + + private: + iterator _begin; + iterator _end; +}; + +/** + * Unboxes boxed element types in containers. + * + * Good examples are: + * + * \code + * std::vector> numbers; + * // ... + * for (int number: unbox(numbers)) { + * // ... juse use number here, instead of number.get() or *number. + * }; + * \endcode + */ +template +UnboxedRange unbox(BoxedContainer& boxedContainer) +{ + return UnboxedRange(boxedContainer); +} + +template +class SuffixTree +{ + public: + using Key = K; + using Elem = typename Key::value_type; + using Value = V; + + SuffixTree(); + ~SuffixTree(); + + void insert(const Key& key, const Value& value); + bool lookup(const Key& key, Value* value) const; + + private: + struct Node + { // {{{ + Node* parent; + Elem element; + std::unordered_map> children; + Value value; + + Node(): parent(nullptr), element(), children(), value() {} + Node(Node* p, Elem e): parent(p), element(e), children(), value() {} + }; // }}} + + Node _root; + + Node* acquire(Elem el, Node* n); +}; + +template +SuffixTree::SuffixTree(): _root() +{ +} + +template +SuffixTree::~SuffixTree() +{ +} + +template +void SuffixTree::insert(const Key& key, const Value& value) +{ + Node* level = &_root; + + // insert reverse + for (auto i = key.rbegin(), e = key.rend(); i != e; ++i) + level = acquire(*i, level); + + level->value = value; +} + +template +typename SuffixTree::Node* SuffixTree::acquire(Elem elem, Node* n) +{ + auto i = n->children.find(elem); + if (i != n->children.end()) + return i->second.get(); + + n->children[elem] = std::make_unique(n, elem); + return n->children[elem].get(); +} + +template +bool SuffixTree::lookup(const Key& key, Value* value) const +{ + const Node* level = &_root; + + for (auto i = key.rbegin(), e = key.rend(); i != e; ++i) + { + auto k = level->children.find(*i); + if (k == level->children.end()) + break; + + level = k->second.get(); + } + + while (level && level->parent) + { + if (level->value) + { + *value = level->value; + return true; + } + level = level->parent; + } + + return false; +} + + +template +class PrefixTree +{ + public: + using Key = K; + using Elem = typename Key::value_type; + using Value = V; + + PrefixTree(); + ~PrefixTree(); + + void insert(const Key& key, const Value& value); + bool lookup(const Key& key, Value* value) const; + + private: + struct Node + { // {{{ + Node* parent; + Elem element; + std::unordered_map> children; + Value value; + + Node(): parent(nullptr), element(), children(), value() {} + Node(Node* p, Elem e): parent(p), element(e), children(), value() {} + }; // }}} + + Node _root; + + Node* acquire(Elem el, Node* n); +}; + +// {{{ +template +PrefixTree::PrefixTree(): _root() +{ +} + +template +PrefixTree::~PrefixTree() +{ +} + +template +void PrefixTree::insert(const Key& key, const Value& value) +{ + Node* level = &_root; + + for (const auto& ke: key) + level = acquire(ke, level); + + level->value = value; +} + +template +typename PrefixTree::Node* PrefixTree::acquire(Elem elem, Node* n) +{ + auto i = n->children.find(elem); + if (i != n->children.end()) + return i->second.get(); + + n->children[elem] = std::make_unique(n, elem); + return n->children[elem].get(); +} + +template +bool PrefixTree::lookup(const Key& key, Value* value) const +{ + const Node* level = &_root; + + for (const auto& ke: key) + { + auto i = level->children.find(ke); + if (i == level->children.end()) + break; + + level = i->second.get(); + } + + while (level && level->parent) + { + if (level->value) + { + *value = level->value; + return true; + } + level = level->parent; + } + + return false; +} +// }}} + +/** + * IPv4 or IPv6 network address. + */ +class IPAddress +{ + public: + enum class Family : int + { + V4 = AF_INET, + V6 = AF_INET6, + }; + + private: + Family _family = Family::V4; + mutable char _cstr[INET6_ADDRSTRLEN] {}; + uint8_t _buf[sizeof(struct in6_addr)] {}; + + public: + IPAddress(); + explicit IPAddress(const in_addr* saddr); + explicit IPAddress(const in6_addr* saddr); + explicit IPAddress(const sockaddr_in* saddr); + explicit IPAddress(const sockaddr_in6* saddr); + explicit IPAddress(const std::string& text); + IPAddress(int family, const void* addr); + IPAddress(const std::string& text, Family v); + + IPAddress(IPAddress const&) = default; + IPAddress& operator=(const IPAddress& value); + + void assign(const std::string& text); + bool assign(const std::string& text, Family family); + + void clear(); + + Family family() const; + const void* data() const; + size_t size() const; + std::string str() const; + const char* c_str() const; + + friend bool operator==(const IPAddress& a, const IPAddress& b); + friend bool operator!=(const IPAddress& a, const IPAddress& b); +}; + +// {{{ impl +inline IPAddress::IPAddress() +{ + _family = Family::V4; + _cstr[0] = '\0'; + memset(_buf, 0, sizeof(_buf)); +} + +inline IPAddress::IPAddress(const in_addr* saddr) +{ + _family = Family::V4; + _cstr[0] = '\0'; + memcpy(_buf, saddr, sizeof(*saddr)); +} + +inline IPAddress::IPAddress(const in6_addr* saddr) +{ + _family = Family::V6; + _cstr[0] = '\0'; + memcpy(_buf, saddr, sizeof(*saddr)); +} + +inline IPAddress::IPAddress(const sockaddr_in* saddr) +{ + _family = Family::V4; + _cstr[0] = '\0'; + memcpy(_buf, &saddr->sin_addr, sizeof(saddr->sin_addr)); +} + +inline IPAddress::IPAddress(const sockaddr_in6* saddr) +{ + _family = Family::V6; + _cstr[0] = '\0'; + memcpy(_buf, &saddr->sin6_addr, sizeof(saddr->sin6_addr)); +} + +// I suggest to use a very strict IP filter to prevent spoofing or injection +inline IPAddress::IPAddress(const std::string& text) +{ + // You should use regex to parse ipv6 :) ( http://home.deds.nl/~aeron/regex/ ) + if (text.find(':') != std::string::npos) + assign(text, Family::V6); + else + assign(text, Family::V4); +} + +inline IPAddress::IPAddress(int family, const void* addr) +{ + _family = static_cast(family); + _cstr[0] = '\0'; + if (_family == Family::V6) + { + memcpy(_buf, addr, sizeof(sockaddr_in6::sin6_addr)); + } + else + { + memcpy(_buf, addr, sizeof(sockaddr_in::sin_addr)); + } +} + +inline IPAddress::IPAddress(const std::string& text, Family version) +{ + assign(text, version); +} + +inline void IPAddress::assign(const std::string& text) +{ + // You should use regex to parse ipv6 :) ( http://home.deds.nl/~aeron/regex/ ) + if (text.find(':') != std::string::npos) + { + assign(text, Family::V6); + } + else + { + assign(text, Family::V4); + } +} + +inline IPAddress& IPAddress::operator=(const IPAddress& v) +{ + if (&v == this) + return *this; + + _family = v._family; +#if defined(_WIN32) || defined(_WIN64) + strncpy_s(_cstr, sizeof(_cstr), v._cstr, sizeof(v._cstr)); +#else + strncpy(_cstr, v._cstr, sizeof(_cstr)); +#endif + memcpy(_buf, v._buf, v.size()); + + return *this; +} + +inline bool IPAddress::assign(const std::string& text, Family family) +{ + _family = family; + int rv = inet_pton(static_cast(family), text.c_str(), _buf); + if (rv <= 0) + { + if (rv < 0) + perror("inet_pton"); + else + fprintf(stderr, "IP address Not in presentation format: %s\n", text.c_str()); + + _cstr[0] = 0; + return false; + } + +#if defined(_WIN32) || defined(_WIN64) + strncpy_s(_cstr, sizeof(_cstr), text.c_str(), text.size()); +#else + strncpy(_cstr, text.c_str(), sizeof(_cstr)); +#endif + + return true; +} + +inline void IPAddress::clear() +{ + _family = Family::V4; + _cstr[0] = 0; + memset(_buf, 0, sizeof(_buf)); +} + +inline IPAddress::Family IPAddress::family() const +{ + return _family; +} + +inline const void* IPAddress::data() const +{ + return _buf; +} + +inline size_t IPAddress::size() const +{ + return _family == Family::V4 ? sizeof(in_addr) : sizeof(in6_addr); +} + +inline std::string IPAddress::str() const +{ + return c_str(); +} + +inline const char* IPAddress::c_str() const +{ + if (*_cstr == '\0') + { + inet_ntop(static_cast(_family), &_buf, _cstr, sizeof(_cstr)); + } + return _cstr; +} + +inline bool operator==(const IPAddress& a, const IPAddress& b) +{ + if (&a == &b) + return true; + + return a.family() == b.family() && memcmp(a.data(), b.data(), a.size()) == 0; +} + +inline bool operator!=(const IPAddress& a, const IPAddress& b) +{ + return !(a == b); +} + /** * @brief CIDR network notation object. * @@ -84,7 +585,6 @@ class Cidr size_t _prefix; }; - class BufferRef; class RegExp @@ -143,5 +643,42 @@ class RegExpContext mutable std::unique_ptr _regexMatch; }; +} // namespace CoreVM::util + +export +{ + + namespace std + { + template <> + struct hash<::CoreVM::util::IPAddress> + { + size_t operator()(const ::CoreVM::util::IPAddress& v) const { return *(uint32_t*) (v.data()); } + }; + } // namespace std + + template <> + struct fmt::formatter: formatter + { + using IPAddress = CoreVM::util::IPAddress; + + auto format(IPAddress const& v, format_context& ctx) -> format_context::iterator + { + return formatter::format(v.str(), ctx); + } + }; + + template <> + struct fmt::formatter>: formatter + { + using IPAddress = CoreVM::util::IPAddress; + auto format(std::optional const& v, format_context& ctx) -> format_context::iterator + { + if (v) + return formatter::format(v->str(), ctx); + else + return formatter::format("NONE", ctx); + } + }; } diff --git a/src/CoreVM/util/Cidr.cpp b/src/CoreVM/util/Cidr.cpp index 08d0783..637e23e 100644 --- a/src/CoreVM/util/Cidr.cpp +++ b/src/CoreVM/util/Cidr.cpp @@ -1,8 +1,20 @@ // SPDX-License-Identifier: Apache-2.0 module; -#include -module CoreVM; +#include + +#include + +#if defined(_WIN32) || defined(_WIN64) + #include + #include +#else + #include // ntohl(), htonl() + #include // in_addr, in6_addr +#endif + +module CoreVM.util; + namespace CoreVM::util { diff --git a/src/CoreVM/util/IPAddress.h b/src/CoreVM/util/IPAddress.h deleted file mode 100644 index 12d2d0e..0000000 --- a/src/CoreVM/util/IPAddress.h +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -#include -#include -#include -#include // memset() -#include // hash<> -#include -#include -#include - -#if defined(_WIN32) || defined(_WIN64) - #include - #include -#else - #include // ntohl(), htonl() - #include // in_addr, in6_addr -#endif - -namespace CoreVM::util -{ - -/** - * IPv4 or IPv6 network address. - */ -class IPAddress -{ - public: - enum class Family : int - { - V4 = AF_INET, - V6 = AF_INET6, - }; - - private: - Family _family = Family::V4; - mutable char _cstr[INET6_ADDRSTRLEN] {}; - uint8_t _buf[sizeof(struct in6_addr)] {}; - - public: - IPAddress(); - explicit IPAddress(const in_addr* saddr); - explicit IPAddress(const in6_addr* saddr); - explicit IPAddress(const sockaddr_in* saddr); - explicit IPAddress(const sockaddr_in6* saddr); - explicit IPAddress(const std::string& text); - IPAddress(int family, const void* addr); - IPAddress(const std::string& text, Family v); - - IPAddress(IPAddress const&) = default; - IPAddress& operator=(const IPAddress& value); - - void assign(const std::string& text); - bool assign(const std::string& text, Family family); - - void clear(); - - Family family() const; - const void* data() const; - size_t size() const; - std::string str() const; - const char* c_str() const; - - friend bool operator==(const IPAddress& a, const IPAddress& b); - friend bool operator!=(const IPAddress& a, const IPAddress& b); -}; - -// {{{ impl -inline IPAddress::IPAddress() -{ - _family = Family::V4; - _cstr[0] = '\0'; - memset(_buf, 0, sizeof(_buf)); -} - -inline IPAddress::IPAddress(const in_addr* saddr) -{ - _family = Family::V4; - _cstr[0] = '\0'; - memcpy(_buf, saddr, sizeof(*saddr)); -} - -inline IPAddress::IPAddress(const in6_addr* saddr) -{ - _family = Family::V6; - _cstr[0] = '\0'; - memcpy(_buf, saddr, sizeof(*saddr)); -} - -inline IPAddress::IPAddress(const sockaddr_in* saddr) -{ - _family = Family::V4; - _cstr[0] = '\0'; - memcpy(_buf, &saddr->sin_addr, sizeof(saddr->sin_addr)); -} - -inline IPAddress::IPAddress(const sockaddr_in6* saddr) -{ - _family = Family::V6; - _cstr[0] = '\0'; - memcpy(_buf, &saddr->sin6_addr, sizeof(saddr->sin6_addr)); -} - -// I suggest to use a very strict IP filter to prevent spoofing or injection -inline IPAddress::IPAddress(const std::string& text) -{ - // You should use regex to parse ipv6 :) ( http://home.deds.nl/~aeron/regex/ ) - if (text.find(':') != std::string::npos) - assign(text, Family::V6); - else - assign(text, Family::V4); -} - -inline IPAddress::IPAddress(int family, const void* addr) -{ - _family = static_cast(family); - _cstr[0] = '\0'; - if (_family == Family::V6) - { - memcpy(_buf, addr, sizeof(sockaddr_in6::sin6_addr)); - } - else - { - memcpy(_buf, addr, sizeof(sockaddr_in::sin_addr)); - } -} - -inline IPAddress::IPAddress(const std::string& text, Family version) -{ - assign(text, version); -} - -inline void IPAddress::assign(const std::string& text) -{ - // You should use regex to parse ipv6 :) ( http://home.deds.nl/~aeron/regex/ ) - if (text.find(':') != std::string::npos) - { - assign(text, Family::V6); - } - else - { - assign(text, Family::V4); - } -} - -inline IPAddress& IPAddress::operator=(const IPAddress& v) -{ - if (&v == this) - return *this; - - _family = v._family; -#if defined(_WIN32) || defined(_WIN64) - strncpy_s(_cstr, sizeof(_cstr), v._cstr, sizeof(v._cstr)); -#else - strncpy(_cstr, v._cstr, sizeof(_cstr)); -#endif - memcpy(_buf, v._buf, v.size()); - - return *this; -} - -inline bool IPAddress::assign(const std::string& text, Family family) -{ - _family = family; - int rv = inet_pton(static_cast(family), text.c_str(), _buf); - if (rv <= 0) - { - if (rv < 0) - perror("inet_pton"); - else - fprintf(stderr, "IP address Not in presentation format: %s\n", text.c_str()); - - _cstr[0] = 0; - return false; - } - -#if defined(_WIN32) || defined(_WIN64) - strncpy_s(_cstr, sizeof(_cstr), text.c_str(), text.size()); -#else - strncpy(_cstr, text.c_str(), sizeof(_cstr)); -#endif - - return true; -} - -inline void IPAddress::clear() -{ - _family = Family::V4; - _cstr[0] = 0; - memset(_buf, 0, sizeof(_buf)); -} - -inline IPAddress::Family IPAddress::family() const -{ - return _family; -} - -inline const void* IPAddress::data() const -{ - return _buf; -} - -inline size_t IPAddress::size() const -{ - return _family == Family::V4 ? sizeof(in_addr) : sizeof(in6_addr); -} - -inline std::string IPAddress::str() const -{ - return c_str(); -} - -inline const char* IPAddress::c_str() const -{ - if (*_cstr == '\0') - { - inet_ntop(static_cast(_family), &_buf, _cstr, sizeof(_cstr)); - } - return _cstr; -} - -inline bool operator==(const IPAddress& a, const IPAddress& b) -{ - if (&a == &b) - return true; - - return a.family() == b.family() && memcmp(a.data(), b.data(), a.size()) == 0; -} - -inline bool operator!=(const IPAddress& a, const IPAddress& b) -{ - return !(a == b); -} - -} // namespace CoreVM::util -// }}} - -namespace std -{ -template <> -struct hash<::CoreVM::util::IPAddress> -{ - size_t operator()(const ::CoreVM::util::IPAddress& v) const { return *(uint32_t*) (v.data()); } -}; -} // namespace std - -template <> -struct fmt::formatter: formatter -{ - using IPAddress = CoreVM::util::IPAddress; - - auto format(IPAddress const& v, format_context& ctx) -> format_context::iterator - { - return formatter::format(v.str(), ctx); - } -}; - -template <> -struct fmt::formatter>: formatter -{ - using IPAddress = CoreVM::util::IPAddress; - - auto format(std::optional const& v, format_context& ctx) -> format_context::iterator - { - if (v) - return formatter::format(v->str(), ctx); - else - return formatter::format("NONE", ctx); - } -}; diff --git a/src/CoreVM/util/PrefixTree-test.cpp b/src/CoreVM/util/PrefixTree-test.cpp index d5f46b4..98d0f4e 100644 --- a/src/CoreVM/util/PrefixTree-test.cpp +++ b/src/CoreVM/util/PrefixTree-test.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -#include - +import CoreVM; #include TEST(PrefixTree, exactMatch) diff --git a/src/CoreVM/util/PrefixTree.h b/src/CoreVM/util/PrefixTree.h deleted file mode 100644 index f31f44f..0000000 --- a/src/CoreVM/util/PrefixTree.h +++ /dev/null @@ -1,103 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -namespace CoreVM::util -{ - -template -class PrefixTree -{ - public: - typedef K Key; - typedef typename Key::value_type Elem; - typedef V Value; - - PrefixTree(); - ~PrefixTree(); - - void insert(const Key& key, const Value& value); - bool lookup(const Key& key, Value* value) const; - - private: - struct Node - { // {{{ - Node* parent; - Elem element; - std::unordered_map> children; - Value value; - - Node(): parent(nullptr), element(), children(), value() {} - Node(Node* p, Elem e): parent(p), element(e), children(), value() {} - }; // }}} - - Node _root; - - Node* acquire(Elem el, Node* n); -}; - -// {{{ -template -PrefixTree::PrefixTree(): _root() -{ -} - -template -PrefixTree::~PrefixTree() -{ -} - -template -void PrefixTree::insert(const Key& key, const Value& value) -{ - Node* level = &_root; - - for (const auto& ke: key) - level = acquire(ke, level); - - level->value = value; -} - -template -typename PrefixTree::Node* PrefixTree::acquire(Elem elem, Node* n) -{ - auto i = n->children.find(elem); - if (i != n->children.end()) - return i->second.get(); - - n->children[elem] = std::make_unique(n, elem); - return n->children[elem].get(); -} - -template -bool PrefixTree::lookup(const Key& key, Value* value) const -{ - const Node* level = &_root; - - for (const auto& ke: key) - { - auto i = level->children.find(ke); - if (i == level->children.end()) - break; - - level = i->second.get(); - } - - while (level && level->parent) - { - if (level->value) - { - *value = level->value; - return true; - } - level = level->parent; - } - - return false; -} -// }}} - -} // namespace CoreVM::util diff --git a/src/CoreVM/util/RegExp.cpp b/src/CoreVM/util/RegExp.cpp index a1cd1d3..ab314b2 100644 --- a/src/CoreVM/util/RegExp.cpp +++ b/src/CoreVM/util/RegExp.cpp @@ -4,7 +4,7 @@ module; #include #include -module CoreVM; +module CoreVM.util; namespace CoreVM::util { diff --git a/src/CoreVM/util/SuffixTree-test.cpp b/src/CoreVM/util/SuffixTree-test.cpp index 2073194..01ad649 100644 --- a/src/CoreVM/util/SuffixTree-test.cpp +++ b/src/CoreVM/util/SuffixTree-test.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 -#include - +import CoreVM; #include TEST(SuffixTree, exactMatch) diff --git a/src/CoreVM/util/SuffixTree.h b/src/CoreVM/util/SuffixTree.h deleted file mode 100644 index 04a50de..0000000 --- a/src/CoreVM/util/SuffixTree.h +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include -#include - -namespace CoreVM::util -{ - -template -class SuffixTree -{ - public: - typedef K Key; - typedef typename Key::value_type Elem; - typedef V Value; - - SuffixTree(); - ~SuffixTree(); - - void insert(const Key& key, const Value& value); - bool lookup(const Key& key, Value* value) const; - - private: - struct Node - { // {{{ - Node* parent; - Elem element; - std::unordered_map> children; - Value value; - - Node(): parent(nullptr), element(), children(), value() {} - Node(Node* p, Elem e): parent(p), element(e), children(), value() {} - }; // }}} - - Node _root; - - Node* acquire(Elem el, Node* n); -}; - -// {{{ -template -SuffixTree::SuffixTree(): _root() -{ -} - -template -SuffixTree::~SuffixTree() -{ -} - -template -void SuffixTree::insert(const Key& key, const Value& value) -{ - Node* level = &_root; - - // insert reverse - for (auto i = key.rbegin(), e = key.rend(); i != e; ++i) - level = acquire(*i, level); - - level->value = value; -} - -template -typename SuffixTree::Node* SuffixTree::acquire(Elem elem, Node* n) -{ - auto i = n->children.find(elem); - if (i != n->children.end()) - return i->second.get(); - - n->children[elem] = std::make_unique(n, elem); - return n->children[elem].get(); -} - -template -bool SuffixTree::lookup(const Key& key, Value* value) const -{ - const Node* level = &_root; - - for (auto i = key.rbegin(), e = key.rend(); i != e; ++i) - { - auto k = level->children.find(*i); - if (k == level->children.end()) - break; - - level = k->second.get(); - } - - while (level && level->parent) - { - if (level->value) - { - *value = level->value; - return true; - } - level = level->parent; - } - - return false; -} -// }}} - -} // namespace CoreVM::util diff --git a/src/CoreVM/util/unbox.h b/src/CoreVM/util/unbox.h deleted file mode 100644 index c0a87ad..0000000 --- a/src/CoreVM/util/unbox.h +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#pragma once - -#include - -namespace CoreVM::util -{ - -template -class UnboxedRange -{ - public: - using BoxedContainer = T; - using BoxedIterator = typename BoxedContainer::iterator; - using element_type = typename BoxedContainer::value_type::element_type; - - class iterator // NOLINT - { // {{{ - public: - using difference_type = typename BoxedContainer::iterator::difference_type; - using value_type = typename BoxedContainer::iterator::value_type::element_type; - using pointer = typename BoxedContainer::iterator::value_type::element_type*; - using reference = typename BoxedContainer::iterator::value_type::element_type&; - using iterator_category = typename BoxedContainer::iterator::iterator_category; - - explicit iterator(BoxedIterator boxed): _it(boxed) {} - - [[nodiscard]] const element_type& operator->() const { return **_it; } - [[nodiscard]] element_type& operator->() { return **_it; } - - [[nodiscard]] const element_type* operator*() const { return (*_it).get(); } - [[nodiscard]] element_type* operator*() { return (*_it).get(); } - - iterator& operator++() - { - ++_it; - return *this; - } - iterator& operator++(int) - { - ++_it; - return *this; - } - - [[nodiscard]] bool operator==(const iterator& other) const { return _it == other._it; } - [[nodiscard]] bool operator!=(const iterator& other) const { return _it != other._it; } - - private: - BoxedIterator _it; - }; // }}} - - UnboxedRange(BoxedIterator begin, BoxedIterator end): _begin(begin), _end(end) {} - explicit UnboxedRange(BoxedContainer& c): _begin(c.begin()), _end(c.end()) {} - - [[nodiscard]] iterator begin() const { return _begin; } - [[nodiscard]] iterator end() const { return _end; } - [[nodiscard]] size_t size() const - { - auto it = _begin; - size_t count = 0; - while (it != _end) - { - ++it; - ++count; - } - return count; - } - - private: - iterator _begin; - iterator _end; -}; - -/** - * Unboxes boxed element types in containers. - * - * Good examples are: - * - * \code - * std::vector> numbers; - * // ... - * for (int number: unbox(numbers)) { - * // ... juse use number here, instead of number.get() or *number. - * }; - * \endcode - */ -template -UnboxedRange unbox(BoxedContainer& boxedContainer) -{ - return UnboxedRange(boxedContainer); -} - -} // namespace CoreVM::util diff --git a/src/CoreVM/vm/ConstantPool.cpp b/src/CoreVM/vm/ConstantPool.cpp index ff1cd07..6b9bc8c 100644 --- a/src/CoreVM/vm/ConstantPool.cpp +++ b/src/CoreVM/vm/ConstantPool.cpp @@ -7,9 +7,9 @@ module; #include #include -#include module CoreVM; +import CoreVM.util; namespace CoreVM { diff --git a/src/CoreVM/vm/Instruction.cpp b/src/CoreVM/vm/Instruction.cpp index 086c9cf..c3b6a6f 100644 --- a/src/CoreVM/vm/Instruction.cpp +++ b/src/CoreVM/vm/Instruction.cpp @@ -1,6 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 module; -#include #include @@ -14,6 +13,7 @@ module; #include module CoreVM; +import CoreVM.util; namespace CoreVM { diff --git a/src/CoreVM/vm/Runner.cpp b/src/CoreVM/vm/Runner.cpp index e322430..1c2e071 100644 --- a/src/CoreVM/vm/Runner.cpp +++ b/src/CoreVM/vm/Runner.cpp @@ -2,7 +2,6 @@ module; #include #include -#include #include #include @@ -15,7 +14,7 @@ module; #include module CoreVM; - +import CoreVM.util; // XXX Visual Studio doesn't support computed goto statements #if defined(_MSC_VER) #define COREVM_VM_LOOP_SWITCH 1