diff --git a/CMakeLists.txt b/CMakeLists.txt index d1491cf5..cd352a25 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ if (POLICY CMP0177) endif() project(PIP) set(PIP_MAJOR 5) -set(PIP_MINOR 2) -set(PIP_REVISION 1) +set(PIP_MINOR 3) +set(PIP_REVISION 0) set(PIP_SUFFIX ) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/code/picodeinfo.cpp b/libs/main/code/picodeinfo.cpp index 7ecb800e..2c7990b7 100644 --- a/libs/main/code/picodeinfo.cpp +++ b/libs/main/code/picodeinfo.cpp @@ -55,11 +55,12 @@ PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name PICodeInfo::__Storage__::__Storage__() { - classesInfo = new PIMap; - enumsInfo = new PIMap; - accessValueFunctions = new PIMap; - accessTypeFunctions = new PIMap; - (*enumsInfo)[""] = new EnumInfo(); + classesInfo = new PIMap; + enumsInfo = new PIMap; + accessValueFunctions = new PIMap; + accessTypeFunctions = new PIMap; + accessOffsetFunctions = new PIMap; + (*enumsInfo)[""] = new EnumInfo(); } @@ -70,6 +71,7 @@ PICodeInfo::__Storage__::~__Storage__() { piDeleteSafety(enumsInfo); piDeleteSafety(accessValueFunctions); piDeleteSafety(accessTypeFunctions); + piDeleteSafety(accessOffsetFunctions); } diff --git a/libs/main/code/picodeinfo.h b/libs/main/code/picodeinfo.h index 715bff71..96c275ae 100644 --- a/libs/main/code/picodeinfo.h +++ b/libs/main/code/picodeinfo.h @@ -58,6 +58,7 @@ typedef PIFlags TypeFlags; typedef PIMap MetaMap; typedef PIByteArray (*AccessValueFunction)(const void *, const char *); typedef const char * (*AccessTypeFunction)(const char *); +typedef int (*AccessOffsetFunction)(const char *); //! \~english Type information @@ -289,6 +290,7 @@ public: PIMap * enumsInfo; PIMap * accessValueFunctions; PIMap * accessTypeFunctions; + PIMap * accessOffsetFunctions; private: NO_COPY_CLASS(__Storage__) @@ -314,6 +316,10 @@ static const PIMap & accessValueF static const PIMap & accessTypeFunctions() { return *(__Storage__::instance()->accessTypeFunctions); } + +static const PIMap & accessOffsetFunctions() { + return *(__Storage__::instance()->accessOffsetFunctions); +} } ; diff --git a/utils/code_model_generator/common.cpp b/utils/code_model_generator/common.cpp index 06039fb1..c2204632 100644 --- a/utils/code_model_generator/common.cpp +++ b/utils/code_model_generator/common.cpp @@ -46,8 +46,15 @@ const char help_string[] = "-M (Metainfo)\n" "with simple << and >> operators.\n" "If PIMETA(no-stream) presence, then class or struct ignored.\n" "\n" + "-J (JSON serialization)\n" + "Generate serialize/deserialize methods for classes and structures.\n" + "These methods uses by PIJSON::serialize(T v) and PIJSON::deserialize(json)\n" + "allow automatic conversion to/from PIJSON. Use member name as key.\n" + "Member can be skipped by providing PIMETA(id=-).\n" + "If PIMETA(no-json) presence, then class or struct ignored.\n" + "\n" "-G (Getter functions)\n" - "Generate anonymous access methods for member typenames and values.\n" + "Generate anonymous access methods for member typenames, values and offsets.\n" "Every class or struct member typename can be obtained with:\n" "const char * getMemberType(const char * class_name, const char * member_name)\n" "Member value can be obtained with:\n" @@ -55,6 +62,7 @@ const char help_string[] = "-M (Metainfo)\n" "where \"p\" - class or struct pointer, and returns serialized value.\n" "PIVariant getMemberAsVariant(const void * p, const char * class_name, const char * member_name)\n" "where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n" + "If PIMETA(no-getter) presence, then class or struct ignored.\n" ""; diff --git a/utils/code_model_generator/getter.cpp b/utils/code_model_generator/getter.cpp index a16ab0d1..5f76f16c 100644 --- a/utils/code_model_generator/getter.cpp +++ b/utils/code_model_generator/getter.cpp @@ -63,8 +63,26 @@ void writeGetterValueMembers(Runtime & rt, const PICodeParser::Entity * e, PIStr } +void writeGetterOffsetMembers(Runtime & rt, const PICodeParser::Entity * e, PIString entity_name, PIString var_prefix) { + if (var_prefix.isNotEmpty() && !var_prefix.endsWith('.')) var_prefix += "."; + PISet used_id; + for (const PICodeParser::Member & m: e->members) { + if (m.is_type_ptr || !m.dims.isEmpty() || m.isBitfield() || (m.visibility != PICodeParser::Public)) continue; + auto type = findEntity(rt, m.type); + if (type) { + if (type->is_anonymous) { + writeGetterOffsetMembers(rt, type, entity_name, var_prefix + m.name); + continue; + } + } + rt.ts << "\tif (strcmp(name, \"" << var_prefix << m.name << "\") == 0) "; + rt.ts << "return PICODEINFO_OFFSET(" << entity_name << ", " << var_prefix << m.name << ");\n"; + } +} + + void makeGetterType(Runtime & rt, const PICodeParser::Entity * e) { - if (!needClassStream(e)) return; + if (!needClassGetter(e)) return; rt.ts << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n"; rt.ts << "\tif (!name) return \"\";\n"; writeGetterTypeMembers(rt, e); @@ -73,7 +91,7 @@ void makeGetterType(Runtime & rt, const PICodeParser::Entity * e) { void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e) { - if (!needClassStream(e)) return; + if (!needClassGetter(e)) return; rt.ts << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n"; rt.ts << "\tPIByteArray ret;\n"; rt.ts << "\tif (!p || !name) return ret;\n"; @@ -81,3 +99,23 @@ void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e) { writeGetterValueMembers(rt, e); rt.ts << "\treturn ret;\n}\n"; } + + +void makeGetterOffset(Runtime & rt, const PICodeParser::Entity * e) { + if (!needClassGetter(e)) return; + rt.ts << "\nint getterOffset" << toCName(e->name) << "(const char * name) {\n"; + rt.ts << "\tif (!name) return 0;\n"; + writeGetterOffsetMembers(rt, e, e->name); + rt.ts << "\treturn 0;\n}\n"; +} + + +bool needClassGetter(const PICodeParser::Entity * e) { + if (e->meta.contains("no-getter")) return false; + for (const PICodeParser::Member & m: e->members) { + if (m.is_type_ptr || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue; + if (m.attributes[PICodeParser::Static]) continue; + return true; + } + return false; +} diff --git a/utils/code_model_generator/getter.h b/utils/code_model_generator/getter.h index 8e7bbe93..1e34d770 100644 --- a/utils/code_model_generator/getter.h +++ b/utils/code_model_generator/getter.h @@ -24,7 +24,10 @@ void writeGetterTypeMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {}); void writeGetterValueMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {}); +void writeGetterOffsetMembers(Runtime & rt, const PICodeParser::Entity * e, PIString entity_name, PIString var_prefix = {}); void makeGetterType(Runtime & rt, const PICodeParser::Entity * e); void makeGetterValue(Runtime & rt, const PICodeParser::Entity * e); +void makeGetterOffset(Runtime & rt, const PICodeParser::Entity * e); +bool needClassGetter(const PICodeParser::Entity * e); #endif diff --git a/utils/code_model_generator/main.cpp b/utils/code_model_generator/main.cpp index 8b70bd9a..1240c760 100755 --- a/utils/code_model_generator/main.cpp +++ b/utils/code_model_generator/main.cpp @@ -66,11 +66,15 @@ bool writeModel(PICodeParser & parser, if (meta || enums || getters) { if (getters) { ts << "\n\n// Getter funtions\n"; + ts << "\n#define PICODEINFO_OFFSET(type, member) reinterpret_cast(&reinterpret_cast((((type " + "*)nullptr)->member)))\n"; for (const PICodeParser::Entity * e: parser.entities) { if (e->is_anonymous || e->name.startsWith("_PI")) continue; makeGetterType(rt, e); makeGetterValue(rt, e); + makeGetterOffset(rt, e); } + ts << "\n#undef PICODEINFO_OFFSET\n"; } ts << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n"; ts << "\tstatic __ClassInfo_" << defname << "_Initializer__::Content content;\n"; @@ -83,6 +87,7 @@ bool writeModel(PICodeParser & parser, if (getters) { ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; + ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n"; } if (meta) { @@ -109,8 +114,10 @@ bool writeModel(PICodeParser & parser, for (const PICodeParser::Entity * e: parser.entities) { if (!needClassStream(e)) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue; - ts << "\tci_avf[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n"; - ts << "\tci_atf[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n"; + auto cname = toCName(e->name); + ts << "\tci_avf[\"" << e->name << "\"] = getterValue" << cname << ";\n"; + ts << "\tci_atf[\"" << e->name << "\"] = getterType" << cname << ";\n"; + ts << "\tci_aof[\"" << e->name << "\"] = getterOffset" << cname << ";\n"; } } ts << "}\n\n"; @@ -121,6 +128,7 @@ bool writeModel(PICodeParser & parser, if (getters) { ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; + ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n"; } if (meta) { ts << "\n// Classes clean\n"; @@ -146,6 +154,7 @@ bool writeModel(PICodeParser & parser, if (e->is_anonymous || e->name.startsWith("_PI")) continue; ts << "\tci_avf.remove(\"" << e->name << "\");\n"; ts << "\tci_atf.remove(\"" << e->name << "\");\n"; + ts << "\tci_aof.remove(\"" << e->name << "\");\n"; } } ts << "}\n";