xo-reader2 stack: + TypeRegistry

This commit is contained in:
Roland Conybeare 2026-02-15 22:57:15 -05:00
commit 5315485270
3 changed files with 143 additions and 2 deletions

View file

@ -7,8 +7,9 @@
#pragma once
#include "TypeRegistry.hpp"
#include "facet_implementation.hpp"
#include "typeseq.hpp"
//#include "typeseq.hpp"
#include "obj.hpp"
#include <xo/arena/DArenaHashMap.hpp>
#include <xo/indentlog/scope.hpp>
@ -74,6 +75,9 @@ namespace xo {
static void register_impl() {
static FacetImplType<AFacet, DRepr> impl;
TypeRegistry::register_type<AFacet>();
TypeRegistry::register_type<DRepr>();
instance()._register_impl(typeseq::id<AFacet>(),
typeseq::id<DRepr>(),
&impl);

View file

@ -0,0 +1,137 @@
/** @file TypeRegistry.hpp
*
* @brief Runtime facet implementation lookup
*
* @author Roland Conybeare, Jan 2026
**/
#pragma once
#include "typeseq.hpp"
#include <xo/arena/DArenaVector.hpp>
#include <xo/indentlog/scope.hpp>
#include <utility>
namespace xo {
namespace facet {
/** @class TypeRegistry
*
* @brief Runtime registry for types.
*
* Just assigns ids and remembers names.
* Not a full reflection implementation
**/
class TypeRegistry {
public:
using ReprType = xo::mm::DArenaVector<typerecd>;
using ArenaConfig = xo::mm::ArenaConfig;
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
using typeseq = xo::reflect::typeseq;
/** singleton instance.
* @p hint_max_capacity is a lower bound for registry capacity.
* Only honored the first time instance is called.
**/
static TypeRegistry & instance(uint32_t hint_max_capacity = 1024) {
static TypeRegistry s_instance(hint_max_capacity);
return s_instance;
}
/** Type-safe registration
*
* Registers the compile-time FacetImplementation<AFacet, DRepr>
* for runtime lookup.
*
* @tparam AFacet abstract facet type
* @tparam DRepr data representation type
**/
template <typename T>
static void register_type() {
typerecd r = typerecd::recd<T>();
instance()._register_type(r);
}
/** Number of registered (facet, repr) pairs **/
std::size_t size() const { return registry_.size(); }
std::string_view id2name(typeseq id) const noexcept {
return instance()._id2name(id);
}
/** visit memory pools owned by facet registry **/
void visit_pools(const MemorySizeVisitor & visitor) {
registry_.visit_pools(visitor);
}
/** Check if type is registered **/
bool contains(typeseq id) const
{
if ((0 <= id.seqno())
&& (id.seqno() < static_cast<int32_t>(registry_.size())))
{
return (registry_.at(id.seqno()).seqno() == id.seqno());
}
return false;
}
void dump(std::ostream * p_out) const {
(*p_out) << std::endl;
(*p_out) << "<TypeRegistry" << std::endl;
for (const auto & item : registry_) {
(*p_out)
<< " [" << item.seqno() << "]"
<< " -> " << item.name() << std::endl;
}
(*p_out) << ">" << std::endl;
}
private:
/** Register a facet implementation (type-erased)
*
* @param facet_id typeseq for abstract facet (e.g., APrintable)
* @param repr_id typeseq for data representation (e.g., DFloat)
* @param impl pointer to stateless implementation instance
**/
void _register_type(const typerecd & recd)
{
if ((recd.seqno() >= 0)
&& (static_cast<int32_t>(registry_.size()) <= recd.seqno()))
{
registry_.resize(recd.seqno() + 1);
}
registry_.at(recd.seqno()) = recd;
}
/** Get typename from @p id.
**/
std::string_view _id2name(typeseq id) const
{
if ((0 <= id.seqno())
&& (static_cast<std::size_t>(id.seqno()) < registry_.size()))
{
return registry_.at(id.seqno()).name();
}
return typerecd::sentinel().name();
}
private:
TypeRegistry(uint32_t hint_max_capacity)
: registry_(ReprType::map(ArenaConfig()
.with_name("types")
.with_size(hint_max_capacity
* sizeof(typerecd))))
{}
/** runtime lookup table (AFacet,DRepr) -> impl **/
ReprType registry_;
};
} /*namespace facet*/
} /*namespace xo*/
/* end TypeRegistry.hpp */

View file

@ -12,7 +12,7 @@
namespace xo {
namespace facet {
// Re-export from xo::arena namespace
using xo::reflect::typeseq_impl;
using xo::reflect::typerecd;
using xo::reflect::typeseq;
}
} /*namespace xo*/