Implement Win32 FileLister as separate class.

Improve the system used to have separate versions of code of FileLister for
Win32 and Linux. New idea is to have Base FileLister class implementing
common code and then derived classes for Win32 and Linux specific code.

FileLister is not anymore a static class. Instead we use singleton of
derived class.
This commit is contained in:
Kimmo Varis 2010-03-11 21:58:59 +02:00
parent 4981cc5843
commit d1bbcf1734
11 changed files with 288 additions and 13 deletions

View File

@ -268,6 +268,10 @@
RelativePath="..\lib\filelister.cpp" RelativePath="..\lib\filelister.cpp"
> >
</File> </File>
<File
RelativePath="..\lib\filelister_win32.cpp"
>
</File>
<File <File
RelativePath="main.cpp" RelativePath="main.cpp"
> >
@ -370,6 +374,10 @@
RelativePath="..\lib\filelister.h" RelativePath="..\lib\filelister.h"
> >
</File> </File>
<File
RelativePath="..\lib\filelister_win32.h"
>
</File>
<File <File
RelativePath="..\lib\mathlib.h" RelativePath="..\lib\mathlib.h"
> >

View File

@ -379,7 +379,7 @@ QStringList MainWindow::RemoveUnacceptedFiles(const QStringList &list)
QString str; QString str;
foreach(str, list) foreach(str, list)
{ {
if (FileLister::acceptFile(str.toStdString())) if (getFileLister()->acceptFile(str.toStdString()))
{ {
result << str; result << str;
} }

View File

@ -100,7 +100,7 @@ void CheckHeaders::warningIncludeHeader()
const std::string includefile = includetok->strAt(1); const std::string includefile = includetok->strAt(1);
while (hfile < _tokenizer->getFiles()->size()) while (hfile < _tokenizer->getFiles()->size())
{ {
if (FileLister::sameFileName(_tokenizer->getFiles()->at(hfile), includefile)) if (getFileLister()->sameFileName(_tokenizer->getFiles()->at(hfile), includefile))
break; break;
++hfile; ++hfile;
} }

View File

@ -61,7 +61,7 @@ void CppCheck::settings(const Settings &settings)
void CppCheck::addFile(const std::string &path) void CppCheck::addFile(const std::string &path)
{ {
FileLister::recursiveAddFiles(_filenames, path.c_str(), true); getFileLister()->recursiveAddFiles(_filenames, path.c_str(), true);
} }
void CppCheck::addFile(const std::string &path, const std::string &content) void CppCheck::addFile(const std::string &path, const std::string &content)
@ -373,7 +373,7 @@ void CppCheck::parseFromArgs(int argc, const char* const argv[])
// Execute recursiveAddFiles() to each given file parameter // Execute recursiveAddFiles() to each given file parameter
std::vector<std::string>::const_iterator iter; std::vector<std::string>::const_iterator iter;
for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) for (iter = pathnames.begin(); iter != pathnames.end(); ++iter)
FileLister::recursiveAddFiles(_filenames, iter->c_str(), true); getFileLister()->recursiveAddFiles(_filenames, iter->c_str(), true);
} }
if (argc <= 1 || showHelp) if (argc <= 1 || showHelp)

View File

@ -17,6 +17,7 @@
*/ */
#include "filelister.h" #include "filelister.h"
#include "fileLister_win32.h"
#include <sstream> #include <sstream>
#include <vector> #include <vector>
#include <cstring> #include <cstring>
@ -34,6 +35,18 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
static FileLister *fileLister;
FileLister * getFileLister()
{
if (fileLister == NULL)
{
fileLister = new FileListerWin32;
return fileLister;
}
return fileLister;
}
std::string FileLister::simplifyPath(const char *originalPath) std::string FileLister::simplifyPath(const char *originalPath)
{ {
std::string subPath = ""; std::string subPath = "";

View File

@ -29,14 +29,16 @@
class FileLister class FileLister
{ {
public: public:
static void recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive); virtual void recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive);
static std::string simplifyPath(const char *originalPath); virtual std::string simplifyPath(const char *originalPath);
static bool sameFileName(const std::string &fname1, const std::string &fname2); virtual bool sameFileName(const std::string &fname1, const std::string &fname2);
static bool acceptFile(const std::string &filename); virtual bool acceptFile(const std::string &filename);
private: private:
}; };
FileLister * getFileLister();
/// @} /// @}
#endif // #ifndef FILELISTER_H #endif // #ifndef FileListerH

