Bom,minhas principais recomendações agora são:extenda um pouco o programa,melhore a separação de classes e melhore a estrutura do XML para facilitar o parsing.
Eis tudo parcialmente demonstrado para que você possa implementar:
Código:
<Processes>
<Process name="Exemplo.exe" running="true">
<Offset address="A0FF" size="10" fill="NOP" raw="false">AAA</Offset>
<Offset address="B0F1" size="+3" repeat="2" fill="NOP" raw="false">AAA</Offset>
</Process>
<Process name="Exemplo2.exe" running="false">
<Offset address="B010" size="6" fill="NULL" raw="true" page_options="RW">FFFF0A</Offset>
</Process>
<Process name="Exemplo3.exe"></Process>
</Processes>
O seu parser de XML básicamente vai ser uma fábrica de objetos (vide builder design pattern) Process baseado nesse XML então faça-a ser assim.
Código:
Process_Builder * pf = new Process_XML_Builder("Caminho do XML");
QVector<Process*> processes = pf->buildProcesses();
for(int i = 0;i < processes.count();i++) {
processes.at(i)->run();
}
qDeleteAll(processes);
delete pf;
Quando eu sugeri que usasse a QDomDocument sugeri que a usasse da seguinte maneira (método buildProcesses):
Código:
QVector<Process*> function_ret;
//...
QDomElement rootElement = doc.documentElement();
if(rootElement.tagName() == "Processes") {
QDomNodeList processes = rootElement.elementsByTagName("Process");
for(int i = 0;i < processes.count();i++) {
QDomNamedNodeMap proc_attrs(processes.at(i).attributes());
QDomElement process(processes.at(i).toElement());
QString name(proc_attrs.namedItem("name").nodeValue());
int pid = proc_attrs.namedItem("pid").nodeValue().toInt();
QString proc_state(proc_attrs.namedItem("running").nodeValue());
Process::State s = Process::New;
if(proc_state == "true") {
s = (pid <= 0)? Process::From_Name : Process::From_PID;
} else if(proc_state == "start_suspended") {
s = Process::NewSuspended;
}
QString args(proc_attrs.namedItem("args").nodeValue());
//Checagem de erro nos argumentos,etc...
//...
Process *p = new Process(name, pid, s, args);
QDomNodeList offsets(process.elementsByTagName("Offset"));
for(int j = 0;j < offsets.count();j++) {
QDomNamedNodeMap offset_attrs(offsets.at(i).attributes());
QByteArray address(QByteArray::fromHex(offset_attrs.namedItem("address").nodeValue()));
bool not_raw = (offset_attrs.namedItem("raw").nodeValue() == "false");
int repeat = offsets_attrs.namedItem("repeat").nodeValue().toInt();
if(!repeat)
repeat = 1;
QString data_s(QString(offsets.at(i).toElement().nodeValue()).repeated(repeat));
if(!not_raw)
data_s = QString(QByteArray::fromHex(data_s));
QString size_envelope(offset_attrs.namedItem("size").nodeValue());
int size = size_envelope.toInt();
if(!size_envelope.isEmpty() && size_envelope.at(0) == '+' && size != 0) {
size += data_s.count();
} else {
size = data_s.count();
}
QString fill(offsets_attrs.namedItem("fill").nodeValue());
//TODO: Melhorar
if(fill == "NOP") {
fill = QString(0x90);
} else if(fill == "NULL") {
fill = QString(0x00);
}
QString page_options(offsets_attrs.namedItem("page_options").nodeValue());
//Checagem de atributos,etc...
//endianess = Offset::BigEndian ou Offset::LittleEndian
//...
Offset off(address, endianess, size);
off.setPageOptions(page_options);
off.setValue(data_s);
off.setFill(fill);
p->setOffset(off);
}
function_ret.push_back(p);
}
}
return function_ret;
Você teria então básicamente 4 classes principais: Process,Offset,Process_Builder e Process_XML_Builder.
Process está engajado em um relacionamento tem um com Offset enquanto Process_Builder (interface) e Process_XML_Builder (implementação) seguem a design pattern builder no contexto.
Process_Builder:
virtual QVector<Process*> buildProcesses();
Process_XML_Builder implementa Process_Builder:
Process_XML_Builder(QString arquivo_xml) {/*...*/}
virtual QVector<Process*> buildProcesses() { /*...*/ }
Process:
Process(QString name, int pid = 0, Process::State proc_state = Process::New, QString args = "") { /*...*/ }
void setOffset(Offset off);
void setArgs(QString args);
int run(); //retorna exit-code
//...Outros métodos que cabe a você descobrir
Offset:
Offset(QByteArray address, Offset::Endianess, int size) { /*...*/ }
void setValue(QString val);
void setFill(QString fill);
void setPageOptions(QString page_options);
//...Outros métodos que cabe a você descobrir
Melhorando esses aspectos (muitos ligados a orientação a objetos) seu código fica bem melhor.
Tenta implementar do jeito que eu te falei seguindo as regras do KISS e OO e tornando o código mais legivel (o código do buildProcesses que apresentei não está legivel mas sim funcional,melhore-o e adicione legibilidade assim como a minhas outras sugestões).
Ainda existe espaço pra melhora.
As outras dicas você seguiu,gostei de ver.
Dessa vez se não conseguir implementar da maneira sugerida eu posto a minha maneira de escrever o código.
Abraço e sucesso sempre!