Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

panda/src/pgraph/findApproxPath.cxx

Go to the documentation of this file.
00001 // Filename: findApproxPath.cxx
00002 // Created by:  drose (13Mar02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 #include "findApproxPath.h"
00020 #include "config_pgraph.h"
00021 
00022 #include "globPattern.h"
00023 #include "pandaNode.h"
00024 
00025 
00026 ////////////////////////////////////////////////////////////////////
00027 //     Function: FindApproxPath::Component::matches
00028 //       Access: Public
00029 //  Description: Returns true if the indicated node matches this
00030 //               component, false otherwise.
00031 ////////////////////////////////////////////////////////////////////
00032 bool FindApproxPath::Component::
00033 matches(PandaNode *node) const {
00034   string node_name;
00035 
00036   switch (_type) {
00037   case CT_match_name:
00038     // Match the node's name exactly.
00039     return (_name == node->get_name());
00040 
00041   case CT_match_name_glob:
00042     // Match the node's name according to filename globbing rules.
00043     {
00044       GlobPattern pattern(_name);
00045       return (pattern.matches(node->get_name()));
00046     }
00047 
00048   case CT_match_exact_type:
00049     // Match the node's type exactly.
00050     return (node->is_exact_type(_type_handle));
00051 
00052   case CT_match_inexact_type:
00053     // Match the node's type inexactly: it's a match if the node
00054     // is the type, or is derived from the type.
00055     return (node->is_of_type(_type_handle));
00056 
00057   case CT_match_one:
00058   case CT_match_many:
00059     // Match any node.
00060     return true;
00061 
00062   case CT_match_pointer:
00063     // Match only this one particular node.
00064     return (_pointer == node);
00065   }
00066 
00067   pgraph_cat.error()
00068     << "Invalid component in FindApproxPath\n";
00069   return false;
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: FindApproxPath::Component::output
00074 //       Access: Public
00075 //  Description:
00076 ////////////////////////////////////////////////////////////////////
00077 void FindApproxPath::Component::
00078 output(ostream &out) const {
00079   out << _type;
00080   if (_type == CT_match_name || _type == CT_match_name_glob) {
00081     out << " \"" << _name << "\"";
00082 
00083   } else if (_type == CT_match_exact_type || _type == CT_match_inexact_type) {
00084     out << " " << _type_handle;
00085 
00086   } else if (_type == CT_match_pointer) {
00087     out << " (" << *_pointer << ")";
00088   }
00089 }
00090 
00091 ////////////////////////////////////////////////////////////////////
00092 //     Function: FindApproxPath::add_string
00093 //       Access: Public
00094 //  Description: Adds a sequence of components separated by slashes,
00095 //               followed optionally by a semicolon and a sequence of
00096 //               control flags, to the path sequence.  Returns true if
00097 //               successful, false if the string contained an error.
00098 ////////////////////////////////////////////////////////////////////
00099 bool FindApproxPath::
00100 add_string(const string &str_path) {
00101   size_t start = 0;
00102   size_t slash = str_path.find('/');
00103   while (slash != string::npos) {
00104     if (!add_component(str_path.substr(start, slash - start))) {
00105       return false;
00106     }
00107     start = slash + 1;
00108     slash = str_path.find('/', start);
00109   }
00110 
00111   size_t semicolon = str_path.rfind(';');
00112 
00113   // We want to find the *last* semicolon at start or later, if there
00114   // happens to be more than one.  rfind will find the rightmost
00115   // semicolon in the entire string; if this is less than start, there
00116   // is no semicolon right of start.
00117   if (semicolon < start) {
00118     semicolon = string::npos;
00119   }
00120 
00121   if (!add_component(str_path.substr(start, semicolon - start))) {
00122     return false;
00123   }
00124 
00125   if (semicolon != string::npos) {
00126     return add_flags(str_path.substr(semicolon + 1));
00127   }
00128 
00129   return true;
00130 }
00131 
00132 ////////////////////////////////////////////////////////////////////
00133 //     Function: FindApproxPath::add_flags
00134 //       Access: Public
00135 //  Description: Adds a sequence of control flags.  This will be a
00136 //               sequence of letters preceded by either '+' or '-',
00137 //               with no intervening punctuation.  Returns true if
00138 //               successful, false otherwise.
00139 ////////////////////////////////////////////////////////////////////
00140 bool FindApproxPath::
00141 add_flags(const string &str_flags) {
00142   string::const_iterator pi = str_flags.begin();
00143   while (pi != str_flags.end()) {
00144     bool on;
00145     switch (*pi) {
00146     case '+':
00147       on = true;
00148       break;
00149     case '-':
00150       on = false;
00151       break;
00152     default:
00153       pgraph_cat.error()
00154         << "Invalid control flag string: " << str_flags << "\n";
00155       return false;
00156     }
00157 
00158     ++pi;
00159     if (pi == str_flags.end()) {
00160       pgraph_cat.error()
00161         << "Invalid control flag string: " << str_flags << "\n";
00162       return false;
00163     }
00164 
00165     switch (*pi) {
00166     case 'h':
00167       _return_hidden = on;
00168       break;
00169 
00170     case 's':
00171       _return_stashed = on;
00172       break;
00173 
00174     default:
00175       pgraph_cat.error()
00176         << "Invalid control flag string: " << str_flags << "\n";
00177       return false;
00178     }
00179 
00180     ++pi;
00181   }
00182 
00183   return true;
00184 }
00185 
00186 
00187 ////////////////////////////////////////////////////////////////////
00188 //     Function: FindApproxPath::add_component
00189 //       Access: Public
00190 //  Description: Adds a single component to the path sequence, defined
00191 //               by a string as might appear between slashes in the
00192 //               path string.  Returns true if successful, false if
00193 //               the string component was in some way invalid.
00194 ////////////////////////////////////////////////////////////////////
00195 bool FindApproxPath::
00196 add_component(string str_component) {
00197   int flags = 0;
00198   if (str_component.size() >= 2 && str_component.substr(0, 2) == "@@") {
00199     flags |= CF_stashed;
00200     str_component = str_component.substr(2);
00201   }
00202 
00203   if (str_component == "*") {
00204     add_match_one(flags);
00205 
00206   } else if (str_component == "**") {
00207     if ((flags & CF_stashed) != 0) {
00208       pgraph_cat.error()
00209         << "@@** is undefined; use @@*/** or **/@@* instead.\n";
00210       return false;
00211     }
00212     add_match_many(flags);
00213 
00214   } else if (!str_component.empty() && str_component[0] == '-') {
00215     string type_name = str_component.substr(1);
00216 
00217     // *** for now, as a quick hack, if a type exists with the ""
00218     // prefix on the named type, we search for that type instead.
00219     TypeHandle handle = TypeRegistry::ptr()->find_type("" + type_name);
00220     if (handle == TypeHandle::none()) {
00221       handle = TypeRegistry::ptr()->find_type(type_name);
00222     }
00223 
00224     if (handle == TypeHandle::none()) {
00225       pgraph_cat.error()
00226         << "Invalid type name: " << type_name << "\n";
00227       return false;
00228 
00229     } else {
00230       add_match_exact_type(handle, flags);
00231     }
00232 
00233   } else if (!str_component.empty() && str_component[0] == '+') {
00234     string type_name = str_component.substr(1);
00235 
00236     // *** for now, as a quick hack, if a type exists with the ""
00237     // prefix on the named type, we search for that type instead.
00238     TypeHandle handle = TypeRegistry::ptr()->find_type("" + type_name);
00239     if (handle == TypeHandle::none()) {
00240       handle = TypeRegistry::ptr()->find_type(type_name);
00241     }
00242 
00243     if (handle == TypeHandle::none()) {
00244       pgraph_cat.error()
00245         << "Invalid type name: " << type_name << "\n";
00246       return false;
00247 
00248     } else {
00249       add_match_inexact_type(handle, flags);
00250     }
00251 
00252   } else {
00253     add_match_name_glob(str_component, flags);
00254   }
00255 
00256   return true;
00257 }
00258 
00259 ////////////////////////////////////////////////////////////////////
00260 //     Function: FindApproxPath::output
00261 //       Access: Public
00262 //  Description:
00263 ////////////////////////////////////////////////////////////////////
00264 void FindApproxPath::
00265 output(ostream &out) const {
00266   out << "(";
00267   if (!_path.empty()) {
00268     Path::const_iterator pi = _path.begin();
00269     out << *pi;
00270     ++pi;
00271     while (pi != _path.end()) {
00272       out << " / " << *pi;
00273       ++pi;
00274     }
00275   }
00276   out << ")";
00277 }
00278 
00279 ostream &
00280 operator << (ostream &out, FindApproxPath::ComponentType type) {
00281   switch (type) {
00282   case FindApproxPath::CT_match_name:
00283     return out << "match_name";
00284 
00285   case FindApproxPath::CT_match_name_glob:
00286     return out << "match_name_glob";
00287 
00288   case FindApproxPath::CT_match_exact_type:
00289     return out << "match_exact_type";
00290 
00291   case FindApproxPath::CT_match_inexact_type:
00292     return out << "match_inexact_type";
00293 
00294   case FindApproxPath::CT_match_one:
00295     return out << "match_one";
00296 
00297   case FindApproxPath::CT_match_many:
00298     return out << "match_many";
00299 
00300   case FindApproxPath::CT_match_pointer:
00301     return out << "match_pointer";
00302   };
00303 
00304   return out << "**invalid**";
00305 };
00306 

Generated on Fri May 2 00:41:36 2003 for Panda by doxygen1.3