diff --git a/ppremake/globPattern.I b/ppremake/globPattern.I index fd4f4a8fb5..72d0c7e118 100644 --- a/ppremake/globPattern.I +++ b/ppremake/globPattern.I @@ -20,6 +20,7 @@ //////////////////////////////////////////////////////////////////// INLINE GlobPattern:: GlobPattern(const string &pattern) : _pattern(pattern) { + _case_sensitive = true; } //////////////////////////////////////////////////////////////////// @@ -28,7 +29,10 @@ GlobPattern(const string &pattern) : _pattern(pattern) { // Description: //////////////////////////////////////////////////////////////////// INLINE GlobPattern:: -GlobPattern(const GlobPattern ©) : _pattern(copy._pattern) { +GlobPattern(const GlobPattern ©) : + _pattern(copy._pattern), + _case_sensitive(copy._case_sensitive) +{ } //////////////////////////////////////////////////////////////////// @@ -39,6 +43,40 @@ GlobPattern(const GlobPattern ©) : _pattern(copy._pattern) { INLINE void GlobPattern:: operator = (const GlobPattern ©) { _pattern = copy._pattern; + _case_sensitive = copy._case_sensitive; +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::operator == +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GlobPattern:: +operator == (const GlobPattern &other) const { + return (_pattern == other._pattern && _case_sensitive == other._case_sensitive); +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::operator != +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GlobPattern:: +operator != (const GlobPattern &other) const { + return !operator == (other); +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::operator < +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +INLINE bool GlobPattern:: +operator < (const GlobPattern &other) const { + if (_case_sensitive != other._case_sensitive) { + return (int)_case_sensitive < (int)other._case_sensitive; + } + return _pattern < other._pattern; } //////////////////////////////////////////////////////////////////// @@ -63,6 +101,52 @@ get_pattern() const { return _pattern; } +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::set_case_sensitive +// Access: Public +// Description: Sets whether the match is case sensitive (true) or +// case insensitive (false). The default is case +// sensitive. +//////////////////////////////////////////////////////////////////// +INLINE void GlobPattern:: +set_case_sensitive(bool case_sensitive) { + _case_sensitive = case_sensitive; +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::get_case_sensitive +// Access: Public +// Description: Returns whether the match is case sensitive (true) or +// case insensitive (false). The default is case +// sensitive. +//////////////////////////////////////////////////////////////////// +INLINE bool GlobPattern:: +get_case_sensitive() const { + return _case_sensitive; +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::set_nomatch_chars +// Access: Public +// Description: Specifies a set of characters that are not matched by +// * or ?. +//////////////////////////////////////////////////////////////////// +INLINE void GlobPattern:: +set_nomatch_chars(const string &nomatch_chars) { + _nomatch_chars = nomatch_chars; +} + +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::get_nomatch_chars +// Access: Public +// Description: Returns the set of characters that are not matched by +// * or ?. +//////////////////////////////////////////////////////////////////// +INLINE const string &GlobPattern:: +get_nomatch_chars() const { + return _nomatch_chars; +} + //////////////////////////////////////////////////////////////////// // Function: GlobPattern::matches // Access: Public diff --git a/ppremake/globPattern.cxx b/ppremake/globPattern.cxx index 48e6974317..911bc47c81 100644 --- a/ppremake/globPattern.cxx +++ b/ppremake/globPattern.cxx @@ -13,6 +13,7 @@ //////////////////////////////////////////////////////////////////// #include "globPattern.h" +#include //////////////////////////////////////////////////////////////////// // Function: GlobPattern::has_glob_characters @@ -43,6 +44,39 @@ has_glob_characters() const { return false; } +//////////////////////////////////////////////////////////////////// +// Function: GlobPattern::get_const_prefix +// Access: Public +// Description: Returns the initial part of the pattern before the +// first glob character. Since many glob patterns begin +// with a sequence of static characters and end with one +// or more glob characters, this can be used to +// optimized searches through sorted indices. +//////////////////////////////////////////////////////////////////// +string GlobPattern:: +get_const_prefix() const { + string prefix; + + size_t p = 0; // current point + size_t q = 0; // starting point + while (p < _pattern.size()) { + switch (_pattern[p]) { + case '*': + case '?': + case '[': + return prefix + _pattern.substr(q, p - q); + + case '\\': + // Skip over the backslash. + prefix += _pattern.substr(q, p - q); + ++p; + q = p; + } + ++p; + } + return prefix += _pattern.substr(q, p - q); +} + //////////////////////////////////////////////////////////////////// // Function: GlobPattern::match_files // Access: Public @@ -179,7 +213,7 @@ matches_substr(string::const_iterator pi, string::const_iterator pend, // A special exception: we allow ci to reach the end before pi, // only if pi is one character before the end and that last // character is '*'. - if ((ci == cend) && (pi + 1 == pend) && (*pi) == '*') { + if ((ci == cend) && (std::distance(pi, pend) == 1) && (*pi) == '*') { return true; } return (pi == pend && ci == cend); @@ -193,9 +227,15 @@ matches_substr(string::const_iterator pi, string::const_iterator pend, // to recurse twice: either consume one character of the candidate // string and continue to try matching the *, or stop trying to // match the * here. - return - matches_substr(pi, pend, ci + 1, cend) || - matches_substr(pi + 1, pend, ci, cend); + if (_nomatch_chars.find(*ci) == string::npos) { + return + matches_substr(pi, pend, ci + 1, cend) || + matches_substr(pi + 1, pend, ci, cend); + } else { + // On the other hand, if this is one of the nomatch chars, we + // can only stop here. + return matches_substr(pi + 1, pend, ci, cend); + } case '?': // A '?' in the pattern string means to match exactly one @@ -231,8 +271,14 @@ matches_substr(string::const_iterator pi, string::const_iterator pend, default: // Anything else means to match exactly that. - if ((*pi) != (*ci)) { - return false; + if (_case_sensitive) { + if ((*pi) != (*ci)) { + return false; + } + } else { + if (tolower(*pi) != tolower(*ci)) { + return false; + } } return matches_substr(pi + 1, pend, ci + 1, cend); } @@ -286,7 +332,10 @@ matches_set(string::const_iterator &pi, string::const_iterator pend, char end = (*pi); ++pi; - if (ch >= start && ch <= end) { + if (ch >= start && ch <= end || + (!_case_sensitive && + ((tolower(ch) >= start && tolower(ch) <= end) || + (toupper(ch) >= start && toupper(ch) <= end)))) { matched = true; } } else { diff --git a/ppremake/globPattern.h b/ppremake/globPattern.h index eddac8fdc6..2c20452cd9 100644 --- a/ppremake/globPattern.h +++ b/ppremake/globPattern.h @@ -40,14 +40,25 @@ public: INLINE GlobPattern(const GlobPattern ©); INLINE void operator = (const GlobPattern ©); + INLINE bool operator == (const GlobPattern &other) const; + INLINE bool operator != (const GlobPattern &other) const; + INLINE bool operator < (const GlobPattern &other) const; + INLINE void set_pattern(const string &pattern); INLINE const string &get_pattern() const; + INLINE void set_case_sensitive(bool case_sensitive); + INLINE bool get_case_sensitive() const; + + INLINE void set_nomatch_chars(const string &nomatch_chars); + INLINE const string &get_nomatch_chars() const; + INLINE bool matches(const string &candidate) const; INLINE void output(ostream &out) const; bool has_glob_characters() const; + string get_const_prefix() const; int match_files(vector_string &results, const Filename &cwd = Filename()); private: @@ -64,6 +75,8 @@ private: vector_string &results, const Filename &cwd); string _pattern; + bool _case_sensitive; + string _nomatch_chars; }; INLINE ostream &operator << (ostream &out, const GlobPattern &glob) {