201
lib/filelister_win32.cpp Normal file
View File

@ -0,0 +1,201 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 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 <http://www.gnu.org/licenses/>.
*/
#include "filelister_win32.h"
#include <sstream>
#include <vector>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
#if defined(_WIN32)
#include <windows.h>
#ifndef __BORLANDC__
#include <shlwapi.h>
#endif
#endif
///////////////////////////////////////////////////////////////////////////////
////// This code is for Microsoft Windows /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#if defined(_WIN32)
// Here is the catch: cppcheck core is Ansi code (using char type).
// When compiling Unicode targets WinAPI automatically uses *W Unicode versions
// of called functions. So we must convert data given to WinAPI functions from
// ANSI to Unicode. Likewise we must convert data we get from WinAPI from
// Unicode to ANSI.
#if defined(UNICODE)
static bool TransformUcs2ToAnsi(LPCWSTR psUcs, LPSTR psAnsi, int nAnsi)
{
WideCharToMultiByte(CP_ACP, 0, psUcs, -1, psAnsi, nAnsi, NULL, NULL);
return true;
}
static bool TransformAnsiToUcs2(LPCSTR psAnsi, LPWSTR psUcs, UINT nUcs)
{
MultiByteToWideChar(CP_ACP, 0, psAnsi, -1, psUcs, nUcs);
return true;
}
static BOOL MyIsDirectory(std::string path)
{
WCHAR * unicodeCleanPath = new WCHAR[path.size() + 1];
TransformAnsiToUcs2(path.c_str(), unicodeCleanPath,
(path.size() * sizeof(WCHAR)) + 1);
// See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx
BOOL res = PathIsDirectory(unicodeCleanPath);
delete [] unicodeCleanPath;
return res;
}
static HANDLE MyFindFirstFile(std::string path, LPWIN32_FIND_DATA findData)
{
WCHAR * unicodeOss = new wchar_t[path.size() + 1];
TransformAnsiToUcs2(path.c_str(), unicodeOss, (path.size() + 1) * sizeof(WCHAR));
HANDLE hFind = FindFirstFile(unicodeOss, findData);
delete [] unicodeOss;
return hFind;
}
#else // defined(UNICODE)
static BOOL MyIsDirectory(std::string path)
{
#ifdef __BORLANDC__
return (GetFileAttributes(path.c_str()) & FILE_ATTRIBUTE_DIRECTORY);
#else
// See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx
return PathIsDirectory(path.c_str());
#endif
}
static HANDLE MyFindFirstFile(std::string path, LPWIN32_FIND_DATA findData)
{
HANDLE hFind = FindFirstFile(path.c_str(), findData);
return hFind;
}
#endif // defined(UNICODE)
void FileListerWin32::recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive)
{
// oss is the search string passed into FindFirst and FindNext.
// bdir is the base directory which is used to form pathnames.
// It always has a trailing backslash available for concatenation.
std::ostringstream bdir, oss;
std::string cleanedPath = path;
std::replace(cleanedPath.begin(), cleanedPath.end(), '/', '\\');
oss << cleanedPath;
if (MyIsDirectory(cleanedPath.c_str()))
{
char c = cleanedPath[ cleanedPath.size()-1 ];
switch (c)
{
case '\\':
oss << '*';
bdir << cleanedPath;
break;
case '*':
bdir << cleanedPath.substr(0, cleanedPath.length() - 1);
break;
default:
oss << "\\*";
bdir << cleanedPath << '\\';
}
}
else
{
std::string::size_type pos;
pos = cleanedPath.find_last_of('\\');
if (std::string::npos != pos)
{
bdir << cleanedPath.substr(0, pos + 1);
}
}
WIN32_FIND_DATA ffd;
HANDLE hFind = MyFindFirstFile(oss.str(), &ffd);
if (INVALID_HANDLE_VALUE == hFind)
return;
do
{
if (ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0')
continue;
#if defined(UNICODE)
char * ansiFfd = new char[wcslen(ffd.cFileName) + 1];
TransformUcs2ToAnsi(ffd.cFileName, ansiFfd, wcslen(ffd.cFileName) + 1);
#else // defined(UNICODE)
char * ansiFfd = &ffd.cFileName[0];
#endif // defined(UNICODE)
std::ostringstream fname;
fname << bdir.str().c_str() << ansiFfd;
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
{
// File
// If recursive is not used, accept all files given by user
if (!recursive || FileLister::acceptFile(ansiFfd))
filenames.push_back(fname.str());
}
else if (recursive)
{
// Directory
FileLister::recursiveAddFiles(filenames, fname.str().c_str(), recursive);
}
#if defined(UNICODE)
delete [] ansiFfd;
#endif // defined(UNICODE)
}
while (FindNextFile(hFind, &ffd) != FALSE);
if (INVALID_HANDLE_VALUE != hFind)
{
FindClose(hFind);
hFind = INVALID_HANDLE_VALUE;
}
}
#endif
//---------------------------------------------------------------------------
bool FileListerWin32::sameFileName(const std::string &fname1, const std::string &fname2)
{
#ifdef __BORLANDC__
return bool(stricmp(fname1.c_str(), fname2.c_str()) == 0);
#endif
#ifdef _MSC_VER
return bool(_stricmp(fname1.c_str(), fname2.c_str()) == 0);
#endif
}

43
lib/filelister_win32.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2009 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 <http://www.gnu.org/licenses/>.
*/
#ifndef FileListerWin32H
#define FileListerWin32H
#include <vector>
#include <string>
#include "filelister.h"
/// @addtogroup Core
/// @{
class FileListerWin32 : public FileLister
{
public:
virtual void recursiveAddFiles(std::vector<std::string> &filenames, const std::string &path, bool recursive);
// virtual static std::string simplifyPath(const char *originalPath);
virtual bool sameFileName(const std::string &fname1, const std::string &fname2);
// virtual static bool acceptFile(const std::string &filename);
private:
};
/// @}
#endif // #ifndef FileListerWin32H

View File

@ -21,6 +21,10 @@ HEADERS += $$PWD/check.h \
$$PWD/token.h \ $$PWD/token.h \
$$PWD/tokenize.h $$PWD/tokenize.h
win32 {
HEADERS += $$PWD/filelister_win32.h
}
SOURCES += $$PWD/checkautovariables.cpp \ SOURCES += $$PWD/checkautovariables.cpp \
$$PWD/checkbufferoverrun.cpp \ $$PWD/checkbufferoverrun.cpp \
$$PWD/checkclass.cpp \ $$PWD/checkclass.cpp \
@ -40,3 +44,7 @@ SOURCES += $$PWD/checkautovariables.cpp \
$$PWD/settings.cpp \ $$PWD/settings.cpp \
$$PWD/token.cpp \ $$PWD/token.cpp \
$$PWD/tokenize.cpp $$PWD/tokenize.cpp
win32 {
SOURCES += $$PWD/filelister_win32.cpp
}

View File

@ -1325,7 +1325,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filename
if (fileOpened) if (fileOpened)
{ {
std::string tempFile = FileLister::simplifyPath(filename.c_str()); std::string tempFile = getFileLister()->simplifyPath(filename.c_str());
std::transform(tempFile.begin(), tempFile.end(), tempFile.begin(), tolowerWrapper); std::transform(tempFile.begin(), tempFile.end(), tempFile.begin(), tolowerWrapper);
if (handledFiles.find(tempFile) != handledFiles.end()) if (handledFiles.find(tempFile) != handledFiles.end())
{ {

View File

@ -230,7 +230,7 @@ void Tokenizer::createTokens(std::istream &code)
fileIndexes.push_back(FileIndex); fileIndexes.push_back(FileIndex);
for (unsigned int i = 0; i < _files.size(); i++) for (unsigned int i = 0; i < _files.size(); i++)
{ {
if (FileLister::sameFileName(_files[i].c_str(), line.c_str())) if (getFileLister()->sameFileName(_files[i].c_str(), line.c_str()))
{ {
// Use this index // Use this index
foundOurfile = true; foundOurfile = true;
@ -241,7 +241,7 @@ void Tokenizer::createTokens(std::istream &code)
if (!foundOurfile) if (!foundOurfile)
{ {
// The "_files" vector remembers what files have been tokenized.. // The "_files" vector remembers what files have been tokenized..
_files.push_back(FileLister::simplifyPath(line.c_str())); _files.push_back(getFileLister()->simplifyPath(line.c_str()));
FileIndex = static_cast<unsigned int>(_files.size() - 1); FileIndex = static_cast<unsigned int>(_files.size() - 1);
} }
@ -1094,7 +1094,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
_configuration = configuration; _configuration = configuration;
// The "_files" vector remembers what files have been tokenized.. // The "_files" vector remembers what files have been tokenized..
_files.push_back(FileLister::simplifyPath(FileName)); _files.push_back(getFileLister()->simplifyPath(FileName));
createTokens(code); createTokens(code);