From c982c78285e091ef931e63deb64b275b38170a1a Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 27 Jun 2020 16:26:01 -0400 Subject: [PATCH] Ensures Reflection::set is widely available. --- Reflection/Struct.cpp | 65 -------------------------------------- Reflection/Struct.hpp | 73 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 65 deletions(-) diff --git a/Reflection/Struct.cpp b/Reflection/Struct.cpp index 17ce28406..46a1c65a8 100644 --- a/Reflection/Struct.cpp +++ b/Reflection/Struct.cpp @@ -7,7 +7,6 @@ // #include "Struct.hpp" -#include "TypeInfo.hpp" #include #include @@ -157,70 +156,6 @@ bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::s return false; } -// MARK: - Getters - -template bool Reflection::get(const Struct &target, const std::string &name, Type &value, size_t offset) { - const auto target_type = target.type_of(name); - if(!target_type) return false; - - // If type is a direct match, copy. - if(*target_type == typeid(Type)) { - const auto address = reinterpret_cast(target.get(name)) + offset * sizeof(Type); - value = *reinterpret_cast(address); - return true; - } - - // If the type is a registered enum and the value type is int, copy. - if constexpr (std::is_integral::value && sizeof(Type) == sizeof(int)) { - if(!Enum::name(*target_type).empty()) { - memcpy(&value, target.get(name), sizeof(int)); - return true; - } - } - - // If the type is an int that is larger than the stored type and matches the signedness, cast upward. - if constexpr (std::is_integral::value) { - if(TypeInfo::is_integral(target_type)) { - const bool target_is_signed = TypeInfo::is_signed(target_type); - const size_t target_size = TypeInfo::size(target_type); - - // An unsigned type can map to any larger type, signed or unsigned; - // a signed type can map to a larger type only if it also is signed. - if(sizeof(Type) > target_size && (!target_is_signed || std::is_signed::value)) { - const auto address = reinterpret_cast(target.get(name)) + offset * target_size; - -#define Map(x) if(*target_type == typeid(x)) { value = static_cast(*reinterpret_cast(address)); } - ForAllInts(Map); -#undef Map - return true; - } - } - } - - // If the type is a double and stored type is a float, cast upward. - if constexpr (std::is_floating_point::value) { - constexpr size_t size = sizeof(Type); - const bool target_is_floating_point = TypeInfo::is_floating_point(target_type); - const size_t target_size = TypeInfo::size(target_type); - - if(size > target_size && target_is_floating_point) { - const auto address = reinterpret_cast(target.get(name)) + offset * target_size; - -#define Map(x) if(*target_type == typeid(x)) { value = static_cast(*reinterpret_cast(address)); } - ForAllFloats(Map); -#undef Map - return true; - } - } - - return false; -} - -template Type Reflection::get(const Struct &target, const std::string &name, size_t offset) { - Type value{}; - get(target, name, value, offset); - return value; -} // MARK: - Description diff --git a/Reflection/Struct.hpp b/Reflection/Struct.hpp index 14870760e..24dbd489d 100644 --- a/Reflection/Struct.hpp +++ b/Reflection/Struct.hpp @@ -20,6 +20,7 @@ #include #include "Enum.hpp" +#include "TypeInfo.hpp" namespace Reflection { @@ -352,6 +353,78 @@ template class StructImpl: public Struct { static inline std::unordered_map> permitted_enum_values_; }; + + + +// MARK: - IMPLEMENTATION DETAILS BELOW +// DO NOT RELY ON THE IMPLEMENTATIONS BELOW. +// Please use the documentation above. + +// MARK: - Getters + +template bool get(const Struct &target, const std::string &name, Type &value, size_t offset) { + const auto target_type = target.type_of(name); + if(!target_type) return false; + + // If type is a direct match, copy. + if(*target_type == typeid(Type)) { + const auto address = reinterpret_cast(target.get(name)) + offset * sizeof(Type); + value = *reinterpret_cast(address); + return true; + } + + // If the type is a registered enum and the value type is int, copy. + if constexpr (std::is_integral::value && sizeof(Type) == sizeof(int)) { + if(!Enum::name(*target_type).empty()) { + memcpy(&value, target.get(name), sizeof(int)); + return true; + } + } + + // If the type is an int that is larger than the stored type and matches the signedness, cast upward. + if constexpr (std::is_integral::value) { + if(TypeInfo::is_integral(target_type)) { + const bool target_is_signed = TypeInfo::is_signed(target_type); + const size_t target_size = TypeInfo::size(target_type); + + // An unsigned type can map to any larger type, signed or unsigned; + // a signed type can map to a larger type only if it also is signed. + if(sizeof(Type) > target_size && (!target_is_signed || std::is_signed::value)) { + const auto address = reinterpret_cast(target.get(name)) + offset * target_size; + +#define Map(x) if(*target_type == typeid(x)) { value = static_cast(*reinterpret_cast(address)); } + ForAllInts(Map); +#undef Map + return true; + } + } + } + + // If the type is a double and stored type is a float, cast upward. + if constexpr (std::is_floating_point::value) { + constexpr size_t size = sizeof(Type); + const bool target_is_floating_point = TypeInfo::is_floating_point(target_type); + const size_t target_size = TypeInfo::size(target_type); + + if(size > target_size && target_is_floating_point) { + const auto address = reinterpret_cast(target.get(name)) + offset * target_size; + +#define Map(x) if(*target_type == typeid(x)) { value = static_cast(*reinterpret_cast(address)); } + ForAllFloats(Map); +#undef Map + return true; + } + } + + return false; +} + +template Type get(const Struct &target, const std::string &name, size_t offset) { + Type value{}; + get(target, name, value, offset); + return value; +} + } #endif /* Struct_hpp */