Panda3D
|
00001 // Filename: configVariableManager.cxx 00002 // Created by: drose (15Oct04) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #include "configVariableManager.h" 00016 #include "configVariableCore.h" 00017 #include "configDeclaration.h" 00018 #include "configPage.h" 00019 #include "config_prc.h" 00020 00021 ConfigVariableManager *ConfigVariableManager::_global_ptr = NULL; 00022 00023 //////////////////////////////////////////////////////////////////// 00024 // Function: ConfigVariableManager::Constructor 00025 // Access: Protected 00026 // Description: The constructor is private (actually, just protected, 00027 // but only to avoid a gcc compiler warning) because it 00028 // should not be explicitly constructed. There is only 00029 // one ConfigVariableManager, and it constructs 00030 // itself. 00031 //////////////////////////////////////////////////////////////////// 00032 ConfigVariableManager:: 00033 ConfigVariableManager() { 00034 init_memory_hook(); 00035 } 00036 00037 //////////////////////////////////////////////////////////////////// 00038 // Function: ConfigVariableManager::Destructor 00039 // Access: Protected 00040 // Description: The ConfigVariableManager destructor should never be 00041 // called, because this is a global object that is never 00042 // freed. 00043 //////////////////////////////////////////////////////////////////// 00044 ConfigVariableManager:: 00045 ~ConfigVariableManager() { 00046 prc_cat->error() 00047 << "Internal error--ConfigVariableManager destructor called!\n"; 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: ConfigVariableManager::make_variable 00052 // Access: Published 00053 // Description: Creates and returns a new, undefined 00054 // ConfigVariableCore with the indicated name; or if a 00055 // variable with this name has already been created, 00056 // returns that one instead. 00057 //////////////////////////////////////////////////////////////////// 00058 ConfigVariableCore *ConfigVariableManager:: 00059 make_variable(const string &name) { 00060 VariablesByName::iterator ni; 00061 ni = _variables_by_name.find(name); 00062 if (ni != _variables_by_name.end()) { 00063 return (*ni).second; 00064 } 00065 00066 ConfigVariableCore *variable = NULL; 00067 00068 // See if there's a template that matches this name. 00069 VariableTemplates::const_iterator ti; 00070 for (ti = _variable_templates.begin(); 00071 ti != _variable_templates.end() && variable == (ConfigVariableCore *)NULL; 00072 ++ti) { 00073 const GlobPattern &pattern = (*ti).first; 00074 ConfigVariableCore *templ = (*ti).second; 00075 if (pattern.matches(name)) { 00076 variable = new ConfigVariableCore(*templ, name); 00077 } 00078 } 00079 00080 if (variable == (ConfigVariableCore *)NULL) { 00081 variable = new ConfigVariableCore(name); 00082 } 00083 00084 _variables_by_name[name] = variable; 00085 _variables.push_back(variable); 00086 00087 return variable; 00088 } 00089 00090 //////////////////////////////////////////////////////////////////// 00091 // Function: ConfigVariableManager::make_variable_template 00092 // Access: Published 00093 // Description: Defines a variable "template" to match against 00094 // dynamically-defined variables that may or may not be 00095 // created in the future. 00096 // 00097 // The template consists of a glob pattern, 00098 // e.g. "notify-level-*", which will be tested against 00099 // any config variable passed to a future call to 00100 // make_variable(). If the pattern matches, the 00101 // returned ConfigVariableCore is copied to define the 00102 // new variable, instead of creating a default, empty 00103 // one. 00104 // 00105 // This is useful to pre-specify default values for a 00106 // family of variables that all have similar properties, 00107 // and all may not be created at the same time. It is 00108 // especially useful to avoid cluttering up the list of 00109 // available variables with user-declared variables that 00110 // have not been defined yet by the application 00111 // (e.g. "egg-object-type-*"). 00112 // 00113 // This method basically pre-defines all variables that 00114 // match the specified glob pattern. 00115 //////////////////////////////////////////////////////////////////// 00116 ConfigVariableCore *ConfigVariableManager:: 00117 make_variable_template(const string &pattern, 00118 ConfigFlags::ValueType value_type, 00119 const string &default_value, 00120 const string &description, int flags) { 00121 ConfigVariableCore *core; 00122 00123 GlobPattern gp(pattern); 00124 VariableTemplates::const_iterator ti = _variable_templates.find(gp); 00125 if (ti != _variable_templates.end()) { 00126 core = (*ti).second; 00127 00128 } else { 00129 core = new ConfigVariableCore(pattern); 00130 _variable_templates[gp] = core; 00131 } 00132 00133 if (value_type != ConfigFlags::VT_undefined) { 00134 core->set_value_type(value_type); 00135 } 00136 if (!default_value.empty() || 00137 core->get_default_value() == (ConfigDeclaration *)NULL) { 00138 core->set_default_value(default_value); 00139 } 00140 if (!description.empty()) { 00141 core->set_description(description); 00142 } 00143 if (flags != 0) { 00144 core->set_flags(flags); 00145 } 00146 core->set_used(); 00147 00148 // Also apply the same changes to any previously-defined variables 00149 // that match the pattern. 00150 Variables::iterator vi; 00151 for (vi = _variables.begin(); vi != _variables.end(); ++vi) { 00152 ConfigVariableCore *variable = (*vi); 00153 if (gp.matches(variable->get_name())) { 00154 if (value_type != ConfigFlags::VT_undefined) { 00155 variable->set_value_type(value_type); 00156 } 00157 if (!default_value.empty() || 00158 variable->get_default_value() == (ConfigDeclaration *)NULL) { 00159 variable->set_default_value(default_value); 00160 } 00161 if (!description.empty()) { 00162 variable->set_description(description); 00163 } 00164 if (flags != 0) { 00165 variable->set_flags(flags); 00166 } 00167 variable->set_used(); 00168 } 00169 } 00170 00171 return core; 00172 } 00173 00174 //////////////////////////////////////////////////////////////////// 00175 // Function: ConfigVariableManager::get_variable_name 00176 // Access: Published 00177 // Description: Returns the name of the nth active ConfigVariable in 00178 // the list. 00179 //////////////////////////////////////////////////////////////////// 00180 string ConfigVariableManager:: 00181 get_variable_name(int n) const { 00182 if (n >= 0 && n < (int)_variables.size()) { 00183 return _variables[n]->get_name(); 00184 } 00185 return string(); 00186 } 00187 00188 //////////////////////////////////////////////////////////////////// 00189 // Function: ConfigVariableManager::is_variable_used 00190 // Access: Published 00191 // Description: Returns true if the nth active ConfigVariable in 00192 // the list has been used by code, false otherwise. 00193 //////////////////////////////////////////////////////////////////// 00194 bool ConfigVariableManager:: 00195 is_variable_used(int n) const { 00196 if (n >= 0 && n < (int)_variables.size()) { 00197 return _variables[n]->is_used(); 00198 } 00199 return false; 00200 } 00201 00202 //////////////////////////////////////////////////////////////////// 00203 // Function: ConfigVariableManager::output 00204 // Access: Published 00205 // Description: 00206 //////////////////////////////////////////////////////////////////// 00207 void ConfigVariableManager:: 00208 output(ostream &out) const { 00209 out << "ConfigVariableManager, " << _variables.size() << " variables."; 00210 } 00211 00212 //////////////////////////////////////////////////////////////////// 00213 // Function: ConfigVariableManager::write 00214 // Access: Published 00215 // Description: 00216 //////////////////////////////////////////////////////////////////// 00217 void ConfigVariableManager:: 00218 write(ostream &out) const { 00219 VariablesByName::const_iterator ni; 00220 for (ni = _variables_by_name.begin(); 00221 ni != _variables_by_name.end(); 00222 ++ni) { 00223 ConfigVariableCore *variable = (*ni).second; 00224 if (variable->get_num_trusted_references() != 0 || 00225 variable->has_local_value()) { 00226 list_variable(variable, false); 00227 } 00228 } 00229 } 00230 00231 //////////////////////////////////////////////////////////////////// 00232 // Function: ConfigVariableManager::write_prc_variables 00233 // Access: Published 00234 // Description: Writes all of the prc-set config variables, as they 00235 // appear in a prc file somewhere, one per line, very 00236 // concisely. This lists the dominant value in the prc 00237 // file; it does not list shadowed values, and it does 00238 // not list locally-set values. 00239 // 00240 // This is mainly intended for generating a hash of the 00241 // input config file state. 00242 //////////////////////////////////////////////////////////////////// 00243 void ConfigVariableManager:: 00244 write_prc_variables(ostream &out) const { 00245 VariablesByName::const_iterator ni; 00246 for (ni = _variables_by_name.begin(); 00247 ni != _variables_by_name.end(); 00248 ++ni) { 00249 ConfigVariableCore *variable = (*ni).second; 00250 if (variable->get_num_trusted_references() != 0) { 00251 if (variable->get_value_type() == ConfigVariableCore::VT_list || 00252 variable->get_value_type() == ConfigVariableCore::VT_search_path) { 00253 // List all of the values for a "list" variable. 00254 int num_references = variable->get_num_trusted_references(); 00255 for (int i = 0; i < num_references; i++) { 00256 out << variable->get_name() << " " 00257 << variable->get_trusted_reference(i)->get_string_value() 00258 << "\n"; 00259 } 00260 } else { 00261 // List just the one value for a non-list variable. 00262 out << variable->get_name() << " " 00263 << variable->get_trusted_reference(0)->get_string_value() 00264 << "\n"; 00265 } 00266 } 00267 } 00268 } 00269 00270 //////////////////////////////////////////////////////////////////// 00271 // Function: ConfigVariableManager::list_unused_variables 00272 // Access: Published 00273 // Description: Writes a list of all the variables that have been 00274 // defined in a prc file without having been declared 00275 // somewhere in code. 00276 //////////////////////////////////////////////////////////////////// 00277 void ConfigVariableManager:: 00278 list_unused_variables() const { 00279 VariablesByName::const_iterator ni; 00280 for (ni = _variables_by_name.begin(); 00281 ni != _variables_by_name.end(); 00282 ++ni) { 00283 ConfigVariableCore *variable = (*ni).second; 00284 if (!variable->is_used()) { 00285 nout << variable->get_name() << "\n"; 00286 int num_references = variable->get_num_references(); 00287 for (int i = 0; i < num_references; i++) { 00288 nout << " " << variable->get_reference(i)->get_page()->get_name() 00289 << "\n"; 00290 } 00291 } 00292 } 00293 } 00294 00295 //////////////////////////////////////////////////////////////////// 00296 // Function: ConfigVariableManager::list_variables 00297 // Access: Published 00298 // Description: Writes a list of all the variables that have been 00299 // declared somewhere in code, along with a brief 00300 // description. 00301 //////////////////////////////////////////////////////////////////// 00302 void ConfigVariableManager:: 00303 list_variables() const { 00304 VariablesByName::const_iterator ni; 00305 for (ni = _variables_by_name.begin(); 00306 ni != _variables_by_name.end(); 00307 ++ni) { 00308 const ConfigVariableCore *variable = (*ni).second; 00309 if (variable->is_used() && !variable->is_dynamic()) { 00310 list_variable(variable, true); 00311 } 00312 } 00313 } 00314 00315 //////////////////////////////////////////////////////////////////// 00316 // Function: ConfigVariableManager::list_dynamic_variables 00317 // Access: Published 00318 // Description: Writes a list of all the "dynamic" variables that 00319 // have been declared somewhere in code, along with a 00320 // brief description. This is a (usually large) list of 00321 // config variables that are declared with a generated 00322 // variable name. 00323 //////////////////////////////////////////////////////////////////// 00324 void ConfigVariableManager:: 00325 list_dynamic_variables() const { 00326 VariablesByName::const_iterator ni; 00327 for (ni = _variables_by_name.begin(); 00328 ni != _variables_by_name.end(); 00329 ++ni) { 00330 const ConfigVariableCore *variable = (*ni).second; 00331 if (variable->is_used() && variable->is_dynamic()) { 00332 list_variable(variable, false); 00333 } 00334 } 00335 } 00336 00337 //////////////////////////////////////////////////////////////////// 00338 // Function: ConfigVariableManager::get_global_ptr 00339 // Access: Published 00340 // Description: 00341 //////////////////////////////////////////////////////////////////// 00342 ConfigVariableManager *ConfigVariableManager:: 00343 get_global_ptr() { 00344 if (_global_ptr == (ConfigVariableManager *)NULL) { 00345 _global_ptr = new ConfigVariableManager; 00346 } 00347 return _global_ptr; 00348 } 00349 00350 //////////////////////////////////////////////////////////////////// 00351 // Function: ConfigVariableManager::list_variable 00352 // Access: Private 00353 // Description: Lists a single variable and its value. 00354 //////////////////////////////////////////////////////////////////// 00355 void ConfigVariableManager:: 00356 list_variable(const ConfigVariableCore *variable, 00357 bool include_descriptions) const { 00358 if (!variable->is_used()) { 00359 // If the variable is unused, just show its name. 00360 nout << variable->get_name() << " not used"; 00361 if (variable->get_num_references() > 0) { 00362 nout << " (referenced in " 00363 << variable->get_reference(0)->get_page()->get_name() 00364 << ")"; 00365 } 00366 nout << "\n"; 00367 00368 } else { 00369 // If the variable is used--it's been defined somewhere--show its 00370 // name, its type, its current and default values, and if 00371 // available, its description. 00372 00373 nout << variable->get_name() << " " 00374 << variable->get_value_type() << "\n"; 00375 00376 const ConfigDeclaration *decl; 00377 00378 if (variable->get_value_type() == ConfigVariableCore::VT_list || 00379 variable->get_value_type() == ConfigVariableCore::VT_search_path) { 00380 // We treat a "list" variable as a special case: list all of 00381 // its values. 00382 nout << " current value:\n"; 00383 int num_references = variable->get_num_trusted_references(); 00384 for (int i = 0; i < num_references; i++) { 00385 decl = variable->get_trusted_reference(i); 00386 nout << " " << decl->get_string_value() 00387 << " (from " << decl->get_page()->get_name() << ")\n"; 00388 } 00389 00390 } else { 00391 // An ordinary, non-list variable gets one line for its 00392 // current value (if it has one) and another line for its 00393 // default value. 00394 decl = variable->get_declaration(0); 00395 if (decl != variable->get_default_value()) { 00396 nout << " current value = " << decl->get_string_value(); 00397 if (!decl->get_page()->is_special()) { 00398 nout << " (from " << decl->get_page()->get_name() << ")\n"; 00399 } else { 00400 nout << " (defined locally)\n"; 00401 } 00402 } 00403 00404 decl = variable->get_default_value(); 00405 if (decl != (ConfigDeclaration *)NULL) { 00406 nout << " default value = " << decl->get_string_value() << "\n"; 00407 } 00408 } 00409 00410 if (!variable->get_description().empty() && include_descriptions) { 00411 nout << " " << variable->get_description() << "\n"; 00412 } 00413 } 00414 00415 nout << "\n"; 00416 }