-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrl.h
134 lines (105 loc) · 3.72 KB
/
trl.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/* tiny reflection library - written by Kevin Chin (https://kevch.in/)
Do this:
#define TINY_REFLECTION_IMPLEMENTATION
before you include this file in *one* C++ file to create the implementation.
// i.e. it should look like this:
#include ...
#define TINY_REFLECTION_IMPLEMENTATION
#include "trl.h"
Features:
- Construction of class from name as a string
- Member field/variable information e.g. list all fields of a class and their types
- Super/base class information from derived class
- Actual class information from a pointer to a base class
- Modify private field/variable externally
*/
#ifndef _INCLUDE_TINY_REFLECTION_LIBRARY_H_
#define _INCLUDE_TINY_REFLECTION_LIBRARY_H_
#if (defined _MSC_VER)
#define _TrlPragma __pragma
#elif (defined __GNUC__)
#define _TrlPragma _Pragma
#else
#define _TrlPragma(ignore)
#endif
#include <vector>
#include <functional>
// INTERFACE STARTS HERE
struct Type
{
const char* name;
int size;
};
struct FieldDescriptor
{
Type type;
const char* name;
int offset;
};
struct StructDescriptor
{
Type type;
const char* name;
std::vector<FieldDescriptor> fields;
std::function<void*()> defaultConstructor;
StructDescriptor* superDescriptor;
StructDescriptor(void(*init)(StructDescriptor*))
: superDescriptor(NULL)
{
init(this);
}
}; typedef StructDescriptor ClassDescriptor;
// PUT IN CONSTRUCTORS OF EVERY REFLECTED CLASS
#define SET_DESCRIPTOR_PTR()\
do{\
if(ReflectionPtr) {\
Reflection.fields.insert(Reflection.fields.begin(), ReflectionPtr->fields.begin(), ReflectionPtr->fields.end());\
Reflection.superDescriptor = ReflectionPtr;\
}\
ReflectionPtr = &Reflection;\
} while(0)
// IN CLASS BODY (MUST BE PUBLIC)
#define REFLECT_BASE_CLASS()\
static StructDescriptor Reflection;\
static void __initReflection(StructDescriptor* desc);\
StructDescriptor* ReflectionPtr = NULL;
#define REFLECT_DERIVED_CLASS()\
static StructDescriptor Reflection;\
static void __initReflection(StructDescriptor* desc);
// IN ONE CPP FILE (TRANSLATION UNIT) WITH ACCESS TO CLASS DECLARATION
#define REFLECT_CLASS_BEGIN(classType)\
StructDescriptor classType::Reflection{classType::__initReflection}\
_TrlPragma("clang diagnostic push");\
_TrlPragma("clang diagnostic ignored \"-Winvalid-offsetof\"");\
void classType::__initReflection(StructDescriptor* desc)\
{\
using T = classType;\
TRLDatabase[#classType] = desc;\
desc->type = { typeid(classType).name(), sizeof(classType) };\
desc->name = #classType;\
desc->defaultConstructor = []()->void*{return new classType;};\
desc->fields = {
#define REFLECT_CLASS_FIELD(fieldName)\
{ { typeid(fieldName).name(), sizeof(fieldName) }, #fieldName, offsetof(T, fieldName) },
#define REFLECT_CLASS_END()\
};\
}\
_TrlPragma("clang diagnostic pop");
// use instead of REFLECT_CLASS_BEGIN if abstract class
#define REFLECT_ABSTRACT_CLASS_BEGIN(classType)\
StructDescriptor classType::Reflection{classType::__initReflection}\
_TrlPragma("clang diagnostic push");\
_TrlPragma("clang diagnostic ignored \"-Winvalid-offsetof\"");\
void classType::__initReflection(StructDescriptor* desc)\
{\
using T = classType;\
TRLDatabase[#classType] = desc;\
desc->type = { typeid(classType).name(), sizeof(classType) };\
desc->name = #classType;\
desc->fields = {
// INTERFACE ENDS HERE
#endif //_INCLUDE_TINY_REFLECTION_LIBRARY_H_
#ifdef TINY_REFLECTION_IMPLEMENTATION
#include <unordered_map>
static std::unordered_map<const char*, StructDescriptor*> TRLDatabase;
#endif