Refactored STL container usage in CLI.

Pathmatcher masks are converted to lowercase only once when instance is created
This commit is contained in:
PKEuS 2012-02-19 17:22:59 +01:00
parent 39b0f1ba95
commit 9f42ce91a1
14 changed files with 125 additions and 143 deletions

View File

@ -88,18 +88,16 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
}
}
std::vector<std::string> pathnames = parser.GetPathNames();
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
const std::vector<std::string>& pathnames = parser.GetPathNames();
if (!pathnames.empty()) {
// Execute recursiveAddFiles() to each given file parameter
std::vector<std::string>::const_iterator iter;
for (iter = pathnames.begin(); iter != pathnames.end(); ++iter)
FileLister::recursiveAddFiles(filenames, filesizes, Path::toNativeSeparators(*iter));
FileLister::recursiveAddFiles(_files, Path::toNativeSeparators(*iter));
}
if (!filenames.empty()) {
if (!_files.empty()) {
// Remove header files from the list of ignored files.
// Also output a warning for the user.
// TODO: Remove all unknown files? (use FileLister::acceptFile())
@ -118,16 +116,16 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
std::cout << "cppcheck: Please use --suppress for ignoring results from the header files." << std::endl;
}
PathMatch matcher(parser.GetIgnoredPaths());
for (std::vector<std::string>::iterator i = filenames.begin() ; i != filenames.end();) {
#if defined(_WIN32)
// For Windows we want case-insensitive path matching
const bool caseSensitive = false;
// For Windows we want case-insensitive path matching
const bool caseSensitive = false;
#else
const bool caseSensitive = true;
const bool caseSensitive = true;
#endif
if (matcher.Match(*i, caseSensitive))
i = filenames.erase(i);
PathMatch matcher(parser.GetIgnoredPaths(), caseSensitive);
for (std::map<std::string, size_t>::iterator i = _files.begin(); i != _files.end();) {
if (matcher.Match(i->first))
_files.erase(i++);
else
++i;
}
@ -136,13 +134,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
return false;
}
if (!filenames.empty()) {
std::vector<std::string>::iterator iter;
for (iter = filenames.begin(); iter != filenames.end(); ++iter) {
_filenames.push_back(*iter);
_filesizes[*iter] = filesizes[*iter];
}
if (!_files.empty()) {
return true;
} else {
std::cout << "cppcheck: error: no files to check - all paths ignored." << std::endl;
@ -171,19 +163,19 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
if (_settings._jobs == 1) {
// Single process
long totalfilesize = 0;
for (std::map<std::string, long>::const_iterator i = _filesizes.begin(); i != _filesizes.end(); ++i) {
size_t totalfilesize = 0;
for (std::map<std::string, size_t>::const_iterator i = _files.begin(); i != _files.end(); ++i) {
totalfilesize += i->second;
}
long processedsize = 0;
for (size_t c = 0; c < _filenames.size(); c++) {
returnValue += cppCheck.check(_filenames[c]);
if (_filesizes.find(_filenames[c]) != _filesizes.end()) {
processedsize += _filesizes[_filenames[c]];
}
size_t processedsize = 0;
unsigned int c = 0;
for (std::map<std::string, size_t>::const_iterator i = _files.begin(); i != _files.end(); ++i) {
returnValue += cppCheck.check(i->first);
processedsize += i->second;
if (!_settings._errorsOnly)
reportStatus(c + 1, _filenames.size(), processedsize, totalfilesize);
reportStatus(c + 1, _files.size(), processedsize, totalfilesize);
c++;
}
cppCheck.checkFunctionUsage();
@ -192,7 +184,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
} else {
// Multiple processes
Settings &settings = cppCheck.settings();
ThreadExecutor executor(_filenames, _filesizes, settings, *this);
ThreadExecutor executor(_files, settings, *this);
returnValue = executor.check();
}
@ -229,10 +221,10 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
void CppCheckExecutor::reportErr(const std::string &errmsg)
{
// Alert only about unique errors
if (std::find(_errorList.begin(), _errorList.end(), errmsg) != _errorList.end())
if (_errorList.find(errmsg) != _errorList.end())
return;
_errorList.push_back(errmsg);
_errorList.insert(errmsg);
std::cerr << errmsg << std::endl;
}
@ -269,7 +261,7 @@ void CppCheckExecutor::reportProgress(const std::string &filename, const char st
}
}
void CppCheckExecutor::reportStatus(size_t fileindex, size_t filecount, long sizedone, long sizetotal)
void CppCheckExecutor::reportStatus(size_t fileindex, size_t filecount, size_t sizedone, size_t sizetotal)
{
if (filecount > 1) {
std::ostringstream oss;

View File

@ -22,8 +22,7 @@
#include "errorlogger.h"
#include "settings.h"
#include <ctime>
#include <vector>
#include <list>
#include <set>
#include <string>
class CppCheck;
@ -81,7 +80,7 @@ public:
* @param sizedone The sum of sizes of the files checked.
* @param sizetotal The total sizes of the files.
*/
static void reportStatus(size_t fileindex, size_t filecount, long sizedone, long sizetotal);
static void reportStatus(size_t fileindex, size_t filecount, size_t sizedone, size_t sizetotal);
protected:
@ -111,7 +110,7 @@ private:
/**
* Used to filter out duplicate error messages.
*/
std::list<std::string> _errorList;
std::set<std::string> _errorList;
/**
* Report progress time
@ -124,14 +123,9 @@ private:
bool errorlist;
/**
* List of files to check.
* Filename associated with size of file
*/
std::vector<std::string> _filenames;
/**
* Sizes of files in _filenames.
*/
std::map<std::string, long> _filesizes;
std::map<std::string, size_t> _files;
};
#endif // CPPCHECKEXECUTOR_H

View File

@ -119,7 +119,7 @@ static BOOL MyFileExists(std::string path)
#endif // defined(UNICODE)
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, std::map<std::string, long> &filesizes, const std::string &path)
void FileLister::recursiveAddFiles(std::map<std::string, size_t> &files, const std::string &path)
{
// oss is the search string passed into FindFirst and FindNext.
// bdir is the base directory which is used to form pathnames.
@ -180,13 +180,15 @@ void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, std::map
// If recursive is not used, accept all files given by user
if (Path::sameFileName(path,ansiFfd) || Path::acceptFile(ansiFfd)) {
const std::string nativename = Path::fromNativeSeparators(fname.str());
filenames.push_back(nativename);
// Limitation: file sizes are assumed to fit in a 'long'
filesizes[nativename] = ffd.nFileSizeLow;
// Limitation: file sizes are assumed to fit in a 'size_t'
if (sizeof(size_t) > 4)
files[nativename] = (static_cast<size_t>(ffd.nFileSizeHigh) << 32) | ffd.nFileSizeLow;
else
files[nativename] = ffd.nFileSizeLow;
}
} else {
// Directory
FileLister::recursiveAddFiles(filenames, filesizes, fname.str());
FileLister::recursiveAddFiles(files, fname.str());
}
#if defined(UNICODE)
delete [] ansiFfd;
@ -242,9 +244,8 @@ std::string FileLister::getAbsolutePath(const std::string& path)
return absolute_path;
}
void FileLister::recursiveAddFiles2(std::vector<std::string> &relative,
std::set<std::string> &seen_paths,
std::map<std::string, long> &filesizes,
void FileLister::recursiveAddFiles2(std::set<std::string> &seen_paths,
std::map<std::string, size_t> &files,
const std::string &path)
{
std::ostringstream oss;
@ -272,30 +273,30 @@ void FileLister::recursiveAddFiles2(std::vector<std::string> &relative,
// File
if (Path::sameFileName(path,filename) || Path::acceptFile(filename)) {
relative.push_back(filename);
seen_paths.insert(absolute_path);
struct stat sb;
if (stat(absolute_path.c_str(), &sb) == 0) {
// Limitation: file sizes are assumed to fit in a 'long'
filesizes[filename] = static_cast<long>(sb.st_size);
}
// Limitation: file sizes are assumed to fit in a 'size_t'
files[filename] = static_cast<size_t>(sb.st_size);
} else
files[filename] = 0;
}
} else {
// Directory
seen_paths.insert(absolute_path);
recursiveAddFiles2(relative, seen_paths, filesizes, filename);
recursiveAddFiles2(seen_paths, files, filename);
}
}
globfree(&glob_results);
}
void FileLister::recursiveAddFiles(std::vector<std::string> &filenames, std::map<std::string, long> &filesizes, const std::string &path)
void FileLister::recursiveAddFiles(std::map<std::string, size_t> &files, const std::string &path)
{
std::set<std::string> seen_paths;
recursiveAddFiles2(filenames, seen_paths, filesizes, path);
recursiveAddFiles2(seen_paths, files, path);
}
bool FileLister::isDirectory(const std::string &path)

View File

@ -19,7 +19,6 @@
#ifndef filelisterH
#define filelisterH
#include <vector>
#include <string>
#include <set>
#include <map>
@ -31,17 +30,14 @@
class FileLister {
public:
/**
* @brief Recursively add source files to a vector.
* @brief Recursively add source files to a map.
* Add source files from given directory and all subdirectries to the
* given vector. Only files with accepted extensions
* given map. Only files with accepted extensions
* (*.c;*.cpp;*.cxx;*.c++;*.cc;*.txx) are added.
* @param filenames output vector that filenames are written to
* @param filesizes output map that contains the size of each file
* @param files output map that associates the size of each file with its name
* @param path root path
*/
static void recursiveAddFiles(std::vector<std::string> &filenames,
std::map<std::string, long> &filesizes,
const std::string &path);
static void recursiveAddFiles(std::map<std::string, size_t> &files, const std::string &path);
/**
* @brief Is given path a directory?
@ -58,9 +54,8 @@ public:
#ifndef _WIN32
static std::string getAbsolutePath(const std::string& path);
static void recursiveAddFiles2(std::vector<std::string> &relative,
std::set<std::string> &seen_paths,
std::map<std::string, long> &filesizes,
static void recursiveAddFiles2(std::set<std::string> &seen_paths,
std::map<std::string, size_t> &files,
const std::string &path);
#endif
};

View File

@ -16,28 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pathmatch.h"
#include <algorithm>
#include <ctype.h> // Borland: tolower
#include "pathmatch.h"
PathMatch::PathMatch(const std::vector<std::string> &masks)
: _masks(masks)
PathMatch::PathMatch(const std::vector<std::string> &masks, bool caseSensitive)
: _masks(masks), _caseSensitive(caseSensitive)
{
if (!_caseSensitive)
for (std::vector<std::string>::iterator i = _masks.begin(); i != _masks.end(); ++i)
std::transform(i->begin(), i->end(), i->begin(), ::tolower);
}
bool PathMatch::Match(const std::string &path, bool caseSensitive) const
bool PathMatch::Match(const std::string &path) const
{
if (path.empty())
return false;
std::vector<std::string>::const_iterator iterMask;
for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) {
std::string mask(*iterMask);
if (!caseSensitive)
std::transform(mask.begin(), mask.end(), mask.begin(), ::tolower);
for (std::vector<std::string>::const_iterator iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) {
const std::string& mask(*iterMask);
std::string findpath(path);
if (!caseSensitive)
if (!_caseSensitive)
std::transform(findpath.begin(), findpath.end(), findpath.begin(), ::tolower);
// Filtering directory name

View File

@ -35,7 +35,7 @@ public:
* The constructor.
* @param masks List of masks.
*/
explicit PathMatch(const std::vector<std::string> &masks);
PathMatch(const std::vector<std::string> &masks, bool caseSensitive = true);
/**
* @brief Match path against list of masks.
@ -44,7 +44,7 @@ public:
* matching paths?
* @return true if any of the masks match the path, false otherwise.
*/
bool Match(const std::string &path, bool caseSensitive = true) const;
bool Match(const std::string &path) const;
protected:
@ -57,6 +57,7 @@ protected:
private:
std::vector<std::string> _masks;
bool _caseSensitive;
};
/// @}

View File

@ -19,8 +19,8 @@
#include "cppcheckexecutor.h"
#include "threadexecutor.h"
#include "cppcheck.h"
#include <algorithm>
#ifdef THREADING_MODEL_FORK
#include <algorithm>
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
@ -33,8 +33,8 @@
#include <cstring>
#endif
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const std::map<std::string, long> &filesizes, Settings &settings, ErrorLogger &errorLogger)
: _filenames(filenames), _filesizes(filesizes), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
ThreadExecutor::ThreadExecutor(const std::map<std::string, size_t> &files, Settings &settings, ErrorLogger &errorLogger)
: _files(files), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
{
#ifdef THREADING_MODEL_FORK
_wpipe = 0;
@ -46,10 +46,6 @@ ThreadExecutor::~ThreadExecutor()
//dtor
}
void ThreadExecutor::addFileContent(const std::string &path, const std::string &content)
{
_fileContents[ path ] = content;
}
///////////////////////////////////////////////////////////////////////////////
////// This code is for platforms that support fork() only ////////////////////
@ -57,6 +53,11 @@ void ThreadExecutor::addFileContent(const std::string &path, const std::string &
#ifdef THREADING_MODEL_FORK
void ThreadExecutor::addFileContent(const std::string &path, const std::string &content)
{
_fileContents[ path ] = content;
}
int ThreadExecutor::handleRead(int rpipe, unsigned int &result)
{
char type = 0;
@ -123,19 +124,19 @@ unsigned int ThreadExecutor::check()
_fileCount = 0;
unsigned int result = 0;
long totalfilesize = 0;
for (std::map<std::string, long>::const_iterator i = _filesizes.begin(); i != _filesizes.end(); ++i) {
size_t totalfilesize = 0;
for (std::map<std::string, size_t>::const_iterator i = _files.begin(); i != _files.end(); ++i) {
totalfilesize += i->second;
}
std::list<int> rpipes;
std::map<pid_t, std::string> childFile;
std::map<int, std::string> pipeFile;
long processedsize = 0;
unsigned int i = 0;
size_t processedsize = 0;
std::map<std::string, size_t>::const_iterator i = _files.begin();
while (true) {
// Start a new child
if (i < _filenames.size() && rpipes.size() < _settings._jobs) {
if (i != _files.end() && rpipes.size() < _settings._jobs) {
int pipes[2];
if (pipe(pipes) == -1) {
std::cerr << "pipe() failed: "<< strerror(errno) << std::endl;
@ -166,12 +167,12 @@ unsigned int ThreadExecutor::check()
fileChecker.settings(_settings);
unsigned int resultOfCheck = 0;
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end()) {
if (_fileContents.size() > 0 && _fileContents.find(i->first) != _fileContents.end()) {
// File content was given as a string
resultOfCheck = fileChecker.check(_filenames[i], _fileContents[ _filenames[i] ]);
resultOfCheck = fileChecker.check(i->first, _fileContents[ i->first ]);
} else {
// Read file from a file
resultOfCheck = fileChecker.check(_filenames[i]);
resultOfCheck = fileChecker.check(i->first);
}
std::ostringstream oss;
@ -182,8 +183,8 @@ unsigned int ThreadExecutor::check()
close(pipes[1]);
rpipes.push_back(pipes[0]);
childFile[pid] = _filenames[i];
pipeFile[pipes[0]] = _filenames[i];
childFile[pid] = i->first;
pipeFile[pipes[0]] = i->first;
++i;
} else if (!rpipes.empty()) {
@ -205,8 +206,8 @@ unsigned int ThreadExecutor::check()
if (p != pipeFile.end()) {
std::string name = p->second;
pipeFile.erase(p);
std::map<std::string, long>::const_iterator fs = _filesizes.find(name);
if (fs != _filesizes.end()) {
std::map<std::string, size_t>::const_iterator fs = _files.find(name);
if (fs != _files.end()) {
size = fs->second;
}
}
@ -214,7 +215,7 @@ unsigned int ThreadExecutor::check()
_fileCount++;
processedsize += size;
if (!_settings._errorsOnly)
CppCheckExecutor::reportStatus(_fileCount, _filenames.size(), processedsize, totalfilesize);
CppCheckExecutor::reportStatus(_fileCount, _files.size(), processedsize, totalfilesize);
close(*rp);
rp = rpipes.erase(rp);
@ -289,6 +290,12 @@ void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &msg)
}
#else
void ThreadExecutor::addFileContent(const std::string &/*path*/, const std::string &/*content*/)
{
}
unsigned int ThreadExecutor::check()
{
return 0;

View File

@ -19,7 +19,7 @@
#ifndef THREADEXECUTOR_H
#define THREADEXECUTOR_H
#include <vector>
#include <map>
#include <string>
#include <list>
#include "settings.h"
@ -38,7 +38,7 @@
*/
class ThreadExecutor : public ErrorLogger {
public:
ThreadExecutor(const std::vector<std::string> &filenames, const std::map<std::string, long> &filesizes, Settings &settings, ErrorLogger &_errorLogger);
ThreadExecutor(const std::map<std::string, size_t> &files, Settings &settings, ErrorLogger &_errorLogger);
virtual ~ThreadExecutor();
unsigned int check();
virtual void reportOut(const std::string &outmsg);
@ -54,16 +54,15 @@ public:
void addFileContent(const std::string &path, const std::string &content);
private:
const std::vector<std::string> &_filenames;
const std::map<std::string, long> &_filesizes;
const std::map<std::string, size_t> &_files;
Settings &_settings;
ErrorLogger &_errorLogger;
unsigned int _fileCount;
#ifdef THREADING_MODEL_FORK
/** @brief Key is file name, and value is the content of the file */
std::map<std::string, std::string> _fileContents;
#ifdef THREADING_MODEL_FORK
private:
enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', CHILD_END='3'};

View File

@ -522,7 +522,7 @@ void CppCheck::reportProgress(const std::string &filename, const char stage[], c
_errorLogger.reportProgress(filename, stage, value);
}
void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, long /*sizedone*/, long /*sizetotal*/)
void CppCheck::reportStatus(unsigned int /*fileindex*/, unsigned int /*filecount*/, size_t /*sizedone*/, size_t /*sizetotal*/)
{
}

View File

@ -111,7 +111,7 @@ public:
*/
static const char * extraVersion();
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, long sizedone, long sizetotal);
virtual void reportStatus(unsigned int fileindex, unsigned int filecount, size_t sizedone, size_t sizetotal);
/**
* @brief Terminate checking. The checking will be terminated as soon as possible.

View File

@ -19,7 +19,6 @@
#include "testsuite.h"
#include "filelister.h"
#include <fstream>
#include <algorithm>
#ifndef _WIN32
#include <limits.h>
@ -66,29 +65,26 @@ private:
void recursiveAddFiles() {
// Recursively add add files..
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
FileLister::recursiveAddFiles(filenames, filesizes, ".");
// Ensure a size entry is present for each listed file
for (std::vector<std::string>::const_iterator i = filenames.begin(); i != filenames.end(); ++i) {
ASSERT(filesizes.find(*i) != filesizes.end());
}
std::map<std::string, size_t> files;
FileLister::recursiveAddFiles(files, ".");
// In case there are leading "./"..
for (unsigned int i = 0; i < filenames.size(); ++i) {
if (filenames[i].compare(0,2,"./") == 0)
filenames[i].erase(0,2);
for (std::map<std::string, size_t>::iterator i = files.begin(); i != files.end();) {
if (i->first.compare(0,2,"./") == 0) {
files[i->first.substr(2)] = i->second;
files.erase(i++);
} else
++i;
}
// Make sure source files are added..
ASSERT(std::find(filenames.begin(), filenames.end(), "cli/main.cpp") != filenames.end());
ASSERT(std::find(filenames.begin(), filenames.end(), "lib/token.cpp") != filenames.end());
ASSERT(std::find(filenames.begin(), filenames.end(), "lib/tokenize.cpp") != filenames.end());
ASSERT(std::find(filenames.begin(), filenames.end(), "test/testfilelister.cpp") != filenames.end());
ASSERT(files.find("cli/main.cpp") != files.end());
ASSERT(files.find("lib/token.cpp") != files.end());
ASSERT(files.find("lib/tokenize.cpp") != files.end());
ASSERT(files.find("test/testfilelister.cpp") != files.end());
// Make sure headers are not added..
ASSERT(std::find(filenames.begin(), filenames.end(), "lib/tokenize.h") == filenames.end());
ASSERT(files.find("lib/tokenize.h") == files.end());
}
};

View File

@ -99,8 +99,8 @@ private:
void onemasksamepathdifferentcase() {
std::vector<std::string> masks;
masks.push_back("sRc/");
PathMatch match(masks);
ASSERT(match.Match("srC/", false));
PathMatch match(masks, false);
ASSERT(match.Match("srC/"));
}
void onemasksamepathwithfile() {
@ -201,8 +201,8 @@ private:
void filemaskdifferentcase() {
std::vector<std::string> masks;
masks.push_back("foo.cPp");
PathMatch match(masks);
ASSERT(match.Match("fOo.cpp", false));
PathMatch match(masks, false);
ASSERT(match.Match("fOo.cpp"));
}
void filemask2() {

View File

@ -130,9 +130,8 @@ private:
errout.str("");
output.str("");
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
filenames.push_back("test.cpp");
std::map<std::string, size_t> files;
files["test.cpp"] = 1;
Settings settings;
settings._jobs = 1;
@ -141,9 +140,9 @@ private:
std::string r = settings.nomsg.addSuppressionLine(suppression);
ASSERT_EQUALS("", r);
}
ThreadExecutor executor(filenames, filesizes, settings, *this);
for (unsigned int i = 0; i < filenames.size(); ++i)
executor.addFileContent(filenames[i], code);
ThreadExecutor executor(files, settings, *this);
for (std::map<std::string, size_t>::const_iterator i = files.begin(); i != files.end(); ++i)
executor.addFileContent(i->first, code);
executor.check();

View File

@ -28,7 +28,6 @@
#include <map>
#include <string>
#include <vector>
extern std::ostringstream errout;
extern std::ostringstream output;
@ -52,19 +51,18 @@ private:
return;
}
std::vector<std::string> filenames;
std::map<std::string, long> filesizes;
std::map<std::string, size_t> filemap;
for (int i = 1; i <= files; ++i) {
std::ostringstream oss;
oss << "file_" << i << ".cpp";
filenames.push_back(oss.str());
filemap[oss.str()] = 1;
}
Settings settings;
settings._jobs = jobs;
ThreadExecutor executor(filenames, filesizes, settings, *this);
for (unsigned int i = 0; i < filenames.size(); ++i)
executor.addFileContent(filenames[i], data);
ThreadExecutor executor(filemap, settings, *this);
for (std::map<std::string, size_t>::const_iterator i = filemap.begin(); i != filemap.end(); ++i)
executor.addFileContent(i->first, data);
ASSERT_EQUALS(result, executor.check());
}