258 lines
9.9 KiB
C++
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)> \
|
|
);
|