mirror of
https://github.com/TomHarte/CLK.git
synced 2025-01-11 08:30:55 +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 "Struct.hpp"
|
||||||
#include "TypeInfo.hpp"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -157,70 +156,6 @@ bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::s
|
|||||||
return false;
|
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
|
// MARK: - Description
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "Enum.hpp"
|
#include "Enum.hpp"
|
||||||
|
#include "TypeInfo.hpp"
|
||||||
|
|
||||||
namespace Reflection {
|
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_;
|
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 */
|
#endif /* Struct_hpp */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user