#include "cdutils_parser.h" #include "cdutils_types.h" #include "pifile.h" #include "piiobytearray.h" #include "piiostring.h" using namespace CDUtils; enum Phase { eName = 1, eBracketOpen, eBracketClose, eMemberName, eMemberEqual, eMemberValue, eMemberComma, eComment, eMultiComment }; void removeComment(PIString & line, PIString * type, PIString * comment) { int ci = line.find("//"); if (ci >= 0) { if (comment) *comment = line.right(line.size_s() - ci - 2); line.cutRight(line.size_s() - ci).trim(); if (type && comment && !line.isEmpty()) { *type = comment->takeLeft(1); comment->trim(); } } } void parseEnumLine(PIString & line, int * value, PIString * type, PIString * comment) { removeComment(line, type, comment); int ci = line.find("="); if (ci >= 0) { if (value) *value = line.right(line.size_s() - ci - 1).trim().toInt(); line.cutRight(line.size_s() - ci).trim(); } if (line.trim().endsWith(",")) line.cutRight(1); } void parseInsert(PIString line, PIString & alias, PIStringList & out) { out.clear(); int ci = line.find("="); if (ci < 0) return; alias = line.right(line.size_s() - ci - 1).trim(); line.cutRight(line.size_s() - ci).trim(); while (line.find("[") > 0) { int is = line.find("["), ie = line.find("]"); PIString arr = line.mid(is + 1, ie - is - 1); out << arr; line.cutMid(is, ie - is + 1); } if (!line.isEmpty()) out.insert(0, line); } PIVector enumValues(const PIString & e, const PIMap & sections, PIStringList & enames) { PIVector ret; enames.clear(); if (sections.contains(e)) { ret = sections.at(e).indexes(); enames = sections.at(e).index_names(); } else { int v = e.toInt(); if (v < 2) return ret; for (int i = 0; i < v; ++i) { ret << i; enames << ""; // PIString::fromNumber(i); } } return ret; } CDSection CDParser::parse(PIIODevice * d, int cdsection_type) { CDType::cdT et = (CDType::cdT)cdsection_type; if (!d) return CDSection(et); if (!d->canRead()) return CDSection(et); // piCout << "[CDSection] parse start"; CDSection cs(et); CDType ck; PIMap sections; PIMap enum_values; PIString content, line, alias, type, comment; PIStringList iarr; if (PIStringAscii(d->className()) == PIStringAscii("PIFile")) { PIByteArray c = ((PIFile *)d)->readAll(); c << uchar(0); content = PIString::fromUTF8((const char *)c.data()); } if (PIStringAscii(d->className()) == PIStringAscii("PIIOString")) content = *(((PIIOString *)d)->string()); if (PIStringAscii(d->className()) == PIStringAscii("PIIOByteArray")) content = PIString(*(((PIIOByteArray *)d)->byteArray())); PIIOString ios(&content); // int phase = 0; int cind = -1; while ((cind = content.find("enum", cind)) >= 0) { ios.seek(cind); line = ios.readLine().trim(); type.clear(); comment.clear(); removeComment(line, &type, &comment); if (line.find("{") < 0) { cind += 4; continue; } line.cutLeft(line.find("enum") + 4).trim(); line.cutRight(line.size_s() - line.find("{")).trim(); if (line.isEmpty()) { cind += 4; continue; } cs = CDSection(et); cs.name = line; // piCout << "enum" << cs.name; int cev = 0; // cevalues.clear(); while (!ios.isEnd()) { line = ios.readLine().trim(); comment.clear(); removeComment(line, &type, &comment); if (line.find("}") >= 0) break; if (line.isEmpty()) { if (comment.find("=") >= 0) { parseInsert(comment, alias, iarr); if (!iarr.isEmpty()) { // piCout << "#" << enum_values; if (!enum_values.contains(alias)) { piCout << "Parse error: can`t find section alias \"" << alias << "\"!"; return CDSection(et); } if (!sections.contains(iarr.front())) { piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!"; return CDSection(et); } // piCout << "insert" << alias << iarr; int aval = enum_values.value(alias); CDSection is = sections.value(iarr.take_front()), ts; int ibpos = is.name.size_s(); piForeachRC(PIString & a, iarr) { PIStringList enames; PIVector evals = enumValues(a, sections, enames); // piCout << a << evals; for (int i = 0; i < evals.size_s(); ++i) { ts.section(evals[i]) = is; ts.section(evals[i]).alias = enames[i]; } ts.name = is.name; ts.name.insert(ibpos, PIString('[') + a + ']'); is = ts; ts = CDSection(et); } is.alias = alias; cs.section(aval) = is; } } } else { parseEnumLine(line, &cev, &type, &comment); // piCout << line << "=" << cev << "//" << type << comment; ck = CDType(cev, line, type, "", "", comment, et); if (type == "e") { if (comment.startsWith("${")) { comment.cutLeft(1); PIString en = comment.inBrackets('{', '}'); comment.cutLeft(en.size_s() + 2).trim(); ck.setEnumValues(sections.value(en).enumValues()); ck.setComment(comment); // piCout << "enum" << en << ck.enumValues(); } } cs[cev] = ck; // cevalues[line] = cev; enum_values[line] = cev; ++cev; } } // piCout << cs.name << cs.k; sections[cs.name] = cs; // piCout << "#" << cevalues; // enum_values << cevalues; cind += 4; } // piCout << "[CDSection] parse end"; switch (et) { case CDType::cdK: return sections.value("KDescription"); case CDType::cdX: return sections.value("XDescription"); case CDType::cdC: return sections.value("CDescription"); case CDType::cdM: return sections.value("MDescription"); default: return CDSection(et); } return CDSection(et); }