27 bool FindApproxPath::Component::
34 return (_name == node->get_name());
36 case CT_match_name_insensitive:
38 return cmp_nocase(_name, node->get_name()) == 0;
40 case CT_match_name_glob:
42 return (_glob.matches(node->get_name()));
44 case CT_match_exact_type:
48 case CT_match_inexact_type:
55 return (node->has_tag(_name));
57 case CT_match_tag_value:
59 if (node->has_tag(_name)) {
60 return _glob.matches(node->get_tag(_name));
69 case CT_match_pointer:
71 return (_pointer == node);
75 <<
"Invalid component in FindApproxPath\n";
82 void FindApproxPath::Component::
83 output(ostream &out)
const {
87 case CT_match_name_insensitive:
88 case CT_match_name_glob:
90 out <<
" \"" << _name <<
"\"";
93 case CT_match_tag_value:
94 out <<
" \"" << _name <<
"\"=\"" << _glob <<
"\"";
97 case CT_match_exact_type:
98 case CT_match_inexact_type:
99 out <<
" " << _type_handle;
102 case CT_match_pointer:
103 out <<
" (" << *_pointer <<
")";
119 vector_string components;
122 size_t slash = str_path.find(
'/');
123 while (slash != string::npos) {
124 components.push_back(str_path.substr(start, slash - start));
126 slash = str_path.find(
'/', start);
129 size_t semicolon = str_path.rfind(
';');
135 if (semicolon < start) {
136 semicolon = string::npos;
139 components.push_back(str_path.substr(start, semicolon - start));
141 if (semicolon != string::npos) {
142 if (!
add_flags(str_path.substr(semicolon + 1))) {
148 vector_string::const_iterator ci;
149 for (ci = components.begin(); ci != components.end(); ++ci) {
165 string::const_iterator pi = str_flags.begin();
166 while (pi != str_flags.end()) {
177 <<
"Invalid control flag string: " << str_flags <<
"\n";
182 if (pi == str_flags.end()) {
184 <<
"Invalid control flag string: " << str_flags <<
"\n";
194 _return_stashed = on;
198 _case_insensitive = on;
203 <<
"Invalid control flag string: " << str_flags <<
"\n";
222 if (str_component.size() >= 2 && str_component.substr(0, 2) ==
"@@") {
224 str_component = str_component.substr(2);
227 if (str_component ==
"*") {
230 }
else if (str_component ==
"**") {
231 if ((flags & CF_stashed) != 0) {
233 <<
"@@** is undefined; use @@*/** or **/@@* instead.\n";
238 }
else if (!str_component.empty() && str_component[0] ==
'-') {
239 string type_name = str_component.substr(1);
242 if (handle == TypeHandle::none()) {
244 <<
"Invalid type name: " << type_name <<
"\n";
251 }
else if (!str_component.empty() && str_component[0] ==
'+') {
252 string type_name = str_component.substr(1);
255 if (handle == TypeHandle::none()) {
257 <<
"Invalid type name: " << type_name <<
"\n";
264 }
else if (!str_component.empty() && str_component[0] ==
'=') {
265 size_t equals = str_component.find(
'=', 1);
266 if (equals != string::npos) {
268 string tag_key = str_component.substr(1, equals - 1);
269 string tag_value = str_component.substr(equals + 1);
273 string tag_key = str_component.substr(1);
290 comp._type = _case_insensitive ? CT_match_name_insensitive : CT_match_name;
293 _path.push_back(comp);
303 comp._type = CT_match_name_glob;
305 comp._glob.set_pattern(name);
306 comp._glob.set_case_sensitive(!_case_insensitive);
308 if (!comp._glob.has_glob_characters()) {
313 _path.push_back(comp);
324 comp._type = CT_match_exact_type;
325 comp._type_handle = type;
327 _path.push_back(comp);
337 comp._type = CT_match_inexact_type;
338 comp._type_handle = type;
340 _path.push_back(comp);
350 comp._type = CT_match_tag;
353 _path.push_back(comp);
364 comp._type = CT_match_tag_value;
366 comp._glob.set_pattern(value);
368 _path.push_back(comp);
377 comp._type = CT_match_one;
379 _path.push_back(comp);
388 comp._type = CT_match_many;
390 _path.push_back(comp);
399 comp._type = CT_match_pointer;
400 comp._pointer = pointer;
402 _path.push_back(comp);
408 void FindApproxPath::
409 output(ostream &out)
const {
411 if (!_path.empty()) {
412 Path::const_iterator pi = _path.begin();
415 while (pi != _path.end()) {
424 operator << (ostream &out, FindApproxPath::ComponentType type) {
426 case FindApproxPath::CT_match_name:
427 return out <<
"match_name";
429 case FindApproxPath::CT_match_name_insensitive:
430 return out <<
"match_name_insensitive";
432 case FindApproxPath::CT_match_name_glob:
433 return out <<
"match_name_glob";
435 case FindApproxPath::CT_match_exact_type:
436 return out <<
"match_exact_type";
438 case FindApproxPath::CT_match_inexact_type:
439 return out <<
"match_inexact_type";
441 case FindApproxPath::CT_match_tag:
442 return out <<
"match_tag";
444 case FindApproxPath::CT_match_tag_value:
445 return out <<
"match_tag_value";
447 case FindApproxPath::CT_match_one:
448 return out <<
"match_one";
450 case FindApproxPath::CT_match_many:
451 return out <<
"match_many";
453 case FindApproxPath::CT_match_pointer:
454 return out <<
"match_pointer";
457 return out <<
"**invalid**";
void add_match_one(int flags)
Adds a component that will match any node (but not a chain of many nodes).
bool add_flags(const std::string &str_flags)
Adds a sequence of control flags.
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_tag_value(const std::string &key, const std::string &value, int flags)
Adds a component that will match a node that has a tag with the indicated key.
bool add_component(std::string str_component)
Adds a single component to the path sequence, defined by a string as might appear between slashes in ...
void add_match_tag(const std::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...
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_many(int flags)
Adds a component that will match a chain of zero or more consecutive nodes.
bool add_string(const std::string &str_path)
Adds a sequence of components separated by slashes, followed optionally by a semicolon and a sequence...
void add_match_name(const std::string &name, int flags)
Adds a component that must match the name of a node exactly.
void add_match_pointer(PandaNode *pointer, int flags)
Adds a component that must match a particular node exactly, by pointer.
void add_match_name_glob(const std::string &glob, int flags)
Adds a component that must match the name of a node using standard shell globbing rules,...
A basic node of the scene graph or data graph.
TypeHandle is the identifier used to differentiate C++ class types.
static TypeRegistry * ptr()
Returns the pointer to the global TypeRegistry object.
TypeHandle find_type(const std::string &name) const
Looks for a previously-registered type of the given name.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.