PICODEINFO::accessOffsetFunction

add offset generation in pip_cmg for retrieve bytes offset of struct member
add pip_cmg -V doc
This commit is contained in:
2025-09-18 17:12:35 +03:00
parent 7083b2c32b
commit 5f3baa5580
7 changed files with 78 additions and 12 deletions

View File

@@ -5,8 +5,8 @@ if (POLICY CMP0177)
endif() endif()
project(PIP) project(PIP)
set(PIP_MAJOR 5) set(PIP_MAJOR 5)
set(PIP_MINOR 2) set(PIP_MINOR 3)
set(PIP_REVISION 1) set(PIP_REVISION 0)
set(PIP_SUFFIX ) set(PIP_SUFFIX )
set(PIP_COMPANY SHS) set(PIP_COMPANY SHS)
set(PIP_DOMAIN org.SHS) set(PIP_DOMAIN org.SHS)

View File

@@ -55,11 +55,12 @@ PIVariant PICodeInfo::getMemberAsVariant(const void * p, const char * class_name
PICodeInfo::__Storage__::__Storage__() { PICodeInfo::__Storage__::__Storage__() {
classesInfo = new PIMap<PIConstChars, ClassInfo *>; classesInfo = new PIMap<PIConstChars, ClassInfo *>;
enumsInfo = new PIMap<PIConstChars, EnumInfo *>; enumsInfo = new PIMap<PIConstChars, EnumInfo *>;
accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>; accessValueFunctions = new PIMap<PIConstChars, AccessValueFunction>;
accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>; accessTypeFunctions = new PIMap<PIConstChars, AccessTypeFunction>;
(*enumsInfo)[""] = new EnumInfo(); accessOffsetFunctions = new PIMap<PIConstChars, AccessOffsetFunction>;
(*enumsInfo)[""] = new EnumInfo();
} }
@@ -70,6 +71,7 @@ PICodeInfo::__Storage__::~__Storage__() {
piDeleteSafety(enumsInfo); piDeleteSafety(enumsInfo);
piDeleteSafety(accessValueFunctions); piDeleteSafety(accessValueFunctions);
piDeleteSafety(accessTypeFunctions); piDeleteSafety(accessTypeFunctions);
piDeleteSafety(accessOffsetFunctions);
} }

View File

@@ -58,6 +58,7 @@ typedef PIFlags<PICodeInfo::TypeFlag> TypeFlags;
typedef PIMap<PIString, PIString> MetaMap; typedef PIMap<PIString, PIString> MetaMap;
typedef PIByteArray (*AccessValueFunction)(const void *, const char *); typedef PIByteArray (*AccessValueFunction)(const void *, const char *);
typedef const char * (*AccessTypeFunction)(const char *); typedef const char * (*AccessTypeFunction)(const char *);
typedef int (*AccessOffsetFunction)(const char *);
//! \~english Type information //! \~english Type information
@@ -289,6 +290,7 @@ public:
PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo; PIMap<PIConstChars, PICodeInfo::EnumInfo *> * enumsInfo;
PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions; PIMap<PIConstChars, PICodeInfo::AccessValueFunction> * accessValueFunctions;
PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions; PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> * accessTypeFunctions;
PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> * accessOffsetFunctions;
private: private:
NO_COPY_CLASS(__Storage__) NO_COPY_CLASS(__Storage__)
@@ -314,6 +316,10 @@ static const PIMap<PIConstChars, PICodeInfo::AccessValueFunction> & accessValueF
static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() { static const PIMap<PIConstChars, PICodeInfo::AccessTypeFunction> & accessTypeFunctions() {
return *(__Storage__::instance()->accessTypeFunctions); return *(__Storage__::instance()->accessTypeFunctions);
} }
static const PIMap<PIConstChars, PICodeInfo::AccessOffsetFunction> & accessOffsetFunctions() {
return *(__Storage__::instance()->accessOffsetFunctions);
}
} }
; ;

View File

@@ -46,8 +46,15 @@ const char help_string[] = "-M (Metainfo)\n"
"with simple << and >> operators.\n" "with simple << and >> operators.\n"
"If PIMETA(no-stream) presence, then class or struct ignored.\n" "If PIMETA(no-stream) presence, then class or struct ignored.\n"
"\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" "-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" "Every class or struct member typename can be obtained with:\n"
"const char * getMemberType(const char * class_name, const char * member_name)\n" "const char * getMemberType(const char * class_name, const char * member_name)\n"
"Member value can be obtained with:\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" "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" "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" "where \"p\" - class or struct pointer, and returns value as registered PIVariant.\n"
"If PIMETA(no-getter) presence, then class or struct ignored.\n"
""; "";

