15template <
typename SchemaBuilder>
19 using Type =
typename SchemaBuilder::Type;
20 using TypeBuildFunction =
typename Type::TypeBuildFunction;
21 using VirtualTablesType =
decltype(SchemaBuilder::vtables);
24 template <u
int32_t MAX_TOTAL_TYPES>
27 ArrayWithSize<Type, MAX_TOTAL_TYPES> types;
28 VirtualTablesType vtables;
32 template <u
int32_t NUM_TYPES>
33 struct FlatTrimmedResult
35 ArrayWithSize<TypeInfo, NUM_TYPES> typeInfos;
36 ArrayWithSize<TypeStringView, NUM_TYPES> typeNames;
37 VirtualTablesType vtables;
39 template <
typename Iterator,
typename BinaryPredicate>
40 static constexpr void bubbleSort(Iterator first, Iterator last, BinaryPredicate predicate)
51 Iterator p1 = first + 1;
54 if (predicate(*p1, *p0))
64 template <u
int32_t MAX_TYPES>
65 [[nodiscard]]
static constexpr bool appendTypesTo(ArrayWithSize<Type, MAX_TYPES>& types, TypeBuildFunction build,
66 SchemaBuilder& builder)
69 const auto baseLinkID = types.size;
70 builder.currentLinkID = types.size;
71 builder.types = {types.values + types.size, MAX_TYPES - types.size};
76 const auto numberOfTypes = builder.currentLinkID - baseLinkID;
77 const auto numberOfChildren = numberOfTypes - 1;
78 if (numberOfChildren >
static_cast<decltype(TypeInfo::numberOfChildren)
>(~0ull))
80 if (not types.values[baseLinkID].typeInfo.setNumberOfChildren(numberOfChildren))
83 struct OrderByMemberOffset
85 constexpr bool operator()(
const Type& a,
const Type& b)
const
87 return a.typeInfo.memberInfo.offsetInBytes < b.typeInfo.memberInfo.offsetInBytes;
91 types.values[baseLinkID].typeInfo.structInfo.isPacked)
94 bubbleSort(types.values + baseLinkID + 1, types.values + baseLinkID + 1 + numberOfChildren,
95 OrderByMemberOffset());
97 types.size += numberOfTypes;
103 template <u
int32_t MAX_LINK_BUFFER_SIZE, u
int32_t MAX_TOTAL_TYPES,
typename Func>
104 constexpr static FlatFullResult<MAX_TOTAL_TYPES> compileAllTypesFor(Func func)
107 FlatFullResult<MAX_TOTAL_TYPES> result;
109 SchemaBuilder container(result.types.values, MAX_TOTAL_TYPES);
112 ArrayWithSize<TypeStringView, MAX_LINK_BUFFER_SIZE> alreadyVisitedTypes;
114 ArrayWithSize<TypeBuildFunction, MAX_LINK_BUFFER_SIZE> alreadyVisitedTypes;
116 ArrayWithSize<uint32_t, MAX_LINK_BUFFER_SIZE> alreadyVisitedLinkID;
117 if (not appendTypesTo(result.types, func, container))
124 while (typeIndex < result.types.size)
126 Type& type = result.types.values[typeIndex];
127 if (not type.typeInfo.isPrimitiveType() and type.typeInfo.needsLinking())
131 if (alreadyVisitedTypes.contains(type.typeName, &outIndex))
133 if (alreadyVisitedTypes.contains(type.typeBuild, &outIndex))
136 if (not type.typeInfo.setLinkIndex(alreadyVisitedLinkID.values[outIndex]))
141 if (not type.typeInfo.setLinkIndex(result.types.size))
143 if (not alreadyVisitedLinkID.push_back(result.types.size))
146 if (not alreadyVisitedTypes.push_back(type.typeName))
148 if (not alreadyVisitedTypes.push_back(type.typeBuild))
151 if (not appendTypesTo(result.types, type.typeBuild, container))
157 result.vtables = container.vtables;
169 template <
typename T, u
int32_t MAX_LINK_BUFFER_SIZE = 20, u
int32_t MAX_TOTAL_TYPES = 100>
170 static constexpr auto compile()
172 constexpr auto schema =
173 compileAllTypesFor<MAX_LINK_BUFFER_SIZE, MAX_TOTAL_TYPES>(&Reflect<T>::template build<SchemaBuilder>);
174 static_assert(schema.types.size > 0,
"Something failed in compileAllTypesFor");
177 FlatTrimmedResult<schema.types.size> result;
178 for (
uint32_t i = 0; i < schema.types.size; ++i)
180 result.typeInfos.values[i] = schema.types.values[i].typeInfo;
181 result.typeNames.values[i] = schema.types.values[i].typeName;
183 result.typeInfos.size = schema.types.size;
184 result.typeNames.size = schema.types.size;
185 result.vtables = schema.vtables;
192template <
typename TypeVisitor>
195 using TypeBuildFunction = bool (*)(TypeVisitor& builder);
198 TypeStringView typeName;
199 TypeBuildFunction typeBuild;
201 constexpr SchemaType() : typeBuild(nullptr) {}
202 constexpr SchemaType(
const TypeInfo typeInfo, TypeStringView typeName, TypeBuildFunction typeBuild)
203 : typeInfo(typeInfo), typeName(typeName), typeBuild(typeBuild)
207 template <
typename T>
208 [[nodiscard]]
static constexpr SchemaType createGeneric()
210 return {TypeInfo(Reflect<T>::getCategory(),
sizeof(T)), TypeToString<T>::get(), &Reflect<T>::build};
214 template <
typename T>
215 [[nodiscard]]
static constexpr SchemaType createStruct(TypeStringView name = TypeToString<T>::get())
217 TypeInfo::StructInfo structInfo(ExtendedTypeInfo<T>::IsPacked);
218 return {TypeInfo(Reflect<T>::getCategory(),
sizeof(T), structInfo), name, &Reflect<T>::build};
222 template <
typename R,
typename T,
int N>
223 [[nodiscard]]
static constexpr SchemaType createMember(
uint8_t memberTag, R T::*,
const char (&name)[N],
226 const auto info = TypeInfo::MemberInfo(memberTag,
static_cast<SC::uint16_t>(offset));
227 return {TypeInfo(Reflect<R>::getCategory(),
sizeof(R), info), TypeStringView(name, N - 1), &Reflect<R>::build};
231 template <
typename T>
232 [[nodiscard]]
static constexpr SchemaType createArray(TypeStringView name,
uint8_t numChildren,
233 TypeInfo::ArrayInfo arrayInfo)
235 return {TypeInfo(Reflect<T>::getCategory(),
sizeof(T), numChildren, arrayInfo), name, &Reflect<T>::build};
240template <
typename TypeVisitor>
243 using Type = SchemaType<TypeVisitor>;
247 WritableRange<Type> types;
249 constexpr SchemaBuilder(Type* output,
const uint32_t capacity) : currentLinkID(0), types(output, capacity) {}
251 template <
typename R,
typename T,
int N>
252 [[nodiscard]]
constexpr bool operator()(
uint8_t memberTag, R T::* field,
const char (&name)[N],
size_t offset)
255 return types.writeAndAdvance(Type::createMember(memberTag, field, name, offset));
258 [[nodiscard]]
constexpr bool addType(Type type)
261 return types.writeAndAdvance(type);
266struct FlatSchemaBuilder :
public SchemaBuilder<FlatSchemaBuilder>
271 EmptyVTables vtables;
272 constexpr FlatSchemaBuilder(Type* output,
const uint32_t capacity) : SchemaBuilder(output, capacity) {}
276using Schema = Reflection::SchemaCompiler<FlatSchemaBuilder>;
unsigned short uint16_t
Platform independent (2) bytes unsigned int.
Definition PrimitiveTypes.h:37
unsigned char uint8_t
Platform independent (1) byte unsigned int.
Definition PrimitiveTypes.h:36
unsigned int uint32_t
Platform independent (4) bytes unsigned int.
Definition PrimitiveTypes.h:38
constexpr void swap(T &t1, T &t2)
Swaps the values of two objects.
Definition Compiler.h:270
Reflection::SchemaCompiler< FlatSchemaBuilder > Schema
Default schema not building any virtual table.
Definition ReflectionSchemaCompiler.h:276
@ TypeStruct
Type is a struct type.