decompose pip_cmg

add serialization/pijsonserialization.h for JSON de/serialization
add -J flag for pip_cmg to make JSON serialization methods
not finished yet, but basically workable now
This commit is contained in:
2025-08-02 18:48:38 +03:00
parent 19daab173c
commit cf25cacc17
19 changed files with 1348 additions and 475 deletions

View File

@@ -0,0 +1,125 @@
/*
PIP - Platform Independent Primitives
Code model generator
Ivan Pelipenko peri4ko@yandex.ru
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "json.h"
#include "pitranslator.h"
bool writeClassJSONMembersOut(Runtime & rt, const PICodeParser::Entity * e) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue;
// if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (m.dims.isEmpty()) {
rt.ts << "\tret[\"" << m.name << "\"] = piSerializeJSON(v." << m.name << ");\n";
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
rt.ts << "\tret[\"" << m.name << "\"] = piSerializeJSON(PIVector<" << ptype << " >((const " << ptype << " *)(v." << m.name
<< "), " << size << "));\n";
}
if (is_union) break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassJSONMembersOut(rt, ce)) return false;
}
return true;
}
bool writeClassJSONMembersIn(Runtime & rt, const PICodeParser::Entity * e) {
PIVector<PICodeParser::Member> ml;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || (m.visibility != PICodeParser::Public)) continue;
ml << m;
}
bool is_union = e->type == "union";
PISet<int> used_id;
for (const PICodeParser::Member & m: ml) {
if (is_union && m.isBitfield()) continue;
if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue;
// if (m.meta.contains("id")) cnt = m.meta.value("id").toInt();
if (m.dims.isEmpty()) {
rt.ts << "\tpiDeserializeJSON(v." << m.name << ", js[\"" << m.name << "\"]);\n";
} else {
PIString ptype = m.type.left(m.type.find('[')).trim();
PIString size = m.dims[0];
for (int i = 1; i < m.dims.size_s(); ++i) {
size += " * ";
size += m.dims[i];
}
rt.ts << "\t{\n\t\tPIVector<" << ptype << " > d;\n";
rt.ts << "\t\tpiDeserializeJSON(d, js[\"" << m.name << "\"]);\n";
rt.ts << "\t\tint cnt = piMini(d.size_s(), " << size << ");\n";
rt.ts << "\t\tfor (int i = 0; i < cnt; ++i)\n";
rt.ts << "\t\t\t((" << ptype << " *)(v." << m.name << "))[i] = d[i];\n";
rt.ts << "\t}\n";
}
if (is_union) break;
}
if (is_union) return true;
for (const PICodeParser::Entity * ce: e->children) {
if (ce->has_name) continue;
if (!writeClassJSONMembersIn(rt, ce)) return false;
}
return true;
}
bool needClassJSON(const PICodeParser::Entity * e) {
if (e->meta.contains("no-json")) return false;
for (const PICodeParser::Member & m: e->members) {
if (m.is_type_ptr || m.isBitfield() || !m.dims.isEmpty() || (m.visibility != PICodeParser::Public)) continue;
if (m.attributes[PICodeParser::Static]) continue;
if (m.meta.value("id") == "-") continue;
return true;
}
return false;
}
bool makeClassJSON(Runtime & rt, const PICodeParser::Entity * e) {
if (!needClassJSON(e)) return true;
rt.ts << "\ntemplate<> inline PIJSON piSerializeJSON(const " << e->name << " & v) {\n";
rt.ts << "\tPIJSON ret;\n";
if (!writeClassJSONMembersOut(rt, e)) return false;
rt.ts << "\treturn ret;\n}\n";
rt.ts << "\ntemplate<> inline void piDeserializeJSON(" << e->name << " & v, const PIJSON & js) {\n";
if (!writeClassJSONMembersIn(rt, e)) return false;
rt.ts << "}\n";
return true;
}