15 #include "findApproxPath.h"
16 #include "config_pgraph.h"
18 #include "string_utils.h"
19 #include "pandaNode.h"
28 bool FindApproxPath::Component::
35 return (_name == node->get_name());
37 case CT_match_name_insensitive:
39 return cmp_nocase(_name, node->get_name()) == 0;
41 case CT_match_name_glob:
43 return (_glob.matches(node->get_name()));
45 case CT_match_exact_type:
49 case CT_match_inexact_type:
58 case CT_match_tag_value:
61 return _glob.matches(node->
get_tag(_name));
70 case CT_match_pointer:
72 return (_pointer == node);
76 <<
"Invalid component in FindApproxPath\n";
85 void FindApproxPath::Component::
86 output(ostream &out)
const {
90 case CT_match_name_insensitive:
91 case CT_match_name_glob:
93 out <<
" \"" << _name <<
"\"";
96 case CT_match_tag_value:
97 out <<
" \"" << _name <<
"\"=\"" << _glob <<
"\"";
100 case CT_match_exact_type:
101 case CT_match_inexact_type:
102 out <<
" " << _type_handle;
105 case CT_match_pointer:
106 out <<
" (" << *_pointer <<
")";
125 vector_string components;
128 size_t slash = str_path.find(
'/');
129 while (slash != string::npos) {
130 components.push_back(str_path.substr(start, slash - start));
132 slash = str_path.find(
'/', start);
135 size_t semicolon = str_path.rfind(
';');
141 if (semicolon < start) {
142 semicolon = string::npos;
145 components.push_back(str_path.substr(start, semicolon - start));
147 if (semicolon != string::npos) {
148 if (!
add_flags(str_path.substr(semicolon + 1))) {
154 vector_string::const_iterator ci;
155 for (ci = components.begin(); ci != components.end(); ++ci) {
174 string::const_iterator pi = str_flags.begin();
175 while (pi != str_flags.end()) {
186 <<
"Invalid control flag string: " << str_flags <<
"\n";
191 if (pi == str_flags.end()) {
193 <<
"Invalid control flag string: " << str_flags <<
"\n";
203 _return_stashed = on;
207 _case_insensitive = on;
212 <<
"Invalid control flag string: " << str_flags <<
"\n";
234 if (str_component.size() >= 2 && str_component.substr(0, 2) ==
"@@") {
236 str_component = str_component.substr(2);
239 if (str_component ==
"*") {
242 }
else if (str_component ==
"**") {
243 if ((flags & CF_stashed) != 0) {
245 <<
"@@** is undefined; use @@*/** or **/@@* instead.\n";
250 }
else if (!str_component.empty() && str_component[0] ==
'-') {
251 string type_name = str_component.substr(1);
256 <<
"Invalid type name: " << type_name <<
"\n";
263 }
else if (!str_component.empty() && str_component[0] ==
'+') {
264 string type_name = str_component.substr(1);
269 <<
"Invalid type name: " << type_name <<
"\n";
276 }
else if (!str_component.empty() && str_component[0] ==
'=') {
277 size_t equals = str_component.find(
'=', 1);
278 if (equals != string::npos) {
280 string tag_key = str_component.substr(1, equals - 1);
281 string tag_value = str_component.substr(equals + 1);
285 string tag_key = str_component.substr(1);
305 comp._type = _case_insensitive ? CT_match_name_insensitive : CT_match_name;
308 _path.push_back(comp);
321 comp._type = CT_match_name_glob;
323 comp._glob.set_pattern(name);
324 comp._glob.set_case_sensitive(!_case_insensitive);
326 if (!comp._glob.has_glob_characters()) {
331 _path.push_back(comp);
344 comp._type = CT_match_exact_type;
345 comp._type_handle = type;
347 _path.push_back(comp);
359 comp._type = CT_match_inexact_type;
360 comp._type_handle = type;
362 _path.push_back(comp);
375 comp._type = CT_match_tag;
378 _path.push_back(comp);
392 comp._type = CT_match_tag_value;
394 comp._glob.set_pattern(value);
396 _path.push_back(comp);
408 comp._type = CT_match_one;
410 _path.push_back(comp);
422 comp._type = CT_match_many;
424 _path.push_back(comp);
436 comp._type = CT_match_pointer;
437 comp._pointer = pointer;
439 _path.push_back(comp);
447 void FindApproxPath::
448 output(ostream &out)
const {
450 if (!_path.empty()) {
451 Path::const_iterator pi = _path.begin();
454 while (pi != _path.end()) {
463 operator << (ostream &out, FindApproxPath::ComponentType type) {
465 case FindApproxPath::CT_match_name:
466 return out <<
"match_name";
468 case FindApproxPath::CT_match_name_insensitive:
469 return out <<
"match_name_insensitive";
471 case FindApproxPath::CT_match_name_glob:
472 return out <<
"match_name_glob";
474 case FindApproxPath::CT_match_exact_type:
475 return out <<
"match_exact_type";
477 case FindApproxPath::CT_match_inexact_type:
478 return out <<
"match_inexact_type";
480 case FindApproxPath::CT_match_tag:
481 return out <<
"match_tag";
483 case FindApproxPath::CT_match_tag_value:
484 return out <<
"match_tag_value";
486 case FindApproxPath::CT_match_one:
487 return out <<
"match_one";
489 case FindApproxPath::CT_match_many:
490 return out <<
"match_many";
492 case FindApproxPath::CT_match_pointer:
493 return out <<
"match_pointer";
496 return out <<
"**invalid**";
void add_match_pointer(PandaNode *pointer, int flags)
Adds a component that must match a particular node exactly, by pointer.
A basic node of the scene graph or data graph.
TypeHandle find_type(const string &name) const
Looks for a previously-registered type of the given name.
static TypeHandle none()
Returns a special zero-valued TypeHandle that is used to indicate no type.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool add_flags(const string &str_flags)
Adds a sequence of control flags.
void add_match_one(int flags)
Adds a component that will match any node (but not a chain of many nodes).
void add_match_inexact_type(TypeHandle type, int flags)
Adds a component that must match the type of a node or be a base class of the node's type...
void add_match_exact_type(TypeHandle type, int flags)
Adds a component that must match the type of a node exactly, with no derived types matching...
void add_match_name_glob(const string &glob, int flags)
Adds a component that must match the name of a node using standard shell globbing rules...
bool has_tag(const string &key, Thread *current_thread=Thread::get_current_thread()) const
Returns true if a value has been defined on this node for the particular key (even if that value is t...
void add_match_many(int flags)
Adds a component that will match a chain of zero or more consecutive nodes.
string get_tag(const string &key, Thread *current_thread=Thread::get_current_thread()) const
Retrieves the user-defined value that was previously set on this node for the particular key...
void add_match_name(const string &name, int flags)
Adds a component that must match the name of a node exactly.
void add_match_tag_value(const string &key, const string &value, int flags)
Adds a component that will match a node that has a tag with the indicated key.
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
void add_match_tag(const string &key, int flags)
Adds a component that will match a node that has a tag with the indicated key, no matter what the val...
bool add_string(const string &str_path)
Adds a sequence of components separated by slashes, followed optionally by a semicolon and a sequence...
TypeHandle is the identifier used to differentiate C++ class types.
bool add_component(string str_component)
Adds a single component to the path sequence, defined by a string as might appear between slashes in ...