new interface for reading directories which helps getting some preprocessor clutter outside of script.cpp
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3781 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
c2c907b2bf
commit
7450c0f23b
3 changed files with 273 additions and 0 deletions
225
Source/dirreader.cpp
Normal file
225
Source/dirreader.cpp
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
#include "Platform.h"
|
||||||
|
#include "dirreader.h"
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <ctype.h> // for tolower()
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
dir_reader::dir_reader() {
|
||||||
|
exclude(".");
|
||||||
|
exclude("..");
|
||||||
|
}
|
||||||
|
|
||||||
|
const set<string>& dir_reader::files() {
|
||||||
|
return m_files;
|
||||||
|
}
|
||||||
|
|
||||||
|
const set<string>& dir_reader::dirs() {
|
||||||
|
return m_dirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dir_reader::exclude(const string& spec) {
|
||||||
|
if (spec.find_first_of("?*") >= 0) {
|
||||||
|
m_wildcard_excluded.insert(spec);
|
||||||
|
} else {
|
||||||
|
m_excluded.insert(spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dir_reader::exclude(const set<string>& specs) {
|
||||||
|
iterator i = specs.begin();
|
||||||
|
iterator e = specs.end();
|
||||||
|
|
||||||
|
for (; i != e; i++) {
|
||||||
|
exclude(*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dir_reader::matches(const string& name, const string& spec) {
|
||||||
|
string::const_iterator name_itr = name.begin();
|
||||||
|
string::const_iterator name_end = name.end();
|
||||||
|
|
||||||
|
string::const_iterator spec_itr = spec.begin();
|
||||||
|
string::const_iterator spec_end = spec.end();
|
||||||
|
|
||||||
|
string::const_iterator last_good_spec = NULL;
|
||||||
|
string::const_iterator last_good_name = NULL;
|
||||||
|
|
||||||
|
while (name_itr != name_end && spec_itr != spec_end) {
|
||||||
|
switch (*spec_itr) {
|
||||||
|
case '?':
|
||||||
|
// question mark mathes one char
|
||||||
|
name_itr++;
|
||||||
|
spec_itr++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '*':
|
||||||
|
// double asterisk is the same as a simgle asterisk
|
||||||
|
while (*spec_itr == '*' && spec_itr != spec_end)
|
||||||
|
spec_itr++;
|
||||||
|
|
||||||
|
// asterisk at the end of the spec matches the end of the name
|
||||||
|
if (spec_itr == spec_end)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// remember last good name and spec for prematurely stopped asterisk
|
||||||
|
last_good_spec = spec_itr;
|
||||||
|
last_good_name = name_itr;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (::tolower(*name_itr) != ::tolower(*spec_itr)) {
|
||||||
|
if (last_good_spec) {
|
||||||
|
// matched wrong part of the name, try again
|
||||||
|
spec_itr = last_good_spec;
|
||||||
|
name_itr = ++last_good_name;
|
||||||
|
} else {
|
||||||
|
// no match and no asterisk to use
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// remember last good name for prematurely stopped asterisk
|
||||||
|
last_good_name = name_itr;
|
||||||
|
|
||||||
|
spec_itr++;
|
||||||
|
name_itr++;
|
||||||
|
|
||||||
|
if (spec_itr == spec_end && name_itr != name_end && last_good_spec) {
|
||||||
|
// asterisk hasn't matched enough, keep matching
|
||||||
|
spec_itr = last_good_spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip any redundant asterisks and periods at the end of the name
|
||||||
|
while (spec_itr != spec_end) {
|
||||||
|
if (*spec_itr != '.' && *spec_itr != '*') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spec_itr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true only if managed to match everything
|
||||||
|
return name_itr == name_end && spec_itr == spec_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dir_reader::add_file(const string& file) {
|
||||||
|
if (!is_excluded(file)) {
|
||||||
|
m_files.insert(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dir_reader::add_dir(const std::string& dir) {
|
||||||
|
if (!is_excluded(dir)) {
|
||||||
|
m_dirs.insert(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dir_reader::is_excluded(const string& name) const {
|
||||||
|
iterator i = m_excluded.begin();
|
||||||
|
iterator e = m_excluded.end();
|
||||||
|
|
||||||
|
for (; i != e; i++) {
|
||||||
|
if (name == *i) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i = m_wildcard_excluded.begin();
|
||||||
|
e = m_wildcard_excluded.end();
|
||||||
|
|
||||||
|
for (; i != e; i++) {
|
||||||
|
if (matches(name, *i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
class win32_dir_reader : public dir_reader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void read(const string& dir) {
|
||||||
|
WIN32_FIND_DATA fd;
|
||||||
|
|
||||||
|
string spec = dir + PLATFORM_PATH_SEPARATOR_STR + "*.*";
|
||||||
|
|
||||||
|
HANDLE h = ::FindFirstFile(spec.c_str(), &fd);
|
||||||
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
|
do {
|
||||||
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
|
dir_reader::add_dir(fd.cFileName);
|
||||||
|
} else {
|
||||||
|
dir_reader::add_file(fd.cFileName);
|
||||||
|
}
|
||||||
|
} while (::FindNextFile(h, &fd));
|
||||||
|
::FindClose(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
|
class posix_dir_reader : public dir_reader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual void read(const string& dir) {
|
||||||
|
//string converted_dir = convert(dir);
|
||||||
|
|
||||||
|
DIR *dip = ::diropen(dir.c_str());
|
||||||
|
if (dip) {
|
||||||
|
dirent *dit;
|
||||||
|
while (dit = ::dirread(dip)) {
|
||||||
|
if (dit->d_type == DT_DIR) {
|
||||||
|
dir_reader::add_dir(dit->d_name);
|
||||||
|
} else {
|
||||||
|
dir_reader::add_file(dit->d_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::closedir(dip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
string& convert(string& path) {
|
||||||
|
string converted = path;
|
||||||
|
|
||||||
|
string::size_type pos = converted.find('\\');
|
||||||
|
while (pos != string::npos) {
|
||||||
|
converted[pos] = '/';
|
||||||
|
pos = converted.find('\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Replace drive letter X: by /x */
|
||||||
|
if (converted[1] == ':') {
|
||||||
|
converted[1] = ::tolower(converted[0]);
|
||||||
|
converted[0] = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dir_reader* new_dir_reader() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return new win32_dir_reader();
|
||||||
|
#else
|
||||||
|
return new posix_dir_reader();
|
||||||
|
#endif
|
||||||
|
}
|
40
Source/dirreader.h
Normal file
40
Source/dirreader.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "Platform.h"
|
||||||
|
#include <string>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
class dir_reader {
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef std::set<std::string>::const_iterator iterator;
|
||||||
|
|
||||||
|
dir_reader();
|
||||||
|
virtual ~dir_reader() {}
|
||||||
|
|
||||||
|
virtual void read(const std::string& dir) = 0;
|
||||||
|
|
||||||
|
virtual const std::set<std::string>& files();
|
||||||
|
virtual const std::set<std::string>& dirs();
|
||||||
|
|
||||||
|
virtual void exclude(const std::string& spec);
|
||||||
|
virtual void exclude(const std::set<std::string>& specs);
|
||||||
|
|
||||||
|
static bool matches(const std::string& name, const std::string& spec);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void add_file(const std::string& file);
|
||||||
|
virtual void add_dir(const std::string& dir);
|
||||||
|
|
||||||
|
virtual bool is_excluded(const std::string& name) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::set<std::string> m_excluded;
|
||||||
|
std::set<std::string> m_wildcard_excluded;
|
||||||
|
|
||||||
|
std::set<std::string> m_files;
|
||||||
|
std::set<std::string> m_dirs;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
dir_reader* new_dir_reader();
|
|
@ -204,6 +204,10 @@ SOURCE=.\DialogTemplate.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dirreader.cpp
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\exedata.cpp
|
SOURCE=.\exedata.cpp
|
||||||
# ADD CPP /G6
|
# ADD CPP /G6
|
||||||
# End Source File
|
# End Source File
|
||||||
|
@ -293,6 +297,10 @@ SOURCE=.\DialogTemplate.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\dirreader.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\exedata.h
|
SOURCE=.\exedata.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue