Browse Source

support case-insensitive NodePath searches

David Rose 22 years ago
parent
commit
c4dc626ead

+ 30 - 1
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 &copy) : _pattern(copy._pattern) {
+GlobPattern(const GlobPattern &copy) : 
+  _pattern(copy._pattern),
+  _case_sensitive(copy._case_sensitive)
+{
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -43,6 +47,7 @@ GlobPattern(const GlobPattern &copy) : _pattern(copy._pattern) {
 INLINE void GlobPattern::
 operator = (const GlobPattern &copy) {
   _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

+ 13 - 3
panda/src/express/globPattern.cxx

@@ -17,6 +17,7 @@
 ////////////////////////////////////////////////////////////////////
 
 #include "globPattern.h"
+#include <ctype.h>
 
 ////////////////////////////////////////////////////////////////////
 //     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 {

+ 4 - 0
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) {

+ 12 - 139
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

+ 175 - 7
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";
 

+ 13 - 9
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 &);