Panda3D
 All Classes Functions Variables Enumerations
configVariableCore.cxx
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 }
 All Classes Functions Variables Enumerations