add relect
This commit is contained in:
parent
5c144d4357
commit
966f7119e7
276
a8/reflect.h
Normal file
276
a8/reflect.h
Normal file
@ -0,0 +1,276 @@
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace a8
|
||||
{
|
||||
namespace reflect
|
||||
{
|
||||
|
||||
enum FieldType
|
||||
{
|
||||
ET_INT32 = 1,
|
||||
ET_UINT32 = 2,
|
||||
ET_INT64 = 3,
|
||||
ET_UINT64 = 4,
|
||||
ET_DOUBLE = 5,
|
||||
ET_STRING = 6,
|
||||
ET_CLASS = 7,
|
||||
ET_INTERFACE = 8,
|
||||
};
|
||||
|
||||
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_;
|
||||
}
|
||||
|
||||
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*)
|
||||
)
|
||||
{
|
||||
a8::reflect::Field *p = fields_ + fieldidx;
|
||||
p->field_name = fieldname;
|
||||
p->type = type;
|
||||
p->subtype = subtype;
|
||||
p->offset = offset;
|
||||
p->pp_generic_class = pp_generic_class;
|
||||
p->create = create;
|
||||
p->destroy = destroy;
|
||||
p->size = size;
|
||||
p->for_each = for_each;
|
||||
p->push_back = push_back;
|
||||
}
|
||||
|
||||
int GetFieldIdx(int offset)
|
||||
{
|
||||
for (int i = 0; i < fieldnum_; i++) {
|
||||
if (fields_[i].offset == offset) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* ClassName()
|
||||
{
|
||||
return class_name_;
|
||||
}
|
||||
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, classname::CLSID); \
|
||||
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, classname::CLSID); \
|
||||
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[classname::CLSID] = 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)> \
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user