1 #ifndef SIPLASPLAS_REFLECTION_DYNAMIC_TYPE_HPP 2 #define SIPLASPLAS_REFLECTION_DYNAMIC_TYPE_HPP 4 #include <siplasplas/reflection/common/type_info.hpp> 5 #include <siplasplas/allocator/freelist_allocator.hpp> 6 #include <siplasplas/utility/exception.hpp> 7 #include <siplasplas/utility/lexical_cast.hpp> 8 #include <siplasplas/utility/meta.hpp> 9 #include <siplasplas/reflection/dynamic/export.hpp> 11 #include <unordered_map> 18 namespace dynamic_reflection
26 static constexpr ctti::unnamed_type_id_t id()
28 return ctti::unnamed_type_id<T>();
32 #define CPP_REFLECTION_CUSTOM_TYPENAME_FOR(type, name) \ 33 namespace cpp { namespace detail { \ 35 struct CustomTypeName<type> { \ 36 static constexpr ::ctti::unnamed_type_id_t id() \ 38 return ::ctti::id_from_name(name); \ 43 #define CPP_REFLECTION_FORCE_TYPENAME(type) CPP_REFLECTION_CUSTOM_TYPENAME_FOR(type, #type) 45 class SIPLASPLAS_REFLECTION_DYNAMIC_EXPORT
Type 52 return _behavior->construct();
55 void* copy_construct(
const void*
object)
const 57 return _behavior->copy_construct(
object);
60 void* move_construct(
void*
object)
const 62 return _behavior->move_construct(
object);
65 void copy_assign(
void*
object,
const void* other)
const 67 _behavior->copy_assign(
object, other);
70 void move_assign(
void*
object,
void* other)
const 72 _behavior->move_assign(
object, other);
75 void destroy(
void*
object)
const 77 _behavior->destroy(
object);
80 std::string toString(
void*
object)
const 82 return _behavior->toString(
object);
85 void* fromString(
const std::string& value)
const 87 return _behavior->fromString(value);
92 return _behavior->type();
100 const ctti::detail::cstring typeName()
const 102 return typeInfo().name();
106 static void registerType()
111 template<
typename... Ts>
112 static void registerTypes()
123 static Type&
get(
const std::string& typeName)
125 auto try_get = [](
const std::string typeName) ->
Type*
127 auto id = ctti::id_from_name(typeName);
128 auto it = types().find(
id);
138 if(!(type = try_get(typeName)) &&
139 !(type = try_get(
"class " + typeName)) &&
140 !(type = try_get(
"struct " + typeName)))
142 throw std::runtime_error{
"Type '" + typeName +
"' not registered"};
150 friend bool operator==(
const Type& lhs,
const Type& rhs)
152 return lhs.typeInfo() == rhs.typeInfo();
155 friend bool operator!=(
const Type& lhs,
const Type& rhs)
157 return !(lhs == rhs);
166 virtual void destroy(
void*
object) = 0;
167 virtual void* copy_construct(
const void*
object) = 0;
168 virtual void* move_construct(
void*
object) = 0;
169 virtual void copy_assign(
void*
object,
const void* other) = 0;
170 virtual void move_assign(
void*
object,
void* other) = 0;
171 virtual std::string toString(
void*
object) = 0;
172 virtual void* fromString(
const std::string& value) = 0;
177 template<
typename Ts,
typename =
void>
178 class TypeRegistration;
180 template<
typename Head,
typename... Tail>
181 class TypeRegistration<meta::list<Head, Tail...>, void>
186 Type::registerType<Head>();
187 TypeRegistration<
meta::list<Tail...>>::apply();
191 template<
typename... Ts>
192 class TypeRegistration<meta::list<meta::list<Ts...>>, void> :
193 public TypeRegistration<meta::list<Ts...>>
196 template<
typename void_>
197 class TypeRegistration<meta::list<>, void_>
209 _type{cpp::TypeInfo::get<T>()}
211 _objectsArena.emplace_back(512 * (
sizeof(T) +
alignof(T)));
216 return new(allocate_object()) T();
219 void* copy_construct(
const void*
object)
override 221 return new(allocate_object()) T(*reinterpret_cast<const T*>(
object));
224 void* move_construct(
void*
object)
override 226 return new(allocate_object()) T(std::move(*reinterpret_cast<T*>(
object)));
229 void copy_assign(
void*
object,
const void* other)
override 231 *
reinterpret_cast<T*
>(object) = *reinterpret_cast<const T*>(other);
234 void move_assign(
void*
object,
void* other)
override 236 *
reinterpret_cast<T*
>(object) = std::move(*reinterpret_cast<T*>(other));
239 void destroy(
void*
object)
override 241 reinterpret_cast<T*
>(object)->~T();
242 deallocate_object(
object);
245 std::string toString(
void*
object)
override 247 return ToString<T>::apply(*static_cast<T*>(
object));
250 void* fromString(
const std::string& value)
override 252 auto object = FromString<T>::apply(value);
253 return copy_construct(&
object);
264 template<
typename U,
typename =
void>
268 static std::string apply(
const U& value)
270 std::ostringstream os;
272 os <<
"'" << ctti::type_id<U>().name() <<
"' instance " 273 <<
"@" <<
static_cast<const void*
>(&value);
279 template<
typename U,
typename =
void>
283 static U apply(
const std::string& value)
285 throw std::runtime_error{
286 "lexical_cast not supported for type i'" +
cpp::lexical_cast(ctti::type_id<U>().name()) +
287 "', you must overload operator>>" 293 class ToString<U, meta::void_t<decltype(std::declval<std::ostream&>() << std::declval<const U&>())>>
296 static std::string apply(const U& value)
298 return cpp::lexical_cast(value);
303 class FromString<U, meta::void_t<decltype(std::declval<std::istream&>() >> std::declval<U&>())>>
306 static U apply(
const std::string& value)
315 StorageBlock(std::size_t bytes) :
316 _block{
new char[bytes]},
318 _freeList{
begin(),
end(),
sizeof(T),
alignof(T) }
328 return _block.get() + _bytes;
331 std::size_t bytes()
const 342 std::unique_ptr<char[]> _block;
347 std::vector<StorageBlock> _objectsArena;
349 void* allocate_object()
351 return std::malloc(
sizeof(T));
354 void* allocate(std::vector<StorageBlock>& arena, std::size_t sizeOf, std::size_t alignment,
int tries = 1)
356 void* slot = arena.back().freeList().allocate(sizeOf, alignment);
365 arena.emplace_back(512*(sizeOf + alignment));
368 return allocate(arena,sizeOf, alignment, tries + 1);
372 cpp::Throw<std::runtime_error>(
"Cannot allocate more storage for meta-instances");
378 void deallocate_object(
void* pointer)
380 return std::free(pointer);
383 void deallocate(std::vector<StorageBlock>& arena,
void* pointer)
386 [pointer](
const StorageBlock& block)
388 return block.freeList().belongs_to_storage(pointer);
393 blockIt->freeList().deallocate(pointer,
sizeof(T));
397 cpp::Throw<std::runtime_error>(
"Cannot deallocate object @{}", pointer);
403 static Type& getType()
417 std::shared_ptr<TypeBehavior> _behavior;
419 using Types = std::unordered_map<ctti::type_index, Type>;
421 static Types& types();
427 #endif // SIPLASPLAS_REFLECTION_DYNAMIC_TYPE_HPP
Definition: messaging.hpp:8
void destroy(T &object)
Invokes the destructor of an object.
Definition: destroy.hpp:16
constexpr auto end(const Sequence &sequence)
Returns an iterator pointing to the end of a sequence.
Definition: algorithm.hpp:86
void construct(void *where, Args &&... args)
constructs an object of type T on the specified address
Definition: destroy.hpp:56
constexpr auto begin(const Sequence &sequence)
Returns an iterator pointing to the beginning of a sequence.
Definition: algorithm.hpp:62
Definition: test_util.hpp:13
Definition: freelist_allocator.hpp:11
Definition: typeinfo.hpp:13
std::string lexical_cast(const T &value)
Returns an string representation of a value.
Definition: lexical_cast.hpp:25