1
0
mirror of https://github.com/TomHarte/CLK.git synced 2026-04-19 19:16:34 +00:00

Makes a not-quite-correct attempt at a .description for reflective structs.

This commit is contained in:
Thomas Harte
2020-03-30 00:24:49 -04:00
parent edc553fa1d
commit 60aa383c95
3 changed files with 125 additions and 29 deletions
+74 -7
View File
@@ -9,6 +9,7 @@
#include "Struct.hpp"
#include <algorithm>
#include <sstream>
// MARK: - Setters
@@ -107,18 +108,84 @@ bool Reflection::fuzzy_set(Struct &target, const std::string &name, const std::s
// MARK: - Getters
template <typename Type> bool Reflection::get(Struct &target, const std::string &name, Type &value) {
return false;
}
template <> bool Reflection::get(Struct &target, const std::string &name, bool &value) {
template <typename Type> bool Reflection::get(const Struct &target, const std::string &name, Type &value) {
const auto target_type = target.type_of(name);
if(!target_type) return false;
if(*target_type == typeid(bool)) {
value = *reinterpret_cast<const bool *>(target.get(name));
if(*target_type == typeid(Type)) {
memcpy(&value, target.get(name), sizeof(Type));
return true;
}
return false;
}
template <typename Type> Type Reflection::get(const Struct &target, const std::string &name) {
Type value;
get(target, name, value);
return value;
}
// MARK: - Description
std::string Reflection::Struct::description() const {
std::ostringstream stream;
stream << "{";
bool is_first = true;
for(const auto &key: all_keys()) {
if(!is_first) stream << ", ";
is_first = false;
stream << key << ": ";
const auto type = type_of(key);
// Output Bools as yes/no.
if(*type == typeid(bool)) {
bool value;
::Reflection::get(*this, key, value);
stream << (value ? "true" : "false");
continue;
}
// Output Ints of all sizes as hex.
#define OutputIntC(int_type, cast_type) if(*type == typeid(int_type)) { stream << std::hex << cast_type(::Reflection::get<int_type>(*this, key)); continue; }
#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
// 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(*type == typeid(Reflection::Struct)) {
const Reflection::Struct *const child = reinterpret_cast<const Reflection::Struct *>(get(key));
stream << child->description();
continue;
}
}
stream << "}";
return stream.str();
}