View File

@@ -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<int> 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) { 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 << "\nconst char * getterType" << toCName(e->name) << "(const char * name) {\n";
rt.ts << "\tif (!name) return \"\";\n"; rt.ts << "\tif (!name) return \"\";\n";
writeGetterTypeMembers(rt, e); writeGetterTypeMembers(rt, e);
@@ -73,7 +91,7 @@ void makeGetterType(Runtime & rt, const PICodeParser::Entity * e) {
void makeGetterValue(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 << "\nPIByteArray getterValue" << toCName(e->name) << "(const void * p, const char * name) {\n";
rt.ts << "\tPIByteArray ret;\n"; rt.ts << "\tPIByteArray ret;\n";
rt.ts << "\tif (!p || !name) return 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); writeGetterValueMembers(rt, e);
rt.ts << "\treturn ret;\n}\n"; 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;
}

View File

@@ -24,7 +24,10 @@
void writeGetterTypeMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {}); void writeGetterTypeMembers(Runtime & rt, const PICodeParser::Entity * e, PIString var_prefix = {});
void writeGetterValueMembers(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 makeGetterType(Runtime & rt, const PICodeParser::Entity * e);
void makeGetterValue(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 #endif

View File

@@ -66,11 +66,15 @@ bool writeModel(PICodeParser & parser,
if (meta || enums || getters) { if (meta || enums || getters) {
if (getters) { if (getters) {
ts << "\n\n// Getter funtions\n"; ts << "\n\n// Getter funtions\n";
ts << "\n#define PICODEINFO_OFFSET(type, member) reinterpret_cast<size_t>(&reinterpret_cast<const char &>((((type "
"*)nullptr)->member)))\n";
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (e->is_anonymous || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
makeGetterType(rt, e); makeGetterType(rt, e);
makeGetterValue(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 << "\n\n// Metainformation\n\n__ClassInfo_" << defname << "_Initializer__::__ClassInfo_" << defname << "_Initializer__() {\n";
ts << "\tstatic __ClassInfo_" << defname << "_Initializer__::Content content;\n"; ts << "\tstatic __ClassInfo_" << defname << "_Initializer__::Content content;\n";
@@ -83,6 +87,7 @@ bool writeModel(PICodeParser & parser,
if (getters) { if (getters) {
ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n";
ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n";
ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n";
} }
if (meta) { if (meta) {
@@ -109,8 +114,10 @@ bool writeModel(PICodeParser & parser,
for (const PICodeParser::Entity * e: parser.entities) { for (const PICodeParser::Entity * e: parser.entities) {
if (!needClassStream(e)) continue; if (!needClassStream(e)) continue;
if (e->is_anonymous || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
ts << "\tci_avf[\"" << e->name << "\"] = getterValue" << toCName(e->name) << ";\n"; auto cname = toCName(e->name);
ts << "\tci_atf[\"" << e->name << "\"] = getterType" << toCName(e->name) << ";\n"; 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"; ts << "}\n\n";
@@ -121,6 +128,7 @@ bool writeModel(PICodeParser & parser,
if (getters) { if (getters) {
ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n"; ts << "\tauto & ci_avf(*ci_ins->accessValueFunctions);\n";
ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n"; ts << "\tauto & ci_atf(*ci_ins->accessTypeFunctions);\n";
ts << "\tauto & ci_aof(*ci_ins->accessOffsetFunctions);\n";
} }
if (meta) { if (meta) {
ts << "\n// Classes clean\n"; ts << "\n// Classes clean\n";
@@ -146,6 +154,7 @@ bool writeModel(PICodeParser & parser,
if (e->is_anonymous || e->name.startsWith("_PI")) continue; if (e->is_anonymous || e->name.startsWith("_PI")) continue;
ts << "\tci_avf.remove(\"" << e->name << "\");\n"; ts << "\tci_avf.remove(\"" << e->name << "\");\n";
ts << "\tci_atf.remove(\"" << e->name << "\");\n"; ts << "\tci_atf.remove(\"" << e->name << "\");\n";
ts << "\tci_aof.remove(\"" << e->name << "\");\n";
} }
} }
ts << "}\n"; ts << "}\n";