From cc8939cef9ff23c628ee4faad8fee4ecacbb148e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 23 Aug 2015 16:03:24 +0200 Subject: [PATCH] GUI: Refactoring library editor, splitting out data to separate file --- gui/gui.pro | 6 +- gui/librarydata.cpp | 260 ++++++++++++++++++++++++++++++++++++++++++ gui/librarydata.h | 108 ++++++++++++++++++ gui/librarydialog.cpp | 160 ++------------------------ gui/librarydialog.h | 45 +------- 5 files changed, 385 insertions(+), 194 deletions(-) create mode 100644 gui/librarydata.cpp create mode 100644 gui/librarydata.h diff --git a/gui/gui.pro b/gui/gui.pro index b45ed9229..891beef47 100644 --- a/gui/gui.pro +++ b/gui/gui.pro @@ -107,7 +107,8 @@ HEADERS += aboutdialog.h \ xmlreport.h \ xmlreportv1.h \ xmlreportv2.h \ - librarydialog.h + librarydialog.h \ + librarydata.h SOURCES += aboutdialog.cpp \ application.cpp \ @@ -142,7 +143,8 @@ SOURCES += aboutdialog.cpp \ xmlreport.cpp \ xmlreportv1.cpp \ xmlreportv2.cpp \ - librarydialog.cpp + librarydialog.cpp \ + librarydata.cpp win32 { DEFINES += _CRT_SECURE_NO_WARNINGS diff --git a/gui/librarydata.cpp b/gui/librarydata.cpp new file mode 100644 index 000000000..bf865dc92 --- /dev/null +++ b/gui/librarydata.cpp @@ -0,0 +1,260 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "librarydata.h" + +#include +#include +#include + +const unsigned int LibraryData::Function::Arg::ANY = ~0U; + +LibraryData::LibraryData() +{ +} + + +static LibraryData::Define loadDefine(const QDomElement &defineElement) +{ + LibraryData::Define define; + define.name = defineElement.attribute("name"); + define.value = defineElement.attribute("value"); + return define; +} + +static LibraryData::Function::Arg loadFunctionArg(const QDomElement &functionArgElement) +{ + LibraryData::Function::Arg arg; + if (functionArgElement.attribute("nr") == "any") + arg.nr = LibraryData::Function::Arg::ANY; + else + arg.nr = functionArgElement.attribute("nr").toUInt(); + for (QDomElement childElement = functionArgElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { + if (childElement.tagName() == "not-bool") + arg.notbool = true; + else if (childElement.tagName() == "not-null") + arg.notnull = true; + else if (childElement.tagName() == "not-uninit") + arg.notuninit = true; + else if (childElement.tagName() == "strz") + arg.strz = true; + else if (childElement.tagName() == "formatstr") + arg.formatstr = true; + else if (childElement.tagName() == "valid") + arg.valid = childElement.text(); + else if (childElement.tagName() == "minsize") { + arg.minsize.type = childElement.attribute("type"); + arg.minsize.arg = childElement.attribute("arg"); + arg.minsize.arg2 = childElement.attribute("arg2"); + } + } + return arg; +} + +static LibraryData::Function loadFunction(const QDomElement &functionElement) +{ + LibraryData::Function function; + function.name = functionElement.attribute("name"); + for (QDomElement childElement = functionElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { + if (childElement.tagName() == "noreturn") + function.noreturn = (childElement.text() == "true"); + else if (childElement.tagName() == "pure") + function.gccPure = true; + else if (childElement.tagName() == "const") + function.gccConst = true; + else if (childElement.tagName() == "leak-ignore") + function.leakignore = true; + else if (childElement.tagName() == "use-retval") + function.useretval = true; + else if (childElement.tagName() == "formatstr") { + function.formatstr.scan = childElement.attribute("scan"); + function.formatstr.secure = childElement.attribute("secure"); + } else if (childElement.tagName() == "arg") { + const LibraryData::Function::Arg fa = loadFunctionArg(childElement); + function.args.append(fa); + } else { + int x = 123; + x++; + + } + } + return function; +} + + +static LibraryData::MemoryResource loadMemoryResource(const QDomElement &element) +{ + LibraryData::MemoryResource memoryresource; + memoryresource.type = element.tagName(); + for (QDomElement childElement = element.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { + if (childElement.tagName() == "alloc") { + LibraryData::MemoryResource::Alloc alloc; + alloc.init = (childElement.attribute("init", "false") == "true"); + alloc.name = childElement.text(); + memoryresource.alloc.append(alloc); + } else if (childElement.tagName() == "dealloc") + memoryresource.dealloc.append(childElement.text()); + else if (childElement.tagName() == "use") + memoryresource.use.append(childElement.text()); + } + return memoryresource; +} + +static LibraryData::PodType loadPodType(const QDomElement &element) +{ + LibraryData::PodType podtype; + podtype.name = element.attribute("name"); + podtype.size = element.attribute("size"); + podtype.sign = element.attribute("sign"); + return podtype; +} + + +bool LibraryData::open(QIODevice &file) +{ + QDomDocument doc; + if (!doc.setContent(&file)) + return false; + + QDomElement rootElement = doc.firstChildElement("def"); + for (QDomElement e = rootElement.firstChildElement(); !e.isNull(); e = e.nextSiblingElement()) { + if (e.tagName() == "define") + defines.append(loadDefine(e)); + else if (e.tagName() == "function") + functions.append(loadFunction(e)); + else if (e.tagName() == "memory" || e.tagName() == "resource") + memoryresource.append(loadMemoryResource(e)); + else if (e.tagName() == "podtype") + podtypes.append(loadPodType(e)); + } + + return true; +} + + + +static QDomElement FunctionElement(QDomDocument &doc, const LibraryData::Function &function) +{ + QDomElement functionElement = doc.createElement("function"); + functionElement.setAttribute("name", function.name); + if (!function.noreturn) { + QDomElement e = doc.createElement("noreturn"); + e.appendChild(doc.createTextNode("false")); + functionElement.appendChild(e); + } + if (function.useretval) + functionElement.appendChild(doc.createElement("useretval")); + if (function.leakignore) + functionElement.appendChild(doc.createElement("leak-ignore")); + + // Argument info.. + foreach(const LibraryData::Function::Arg &arg, function.args) { + QDomElement argElement = doc.createElement("arg"); + functionElement.appendChild(argElement); + if (arg.nr == LibraryData::Function::Arg::ANY) + argElement.setAttribute("nr", "any"); + else + argElement.setAttribute("nr", arg.nr); + if (arg.notbool) + argElement.appendChild(doc.createElement("not-bool")); + if (arg.notnull) + argElement.appendChild(doc.createElement("not-null")); + if (arg.notuninit) + argElement.appendChild(doc.createElement("not-uninit")); + if (arg.strz) + argElement.appendChild(doc.createElement("strz")); + if (arg.formatstr) + argElement.appendChild(doc.createElement("formatstr")); + + if (!arg.valid.isEmpty()) { + QDomElement e = doc.createElement("valid"); + e.appendChild(doc.createTextNode(arg.valid)); + argElement.appendChild(e); + } + + if (!arg.minsize.type.isEmpty()) { + QDomElement e = doc.createElement("minsize"); + e.setAttribute("type", arg.minsize.type); + e.setAttribute("arg", arg.minsize.arg); + if (!arg.minsize.arg2.isEmpty()) + e.setAttribute("arg2", arg.minsize.arg2); + argElement.appendChild(e); + } + } + + return functionElement; +} + +static QDomElement MemoryResourceElement(QDomDocument &doc, const LibraryData::MemoryResource &mr) +{ + QDomElement element = doc.createElement(mr.type); + foreach(const LibraryData::MemoryResource::Alloc &alloc, mr.alloc) { + QDomElement e = doc.createElement("alloc"); + if (alloc.init) + e.setAttribute("init", "true"); + e.appendChild(doc.createTextNode(alloc.name)); + element.appendChild(e); + } + foreach(const QString &dealloc, mr.dealloc) { + QDomElement e = doc.createElement("dealloc"); + e.appendChild(doc.createTextNode(dealloc)); + element.appendChild(e); + } + foreach(const QString &use, mr.use) { + QDomElement e = doc.createElement("use"); + e.appendChild(doc.createTextNode(use)); + element.appendChild(e); + } + return element; +} + + +QString LibraryData::toString() const +{ + QDomDocument doc; + QDomElement root = doc.createElement("def"); + doc.appendChild(root); + root.setAttribute("format","2"); + + foreach(const Define &define, defines) { + QDomElement defineElement = doc.createElement("define"); + defineElement.setAttribute("name", define.name); + defineElement.setAttribute("value", define.value); + root.appendChild(defineElement); + } + + foreach(const Function &function, functions) { + root.appendChild(FunctionElement(doc, function)); + } + + foreach(const MemoryResource &mr, memoryresource) { + root.appendChild(MemoryResourceElement(doc, mr)); + } + + foreach(const PodType &podtype, podtypes) { + QDomElement podtypeElement = doc.createElement("podtype"); + podtypeElement.setAttribute("name", podtype.name); + podtypeElement.setAttribute("size", podtype.size); + podtypeElement.setAttribute("sign", podtype.sign); + root.appendChild(podtypeElement); + } + + return doc.toString(); +} + + diff --git a/gui/librarydata.h b/gui/librarydata.h new file mode 100644 index 000000000..69e620cf9 --- /dev/null +++ b/gui/librarydata.h @@ -0,0 +1,108 @@ +/* + * Cppcheck - A tool for static C/C++ code analysis + * Copyright (C) 2007-2015 Daniel Marjamäki and Cppcheck team. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef LIBRARYDATA_H +#define LIBRARYDATA_H + +#include +#include +#include +#include + +class LibraryData { +public: + LibraryData(); + + struct Define { + QString name; + QString value; + }; + + struct Function { + Function() : noreturn(true), gccPure(false), gccConst(false), + leakignore(false), useretval(false) { + } + + QString name; + bool noreturn; + bool gccPure; + bool gccConst; + bool leakignore; + bool useretval; + struct { + QString scan; + QString secure; + } formatstr; + struct Arg { + Arg() : nr(0), notbool(false), notnull(false), notuninit(false), + formatstr(false), strz(false) { + } + + QString name; + unsigned int nr; + static const unsigned int ANY; + bool notbool; + bool notnull; + bool notuninit; + bool formatstr; + bool strz; + QString valid; + struct { + QString type; + QString arg; + QString arg2; + } minsize; + }; + QList args; + }; + + struct MemoryResource { + QString type; // "memory" or "resource" + struct Alloc { + Alloc() : init(false) {} + bool init; + QString name; + }; + QList alloc; + QStringList dealloc; + QStringList use; + }; + + struct PodType { + QString name; + QString size; + QString sign; + }; + + void clear() { + defines.clear(); + functions.clear(); + memoryresource.clear(); + podtypes.clear(); + } + + bool open(QIODevice &file); + QString toString() const; + + QList defines; + QList functions; + QList memoryresource; + QList podtypes; +}; + +#endif // LIBRARYDATA_H diff --git a/gui/librarydialog.cpp b/gui/librarydialog.cpp index aaa60c920..386087048 100644 --- a/gui/librarydialog.cpp +++ b/gui/librarydialog.cpp @@ -20,15 +20,10 @@ #include "ui_librarydialog.h" #include -#include -#include -#include #include #include #include -const unsigned int LibraryDialog::Function::Arg::ANY = ~0U; - // TODO: get/compare functions from header LibraryDialog::LibraryDialog(QWidget *parent) : @@ -43,81 +38,6 @@ LibraryDialog::~LibraryDialog() { delete ui; } - -static LibraryDialog::Function::Arg loadFunctionArg(const QDomElement &functionArgElement) -{ - LibraryDialog::Function::Arg arg; - if (functionArgElement.attribute("nr") == "any") - arg.nr = LibraryDialog::Function::Arg::ANY; - else - arg.nr = functionArgElement.attribute("nr").toUInt(); - for (QDomElement childElement = functionArgElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { - if (childElement.tagName() == "not-bool") - arg.notbool = true; - else if (childElement.tagName() == "not-null") - arg.notnull = true; - else if (childElement.tagName() == "not-uninit") - arg.notuninit = true; - else if (childElement.tagName() == "strz") - arg.strz = true; - else if (childElement.tagName() == "formatstr") - arg.formatstr = true; - else if (childElement.tagName() == "valid") - arg.valid = childElement.text(); - else if (childElement.tagName() == "minsize") { - arg.minsize.type = childElement.attribute("type"); - arg.minsize.arg = childElement.attribute("arg"); - arg.minsize.arg2 = childElement.attribute("arg2"); - } - } - return arg; -} - -static LibraryDialog::Function loadFunction(const QDomElement &functionElement) -{ - LibraryDialog::Function function; - function.name = functionElement.attribute("name"); - for (QDomElement childElement = functionElement.firstChildElement(); !childElement.isNull(); childElement = childElement.nextSiblingElement()) { - const QString tagName = childElement.tagName(); - if (childElement.tagName() == "noreturn") - function.noreturn = (childElement.text() == "true"); - else if (childElement.tagName() == "pure") - function.gccPure = true; - else if (childElement.tagName() == "const") - function.gccConst = true; - else if (childElement.tagName() == "leak-ignore") - function.leakignore = true; - else if (childElement.tagName() == "use-retval") - function.useretval = true; - else if (childElement.tagName() == "formatstr") { - function.formatstr.scan = childElement.attribute("scan"); - function.formatstr.secure = childElement.attribute("secure"); - } else if (childElement.tagName() == "arg") { - const LibraryDialog::Function::Arg fa = loadFunctionArg(childElement); - function.args.append(fa); - } else { - int x = 123; - x++; - - } - } - return function; -} - -bool LibraryDialog::loadFile(QFile &file) -{ - QDomDocument doc; - if (!doc.setContent(&file)) - return false; - - QDomElement rootElement = doc.firstChildElement("def"); - for (QDomElement functionElement = rootElement.firstChildElement("function"); !functionElement.isNull(); functionElement = functionElement.nextSiblingElement("function")) { - functions.append(loadFunction(functionElement)); - } - - return true; -} - void LibraryDialog::openCfg() { const QSettings settings; @@ -132,101 +52,41 @@ void LibraryDialog::openCfg() &selectedFilter); if (!selectedFile.isEmpty()) { + mFileName.clear(); QFile file(selectedFile); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { - loadFile(file); - + data.open(file); mFileName = selectedFile; - ui->buttonSave->setEnabled(false); ui->functions->clear(); - foreach(const struct Function &function, functions) + foreach(const struct LibraryData::Function &function, data.functions) ui->functions->addItem(function.name); } } } -static QDomElement FunctionElement(QDomDocument &doc, const LibraryDialog::Function &function) -{ - QDomElement functionElement = doc.createElement("function"); - functionElement.setAttribute("name", function.name); - if (!function.noreturn) { - QDomElement e = doc.createElement("noreturn"); - e.appendChild(doc.createTextNode("false")); - functionElement.appendChild(e); - } - if (function.useretval) - functionElement.appendChild(doc.createElement("useretval")); - if (function.leakignore) - functionElement.appendChild(doc.createElement("leak-ignore")); - - // Argument info.. - foreach(const LibraryDialog::Function::Arg &arg, function.args) { - QDomElement argElement = doc.createElement("arg"); - functionElement.appendChild(argElement); - if (arg.nr == LibraryDialog::Function::Arg::ANY) - argElement.setAttribute("nr", "any"); - else - argElement.setAttribute("nr", arg.nr); - if (arg.notbool) - argElement.appendChild(doc.createElement("not-bool")); - if (arg.notnull) - argElement.appendChild(doc.createElement("not-null")); - if (arg.notuninit) - argElement.appendChild(doc.createElement("not-uninit")); - if (arg.strz) - argElement.appendChild(doc.createElement("strz")); - if (arg.formatstr) - argElement.appendChild(doc.createElement("formatstr")); - - if (!arg.valid.isEmpty()) { - QDomElement e = doc.createElement("valid"); - e.appendChild(doc.createTextNode(arg.valid)); - argElement.appendChild(e); - } - - if (!arg.minsize.type.isEmpty()) { - QDomElement e = doc.createElement("minsize"); - e.setAttribute("type", arg.minsize.type); - e.setAttribute("arg", arg.minsize.arg); - if (!arg.minsize.arg2.isEmpty()) - e.setAttribute("arg2", arg.minsize.arg2); - argElement.appendChild(e); - } - } - - return functionElement; -} - void LibraryDialog::saveCfg() { - QDomDocument doc; - QDomElement root = doc.createElement("def"); - doc.appendChild(root); - root.setAttribute("format","2"); - - foreach(const Function &function, functions) { - root.appendChild(FunctionElement(doc, function)); - } - + if (mFileName.isNull()) + return; QFile file(mFileName); if (file.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream ts(&file); - ts << doc.toString(); + ts << data.toString(); ui->buttonSave->setEnabled(false); } } void LibraryDialog::selectFunction(int row) { - const Function &function = functions[row]; + const LibraryData::Function &function = data.functions[row]; ui->functionreturn->setChecked(!function.noreturn); ui->useretval->setChecked(function.useretval); ui->leakignore->setChecked(function.leakignore); ui->arguments->clear(); - foreach(const Function::Arg &arg, function.args) { + foreach(const LibraryData::Function::Arg &arg, function.args) { QString s("arg"); - if (arg.nr != Function::Arg::ANY) + if (arg.nr != LibraryData::Function::Arg::ANY) s += QString::number(arg.nr); if (arg.formatstr) s += " formatstr"; @@ -241,7 +101,7 @@ void LibraryDialog::selectFunction(int row) void LibraryDialog::changeFunction() { foreach(const QListWidgetItem *item, ui->functions->selectedItems()) { - Function &function = functions[ui->functions->row(item)]; + LibraryData::Function &function = data.functions[ui->functions->row(item)]; function.noreturn = !ui->functionreturn->isChecked(); function.useretval = ui->useretval->isChecked(); function.leakignore = ui->leakignore->isChecked(); diff --git a/gui/librarydialog.h b/gui/librarydialog.h index 5c60d0e50..f4f7dcdd5 100644 --- a/gui/librarydialog.h +++ b/gui/librarydialog.h @@ -22,6 +22,8 @@ #include #include +#include "librarydata.h" + namespace Ui { class LibraryDialog; } @@ -33,44 +35,6 @@ public: explicit LibraryDialog(QWidget *parent = 0); ~LibraryDialog(); - struct Function { - Function() : noreturn(true), gccPure(false), gccConst(false), - leakignore(false), useretval(false) { - } - - QString name; - bool noreturn; - bool gccPure; - bool gccConst; - bool leakignore; - bool useretval; - struct { - QString scan; - QString secure; - } formatstr; - struct Arg { - Arg() : nr(0), notbool(false), notnull(false), notuninit(false), - formatstr(false), strz(false) { - } - - QString name; - unsigned int nr; - static const unsigned int ANY; - bool notbool; - bool notnull; - bool notuninit; - bool formatstr; - bool strz; - QString valid; - struct { - QString type; - QString arg; - QString arg2; - } minsize; - }; - QList args; - }; - private slots: void openCfg(); void saveCfg(); @@ -79,10 +43,7 @@ private slots: private: Ui::LibraryDialog *ui; - - void updateui(); - bool loadFile(QFile &file); - QList functions; + LibraryData data; QString mFileName; };