From 4481386a3dfd63abf9f43aef76c3b7bbd7575699 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 May 2020 22:59:44 -0400 Subject: [PATCH] Extends `Reflection::Struct` slightly to capture the lengths of arrays. --- .../Implementation/MultiConfigurable.cpp | 8 +++++ Reflection/Struct.hpp | 29 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp index 55bf935ba..5d8fb89cd 100644 --- a/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp +++ b/Analyser/Dynamic/MultiMachine/Implementation/MultiConfigurable.cpp @@ -56,6 +56,14 @@ class MultiStruct: public Reflection::Struct { return nullptr; } + size_t count_of(const std::string &name) const final { + for(auto &options: options_) { + auto info = options->type_of(name); + if(info) return options->count_of(name); + } + return 0; + } + const void *get(const std::string &name) const final { for(auto &options: options_) { auto value = options->get(name); diff --git a/Reflection/Struct.hpp b/Reflection/Struct.hpp index c51758d8a..1e4e01c3d 100644 --- a/Reflection/Struct.hpp +++ b/Reflection/Struct.hpp @@ -27,6 +27,7 @@ namespace Reflection { struct Struct { virtual std::vector all_keys() const = 0; virtual const std::type_info *type_of(const std::string &name) const = 0; + virtual size_t count_of(const std::string &name) const = 0; virtual void set(const std::string &name, const void *value) = 0; virtual const void *get(const std::string &name) const = 0; virtual std::vector values_for(const std::string &name) const = 0; @@ -144,6 +145,15 @@ template class StructImpl: public Struct { return iterator->second.type; } + /*! + @returns The number of instances of objects of the same type as @c name that sit consecutively in memory. + */ + size_t count_of(const std::string &name) const final { + const auto iterator = contents_.find(name); + if(iterator == contents_.end()) return 0; + return iterator->second.count; + } + /*! @returns a list of the valid enum value names for field @c name if it is a declared enum field of this struct; the empty list otherwise. @@ -206,9 +216,19 @@ template class StructImpl: public Struct { it'll be the struct that's exposed. */ template void declare(Type *t, const std::string &name) { + // If the declared item is a class, see whether it can be dynamically cast + // to a reflectable for emplacement. If so, exit early. if constexpr (std::is_class()) { if(declare_reflectable(t, name)) return; } + + // If the declared item is an array, record it as a pointer to the + // first element plus a size. + if constexpr (std::is_array()) { + declare_emplace(&t[0], name, sizeof(*t) / sizeof(*t[0])); + return; + } + declare_emplace(t, name); } @@ -278,11 +298,11 @@ template class StructImpl: public Struct { return false; } - template void declare_emplace(Type *t, const std::string &name) { + template void declare_emplace(Type *t, const std::string &name, size_t count = 1) { contents_.emplace( std::make_pair( name, - Field(typeid(Type), reinterpret_cast(t) - reinterpret_cast(this), sizeof(Type)) + Field(typeid(Type), reinterpret_cast(t) - reinterpret_cast(this), sizeof(Type), count) )); } @@ -290,8 +310,9 @@ template class StructImpl: public Struct { const std::type_info *type; ssize_t offset; size_t size; - Field(const std::type_info &type, ssize_t offset, size_t size) : - type(&type), offset(offset), size(size) {} + size_t count; + Field(const std::type_info &type, ssize_t offset, size_t size, size_t count) : + type(&type), offset(offset), size(size), count(count) {} }; static inline std::unordered_map contents_; static inline std::unordered_map> permitted_enum_values_;