a8/a8/reflect.h
aozhiwei b69451720a 1
2022-12-26 16:22:19 +08:00

258 lines
9.9 KiB
C++

#pragma once
#include <assert.h>
#include <type_traits>
namespace a8
{
namespace reflect
{
class Class;
}
struct ReflectibleObject
{
a8::reflect::Class *metaclass = NULL;
};
namespace reflect
{
enum FieldType
{
ET_INT32 = 1,
ET_UINT32 = 2,
ET_INT64 = 3,
ET_UINT64 = 4,
ET_FLOAT = 5,
ET_DOUBLE = 6,
ET_STRING = 7,
ET_CLASS = 8,
ET_INTERFACE = 9,
};
enum FieldSubType
{
EST_SIMPLE = 1,
EST_SIMPLE_POINTER = 2,
EST_CONTAINRER = 3,
EST_CONTAINRER_POINTER = 4,
};
struct Field;
class Class;
typedef bool (*FIELD_FOR_EACH_FUNC)(a8::reflect::Field*, void*, void*);
struct Field
{
const char* field_name = nullptr;
int type = 0; //int uint int64 uint64 double string class interface class_pointer
int subtype = 0; //std::vector<x> std::list<x>
int offset = 0;
a8::reflect::Class **pp_generic_class = nullptr; //泛型容器类型指针的指针
void* (*create)() = nullptr;
void (*destroy)(void*) = nullptr;
int (*size)(void*) = nullptr;
void (*for_each)(a8::reflect::Field*, void*, void* , FIELD_FOR_EACH_FUNC) = nullptr;
char* (*push_back)(void*) = nullptr;
};
class Class
{
public:
void* (*create)() = nullptr;
void (*destroy)(void*) = nullptr;
void (*copy)(void*, void*) = nullptr;
Class(const char* classname, int fieldnum, int tag)
{
class_name_ = classname;
tag_ = tag;
fields_ = new a8::reflect::Field[fieldnum];
fieldnum_ = fieldnum;
}
a8::reflect::Field* GetDeclaredFields() { return fields_; }
int FieldNum() { return fieldnum_; }
int ClassId() { return class_id_; }
int Tag() { return tag_; }
const char* ClassName() { return class_name_; }
Field* GetFieldByName(const std::string& name);
long long GetFieldValueAsInt64(a8::reflect::Field* field, char* p);
std::string GetFieldValueAsString(a8::reflect::Field* field, char* p);
void SetSimpleField(
int fieldidx,
const char* fieldname,
int type,
int offset
);
void SetField(int fieldidx,
const char* fieldname,
int type,
int subtype,
int offset,
a8::reflect::Class **pp_generic_class,
void* (*create)(),
void (*destroy)(void*),
int (*size)(void*),
void (*for_each)(a8::reflect::Field*, void*, void*, FIELD_FOR_EACH_FUNC),
char* (*push_back)(void*)
);
int GetFieldIdx(int offset);
private:
int class_id_ = 0;
int tag_ = 0;
int fieldnum_ = 0;
const char* class_name_ = nullptr;
a8::reflect::Field* fields_ = nullptr;
};
template <typename T>
static void* _create()
{
return (void*) new T();
}
template <typename T>
static void _destroy(void* instance)
{
T* p = (T*)instance;
delete p;
}
template <typename T>
static void _copy(void* a, void* b)
{
*(T*)a = *(T*)b;
}
template <typename T>
static int _size(void* instance)
{
T* p = (T*)instance;
return p->size();
}
template <typename T>
static void _for_each(a8::reflect::Field* field, void* instance, void* userdata,
FIELD_FOR_EACH_FUNC callback)
{
T* p = (T*)instance;
for (auto &itr : *p) {
if (callback && !callback(field, userdata, (void*)&itr)) {
break;
}
}
}
template <typename T>
static char* _push_back(void* instance)
{
T* p = (T*)instance;
return (char*)&a8::FastAppend(*p);
}
template <typename T>
inline a8::reflect::Class** get_pp_generic_class(a8::ReflectibleObject& obj)
{
return &T::__metaclass;
}
template <typename T>
inline a8::reflect::Class** get_pp_generic_class(const T& obj)
{
return nullptr;
}
}
}
#define my_offsetof2(TYPE, MEMBER) \
((size_t)((char *)&(((TYPE *)0x10)->MEMBER) - (char*)0x10))
#define container_of2(ptr, type, member) ({ \
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - my_offsetof2(type,member) );})
#define BEGIN_MSG_CLASS(classname, fieldnum) \
{ \
a8::reflect::Class *metaclass = new a8::reflect::Class(#classname, fieldnum, 0); \
metaclass->create =&a8::reflect::_create<classname>; \
metaclass->destroy =&a8::reflect::_destroy<classname>; \
metaclass->copy =&a8::reflect::_copy<classname>; \
classname::__metaclass = metaclass; \
classname p;
#define END_MSG_CLASS() \
}
#define BEGIN_MFMSG_CLASS(classname, fieldnum) \
{ \
a8::reflect::Class *metaclass = new a8::reflect::Class(#classname, fieldnum, 0); \
metaclass->create =&a8::reflect::_create<classname>; \
metaclass->destroy =&a8::reflect::_destroy<classname>; \
metaclass->copy =&a8::reflect::_copy<classname>; \
/*classname::__metaclass = metaclass;*/ \
/*assert(classname::CLSID < 1024);*/ \
/*s_mfclass_metaclasses[0] = metaclass;*/ \
classname p;
#define END_MFMSG_CLASS() \
}
#define DEFINE_SIMPLE_FIELD(fieldidx, fieldname, type) \
metaclass->SetField(fieldidx, \
#fieldname, \
type, \
a8::reflect::EST_SIMPLE, \
my_offsetof2(decltype(p), fieldname), \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL);
#define DEFINE_SIMPLE_POINTER_FIELD(fieldidx, fieldname, type) \
metaclass->SetField(fieldidx, \
#fieldname, \
type, \
a8::reflect::EST_SIMPLE_POINTER, \
my_offsetof2(decltype(p), fieldname), \
NULL, \
NULL, \
NULL, \
NULL, \
NULL, \
NULL);
#define DEFINE_CONTAINRER_FIELD(fieldidx, fieldname, type) \
metaclass->SetField(fieldidx, \
#fieldname, \
type, \
a8::reflect::EST_CONTAINRER, \
my_offsetof2(decltype(p), fieldname), \
a8::reflect::get_pp_generic_class<decltype(p.fieldname)>(p.fieldname), \
&a8::reflect::_create<decltype(p.fieldname)>, \
&a8::reflect::_destroy<decltype(p.fieldname)>, \
&a8::reflect::_size<decltype(p.fieldname)>, \
&a8::reflect::_for_each<decltype(p.fieldname)> , \
&a8::reflect::_push_back<decltype(p.fieldname)> \
);
#define DEFINE_CONTAINRER_POINTER_FIELD(fieldidx, fieldname, type) \
metaclass->SetField(fieldidx, \
#fieldname, \
type, \
a8::reflect::EST_CONTAINRER_POINTER, \
my_offsetof2(decltype(p), fieldname), \
a8::reflect::get_pp_generic_class<decltype(p.fieldname)>(p.fieldname), \
&a8::reflect::_create<decltype(p.fieldname)>, \
&a8::reflect::_destroy<decltype(p.fieldname)>, \
&a8::reflect::_size<decltype(p.fieldname)>, \
&a8::reflect::_for_each<decltype(p.fieldname)> , \
&a8::reflect::_push_back<decltype(p.fieldname)> \
);