diff --git a/panda/src/express/globPattern.I b/panda/src/express/globPattern.I index 2f4db8126c..786f836dd7 100644 --- a/panda/src/express/globPattern.I +++ b/panda/src/express/globPattern.I @@ -24,6 +24,7 @@ //////////////////////////////////////////////////////////////////// INLINE GlobPattern:: GlobPattern(const string &pattern) : _pattern(pattern) { + _case_sensitive = true; } //////////////////////////////////////////////////////////////////// @@ -32,7 +33,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) +{ } //////////////////////////////////////////////////////////////////// @@ -43,6 +47,7 @@ GlobPattern(const GlobPattern ©) : _pattern(copy._pattern) { INLINE void GlobPattern:: operator = (const GlobPattern ©) { _pattern = copy._pattern; + _case_sensitive = copy._case_sensitive; } //////////////////////////////////////////////////////////////////// @@ -67,6 +72,30 @@ 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::matches // Access: Public diff --git a/panda/src/express/globPattern.cxx b/panda/src/express/globPattern.cxx index a061cdf06a..51de16893b 100644 --- a/panda/src/express/globPattern.cxx +++ b/panda/src/express/globPattern.cxx @@ -17,6 +17,7 @@ //////////////////////////////////////////////////////////////////// #include "globPattern.h" +#include //////////////////////////////////////////////////////////////////// // Function: GlobPattern::has_glob_characters @@ -235,8 +236,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); } @@ -290,7 +297,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/panda/src/express/globPattern.h b/panda/src/express/globPattern.h index 5529cc9f8a..db89cb14a8 100644 --- a/panda/src/express/globPattern.h +++ b/panda/src/express/globPattern.h @@ -47,6 +47,9 @@ public: 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 bool matches(const string &candidate) const; INLINE void output(ostream &out) const; @@ -68,6 +71,7 @@ private: vector_string &results, const Filename &cwd); string _pattern; + bool _case_sensitive; }; INLINE ostream &operator << (ostream &out, const GlobPattern &glob) { diff --git a/panda/src/pgraph/findApproxPath.I b/panda/src/pgraph/findApproxPath.I index 36c6fe659c..7b4d064414 100644 --- a/panda/src/pgraph/findApproxPath.I +++ b/panda/src/pgraph/findApproxPath.I @@ -26,145 +26,7 @@ INLINE FindApproxPath:: FindApproxPath() { _return_hidden = true; _return_stashed = false; -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_name -// Access: Public -// Description: Adds a component that must match the name of a node -// exactly. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_name(const string &name, int flags) { - Component comp; - comp._type = CT_match_name; - comp._name = name; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_name_glob -// Access: Public -// Description: Adds a component that must match the name of a node -// using standard shell globbing rules, with wildcard -// characters accepted. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_name_glob(const string &name, int flags) { - Component comp; - comp._type = CT_match_name_glob; - comp._name = name; - comp._glob.set_pattern(name); - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_exact_type -// Access: Public -// Description: Adds a component that must match the type of a node -// exactly, with no derived types matching. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_exact_type(TypeHandle type, int flags) { - Component comp; - comp._type = CT_match_exact_type; - comp._type_handle = type; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_inexact_type -// Access: Public -// Description: Adds a component that must match the type of a node -// or be a base class of the node's type. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_inexact_type(TypeHandle type, int flags) { - Component comp; - comp._type = CT_match_inexact_type; - comp._type_handle = type; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_tag -// Access: Public -// Description: Adds a component that will match a node that has a -// tag with the indicated key, no matter what the value -// is. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_tag(const string &name, int flags) { - Component comp; - comp._type = CT_match_tag; - comp._name = name; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_tag_value -// Access: Public -// Description: Adds a component that will match a node that has a -// tag with the indicated key. The value may be "*" to -// match any value, or a particular glob pattern to -// match only those nodes with the indicated value. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_tag_value(const string &name, const string &value, int flags) { - Component comp; - comp._type = CT_match_tag_value; - comp._name = name; - comp._glob.set_pattern(value); - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_one -// Access: Public -// Description: Adds a component that will match any node (but not a -// chain of many nodes). -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_one(int flags) { - Component comp; - comp._type = CT_match_one; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_many -// Access: Public -// Description: Adds a component that will match a chain of zero or -// more consecutive nodes. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_many(int flags) { - Component comp; - comp._type = CT_match_many; - comp._flags = flags; - _path.push_back(comp); -} - -//////////////////////////////////////////////////////////////////// -// Function: FindApproxPath::add_match_pointer -// Access: Public -// Description: Adds a component that must match a particular node -// exactly, by pointer. -//////////////////////////////////////////////////////////////////// -INLINE void FindApproxPath:: -add_match_pointer(PandaNode *pointer, int flags) { - Component comp; - comp._type = CT_match_pointer; - comp._pointer = pointer; - comp._flags = flags; - _path.push_back(comp); + _case_insensitive = false; } //////////////////////////////////////////////////////////////////// @@ -238,6 +100,17 @@ return_stashed() const { return _return_stashed; } +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::case_insensitive +// Access: Public +// Description: Returns true if the search is case-insensitive, false +// if it is case-sensitive. +//////////////////////////////////////////////////////////////////// +INLINE bool FindApproxPath:: +case_insensitive() const { + return _case_insensitive; +} + //////////////////////////////////////////////////////////////////// // Function: FindApproxPath::output_component // Access: Public diff --git a/panda/src/pgraph/findApproxPath.cxx b/panda/src/pgraph/findApproxPath.cxx index 7f06c1ba5a..e3a92d7f97 100644 --- a/panda/src/pgraph/findApproxPath.cxx +++ b/panda/src/pgraph/findApproxPath.cxx @@ -19,6 +19,7 @@ #include "findApproxPath.h" #include "config_pgraph.h" +#include "string_utils.h" #include "pandaNode.h" @@ -37,6 +38,10 @@ matches(PandaNode *node) const { // Match the node's name exactly. return (_name == node->get_name()); + case CT_match_name_insensitive: + // Match the node's name exactly, with case-insensitive comparison. + return cmp_nocase(_name, node->get_name()) == 0; + case CT_match_name_glob: // Match the node's name according to filename globbing rules. return (_glob.matches(node->get_name())); @@ -86,6 +91,7 @@ output(ostream &out) const { out << _type; switch (_type) { case CT_match_name: + case CT_match_name_insensitive: case CT_match_name_glob: case CT_match_tag: out << " \"" << _name << "\""; @@ -119,12 +125,13 @@ output(ostream &out) const { //////////////////////////////////////////////////////////////////// bool FindApproxPath:: add_string(const string &str_path) { + // First, chop the string up by slashes into its components. + vector_string components; + size_t start = 0; size_t slash = str_path.find('/'); while (slash != string::npos) { - if (!add_component(str_path.substr(start, slash - start))) { - return false; - } + components.push_back(str_path.substr(start, slash - start)); start = slash + 1; slash = str_path.find('/', start); } @@ -139,12 +146,20 @@ add_string(const string &str_path) { semicolon = string::npos; } - if (!add_component(str_path.substr(start, semicolon - start))) { - return false; - } + components.push_back(str_path.substr(start, semicolon - start)); if (semicolon != string::npos) { - return add_flags(str_path.substr(semicolon + 1)); + if (!add_flags(str_path.substr(semicolon + 1))) { + return false; + } + } + + // Now decode each component and add it to the path. + vector_string::const_iterator ci; + for (ci = components.begin(); ci != components.end(); ++ci) { + if (!add_component(*ci)) { + return false; + } } return true; @@ -192,6 +207,10 @@ add_flags(const string &str_flags) { _return_stashed = on; break; + case 'i': + _case_insensitive = on; + break; + default: pgraph_cat.error() << "Invalid control flag string: " << str_flags << "\n"; @@ -278,6 +297,152 @@ add_component(string str_component) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_name +// Access: Public +// Description: Adds a component that must match the name of a node +// exactly. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_name(const string &name, int flags) { + Component comp; + comp._type = _case_insensitive ? CT_match_name_insensitive : CT_match_name; + comp._name = name; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_name_glob +// Access: Public +// Description: Adds a component that must match the name of a node +// using standard shell globbing rules, with wildcard +// characters accepted. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_name_glob(const string &name, int flags) { + Component comp; + comp._type = CT_match_name_glob; + comp._name = name; + comp._glob.set_pattern(name); + comp._glob.set_case_sensitive(!_case_insensitive); + comp._flags = flags; + if (!comp._glob.has_glob_characters()) { + // The glob pattern contains no special characters; make it a + // literal match for efficiency. + add_match_name(name, flags); + } else { + _path.push_back(comp); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_exact_type +// Access: Public +// Description: Adds a component that must match the type of a node +// exactly, with no derived types matching. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_exact_type(TypeHandle type, int flags) { + Component comp; + comp._type = CT_match_exact_type; + comp._type_handle = type; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_inexact_type +// Access: Public +// Description: Adds a component that must match the type of a node +// or be a base class of the node's type. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_inexact_type(TypeHandle type, int flags) { + Component comp; + comp._type = CT_match_inexact_type; + comp._type_handle = type; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_tag +// Access: Public +// Description: Adds a component that will match a node that has a +// tag with the indicated key, no matter what the value +// is. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_tag(const string &name, int flags) { + Component comp; + comp._type = CT_match_tag; + comp._name = name; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_tag_value +// Access: Public +// Description: Adds a component that will match a node that has a +// tag with the indicated key. The value may be "*" to +// match any value, or a particular glob pattern to +// match only those nodes with the indicated value. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_tag_value(const string &name, const string &value, int flags) { + Component comp; + comp._type = CT_match_tag_value; + comp._name = name; + comp._glob.set_pattern(value); + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_one +// Access: Public +// Description: Adds a component that will match any node (but not a +// chain of many nodes). +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_one(int flags) { + Component comp; + comp._type = CT_match_one; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_many +// Access: Public +// Description: Adds a component that will match a chain of zero or +// more consecutive nodes. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_many(int flags) { + Component comp; + comp._type = CT_match_many; + comp._flags = flags; + _path.push_back(comp); +} + +//////////////////////////////////////////////////////////////////// +// Function: FindApproxPath::add_match_pointer +// Access: Public +// Description: Adds a component that must match a particular node +// exactly, by pointer. +//////////////////////////////////////////////////////////////////// +void FindApproxPath:: +add_match_pointer(PandaNode *pointer, int flags) { + Component comp; + comp._type = CT_match_pointer; + comp._pointer = pointer; + comp._flags = flags; + _path.push_back(comp); +} + //////////////////////////////////////////////////////////////////// // Function: FindApproxPath::output // Access: Public @@ -304,6 +469,9 @@ operator << (ostream &out, FindApproxPath::ComponentType type) { case FindApproxPath::CT_match_name: return out << "match_name"; + case FindApproxPath::CT_match_name_insensitive: + return out << "match_name_insensitive"; + case FindApproxPath::CT_match_name_glob: return out << "match_name_glob"; diff --git a/panda/src/pgraph/findApproxPath.h b/panda/src/pgraph/findApproxPath.h index d056bbb43d..49df7e1f10 100644 --- a/panda/src/pgraph/findApproxPath.h +++ b/panda/src/pgraph/findApproxPath.h @@ -42,15 +42,16 @@ public: bool add_flags(const string &str_flags); bool add_component(string str_component); - INLINE void add_match_name(const string &name, int flags); - INLINE void add_match_name_glob(const string &glob, int flags); - INLINE void add_match_exact_type(TypeHandle type, int flags); - INLINE void add_match_inexact_type(TypeHandle type, int flags); - INLINE void add_match_tag(const string &key, int flags); - INLINE void add_match_tag_value(const string &key, const string &value, int flags); - INLINE void add_match_one(int flags); - INLINE void add_match_many(int flags); - INLINE void add_match_pointer(PandaNode *pointer, int flags); + void add_match_name(const string &name, int flags); + void add_match_name_glob(const string &glob, int flags); + void add_match_exact_type(TypeHandle type, int flags); + void add_match_inexact_type(TypeHandle type, int flags); + void add_match_tag(const string &key, int flags); + void add_match_tag_value(const string &key, const string &value, int flags); + + void add_match_one(int flags); + void add_match_many(int flags); + void add_match_pointer(PandaNode *pointer, int flags); INLINE int get_num_components() const; INLINE bool is_component_match_many(int index) const; @@ -59,6 +60,7 @@ public: INLINE bool return_hidden() const; INLINE bool return_stashed() const; + INLINE bool case_insensitive() const; void output(ostream &out) const; INLINE void output_component(ostream &out, int index) const; @@ -70,6 +72,7 @@ private: #endif enum ComponentType { CT_match_name, + CT_match_name_insensitive, CT_match_name_glob, CT_match_exact_type, CT_match_inexact_type, @@ -101,6 +104,7 @@ private: bool _return_hidden; bool _return_stashed; + bool _case_insensitive; friend ostream &operator << (ostream &, FindApproxPath::ComponentType); friend INLINE ostream &operator << (ostream &, const FindApproxPath::Component &);