mirror of
https://github.com/TomHarte/CLK.git
synced 2024-12-23 20:29:42 +00:00
Ensures Reflection::set is widely available.
This commit is contained in:
parent
b4cdf8d987
commit
c982c78285
@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#include "Struct.hpp"
|
||||
#include "TypeInfo.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@ -157,70 +156,6 @@ bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::s
|
||||
return false;
|
||||
}
|
||||
|
||||
// MARK: - Getters
|
||||
|
||||
template <typename Type> 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<const uint8_t *>(target.get(name)) + offset * sizeof(Type);
|
||||
value = *reinterpret_cast<const Type *>(address);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the type is a registered enum and the value type is int, copy.
|
||||
if constexpr (std::is_integral<Type>::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<Type>::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<Type>::value)) {
|
||||
const auto address = reinterpret_cast<const uint8_t *>(target.get(name)) + offset * target_size;
|
||||
|
||||
#define Map(x) if(*target_type == typeid(x)) { value = static_cast<Type>(*reinterpret_cast<const x *>(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<Type>::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<const uint8_t *>(target.get(name)) + offset * target_size;
|
||||
|
||||
#define Map(x) if(*target_type == typeid(x)) { value = static_cast<Type>(*reinterpret_cast<const x *>(address)); }
|
||||
ForAllFloats(Map);
|
||||
#undef Map
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Type> Type Reflection::get(const Struct &target, const std::string &name, size_t offset) {
|
||||
Type value{};
|
||||
get(target, name, value, offset);
|
||||
return value;
|
||||
}
|
||||
|
||||
// MARK: - Description
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "Enum.hpp"
|
||||
#include "TypeInfo.hpp"
|
||||
|
||||
namespace Reflection {
|
||||
|
||||
@ -352,6 +353,78 @@ template <typename Owner> class StructImpl: public Struct {
|
||||
static inline std::unordered_map<std::string, std::vector<bool>> permitted_enum_values_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: - IMPLEMENTATION DETAILS BELOW
|
||||
// DO NOT RELY ON THE IMPLEMENTATIONS BELOW.
|
||||
// Please use the documentation above.
|
||||
|
||||
// MARK: - Getters
|
||||
|
||||
template <typename Type> 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<const uint8_t *>(target.get(name)) + offset * sizeof(Type);
|
||||
value = *reinterpret_cast<const Type *>(address);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the type is a registered enum and the value type is int, copy.
|
||||
if constexpr (std::is_integral<Type>::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<Type>::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<Type>::value)) {
|
||||
const auto address = reinterpret_cast<const uint8_t *>(target.get(name)) + offset * target_size;
|
||||
|
||||
#define Map(x) if(*target_type == typeid(x)) { value = static_cast<Type>(*reinterpret_cast<const x *>(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<Type>::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<const uint8_t *>(target.get(name)) + offset * target_size;
|
||||
|
||||
#define Map(x) if(*target_type == typeid(x)) { value = static_cast<Type>(*reinterpret_cast<const x *>(address)); }
|
||||
ForAllFloats(Map);
|
||||
#undef Map
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename Type> Type get(const Struct &target, const std::string &name, size_t offset) {
|
||||
Type value{};
|
||||
get(target, name, value, offset);
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif /* Struct_hpp */
|
||||
|
Loading…
Reference in New Issue
Block a user