184 lines
5.1 KiB
C++
184 lines
5.1 KiB
C++
#include "cdutils_parser.h"
|
|
#include "cdutils_types.h"
|
|
#include "piiostring.h"
|
|
#include "pifile.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<int> enumValues(const PIString & e, const PIMap<PIString, CDSection> & sections, PIStringList & enames) {
|
|
PIVector<int> ret;
|
|
enames.clear();
|
|
if (sections.contains(e)) {
|
|
ret = sections[e].indexes();
|
|
enames = sections[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();
|
|
if (!d->canRead()) return CDSection();
|
|
//piCout << "[CDSection] parse start";
|
|
CDSection cs;
|
|
CDType ck;
|
|
PIMap<PIString, CDSection> sections;
|
|
PIMap<PIString, int> 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());
|
|
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();
|
|
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();
|
|
}
|
|
if (!sections.contains(iarr.front())) {
|
|
piCout << "Parse error: can`t find section \"" << iarr.front() << "\"!";
|
|
return CDSection();
|
|
}
|
|
//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<int> 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();
|
|
}
|
|
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);
|
|
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");
|
|
default: return CDSection();
|
|
}
|
|
return CDSection();
|
|
}
|