00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "findApproxPath.h"
00016 #include "config_pgraph.h"
00017
00018 #include "string_utils.h"
00019 #include "pandaNode.h"
00020
00021
00022
00023
00024
00025
00026
00027
00028 bool FindApproxPath::Component::
00029 matches(PandaNode *node) const {
00030 string node_name;
00031
00032 switch (_type) {
00033 case CT_match_name:
00034
00035 return (_name == node->get_name());
00036
00037 case CT_match_name_insensitive:
00038
00039 return cmp_nocase(_name, node->get_name()) == 0;
00040
00041 case CT_match_name_glob:
00042
00043 return (_glob.matches(node->get_name()));
00044
00045 case CT_match_exact_type:
00046
00047 return (node->is_exact_type(_type_handle));
00048
00049 case CT_match_inexact_type:
00050
00051
00052 return (node->is_of_type(_type_handle));
00053
00054 case CT_match_tag:
00055
00056 return (node->has_tag(_name));
00057
00058 case CT_match_tag_value:
00059
00060 if (node->has_tag(_name)) {
00061 return _glob.matches(node->get_tag(_name));
00062 }
00063 return false;
00064
00065 case CT_match_one:
00066 case CT_match_many:
00067
00068 return true;
00069
00070 case CT_match_pointer:
00071
00072 return (_pointer == node);
00073 }
00074
00075 pgraph_cat.error()
00076 << "Invalid component in FindApproxPath\n";
00077 return false;
00078 }
00079
00080
00081
00082
00083
00084
00085 void FindApproxPath::Component::
00086 output(ostream &out) const {
00087 out << _type;
00088 switch (_type) {
00089 case CT_match_name:
00090 case CT_match_name_insensitive:
00091 case CT_match_name_glob:
00092 case CT_match_tag:
00093 out << " \"" << _name << "\"";
00094 break;
00095
00096 case CT_match_tag_value:
00097 out << " \"" << _name << "\"=\"" << _glob << "\"";
00098 break;
00099
00100 case CT_match_exact_type:
00101 case CT_match_inexact_type:
00102 out << " " << _type_handle;
00103 break;
00104
00105 case CT_match_pointer:
00106 out << " (" << *_pointer << ")";
00107 break;
00108
00109 default:
00110 break;
00111 }
00112 }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 bool FindApproxPath::
00123 add_string(const string &str_path) {
00124
00125 vector_string components;
00126
00127 size_t start = 0;
00128 size_t slash = str_path.find('/');
00129 while (slash != string::npos) {
00130 components.push_back(str_path.substr(start, slash - start));
00131 start = slash + 1;
00132 slash = str_path.find('/', start);
00133 }
00134
00135 size_t semicolon = str_path.rfind(';');
00136
00137
00138
00139
00140
00141 if (semicolon < start) {
00142 semicolon = string::npos;
00143 }
00144
00145 components.push_back(str_path.substr(start, semicolon - start));
00146
00147 if (semicolon != string::npos) {
00148 if (!add_flags(str_path.substr(semicolon + 1))) {
00149 return false;
00150 }
00151 }
00152
00153
00154 vector_string::const_iterator ci;
00155 for (ci = components.begin(); ci != components.end(); ++ci) {
00156 if (!add_component(*ci)) {
00157 return false;
00158 }
00159 }
00160
00161 return true;
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172 bool FindApproxPath::
00173 add_flags(const string &str_flags) {
00174 string::const_iterator pi = str_flags.begin();
00175 while (pi != str_flags.end()) {
00176 bool on;
00177 switch (*pi) {
00178 case '+':
00179 on = true;
00180 break;
00181 case '-':
00182 on = false;
00183 break;
00184 default:
00185 pgraph_cat.error()
00186 << "Invalid control flag string: " << str_flags << "\n";
00187 return false;
00188 }
00189
00190 ++pi;
00191 if (pi == str_flags.end()) {
00192 pgraph_cat.error()
00193 << "Invalid control flag string: " << str_flags << "\n";
00194 return false;
00195 }
00196
00197 switch (*pi) {
00198 case 'h':
00199 _return_hidden = on;
00200 break;
00201
00202 case 's':
00203 _return_stashed = on;
00204 break;
00205
00206 case 'i':
00207 _case_insensitive = on;
00208 break;
00209
00210 default:
00211 pgraph_cat.error()
00212 << "Invalid control flag string: " << str_flags << "\n";
00213 return false;
00214 }
00215
00216 ++pi;
00217 }
00218
00219 return true;
00220 }
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 bool FindApproxPath::
00232 add_component(string str_component) {
00233 int flags = 0;
00234 if (str_component.size() >= 2 && str_component.substr(0, 2) == "@@") {
00235 flags |= CF_stashed;
00236 str_component = str_component.substr(2);
00237 }
00238
00239 if (str_component == "*") {
00240 add_match_one(flags);
00241
00242 } else if (str_component == "**") {
00243 if ((flags & CF_stashed) != 0) {
00244 pgraph_cat.error()
00245 << "@@** is undefined; use @@*/** or **/@@* instead.\n";
00246 return false;
00247 }
00248 add_match_many(flags);
00249
00250 } else if (!str_component.empty() && str_component[0] == '-') {
00251 string type_name = str_component.substr(1);
00252 TypeHandle handle = TypeRegistry::ptr()->find_type(type_name);
00253
00254 if (handle == TypeHandle::none()) {
00255 pgraph_cat.error()
00256 << "Invalid type name: " << type_name << "\n";
00257 return false;
00258
00259 } else {
00260 add_match_exact_type(handle, flags);
00261 }
00262
00263 } else if (!str_component.empty() && str_component[0] == '+') {
00264 string type_name = str_component.substr(1);
00265 TypeHandle handle = TypeRegistry::ptr()->find_type(type_name);
00266
00267 if (handle == TypeHandle::none()) {
00268 pgraph_cat.error()
00269 << "Invalid type name: " << type_name << "\n";
00270 return false;
00271
00272 } else {
00273 add_match_inexact_type(handle, flags);
00274 }
00275
00276 } else if (!str_component.empty() && str_component[0] == '=') {
00277 size_t equals = str_component.find('=', 1);
00278 if (equals != string::npos) {
00279
00280 string tag_key = str_component.substr(1, equals - 1);
00281 string tag_value = str_component.substr(equals + 1);
00282 add_match_tag_value(tag_key, tag_value, flags);
00283 } else {
00284
00285 string tag_key = str_component.substr(1);
00286 add_match_tag(tag_key, flags);
00287 }
00288
00289 } else {
00290 add_match_name_glob(str_component, flags);
00291 }
00292
00293 return true;
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 void FindApproxPath::
00303 add_match_name(const string &name, int flags) {
00304 Component comp;
00305 comp._type = _case_insensitive ? CT_match_name_insensitive : CT_match_name;
00306 comp._name = name;
00307 comp._flags = flags;
00308 _path.push_back(comp);
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318 void FindApproxPath::
00319 add_match_name_glob(const string &name, int flags) {
00320 Component comp;
00321 comp._type = CT_match_name_glob;
00322 comp._name = name;
00323 comp._glob.set_pattern(name);
00324 comp._glob.set_case_sensitive(!_case_insensitive);
00325 comp._flags = flags;
00326 if (!comp._glob.has_glob_characters()) {
00327
00328
00329 add_match_name(name, flags);
00330 } else {
00331 _path.push_back(comp);
00332 }
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 void FindApproxPath::
00342 add_match_exact_type(TypeHandle type, int flags) {
00343 Component comp;
00344 comp._type = CT_match_exact_type;
00345 comp._type_handle = type;
00346 comp._flags = flags;
00347 _path.push_back(comp);
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 void FindApproxPath::
00357 add_match_inexact_type(TypeHandle type, int flags) {
00358 Component comp;
00359 comp._type = CT_match_inexact_type;
00360 comp._type_handle = type;
00361 comp._flags = flags;
00362 _path.push_back(comp);
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 void FindApproxPath::
00373 add_match_tag(const string &name, int flags) {
00374 Component comp;
00375 comp._type = CT_match_tag;
00376 comp._name = name;
00377 comp._flags = flags;
00378 _path.push_back(comp);
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 void FindApproxPath::
00390 add_match_tag_value(const string &name, const string &value, int flags) {
00391 Component comp;
00392 comp._type = CT_match_tag_value;
00393 comp._name = name;
00394 comp._glob.set_pattern(value);
00395 comp._flags = flags;
00396 _path.push_back(comp);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405 void FindApproxPath::
00406 add_match_one(int flags) {
00407 Component comp;
00408 comp._type = CT_match_one;
00409 comp._flags = flags;
00410 _path.push_back(comp);
00411 }
00412
00413
00414
00415
00416
00417
00418
00419 void FindApproxPath::
00420 add_match_many(int flags) {
00421 Component comp;
00422 comp._type = CT_match_many;
00423 comp._flags = flags;
00424 _path.push_back(comp);
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 void FindApproxPath::
00434 add_match_pointer(PandaNode *pointer, int flags) {
00435 Component comp;
00436 comp._type = CT_match_pointer;
00437 comp._pointer = pointer;
00438 comp._flags = flags;
00439 _path.push_back(comp);
00440 }
00441
00442
00443
00444
00445
00446
00447 void FindApproxPath::
00448 output(ostream &out) const {
00449 out << "(";
00450 if (!_path.empty()) {
00451 Path::const_iterator pi = _path.begin();
00452 out << *pi;
00453 ++pi;
00454 while (pi != _path.end()) {
00455 out << " / " << *pi;
00456 ++pi;
00457 }
00458 }
00459 out << ")";
00460 }
00461
00462 ostream &
00463 operator << (ostream &out, FindApproxPath::ComponentType type) {
00464 switch (type) {
00465 case FindApproxPath::CT_match_name:
00466 return out << "match_name";
00467
00468 case FindApproxPath::CT_match_name_insensitive:
00469 return out << "match_name_insensitive";
00470
00471 case FindApproxPath::CT_match_name_glob:
00472 return out << "match_name_glob";
00473
00474 case FindApproxPath::CT_match_exact_type:
00475 return out << "match_exact_type";
00476
00477 case FindApproxPath::CT_match_inexact_type:
00478 return out << "match_inexact_type";
00479
00480 case FindApproxPath::CT_match_tag:
00481 return out << "match_tag";
00482
00483 case FindApproxPath::CT_match_tag_value:
00484 return out << "match_tag_value";
00485
00486 case FindApproxPath::CT_match_one:
00487 return out << "match_one";
00488
00489 case FindApproxPath::CT_match_many:
00490 return out << "match_many";
00491
00492 case FindApproxPath::CT_match_pointer:
00493 return out << "match_pointer";
00494 };
00495
00496 return out << "**invalid**";
00497 };
00498