Написал небольшой парсер для BSDL файлов, но получилось как-то функционально что ли, я не смог выделить абстракции, к тому же приходится создавать объект парсера, затем вызвать функцию и передавать ему имя файла и объект для того что он разобрал(jtagDevice), мне кажется можно проще или более гибко но не могу придумать как, плюс зачемто унаследовал его от QObject что было лишним это я уберу, с помощью него разбираю отдельно файлы или папки вызывая для каждого файла parse(), еще вопрос как обрабатывать ситуации когда он не нашел чегото, можно ли использовать исключения или они не подходят и это будет избыточным, пока что просто вывожу в консоль если чтото не так, еще не встречал файла с ошибкой.
Вот класс:
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QStringList>
#include <QRegExp>
#include "jtagdevice.h"
class parser : public QObject
{
Q_OBJECT
public:
explicit parser(QObject *parent = 0);
bool parse(QString filename,jtagDevice* device);
private:
QFile* File;
QString* fileStr;
jtagDevice* dev;
bool openFile(QString file);
void removeGarbage();
QString extractName();
QString extractID();
int extractDRLength();
int extractIRLength();
signals:
public slots:
};
#endif
#include "parser.h"
parser::parser(QObject *parent) :
QObject(parent){
}
bool parser::parse(QString filename, jtagDevice *device){
File=new QFile(filename);
File->open(QIODevice::ReadOnly);
if(!File->exists()){
qDebug()<<"File not exist"<<filename;
return false;}
QString name,ID;
int IRL,DRL;
QMap < QString,QString > commands;
fileStr = new QString(File->readAll());
removeGarbage();
name=extractName();
ID=extractID();
IRL=extractIRLength();
DRL=extractDRLength();
commands=extractInstructions();
if(name.isEmpty()||ID.isEmpty()){
qDebug()<<"name or ID is empty";
return false;}
device->setName(name);
device->setIDBIN(ID);
device->setDRLength(DRL);
device->setIRLength(IRL);
device->setInstructions(commands);
delete File;
delete fileStr;
return true;
}
void parser::removeGarbage(){
qDebug()<<"garbage";
QRegExp rx;
int pos = 0;
rx.setPattern("(\\-\\-.+\\n)");
rx.setMinimal(true);
while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // Убираем комментарии
fileStr->remove(rx);
pos += rx.matchedLength();
}
pos=0;
rx.setMinimal(false);
rx.setPattern("\\s+");
while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // Убираем повторяющиеся пробелы
fileStr->replace(pos,rx.matchedLength()," ");
pos += (rx.matchedLength()-(rx.matchedLength()-1));
}
pos=0;
rx.setPattern("\\r|\\n");
rx.setMinimal(true);
while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // приводим все к одной строке
fileStr->remove(rx);
pos += rx.matchedLength();
}
pos=0;
rx.setMinimal(false);
rx.setPattern("\\s*([,:;\"\\)\\]\\(\\[])\\s*");
while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // убираем пробелы у разделительных(,.:) знаков
fileStr->replace(pos,rx.matchedLength(),rx.cap(1));
pos += (rx.matchedLength()-(rx.matchedLength()-1));
}
}
QString parser::extractName(){
QString name;
int index=fileStr->indexOf(";end ");
if(index==-1){
qDebug()<<"Can't find ID. 1";
return name;}
index+=5;
if(fileStr->endsWith(";")){
while(index!=fileStr->length()-1){
name.push_back(fileStr->at(index));
index++;
}
return name;}
else{
qDebug()<<"Can't find ID. 2";
return name;
}
}
QString parser::extractID(){
QString ID,temp;
int end;
int index = fileStr->indexOf("IDCODE_REGISTER",0,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"IDCODE_REGISTER not found. 1";
return ID;}
index+=15;
index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"IDCODE_REGISTER start not found. 2";
return ID;}
end=fileStr->indexOf(";",index,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"IDCODE_REGISTER end not found. 3";
return ID;}
while(index!=end){
temp=fileStr->at(index);
if(temp=="0"||temp=="1"||temp=="X")
ID.push_back(temp);
temp.clear();
index++;
}
return ID;
}
int parser::extractIRLength(){
QString result;
int index=fileStr->indexOf("instruction_length",0,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"Can't extract IRLength";
return -1;
}
index+=18;
index=fileStr->indexOf(";",index,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"Can't extract IRLength";
return -1;
}
index--;
while(fileStr->at(index).isDigit()){
result.push_front(fileStr->at(index));
index--;
}
return result.toInt();
}
QMap<QString,QString> parser::extractInstructions(){
QMap<QString,QString> result;
QString command,code1;
int end;
int index=fileStr->indexOf("instruction_opcode",0,Qt::CaseInsensitive);
index+=18;
index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
end=fileStr->indexOf(";",index,Qt::CaseInsensitive);
while(index<end){
index++;
while(fileStr->at(index)!='('){
command.push_back(fileStr->at(index));
index++;
}
index++;
while(fileStr->at(index)!=')'){
code1.push_back(fileStr->at(index));
index++;
}
result[code1]=command;
command.clear();
code1.clear();
index=fileStr->indexOf("&",index,Qt::CaseInsensitive);
index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
}
return result;
}
int parser::extractDRLength(){
QString result;
int index=fileStr->indexOf("boundary_length",0,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"Can't extract DRLength";
return -1;
}
index+=15;
index=fileStr->indexOf(";",index,Qt::CaseInsensitive);
if(index==-1){
qDebug()<<"Can't extract DRLength";
return -1;
}
index--;
while(fileStr->at(index).isDigit()){
result.push_front(fileStr->at(index));
index--;
}
return result.toInt();
}
И еще вопрос
Допустим есть два класса
class Obj1{
public:
Obj2(string str, int num);
int getNumBase();
string getStrBase();
virtual int getNumChild();
virtual string getStrChild();
private:
string strBase;
int numBase
};
class Obj2 : public Obj1
{
public:
Obj2(string str, int num, string str_cild, int num_chuld);
int getNumChild();
string getStrChild();
private:
int numChild;
string strChild;
};
Мне нужно хранить много экземпляров этих класов, я создал класс хранилище который хранит указатели на базовый класс в векторе, дает доступ к желементам и еще какойто функционал.
Я передаю в вектор указатели на объект так push(new Obj1()) push(new Obj2()).
Соответственно обратно тоже указатель на базовый класс.
Удаляю обьекты в деструкторе хранилища
for(;;)
delete vector[i];
Если комуто не лень скажите пожалуйста
1)Это хорошее решение хранить указатели а не объекты, и удалять их в деструкторе вышеописанным образом
2)Можно ли так использовать наследование как в Obj1 Obj2 или стоит определить виртуальный класс и два наследника(или вобще хранить все в одном и определять тип как пустая строка Str_Child или нет, что в принципе я и собираюсь делать с классами Obj1 Obj2 тк нужно определять тип)
3) Как выбрать хранить указатель на данные (str_Base,str_child) или переменные.
Спасибо всем ответившим и прочитавшим до конца.