#include "pch.h" #ifndef XG_REFLECT_CPP #define XG_REFLECT_CPP /////////////////////////////////////////////////////////////////// #include "Reflect.h" Object::~Object() { } string Object::toString() const { char buffer[16]; sprintf(buffer, "%p", this); return buffer; } const char* Object::getClassName() const { #ifdef _MSC_VER return typeid(*this).name() + 6; #else const char* str = typeid(*this).name(); while (*str >= '0' && *str <= '9') str++; return str; #endif } class ReflectAttrMap { friend class ReflectHelper; public: class Item { public: const char* type; const char* name; Item() : type(NULL), name(NULL) { } }; class Data : public SpinMutex { public: int ofs; int end; ReflectKey key; mutable Item arr[10000]; vector vec; public: Data(const Data& obj) { ofs = obj.ofs; end = obj.end; key = obj.key; } Data(ReflectKey _key = 0) : ofs(-1), end(-1), key(_key) { } public: vector getArrList() { if (end >= ofs) return vec; lock(); vector res; for (int i = 0; i <= ofs; i++) { const Item& item = arr[i]; if (item.name) res.push_back(ReflectItem(i, item.type, item.name)); } vec = res; end = ofs; unlock(); return res; } void add(int offset, const char* type, const char* name) { if (ofs >= offset) return; if (strcmp(type, "int") && strcmp(type, "bool") && strcmp(type, "float") && strcmp(type, "double") && strcmp(type, "string")) type = "object"; assert(offset < ARR_LEN(arr)); Item& item = arr[offset]; lock(); ofs = offset; item.type = type; item.name = name; unlock(); } }; protected: SpinMutex mtx; vector arr[10000]; vector getAttrList(ReflectKey key) { vector& vec = arr[(key >> 3) % ARR_LEN(arr)]; for (Data& item : vec) if (key == item.key) return item.getArrList(); return vector(); } void add(Object* self, void* data, const char* type, const char* name) { ReflectKey key = ReflectHelper::GetKey(self); vector& vec = arr[(key >> 3) % ARR_LEN(arr)]; for (Data& item : vec) { if (key == item.key) { item.add((char*)(data) - (char*)(self), type, name); return; } } { SpinLocker lk(mtx); for (Data& item : vec) { if (key == item.key) { item.add((char*)(data) - (char*)(self), type, name); return; } } vec.push_back(Data(key)); vec.back().add((char*)(data) - (char*)(self), type, name); } } void add(Object* self, Object* data, const char* type, const char* name) { ReflectKey key = ReflectHelper::GetKey(data); vector& vec = arr[(key >> 3) % ARR_LEN(arr)]; if (vec.size() > 0) add(self, (void*)(data), type, name); } }; string ReflectItem::get(const void* obj) const { char* dest = (char*)(obj) + offset; if (type == NULL || strcmp(type, "object") == 0) return ""; if (strcmp(type, "int") == 0) return to_string(*(int*)(dest)); if (strcmp(type, "bool") == 0) return *(bool*)(dest) ? "true" : "false"; if (strcmp(type, "float") == 0) return to_string(*(float*)(dest)); if (strcmp(type, "double") == 0) return to_string(*(double*)(dest)); return *(string*)(dest); } bool ReflectItem::set(void* obj, int val) const { char* dest = (char*)(obj) + offset; if (type == NULL || strcmp(type, "object") == 0) return false; if (strcmp(type, "int") == 0) { *(int*)(dest) = val; } else if (strcmp(type, "bool") == 0) { *(bool*)(dest) = val ? true : false; } else if (strcmp(type, "float") == 0) { *(float*)(dest) = val; } else if (strcmp(type, "double") == 0) { *(double*)(dest) = val; } else { *(string*)(dest) = to_string(val); } return true; } bool ReflectItem::set(void* obj, double val) const { char* dest = (char*)(obj) + offset; if (type == NULL || strcmp(type, "object") == 0) return false; if (strcmp(type, "int") == 0) { *(int*)(dest) = val; } else if (strcmp(type, "bool") == 0) { *(bool*)(dest) = val < -0.000001 || val > 0.000001; } else if (strcmp(type, "float") == 0) { *(float*)(dest) = val; } else if (strcmp(type, "double") == 0) { *(double*)(dest) = val; } else { *(string*)(dest) = to_string(val); } return true; } bool ReflectItem::set(void* obj, const char* val) const { char* dest = (char*)(obj) + offset; if (val == NULL || type == NULL || strcmp(type, "object") == 0) return false; if (strcmp(type, "string") == 0) { *(string*)(dest) = val; } else { if (*val == 0) return true; if (strcmp(type, "int") == 0) { *(int*)(dest) = atoi(val); } else if (strcmp(type, "bool") == 0) { *(bool*)(dest) = strcasecmp(val, "true") == 0; } else if (strcmp(type, "float") == 0) { *(float*)(dest) = atof(val); } else { *(double*)(dest) = atof(val); } } return true; } static ReflectAttrMap attrmap; string ReflectHelper::GetAttrString(ReflectKey key) { string res; string gap = ","; vector vec = attrmap.getAttrList(key); if (vec.empty()) return res; for (auto& item : vec) res += gap + item.getName(); return res.substr(gap.length()); } vector ReflectHelper::GetAttrList(ReflectKey key) { return attrmap.getAttrList(key); } ReflectHelper::ReflectHelper(Object* self, void* data, const char* type, const char* name) { attrmap.add(self, data, type, name); } ReflectHelper::ReflectHelper(Object* self, Object* data, const char* type, const char* name) { attrmap.add(self, data, type, name); } /////////////////////////////////////////////////////////////////// #endif