diff --git a/include/wrenpp/detail/module_and_name.hpp b/include/wrenpp/detail/module_and_name.hpp index a497c31..7dd3bbd 100644 --- a/include/wrenpp/detail/module_and_name.hpp +++ b/include/wrenpp/detail/module_and_name.hpp @@ -20,13 +20,20 @@ #include "string_bt.hpp" #include #include +#include +#include namespace wren { + class ModuleAndName; + namespace detail { template struct ModuleAndNameStaticStorage { static constexpr const auto value = S; }; + + [[gnu::const]] + bool deep_equal (const ModuleAndName& a, const ModuleAndName& b) noexcept; } //unnamed namespace //Non-owning, lightweight class for storing a module nome/class name pair. @@ -40,10 +47,15 @@ namespace wren { //of this class get hardcoded in the dynamic functions that DynafuncMaker //spits out. class ModuleAndName { + friend bool detail::deep_equal(const ModuleAndName&, const ModuleAndName&) noexcept; public: constexpr ModuleAndName(); constexpr ModuleAndName (const char* base, std::uint32_t hash, std::size_t mod_name_len, std::size_t class_name_len); + constexpr bool operator==(const ModuleAndName& other) const noexcept; + constexpr bool operator!=(const ModuleAndName& other) const noexcept; + constexpr bool deep_equal(const ModuleAndName& other) const noexcept; + constexpr const char* module_name_char() const noexcept { return m_base; } constexpr const char* class_name_char() const noexcept { return m_base + 1 + m_mod_name_len; } constexpr std::size_t module_name_len() const noexcept { return m_mod_name_len; } @@ -53,6 +65,8 @@ namespace wren { constexpr const char* buffer_address() const noexcept { return m_base; } private: + constexpr std::size_t raw_buffer_size() const noexcept; + const char* m_base; std::uint32_t m_hash; std::uint16_t m_mod_name_len; @@ -85,6 +99,35 @@ namespace wren { m_class_name_len(class_name_len) {} + constexpr bool ModuleAndName::operator==(const ModuleAndName& other) const noexcept { + const bool retval = (this->m_hash == other.m_hash); + assert(not retval or deep_equal(other)); + return retval; + } + + constexpr bool ModuleAndName::operator!=(const ModuleAndName& other) const noexcept { + return not this->operator==(other); + } + + constexpr bool ModuleAndName::deep_equal(const ModuleAndName& other) const noexcept { + if (not std::is_constant_evaluated()) { + return detail::deep_equal(*this, other); + } + else { + if (this->raw_buffer_size() != other.raw_buffer_size()) + return false; + for (std::size_t z = 0; z < raw_buffer_size(); ++z) { + if (this->m_base[z] != other.m_base[z]) + return false; + } + return true; + } + } + + constexpr std::size_t ModuleAndName::raw_buffer_size() const noexcept { + return m_mod_name_len + m_class_name_len + 2; + } + template constexpr ModuleAndName make_module_and_name() { using dhandy::bt::string; diff --git a/meson.build b/meson.build index 8bda0ca..e59c60c 100644 --- a/meson.build +++ b/meson.build @@ -74,6 +74,7 @@ wrenpp = library(meson.project_name(), 'src/class_manager.cpp', 'src/wren_class_name_from_type.cpp', 'src/crc32.cpp', + 'src/module_and_name.cpp', dependencies: [wren_dep], include_directories: public_incl, install: (not meson.is_subproject() or get_option('default_library')=='shared'), diff --git a/src/module_and_name.cpp b/src/module_and_name.cpp new file mode 100644 index 0000000..a50322e --- /dev/null +++ b/src/module_and_name.cpp @@ -0,0 +1,30 @@ +/* Copyright 2020-2022, Michele Santullo + * This file is part of wrenpp. + * + * Wrenpp is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Wrenpp is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with wrenpp. If not, see . + */ + +#include "wrenpp/detail/module_and_name.hpp" +#include + +namespace wren::detail { + bool deep_equal(const ModuleAndName& a, const ModuleAndName& b) noexcept { + const auto a_size = a.raw_buffer_size(); + const auto b_size = b.raw_buffer_size(); + if (a_size != b_size) + return false; + + return std::equal(a.m_base, a.m_base + a_size, b.m_base); + } +} //namespace wren::detail