Panda3D
|
00001 // Filename: configVariableCore.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 "configVariableCore.h" 00016 #include "configDeclaration.h" 00017 #include "configPage.h" 00018 #include "pset.h" 00019 #include "pnotify.h" 00020 #include "config_prc.h" 00021 00022 // This file is generated by ppremake. 00023 #include "prc_parameters.h" 00024 00025 #include <algorithm> 00026 00027 00028 //////////////////////////////////////////////////////////////////// 00029 // Function: ConfigVariableCore::Constructor 00030 // Access: Private 00031 // Description: Use the ConfigVariableManager::make_variable() 00032 // interface to create a new ConfigVariableCore. 00033 //////////////////////////////////////////////////////////////////// 00034 ConfigVariableCore:: 00035 ConfigVariableCore(const string &name) : 00036 _name(name), 00037 _is_used(false), 00038 _value_type(VT_undefined), 00039 _flags(0), 00040 _default_value(NULL), 00041 _local_value(NULL), 00042 _declarations_sorted(true), 00043 _value_queried(false) 00044 { 00045 #if defined(PRC_INC_TRUST_LEVEL) && PRC_INC_TRUST_LEVEL != 0 00046 _flags = (_flags & ~F_trust_level_mask) | ((_flags & F_trust_level_mask) + PRC_INC_TRUST_LEVEL); 00047 #endif // PRC_INC_TRUST_LEVEL 00048 } 00049 00050 //////////////////////////////////////////////////////////////////// 00051 // Function: ConfigVariableCore::Copy Constructor 00052 // Access: Private 00053 // Description: This is used by ConfigVariableManager to create the 00054 // variable from a template--basically, another variable 00055 // with all of the initial properties pre-defined. 00056 //////////////////////////////////////////////////////////////////// 00057 ConfigVariableCore:: 00058 ConfigVariableCore(const ConfigVariableCore &templ, const string &name) : 00059 _name(name), 00060 _is_used(templ._is_used), 00061 _value_type(templ._value_type), 00062 _description(templ._description), 00063 _flags(templ._flags), 00064 _default_value(NULL), 00065 _local_value(NULL), 00066 _declarations_sorted(false), 00067 _value_queried(false) 00068 { 00069 if (templ._default_value != (ConfigDeclaration *)NULL) { 00070 set_default_value(templ._default_value->get_string_value()); 00071 } 00072 } 00073 00074 //////////////////////////////////////////////////////////////////// 00075 // Function: ConfigVariableCore::Destructor 00076 // Access: Private 00077 // Description: The destructor should never be called; 00078 // ConfigVariableCore objects live forever and never get 00079 // destructed. 00080 //////////////////////////////////////////////////////////////////// 00081 ConfigVariableCore:: 00082 ~ConfigVariableCore() { 00083 prc_cat->error() 00084 << "Internal error--ConfigVariableCore destructor called!\n"; 00085 } 00086 00087 //////////////////////////////////////////////////////////////////// 00088 // Function: ConfigVariableCore::set_value_type 00089 // Access: Public 00090 // Description: Specifies the type of this variable. See 00091 // get_value_type(). It is not an error to call this 00092 // multiple times, but if the value changes once 00093 // get_declaration() has been called, a warning is printed. 00094 //////////////////////////////////////////////////////////////////// 00095 void ConfigVariableCore:: 00096 set_value_type(ConfigVariableCore::ValueType value_type) { 00097 if (_value_queried && _value_type != value_type) { 00098 if ((_flags & F_dconfig) != 0) { 00099 // As a special exception, if the flags include F_dconfig, we 00100 // don't report a warning for changing the type, assuming the 00101 // variable is being defined through the older DConfig 00102 // interface. 00103 00104 } else { 00105 prc_cat->warning() 00106 << "changing type for ConfigVariable " 00107 << get_name() << " from " << _value_type << " to " 00108 << value_type << ".\n"; 00109 } 00110 } 00111 00112 _value_type = value_type; 00113 } 00114 00115 //////////////////////////////////////////////////////////////////// 00116 // Function: ConfigVariableCore::set_flags 00117 // Access: Public 00118 // Description: Specifies the trust level of this variable. See 00119 // get_flags(). It is not an error to call this 00120 // multiple times, but if the value changes once 00121 // get_declaration() has been called, a warning is 00122 // printed. 00123 //////////////////////////////////////////////////////////////////// 00124 void ConfigVariableCore:: 00125 set_flags(int flags) { 00126 if ((flags & F_dconfig) != 0) { 00127 flags = (flags & ~F_trust_level_mask) | PRC_DCONFIG_TRUST_LEVEL; 00128 } 00129 00130 #if defined(PRC_INC_TRUST_LEVEL) && PRC_INC_TRUST_LEVEL != 0 00131 flags = (flags & ~F_trust_level_mask) | ((flags & F_trust_level_mask) + PRC_INC_TRUST_LEVEL); 00132 #endif // PRC_INC_TRUST_LEVEL 00133 00134 if (_value_queried) { 00135 int bits_changed = (_flags ^ flags); 00136 if ((bits_changed & F_trust_level_mask) != 0) { 00137 prc_cat->warning() 00138 << "changing trust level for ConfigVariable " 00139 << get_name() << " from " << (_flags & F_trust_level_mask) << " to " 00140 << (flags & F_trust_level_mask) << ".\n"; 00141 } 00142 if ((bits_changed & ~(F_trust_level_mask | F_dconfig)) != 0) { 00143 prc_cat->warning() 00144 << "changing flags for ConfigVariable " 00145 << get_name() << " from " << hex 00146 << (_flags & ~F_trust_level_mask) << " to " 00147 << (flags & ~F_trust_level_mask) << dec << ".\n"; 00148 } 00149 } 00150 00151 _flags = flags; 00152 00153 // Changing the trust level will require re-sorting the 00154 // declarations. 00155 _declarations_sorted = false; 00156 } 00157 00158 //////////////////////////////////////////////////////////////////// 00159 // Function: ConfigVariableCore::set_description 00160 // Access: Public 00161 // Description: Specifies the one-line description of this variable. 00162 // See get_description(). It is not an error to call 00163 // this multiple times, but if the value changes once 00164 // get_declaration() has been called, a warning is printed. 00165 //////////////////////////////////////////////////////////////////// 00166 void ConfigVariableCore:: 00167 set_description(const string &description) { 00168 if (_value_queried && _description != description) { 00169 if ((_flags & F_dconfig) != 0) { 00170 // As a special exception, if the flags include F_dconfig, we 00171 // don't change it, since this is presumably coming from the 00172 // older DConfig interface. 00173 return; 00174 } 00175 if (description == "DConfig") { 00176 // As a similar exception, we don't replace an existing 00177 // description with one that reads simply "DConfig", unless it 00178 // was empty previously. 00179 if (_description.empty()) { 00180 _description = description; 00181 } 00182 return; 00183 } 00184 00185 if (description.empty()) { 00186 // If the new description is empty, we don't do anything. 00187 return; 00188 } 00189 00190 if (_description.empty()) { 00191 // If the previous description was empty, we quietly replace it. 00192 _description = description; 00193 return; 00194 } 00195 00196 prc_cat->warning() 00197 << "changing description for ConfigVariable " 00198 << get_name() << ".\n"; 00199 } 00200 00201 _description = description; 00202 } 00203 00204 //////////////////////////////////////////////////////////////////// 00205 // Function: ConfigVariableCore::set_default_value 00206 // Access: Public 00207 // Description: Specifies the default value for this variable if it 00208 // is not defined in any prc file. 00209 //////////////////////////////////////////////////////////////////// 00210 void ConfigVariableCore:: 00211 set_default_value(const string &default_value) { 00212 if (_default_value == (ConfigDeclaration *)NULL) { 00213 // Defining the default value for the first time. 00214 ConfigPage *default_page = ConfigPage::get_default_page(); 00215 _default_value = default_page->make_declaration(this, default_value); 00216 00217 } else { 00218 // Modifying an existing default value. 00219 00220 // We set the original default value first, to avoid infinite 00221 // recursion when the config variable in question happens to be 00222 // consulted in NotifyCategory::out() (for instance, 00223 // notify-timestamp). 00224 string orig_default_value = _default_value->get_string_value(); 00225 _default_value->set_string_value(default_value); 00226 00227 if (orig_default_value != default_value) { 00228 if ((_flags & F_dconfig) != 0) { 00229 // As a special exception, if the flags include F_dconfig, we 00230 // don't report a warning for changing the default value, 00231 // assuming the variable is being defined through the older 00232 // DConfig interface. 00233 00234 } else { 00235 prc_cat->warning() 00236 << "changing default value for ConfigVariable " 00237 << get_name() << " from '" << orig_default_value 00238 << "' to '" << default_value << "'.\n"; 00239 } 00240 } 00241 } 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: ConfigVariableCore::make_local_value 00246 // Access: Public 00247 // Description: Creates a new local value for this variable, if there 00248 // is not already one specified. This will shadow any 00249 // values defined in the various .prc files. 00250 // 00251 // If there is already a local value defined for this 00252 // variable, simply returns that one. 00253 // 00254 // Use clear_local_value() to remove the local value 00255 // definition. 00256 //////////////////////////////////////////////////////////////////// 00257 ConfigDeclaration *ConfigVariableCore:: 00258 make_local_value() { 00259 if (_local_value == (ConfigDeclaration *)NULL) { 00260 ConfigPage *local_page = ConfigPage::get_local_page(); 00261 string string_value = get_declaration(0)->get_string_value(); 00262 _local_value = local_page->make_declaration(this, string_value); 00263 00264 if (is_closed()) { 00265 prc_cat.warning() 00266 << "Assigning a local value to a \"closed\" ConfigVariable. " 00267 "This is legal in a development build, but illegal in a release " 00268 "build and may result in a compilation error or exception.\n"; 00269 } 00270 } 00271 00272 return _local_value; 00273 } 00274 00275 //////////////////////////////////////////////////////////////////// 00276 // Function: ConfigVariableCore::clear_local_value 00277 // Access: Public 00278 // Description: Removes the local value defined for this variable, 00279 // and allows its value to be once again retrieved from 00280 // the .prc files. 00281 // 00282 // Returns true if the value was successfully removed, 00283 // false if it did not exist in the first place. 00284 //////////////////////////////////////////////////////////////////// 00285 bool ConfigVariableCore:: 00286 clear_local_value() { 00287 if (_local_value != (ConfigDeclaration *)NULL) { 00288 ConfigPage::get_local_page()->delete_declaration(_local_value); 00289 _local_value = (ConfigDeclaration *)NULL; 00290 invalidate_cache(); 00291 return true; 00292 } 00293 00294 return false; 00295 } 00296 00297 //////////////////////////////////////////////////////////////////// 00298 // Function: ConfigVariableCore::has_value 00299 // Access: Public 00300 // Description: Returns true if this variable has an explicit value, 00301 // either from a prc file or locally set, or false if 00302 // variable has its default value. 00303 //////////////////////////////////////////////////////////////////// 00304 bool ConfigVariableCore:: 00305 has_value() const { 00306 if (has_local_value()) { 00307 return true; 00308 } 00309 check_sort_declarations(); 00310 return (!_trusted_declarations.empty()); 00311 } 00312 00313 //////////////////////////////////////////////////////////////////// 00314 // Function: ConfigVariableCore::get_num_declarations 00315 // Access: Public 00316 // Description: Returns the number of declarations that contribute to 00317 // this variable's value. If the variable has been 00318 // defined, this will always be at least 1 (for the 00319 // default value, at least). 00320 //////////////////////////////////////////////////////////////////// 00321 int ConfigVariableCore:: 00322 get_num_declarations() const { 00323 if (has_local_value()) { 00324 return 1; 00325 } 00326 check_sort_declarations(); 00327 if (!_trusted_declarations.empty()) { 00328 return _trusted_declarations.size(); 00329 } 00330 00331 // We always have at least one: the default value. 00332 return 1; 00333 } 00334 00335 //////////////////////////////////////////////////////////////////// 00336 // Function: ConfigVariableCore::get_declaration 00337 // Access: Public 00338 // Description: Returns the nth declarations that contributes to 00339 // this variable's value. The declarations are arranged 00340 // in order such that earlier declarations shadow later 00341 // declarations; thus, get_declaration(0) is always 00342 // defined and always returns the current value of the 00343 // variable. 00344 //////////////////////////////////////////////////////////////////// 00345 const ConfigDeclaration *ConfigVariableCore:: 00346 get_declaration(int n) const { 00347 ((ConfigVariableCore *)this)->_value_queried = true; 00348 if (_default_value == (ConfigDeclaration *)NULL) { 00349 prc_cat->warning() 00350 << "value queried before default value set for " 00351 << get_name() << ".\n"; 00352 ((ConfigVariableCore *)this)->set_default_value(""); 00353 } 00354 00355 if (has_local_value()) { 00356 return _local_value; 00357 } 00358 check_sort_declarations(); 00359 if (n >= 0 && n < (int)_trusted_declarations.size()) { 00360 return _trusted_declarations[n]; 00361 } 00362 return _default_value; 00363 } 00364 00365 //////////////////////////////////////////////////////////////////// 00366 // Function: ConfigVariableCore::output 00367 // Access: Public 00368 // Description: 00369 //////////////////////////////////////////////////////////////////// 00370 void ConfigVariableCore:: 00371 output(ostream &out) const { 00372 out << get_declaration(0)->get_string_value(); 00373 } 00374 00375 //////////////////////////////////////////////////////////////////// 00376 // Function: ConfigVariableCore::write 00377 // Access: Public 00378 // Description: 00379 //////////////////////////////////////////////////////////////////// 00380 void ConfigVariableCore:: 00381 write(ostream &out) const { 00382 out << "ConfigVariable " << get_name() << ":\n"; 00383 00384 check_sort_declarations(); 00385 00386 if (has_local_value()) { 00387 out << " " << *_local_value << " (defined locally)\n"; 00388 } 00389 00390 Declarations::const_iterator di; 00391 for (di = _trusted_declarations.begin(); 00392 di != _trusted_declarations.end(); 00393 ++di) { 00394 out << " " << *(*di) 00395 << " (from " << (*di)->get_page()->get_name() << ")\n"; 00396 } 00397 00398 if (_default_value != (ConfigDeclaration *)NULL) { 00399 out << " " << *_default_value << " (default value)\n"; 00400 } 00401 00402 for (di = _untrusted_declarations.begin(); 00403 di != _untrusted_declarations.end(); 00404 ++di) { 00405 out << " " << *(*di) 00406 << " (from " << (*di)->get_page()->get_name() << ", untrusted)\n"; 00407 } 00408 00409 if (!_description.empty()) { 00410 out << "\n" << _description << "\n"; 00411 } 00412 } 00413 00414 //////////////////////////////////////////////////////////////////// 00415 // Function: ConfigVariableCore::add_declaration 00416 // Access: Private 00417 // Description: Called only by the ConfigDeclaration constructor, 00418 // this adds the indicated declaration to the list of 00419 // declarations that reference this variable. 00420 //////////////////////////////////////////////////////////////////// 00421 void ConfigVariableCore:: 00422 add_declaration(ConfigDeclaration *decl) { 00423 _declarations.push_back(decl); 00424 00425 _declarations_sorted = false; 00426 } 00427 00428 //////////////////////////////////////////////////////////////////// 00429 // Function: ConfigVariableCore::remove_declaration 00430 // Access: Private 00431 // Description: Called only by the ConfigDeclaration destructor, 00432 // this removes the indicated declaration from the list 00433 // of declarations that reference this variable. 00434 //////////////////////////////////////////////////////////////////// 00435 void ConfigVariableCore:: 00436 remove_declaration(ConfigDeclaration *decl) { 00437 Declarations::iterator di; 00438 for (di = _declarations.begin(); di != _declarations.end(); ++di) { 00439 if ((*di) == decl) { 00440 // Rather than deleting the declaration from the middle of the 00441 // list, we maybe save a bit of time by swapping in the one at 00442 // the end of the list (although this will unsort the list). 00443 Declarations::iterator di2 = _declarations.end(); 00444 di2--; 00445 (*di) = (*di2); 00446 _declarations.erase(di2); 00447 _declarations_sorted = false; 00448 return; 00449 } 00450 } 00451 00452 // Hmm, it wasn't here. Oh well. 00453 } 00454 00455 // This class is used in sort_declarations, below. 00456 class CompareConfigDeclarations { 00457 public: 00458 bool operator () (const ConfigDeclaration *a, const ConfigDeclaration *b) const { 00459 return (*a) < (*b); 00460 } 00461 }; 00462 00463 //////////////////////////////////////////////////////////////////// 00464 // Function: ConfigVariableCore::sort_declarations 00465 // Access: Private 00466 // Description: Sorts the list of declarations into priority order, 00467 // so that the declaration at the front of the list is 00468 // the one that shadows all following declarations. 00469 //////////////////////////////////////////////////////////////////// 00470 void ConfigVariableCore:: 00471 sort_declarations() { 00472 sort(_declarations.begin(), _declarations.end(), CompareConfigDeclarations()); 00473 Declarations::iterator di; 00474 00475 // Now that they're sorted, divide them into either trusted or 00476 // untrusted declarations. 00477 #ifdef PRC_RESPECT_TRUST_LEVEL 00478 // In this mode, normally for a release build, we sort the 00479 // declarations honestly according to whether the prc file that 00480 // defines them meets the required trust level. 00481 _trusted_declarations.clear(); 00482 _untrusted_declarations.clear(); 00483 for (di = _declarations.begin(); di != _declarations.end(); ++di) { 00484 const ConfigDeclaration *decl = (*di); 00485 if (!is_closed() && 00486 get_trust_level() <= decl->get_page()->get_trust_level()) { 00487 _trusted_declarations.push_back(decl); 00488 } else { 00489 _untrusted_declarations.push_back(decl); 00490 } 00491 } 00492 00493 #else // PRC_RESPECT_TRUST_LEVEL 00494 // In this mode, normally for the development environment, all 00495 // declarations are trusted, regardless of the trust level. 00496 _trusted_declarations = _declarations; 00497 _untrusted_declarations.clear(); 00498 00499 #endif // PRC_RESPECT_TRUST_LEVEL 00500 00501 // Finally, determine the set of unique, trusted 00502 // declarations--trusted declarations that have a unique string 00503 // value. This is usually unneeded, but what the heck, it doesn't 00504 // need to be recomputed all that often. 00505 _unique_declarations.clear(); 00506 00507 init_system_type_handles(); // Make sure pset_type_handle is initted. 00508 pset<string> already_added; 00509 for (di = _trusted_declarations.begin(); 00510 di != _trusted_declarations.end(); 00511 ++di) { 00512 const ConfigDeclaration *decl = (*di); 00513 if (already_added.insert(decl->get_string_value()).second) { 00514 _unique_declarations.push_back(decl); 00515 } 00516 } 00517 00518 _declarations_sorted = true; 00519 }