mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-17 20:23:47 -04:00
add GlobPattern::match_files()
This commit is contained in:
parent
d2511eda84
commit
af3861a402
@ -159,6 +159,7 @@
|
||||
test_glob.cxx
|
||||
|
||||
#define LOCAL_LIBS $[LOCAL_LIBS] putil
|
||||
#define OTHER_LIBS $[OTHER_LIBS] pystub
|
||||
|
||||
#end test_bin_target
|
||||
|
||||
|
@ -18,6 +18,147 @@
|
||||
|
||||
#include "globPattern.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobPattern::has_glob_characters
|
||||
// Access: Public
|
||||
// Description: Returns true if the pattern includes any special
|
||||
// globbing characters, or false if it is just a literal
|
||||
// string.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GlobPattern::
|
||||
has_glob_characters() const {
|
||||
string::const_iterator pi;
|
||||
pi = _pattern.begin();
|
||||
while (pi != _pattern.end()) {
|
||||
switch (*pi) {
|
||||
case '*':
|
||||
case '?':
|
||||
case '[':
|
||||
return true;
|
||||
|
||||
case '\\':
|
||||
++pi;
|
||||
if (pi == _pattern.end()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
++pi;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobPattern::match_files
|
||||
// Access: Public
|
||||
// Description: Treats the GlobPattern as a filename pattern, and
|
||||
// returns a list of any actual files that match the
|
||||
// pattern. This is the behavior of the standard Posix
|
||||
// glob() function. Any part of the filename may
|
||||
// contain glob characters, including intermediate
|
||||
// directory names.
|
||||
//
|
||||
// If cwd is specified, it is the directory that
|
||||
// relative filenames are taken to be relative to;
|
||||
// otherwise, the actual current working directory is
|
||||
// assumed.
|
||||
//
|
||||
// The return value is the number of files matched,
|
||||
// which are added to the results vector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int GlobPattern::
|
||||
match_files(vector_string &results, const Filename &cwd) {
|
||||
string next_pattern, next_suffix;
|
||||
|
||||
size_t slash = _pattern.find('/');
|
||||
if (slash == string::npos) {
|
||||
next_pattern = _pattern;
|
||||
} else {
|
||||
next_pattern = _pattern.substr(0, slash);
|
||||
next_suffix = _pattern.substr(slash + 1);
|
||||
}
|
||||
|
||||
GlobPattern next_glob(next_pattern);
|
||||
return next_glob.r_match_files(Filename(), next_suffix, results, cwd);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobPattern::r_match_files
|
||||
// Access: Private
|
||||
// Description: The recursive implementation of match_files().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int GlobPattern::
|
||||
r_match_files(const Filename &prefix, const string &suffix,
|
||||
vector_string &results, const Filename &cwd) {
|
||||
string next_pattern, next_suffix;
|
||||
|
||||
size_t slash = suffix.find('/');
|
||||
if (slash == string::npos) {
|
||||
next_pattern = suffix;
|
||||
} else {
|
||||
next_pattern = suffix.substr(0, slash);
|
||||
next_suffix = suffix.substr(slash + 1);
|
||||
}
|
||||
|
||||
Filename parent_dir;
|
||||
if (prefix.is_local() && !cwd.empty()) {
|
||||
parent_dir = Filename(cwd, prefix);
|
||||
} else {
|
||||
parent_dir = prefix;
|
||||
}
|
||||
|
||||
GlobPattern next_glob(next_pattern);
|
||||
|
||||
if (!has_glob_characters()) {
|
||||
// If there are no special characters in the pattern, it's a
|
||||
// literal match.
|
||||
if (suffix.empty()) {
|
||||
// Time to stop.
|
||||
Filename single_filename(parent_dir, _pattern);
|
||||
if (single_filename.exists()) {
|
||||
results.push_back(Filename(prefix, _pattern));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return next_glob.r_match_files(Filename(prefix, _pattern),
|
||||
next_suffix, results, cwd);
|
||||
|
||||
}
|
||||
|
||||
// If there *are* special glob characters, we must attempt to
|
||||
// match the pattern against the files in this directory.
|
||||
|
||||
vector_string dir_files;
|
||||
if (!parent_dir.scan_directory(dir_files)) {
|
||||
// Not a directory, or unable to read directory; stop here.
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Now go through each file in the directory looking for one that
|
||||
// matches the pattern.
|
||||
int num_matched = 0;
|
||||
|
||||
vector_string::const_iterator fi;
|
||||
for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
|
||||
const string &local_file = (*fi);
|
||||
if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
|
||||
if (matches(local_file)) {
|
||||
// We have a match; continue.
|
||||
if (suffix.empty()) {
|
||||
results.push_back(Filename(prefix, local_file));
|
||||
num_matched++;
|
||||
} else {
|
||||
num_matched += next_glob.r_match_files(Filename(prefix, local_file),
|
||||
next_suffix, results, cwd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return num_matched;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GlobPattern::matches_substr
|
||||
// Access: Private
|
||||
|
@ -19,7 +19,9 @@
|
||||
#ifndef GLOBPATTERN_H
|
||||
#define GLOBPATTERN_H
|
||||
|
||||
#include <pandabase.h>
|
||||
#include "pandabase.h"
|
||||
#include "filename.h"
|
||||
#include "vector_string.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : GlobPattern
|
||||
@ -49,6 +51,9 @@ public:
|
||||
|
||||
INLINE void output(ostream &out) const;
|
||||
|
||||
bool has_glob_characters() const;
|
||||
int match_files(vector_string &results, const Filename &cwd = Filename());
|
||||
|
||||
private:
|
||||
bool matches_substr(string::const_iterator pi,
|
||||
string::const_iterator pend,
|
||||
@ -59,6 +64,9 @@ private:
|
||||
string::const_iterator pend,
|
||||
char ch) const;
|
||||
|
||||
int r_match_files(const Filename &prefix, const string &suffix,
|
||||
vector_string &results, const Filename &cwd);
|
||||
|
||||
string _pattern;
|
||||
};
|
||||
|
||||
|
@ -18,20 +18,14 @@
|
||||
|
||||
#include "globPattern.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
if (argc != 2) {
|
||||
if (argc != 2 && argc != 3) {
|
||||
cerr
|
||||
<< "test_glob \"pattern\"\n\n"
|
||||
<< "test_glob \"pattern\" [from-directory]\n\n"
|
||||
<< "Attempts to match the pattern against each of the files in the\n"
|
||||
<< "current directory. Reports all of the matching files. This is,\n"
|
||||
<< "indicated directory if specified, or the current directory\n"
|
||||
<< "otherwise. Reports all of the matching files. This is,\n"
|
||||
<< "of course, exactly the normal behavior of the shell; this test\n"
|
||||
<< "program merely exercises the Panda GlobPattern object, which\n"
|
||||
<< "duplicates the shell functionality.\n\n";
|
||||
@ -39,42 +33,20 @@ main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
GlobPattern pattern(argv[1]);
|
||||
|
||||
#ifdef WIN32
|
||||
struct _finddata_t fd;
|
||||
long dp = _findfirst("*.*", &fd);
|
||||
|
||||
if (dp != 0) {
|
||||
do {
|
||||
if (pattern.matches(fd.name)) {
|
||||
cout << "Matches: " << fd.name << "\n";
|
||||
} else {
|
||||
cout << "Fails: " << fd.name << "\n";
|
||||
}
|
||||
} while (_findnext(dp, &fd) == 0);
|
||||
Filename from_directory;
|
||||
if (argc == 3) {
|
||||
from_directory = argv[2];
|
||||
}
|
||||
|
||||
#else // WIN32
|
||||
DIR *dp = opendir(".");
|
||||
if (dp == (DIR *)NULL) {
|
||||
cerr << "Unable to scan directory '.'\n";
|
||||
exit(1);
|
||||
}
|
||||
vector_string results;
|
||||
int num_matched = pattern.match_files(results, from_directory);
|
||||
|
||||
struct dirent *ent;
|
||||
ent = readdir(dp);
|
||||
while (ent != (struct dirent *)NULL) {
|
||||
if (pattern.matches(ent->d_name)) {
|
||||
cout << "Matches: " << ent->d_name << "\n";
|
||||
} else {
|
||||
cout << "Fails: " << ent->d_name << "\n";
|
||||
}
|
||||
ent = readdir(dp);
|
||||
cerr << num_matched << " results:\n";
|
||||
vector_string::const_iterator si;
|
||||
for (si = results.begin(); si != results.end(); ++si) {
|
||||
cerr << " " << *si << "\n";
|
||||
}
|
||||
|
||||
closedir(dp);
|
||||
#endif // WIN32
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user