1
0
mirror of https://github.com/TomHarte/CLK.git synced 2025-01-02 08:34:14 +00:00

Extends .description() to handle arrays.

This commit is contained in:
Thomas Harte 2020-05-14 23:58:17 -04:00
parent 4481386a3d
commit 375835a950
2 changed files with 62 additions and 42 deletions

View File

@ -110,13 +110,13 @@ bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::s
// MARK: - Getters // MARK: - Getters
template <typename Type> bool Reflection::get(const Struct &target, const std::string &name, Type &value) { 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); const auto target_type = target.type_of(name);
if(!target_type) return false; if(!target_type) return false;
// If type is a direct match, copy. // If type is a direct match, copy.
if(*target_type == typeid(Type)) { if(*target_type == typeid(Type)) {
memcpy(&value, target.get(name), sizeof(Type)); memcpy(&value, reinterpret_cast<const uint8_t *>(target.get(name)) + offset * sizeof(Type), sizeof(Type));
return true; return true;
} }
@ -131,14 +131,58 @@ template <typename Type> bool Reflection::get(const Struct &target, const std::s
return false; return false;
} }
template <typename Type> Type Reflection::get(const Struct &target, const std::string &name) { template <typename Type> Type Reflection::get(const Struct &target, const std::string &name, size_t offset) {
Type value{}; Type value{};
get(target, name, value); get(target, name, value, offset);
return value; return value;
} }
// MARK: - Description // MARK: - Description
void Reflection::Struct::append(std::ostringstream &stream, const std::string &key, const std::type_info *const type, size_t offset) const {
// Output Bools as yes/no.
if(*type == typeid(bool)) {
stream << ::Reflection::get<bool>(*this, key, offset);
return;
}
// Output Ints of all sizes as hex.
#define OutputIntC(int_type, cast_type) if(*type == typeid(int_type)) { stream << std::setfill('0') << std::setw(sizeof(int_type)*2) << std::hex << cast_type(::Reflection::get<int_type>(*this, key, offset)); return; }
#define OutputInt(int_type) OutputIntC(int_type, int_type)
OutputIntC(int8_t, int16_t);
OutputIntC(uint8_t, uint16_t);
OutputInt(int16_t);
OutputInt(uint16_t);
OutputInt(int32_t);
OutputInt(uint32_t);
OutputInt(int64_t);
OutputInt(uint64_t);
#undef OutputInt
#undef OutputIntC
// Output floats and strings natively.
#define OutputNative(val_type) if(*type == typeid(val_type)) { stream << ::Reflection::get<val_type>(*this, key, offset); return; }
OutputNative(float);
OutputNative(double);
OutputNative(char *);
OutputNative(std::string);
#undef OutputNative
// Output the current value of any enums.
if(!Enum::name(*type).empty()) {
const int value = ::Reflection::get<int>(*this, key, offset);
stream << Enum::to_string(*type, value);
return;
}
// Recurse to deal with embedded objects.
if(*type == typeid(Reflection::Struct)) {
const Reflection::Struct *const child = reinterpret_cast<const Reflection::Struct *>(get(key));
stream << child->description();
return;
}
}
std::string Reflection::Struct::description() const { std::string Reflection::Struct::description() const {
std::ostringstream stream; std::ostringstream stream;
@ -150,47 +194,20 @@ std::string Reflection::Struct::description() const {
is_first = false; is_first = false;
stream << key << ": "; stream << key << ": ";
const auto count = count_of(key);
const auto type = type_of(key); const auto type = type_of(key);
// Output Bools as yes/no. if(count != 1) {
if(*type == typeid(bool)) { stream << "[";
stream << ::Reflection::get<bool>(*this, key);
continue;
} }
// Output Ints of all sizes as hex. for(size_t index = 0; index < count; ++index) {
#define OutputIntC(int_type, cast_type) if(*type == typeid(int_type)) { stream << std::setfill('0') << std::setw(sizeof(int_type)*2) << std::hex << cast_type(::Reflection::get<int_type>(*this, key)); continue; } append(stream, key, type, index);
#define OutputInt(int_type) OutputIntC(int_type, int_type) if(index != count-1) stream << ", ";
OutputIntC(int8_t, int16_t);
OutputIntC(uint8_t, uint16_t);
OutputInt(int16_t);
OutputInt(uint16_t);
OutputInt(int32_t);
OutputInt(uint32_t);
OutputInt(int64_t);
OutputInt(uint64_t);
#undef OutputInt
// Output floats and strings natively.
#define OutputNative(val_type) if(*type == typeid(val_type)) { stream << ::Reflection::get<val_type>(*this, key); continue; }
OutputNative(float);
OutputNative(double);
OutputNative(char *);
OutputNative(std::string);
#undef OutputNAtive
// Output the current value of any enums.
if(!Enum::name(*type).empty()) {
const int value = ::Reflection::get<int>(*this, key);
stream << Enum::to_string(*type, value);
continue;
} }
// Recurse to deal with embedded objects. if(count != 1) {
if(*type == typeid(Reflection::Struct)) { stream << "]";
const Reflection::Struct *const child = reinterpret_cast<const Reflection::Struct *>(get(key));
stream << child->description();
continue;
} }
} }

View File

@ -38,6 +38,9 @@ struct Struct {
sufficiently formed for a formal language parser, etc. sufficiently formed for a formal language parser, etc.
*/ */
std::string description() const; std::string description() const;
private:
void append(std::ostringstream &stream, const std::string &key, const std::type_info *type, size_t offset) const;
}; };
/*! /*!
@ -94,14 +97,14 @@ bool fuzzy_set(Struct &target, const std::string &name, const std::string &value
@returns @c true if the property was successfully read; @c false otherwise. @returns @c true if the property was successfully read; @c false otherwise.
*/ */
template <typename Type> bool get(const Struct &target, const std::string &name, Type &value); template <typename Type> bool get(const Struct &target, const std::string &name, Type &value, size_t offset = 0);
/*! /*!
Attempts to get the property @c name to @c value ; will perform limited type conversions. Attempts to get the property @c name to @c value ; will perform limited type conversions.
@returns @c true if the property was successfully read; a default-constructed instance of Type otherwise. @returns @c true if the property was successfully read; a default-constructed instance of Type otherwise.
*/ */
template <typename Type> Type get(const Struct &target, const std::string &name); template <typename Type> Type get(const Struct &target, const std::string &name, size_t offset = 0);
// TODO: move this elsewhere. It's just a sketch anyway. // TODO: move this elsewhere. It's just a sketch anyway.
@ -225,7 +228,7 @@ template <typename Owner> class StructImpl: public Struct {
// If the declared item is an array, record it as a pointer to the // If the declared item is an array, record it as a pointer to the
// first element plus a size. // first element plus a size.
if constexpr (std::is_array<Type>()) { if constexpr (std::is_array<Type>()) {
declare_emplace(&t[0], name, sizeof(*t) / sizeof(*t[0])); declare_emplace(&(*t)[0], name, sizeof(*t) / sizeof(*t[0]));
return; return;
} }