Cppcheck
projectfile.cpp
Go to the documentation of this file.
00001 /*
00002  * Cppcheck - A tool for static C/C++ code analysis
00003  * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team.
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <QObject>
00020 #include <QString>
00021 #include <QXmlStreamReader>
00022 #include <QXmlStreamWriter>
00023 #include <QFile>
00024 #include <QDir>
00025 #include "projectfile.h"
00026 
00027 static const char ProjectElementName[] = "project";
00028 static const char ProjectVersionAttrib[] = "version";
00029 static const char ProjectFileVersion[] = "1";
00030 static const char IncludeDirElementName[] = "includedir";
00031 static const char DirElementName[] = "dir";
00032 static const char DirNameAttrib[] = "name";
00033 static const char DefinesElementName[] = "defines";
00034 static const char DefineName[] = "define";
00035 static const char DefineNameAttrib[] = "name";
00036 static const char PathsElementName[] = "paths";
00037 static const char PathName[] = "dir";
00038 static const char PathNameAttrib[] = "name";
00039 static const char RootPathName[] = "root";
00040 static const char RootPathNameAttrib[] = "name";
00041 static const char IgnoreElementName[] = "ignore";
00042 static const char IgnorePathName[] = "path";
00043 static const char IgnorePathNameAttrib[] = "name";
00044 static const char ExcludeElementName[] = "exclude";
00045 static const char ExcludePathName[] = "path";
00046 static const char ExcludePathNameAttrib[] = "name";
00047 
00048 ProjectFile::ProjectFile(QObject *parent) :
00049     QObject(parent)
00050 {
00051 }
00052 
00053 ProjectFile::ProjectFile(const QString &filename, QObject *parent) :
00054     QObject(parent),
00055     mFilename(filename)
00056 {
00057 }
00058 
00059 bool ProjectFile::Read(const QString &filename)
00060 {
00061     if (!filename.isEmpty())
00062         mFilename = filename;
00063 
00064     QFile file(mFilename);
00065     if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
00066         return false;
00067 
00068     QXmlStreamReader xmlReader(&file);
00069     bool insideProject = false;
00070     bool projectTagFound = false;
00071     while (!xmlReader.atEnd()) {
00072         switch (xmlReader.readNext()) {
00073         case QXmlStreamReader::StartElement:
00074             if (xmlReader.name() == ProjectElementName) {
00075                 insideProject = true;
00076                 projectTagFound = true;
00077             }
00078             // Read root path from inside project element
00079             if (insideProject && xmlReader.name() == RootPathName)
00080                 ReadRootPath(xmlReader);
00081 
00082             // Find paths to check from inside project element
00083             if (insideProject && xmlReader.name() == PathsElementName)
00084                 ReadCheckPaths(xmlReader);
00085 
00086             // Find include directory from inside project element
00087             if (insideProject && xmlReader.name() == IncludeDirElementName)
00088                 ReadIncludeDirs(xmlReader);
00089 
00090             // Find preprocessor define from inside project element
00091             if (insideProject && xmlReader.name() == DefinesElementName)
00092                 ReadDefines(xmlReader);
00093 
00094             // Find exclude list from inside project element
00095             if (insideProject && xmlReader.name() == ExcludeElementName)
00096                 ReadExcludes(xmlReader);
00097 
00098             // Find ignore list from inside project element
00099             // These are read for compatibility
00100             if (insideProject && xmlReader.name() == IgnoreElementName)
00101                 ReadExcludes(xmlReader);
00102 
00103             break;
00104 
00105         case QXmlStreamReader::EndElement:
00106             if (xmlReader.name() == ProjectElementName)
00107                 insideProject = false;
00108             break;
00109 
00110             // Not handled
00111         case QXmlStreamReader::NoToken:
00112         case QXmlStreamReader::Invalid:
00113         case QXmlStreamReader::StartDocument:
00114         case QXmlStreamReader::EndDocument:
00115         case QXmlStreamReader::Characters:
00116         case QXmlStreamReader::Comment:
00117         case QXmlStreamReader::DTD:
00118         case QXmlStreamReader::EntityReference:
00119         case QXmlStreamReader::ProcessingInstruction:
00120             break;
00121         }
00122     }
00123 
00124     file.close();
00125     if (projectTagFound)
00126         return true;
00127     else
00128         return false;
00129 }
00130 
00131 QStringList ProjectFile::GetIncludeDirs() const
00132 {
00133     QStringList dirs;
00134     foreach(QString path, mIncludeDirs) {
00135         dirs << QDir::fromNativeSeparators(path);
00136     }
00137     return dirs;
00138 }
00139 
00140 QStringList ProjectFile::GetDefines() const
00141 {
00142     return mDefines;
00143 }
00144 
00145 QStringList ProjectFile::GetCheckPaths() const
00146 {
00147     QStringList paths;
00148     foreach(QString path, mPaths) {
00149         paths << QDir::fromNativeSeparators(path);
00150     }
00151     return paths;
00152 }
00153 
00154 QStringList ProjectFile::GetExcludedPaths() const
00155 {
00156     QStringList paths;
00157     foreach(QString path, mExcludedPaths) {
00158         paths << QDir::fromNativeSeparators(path);
00159     }
00160     return paths;
00161 }
00162 
00163 void ProjectFile::ReadRootPath(QXmlStreamReader &reader)
00164 {
00165     QXmlStreamAttributes attribs = reader.attributes();
00166     QString name = attribs.value("", RootPathNameAttrib).toString();
00167     if (!name.isEmpty())
00168         mRootPath = name;
00169 }
00170 
00171 void ProjectFile::ReadIncludeDirs(QXmlStreamReader &reader)
00172 {
00173     QXmlStreamReader::TokenType type;
00174     bool allRead = false;
00175     do {
00176         type = reader.readNext();
00177         switch (type) {
00178         case QXmlStreamReader::StartElement:
00179 
00180             // Read dir-elements
00181             if (reader.name().toString() == DirElementName) {
00182                 QXmlStreamAttributes attribs = reader.attributes();
00183                 QString name = attribs.value("", DirNameAttrib).toString();
00184                 if (!name.isEmpty())
00185                     mIncludeDirs << name;
00186             }
00187             break;
00188 
00189         case QXmlStreamReader::EndElement:
00190             if (reader.name().toString() == IncludeDirElementName)
00191                 allRead = true;
00192             break;
00193 
00194             // Not handled
00195         case QXmlStreamReader::NoToken:
00196         case QXmlStreamReader::Invalid:
00197         case QXmlStreamReader::StartDocument:
00198         case QXmlStreamReader::EndDocument:
00199         case QXmlStreamReader::Characters:
00200         case QXmlStreamReader::Comment:
00201         case QXmlStreamReader::DTD:
00202         case QXmlStreamReader::EntityReference:
00203         case QXmlStreamReader::ProcessingInstruction:
00204             break;
00205         }
00206     } while (!allRead);
00207 }
00208 
00209 void ProjectFile::ReadDefines(QXmlStreamReader &reader)
00210 {
00211     QXmlStreamReader::TokenType type;
00212     bool allRead = false;
00213     do {
00214         type = reader.readNext();
00215         switch (type) {
00216         case QXmlStreamReader::StartElement:
00217             // Read define-elements
00218             if (reader.name().toString() == DefineName) {
00219                 QXmlStreamAttributes attribs = reader.attributes();
00220                 QString name = attribs.value("", DefineNameAttrib).toString();
00221                 if (!name.isEmpty())
00222                     mDefines << name;
00223             }
00224             break;
00225 
00226         case QXmlStreamReader::EndElement:
00227             if (reader.name().toString() == DefinesElementName)
00228                 allRead = true;
00229             break;
00230 
00231             // Not handled
00232         case QXmlStreamReader::NoToken:
00233         case QXmlStreamReader::Invalid:
00234         case QXmlStreamReader::StartDocument:
00235         case QXmlStreamReader::EndDocument:
00236         case QXmlStreamReader::Characters:
00237         case QXmlStreamReader::Comment:
00238         case QXmlStreamReader::DTD:
00239         case QXmlStreamReader::EntityReference:
00240         case QXmlStreamReader::ProcessingInstruction:
00241             break;
00242         }
00243     } while (!allRead);
00244 }
00245 
00246 void ProjectFile::ReadCheckPaths(QXmlStreamReader &reader)
00247 {
00248     QXmlStreamReader::TokenType type;
00249     bool allRead = false;
00250     do {
00251         type = reader.readNext();
00252         switch (type) {
00253         case QXmlStreamReader::StartElement:
00254 
00255             // Read dir-elements
00256             if (reader.name().toString() == PathName) {
00257                 QXmlStreamAttributes attribs = reader.attributes();
00258                 QString name = attribs.value("", PathNameAttrib).toString();
00259                 if (!name.isEmpty())
00260                     mPaths << name;
00261             }
00262             break;
00263 
00264         case QXmlStreamReader::EndElement:
00265             if (reader.name().toString() == PathsElementName)
00266                 allRead = true;
00267             break;
00268 
00269             // Not handled
00270         case QXmlStreamReader::NoToken:
00271         case QXmlStreamReader::Invalid:
00272         case QXmlStreamReader::StartDocument:
00273         case QXmlStreamReader::EndDocument:
00274         case QXmlStreamReader::Characters:
00275         case QXmlStreamReader::Comment:
00276         case QXmlStreamReader::DTD:
00277         case QXmlStreamReader::EntityReference:
00278         case QXmlStreamReader::ProcessingInstruction:
00279             break;
00280         }
00281     } while (!allRead);
00282 }
00283 
00284 void ProjectFile::ReadExcludes(QXmlStreamReader &reader)
00285 {
00286     QXmlStreamReader::TokenType type;
00287     bool allRead = false;
00288     do {
00289         type = reader.readNext();
00290         switch (type) {
00291         case QXmlStreamReader::StartElement:
00292             // Read exclude-elements
00293             if (reader.name().toString() == ExcludePathName) {
00294                 QXmlStreamAttributes attribs = reader.attributes();
00295                 QString name = attribs.value("", ExcludePathNameAttrib).toString();
00296                 if (!name.isEmpty())
00297                     mExcludedPaths << name;
00298             }
00299             // Read ignore-elements - deprecated but support reading them
00300             else if (reader.name().toString() == IgnorePathName) {
00301                 QXmlStreamAttributes attribs = reader.attributes();
00302                 QString name = attribs.value("", IgnorePathNameAttrib).toString();
00303                 if (!name.isEmpty())
00304                     mExcludedPaths << name;
00305             }
00306             break;
00307 
00308         case QXmlStreamReader::EndElement:
00309             if (reader.name().toString() == IgnoreElementName)
00310                 allRead = true;
00311             if (reader.name().toString() == ExcludeElementName)
00312                 allRead = true;
00313             break;
00314 
00315             // Not handled
00316         case QXmlStreamReader::NoToken:
00317         case QXmlStreamReader::Invalid:
00318         case QXmlStreamReader::StartDocument:
00319         case QXmlStreamReader::EndDocument:
00320         case QXmlStreamReader::Characters:
00321         case QXmlStreamReader::Comment:
00322         case QXmlStreamReader::DTD:
00323         case QXmlStreamReader::EntityReference:
00324         case QXmlStreamReader::ProcessingInstruction:
00325             break;
00326         }
00327     } while (!allRead);
00328 }
00329 
00330 void ProjectFile::SetIncludes(const QStringList &includes)
00331 {
00332     mIncludeDirs = includes;
00333 }
00334 
00335 void ProjectFile::SetDefines(const QStringList &defines)
00336 {
00337     mDefines = defines;
00338 }
00339 
00340 void ProjectFile::SetCheckPaths(const QStringList &paths)
00341 {
00342     mPaths = paths;
00343 }
00344 
00345 void ProjectFile::SetExcludedPaths(const QStringList &paths)
00346 {
00347     mExcludedPaths = paths;
00348 }
00349 
00350 bool ProjectFile::Write(const QString &filename)
00351 {
00352     if (!filename.isEmpty())
00353         mFilename = filename;
00354 
00355     QFile file(mFilename);
00356     if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
00357         return false;
00358 
00359     QXmlStreamWriter xmlWriter(&file);
00360     xmlWriter.setAutoFormatting(true);
00361     xmlWriter.writeStartDocument("1.0");
00362     xmlWriter.writeStartElement(ProjectElementName);
00363     xmlWriter.writeAttribute(ProjectVersionAttrib, ProjectFileVersion);
00364 
00365     if (!mRootPath.isEmpty()) {
00366         xmlWriter.writeStartElement(RootPathName);
00367         xmlWriter.writeAttribute(RootPathNameAttrib, mRootPath);
00368         xmlWriter.writeEndElement();
00369     }
00370 
00371     if (!mIncludeDirs.isEmpty()) {
00372         xmlWriter.writeStartElement(IncludeDirElementName);
00373         foreach(QString incdir, mIncludeDirs) {
00374             xmlWriter.writeStartElement(DirElementName);
00375             xmlWriter.writeAttribute(DirNameAttrib, incdir);
00376             xmlWriter.writeEndElement();
00377         }
00378         xmlWriter.writeEndElement();
00379     }
00380 
00381     if (!mDefines.isEmpty()) {
00382         xmlWriter.writeStartElement(DefinesElementName);
00383         foreach(QString define, mDefines) {
00384             xmlWriter.writeStartElement(DefineName);
00385             xmlWriter.writeAttribute(DefineNameAttrib, define);
00386             xmlWriter.writeEndElement();
00387         }
00388         xmlWriter.writeEndElement();
00389     }
00390 
00391     if (!mPaths.isEmpty()) {
00392         xmlWriter.writeStartElement(PathsElementName);
00393         foreach(QString path, mPaths) {
00394             xmlWriter.writeStartElement(PathName);
00395             xmlWriter.writeAttribute(PathNameAttrib, path);
00396             xmlWriter.writeEndElement();
00397         }
00398         xmlWriter.writeEndElement();
00399     }
00400 
00401     if (!mExcludedPaths.isEmpty()) {
00402         xmlWriter.writeStartElement(ExcludeElementName);
00403         foreach(QString path, mExcludedPaths) {
00404             xmlWriter.writeStartElement(ExcludePathName);
00405             xmlWriter.writeAttribute(ExcludePathNameAttrib, path);
00406             xmlWriter.writeEndElement();
00407         }
00408         xmlWriter.writeEndElement();
00409     }
00410 
00411     xmlWriter.writeEndDocument();
00412     file.close();
00413     return true;
00414 }