Panda3D
Loading...
Searching...
No Matches
configVariableManager.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file configVariableManager.cxx
10 * @author drose
11 * @date 2004-10-15
12 */
13
15#include "configVariableCore.h"
16#include "configDeclaration.h"
17#include "configPage.h"
18#include "config_prc.h"
19
20using std::string;
21
22ConfigVariableManager *ConfigVariableManager::_global_ptr = nullptr;
23
24/**
25 * The constructor is private (actually, just protected, but only to avoid a
26 * gcc compiler warning) because it should not be explicitly constructed.
27 * There is only one ConfigVariableManager, and it constructs itself.
28 */
29ConfigVariableManager::
30ConfigVariableManager() {
32}
33
34/**
35 * The ConfigVariableManager destructor should never be called, because this
36 * is a global object that is never freed.
37 */
38ConfigVariableManager::
39~ConfigVariableManager() {
40 prc_cat->error()
41 << "Internal error--ConfigVariableManager destructor called!\n";
42}
43
44/**
45 * Creates and returns a new, undefined ConfigVariableCore with the indicated
46 * name; or if a variable with this name has already been created, returns
47 * that one instead.
48 */
50make_variable(const string &name) {
51 VariablesByName::iterator ni;
52 ni = _variables_by_name.find(name);
53 if (ni != _variables_by_name.end()) {
54 return (*ni).second;
55 }
56
57 ConfigVariableCore *variable = nullptr;
58
59 // See if there's a template that matches this name.
60 VariableTemplates::const_iterator ti;
61 for (ti = _variable_templates.begin();
62 ti != _variable_templates.end() && variable == nullptr;
63 ++ti) {
64 const GlobPattern &pattern = (*ti).first;
65 ConfigVariableCore *templ = (*ti).second;
66 if (pattern.matches(name)) {
67 variable = new ConfigVariableCore(*templ, name);
68 }
69 }
70
71 if (variable == nullptr) {
72 variable = new ConfigVariableCore(name);
73 }
74
75 _variables_by_name[name] = variable;
76 _variables.push_back(variable);
77
78 return variable;
79}
80
81/**
82 * Defines a variable "template" to match against dynamically-defined
83 * variables that may or may not be created in the future.
84 *
85 * The template consists of a glob pattern, e.g. `notify-level-*`, which will
86 * be tested against any config variable passed to a future call to
87 * make_variable(). If the pattern matches, the returned ConfigVariableCore
88 * is copied to define the new variable, instead of creating a default, empty
89 * one.
90 *
91 * This is useful to pre-specify default values for a family of variables that
92 * all have similar properties, and all may not be created at the same time.
93 * It is especially useful to avoid cluttering up the list of available
94 * variables with user-declared variables that have not been defined yet by
95 * the application (e.g. `egg-object-type-*`).
96 *
97 * This method basically pre-defines all variables that match the specified
98 * glob pattern.
99 */
101make_variable_template(const string &pattern,
102 ConfigFlags::ValueType value_type,
103 const string &default_value,
104 const string &description, int flags) {
105 ConfigVariableCore *core;
106
107 GlobPattern gp(pattern);
108 VariableTemplates::const_iterator ti = _variable_templates.find(gp);
109 if (ti != _variable_templates.end()) {
110 core = (*ti).second;
111
112 } else {
113 core = new ConfigVariableCore(pattern);
114 _variable_templates[gp] = core;
115 }
116
117 if (value_type != ConfigFlags::VT_undefined) {
118 core->set_value_type(value_type);
119 }
120 if (!default_value.empty() ||
121 core->get_default_value() == nullptr) {
122 core->set_default_value(default_value);
123 }
124 if (!description.empty()) {
125 core->set_description(description);
126 }
127 if (flags != 0) {
128 core->set_flags(flags);
129 }
130 core->set_used();
131
132 // Also apply the same changes to any previously-defined variables that
133 // match the pattern.
134 Variables::iterator vi;
135 for (vi = _variables.begin(); vi != _variables.end(); ++vi) {
136 ConfigVariableCore *variable = (*vi);
137 if (gp.matches(variable->get_name())) {
138 if (value_type != ConfigFlags::VT_undefined) {
139 variable->set_value_type(value_type);
140 }
141 if (!default_value.empty() ||
142 variable->get_default_value() == nullptr) {
143 variable->set_default_value(default_value);
144 }
145 if (!description.empty()) {
146 variable->set_description(description);
147 }
148 if (flags != 0) {
149 variable->set_flags(flags);
150 }
151 variable->set_used();
152 }
153 }
154
155 return core;
156}
157
158/**
159 * Returns the name of the nth active ConfigVariable in the list.
160 */
162get_variable_name(size_t n) const {
163 if (n < _variables.size()) {
164 return _variables[n]->get_name();
165 }
166 return string();
167}
168
169/**
170 * Returns true if the nth active ConfigVariable in the list has been used by
171 * code, false otherwise.
172 */
174is_variable_used(size_t n) const {
175 if (n < _variables.size()) {
176 return _variables[n]->is_used();
177 }
178 return false;
179}
180
181/**
182 *
183 */
184void ConfigVariableManager::
185output(std::ostream &out) const {
186 out << "ConfigVariableManager, " << _variables.size() << " variables.";
187}
188
189/**
190 *
191 */
192void ConfigVariableManager::
193write(std::ostream &out) const {
194 VariablesByName::const_iterator ni;
195 for (ni = _variables_by_name.begin();
196 ni != _variables_by_name.end();
197 ++ni) {
198 ConfigVariableCore *variable = (*ni).second;
199 if (variable->get_num_trusted_references() != 0 ||
200 variable->has_local_value()) {
201 list_variable(variable, false);
202 }
203 }
204}
205
206/**
207 * Writes all of the prc-set config variables, as they appear in a prc file
208 * somewhere, one per line, very concisely. This lists the dominant value in
209 * the prc file; it does not list shadowed values, and it does not list
210 * locally-set values.
211 *
212 * This is mainly intended for generating a hash of the input config file
213 * state.
214 */
216write_prc_variables(std::ostream &out) const {
217 VariablesByName::const_iterator ni;
218 for (ni = _variables_by_name.begin();
219 ni != _variables_by_name.end();
220 ++ni) {
221 ConfigVariableCore *variable = (*ni).second;
222 if (variable->get_num_trusted_references() != 0) {
223 if (variable->get_value_type() == ConfigVariableCore::VT_list ||
224 variable->get_value_type() == ConfigVariableCore::VT_search_path) {
225 // List all of the values for a "list" variable.
226 size_t num_references = variable->get_num_trusted_references();
227 for (size_t i = 0; i < num_references; ++i) {
228 out << variable->get_name() << " "
229 << variable->get_trusted_reference(i)->get_string_value()
230 << "\n";
231 }
232 } else {
233 // List just the one value for a non-list variable.
234 out << variable->get_name() << " "
235 << variable->get_trusted_reference(0)->get_string_value()
236 << "\n";
237 }
238 }
239 }
240}
241
242/**
243 * Writes a list of all the variables that have been defined in a prc file
244 * without having been declared somewhere in code.
245 */
247list_unused_variables() const {
248 VariablesByName::const_iterator ni;
249 for (ni = _variables_by_name.begin();
250 ni != _variables_by_name.end();
251 ++ni) {
252 ConfigVariableCore *variable = (*ni).second;
253 if (!variable->is_used()) {
254 nout << variable->get_name() << "\n";
255 size_t num_references = variable->get_num_references();
256 for (size_t i = 0; i < num_references; i++) {
257 nout << " " << variable->get_reference(i)->get_page()->get_name()
258 << "\n";
259 }
260 }
261 }
262}
263
264/**
265 * Writes a list of all the variables that have been declared somewhere in
266 * code, along with a brief description.
267 */
269list_variables() const {
270 VariablesByName::const_iterator ni;
271 for (ni = _variables_by_name.begin();
272 ni != _variables_by_name.end();
273 ++ni) {
274 const ConfigVariableCore *variable = (*ni).second;
275 if (variable->is_used() && !variable->is_dynamic()) {
276 list_variable(variable, true);
277 }
278 }
279}
280
281/**
282 * Writes a list of all the "dynamic" variables that have been declared
283 * somewhere in code, along with a brief description. This is a (usually
284 * large) list of config variables that are declared with a generated variable
285 * name.
286 */
289 VariablesByName::const_iterator ni;
290 for (ni = _variables_by_name.begin();
291 ni != _variables_by_name.end();
292 ++ni) {
293 const ConfigVariableCore *variable = (*ni).second;
294 if (variable->is_used() && variable->is_dynamic()) {
295 list_variable(variable, false);
296 }
297 }
298}
299
300/**
301 *
302 */
303ConfigVariableManager *ConfigVariableManager::
304get_global_ptr() {
305 if (_global_ptr == nullptr) {
306 _global_ptr = new ConfigVariableManager;
307 }
308 return _global_ptr;
309}
310
311/**
312 * Lists a single variable and its value.
313 */
314void ConfigVariableManager::
315list_variable(const ConfigVariableCore *variable,
316 bool include_descriptions) const {
317 if (!variable->is_used()) {
318 // If the variable is unused, just show its name.
319 nout << variable->get_name() << " not used";
320 if (variable->get_num_references() > 0) {
321 nout << " (referenced in "
322 << variable->get_reference(0)->get_page()->get_name()
323 << ")";
324 }
325 nout << "\n";
326
327 } else {
328 // If the variable is used--it's been defined somewhere--show its name,
329 // its type, its current and default values, and if available, its
330 // description.
331
332 nout << variable->get_name() << " "
333 << variable->get_value_type() << "\n";
334
335 const ConfigDeclaration *decl;
336
337 if (variable->get_value_type() == ConfigVariableCore::VT_list ||
338 variable->get_value_type() == ConfigVariableCore::VT_search_path) {
339 // We treat a "list" variable as a special case: list all of its values.
340 nout << " current value:\n";
341 size_t num_references = variable->get_num_trusted_references();
342 for (size_t i = 0; i < num_references; ++i) {
343 decl = variable->get_trusted_reference(i);
344 nout << " " << decl->get_string_value()
345 << " (from " << decl->get_page()->get_name() << ")\n";
346 }
347
348 } else {
349 // An ordinary, non-list variable gets one line for its current value
350 // (if it has one) and another line for its default value.
351 decl = variable->get_declaration(0);
352 if (decl != variable->get_default_value()) {
353 nout << " current value = " << decl->get_string_value();
354 if (!decl->get_page()->is_special()) {
355 nout << " (from " << decl->get_page()->get_name() << ")\n";
356 } else {
357 nout << " (defined locally)\n";
358 }
359 }
360
361 decl = variable->get_default_value();
362 if (decl != nullptr) {
363 nout << " default value = " << decl->get_string_value() << "\n";
364 }
365 }
366
367 if (!variable->get_description().empty() && include_descriptions) {
368 nout << " " << variable->get_description() << "\n";
369 }
370 }
371
372 nout << "\n";
373}
A single declaration of a config variable, typically defined as one line in a .prc file,...
const std::string & get_string_value() const
Returns the value assigned to this variable.
get_page
Returns the page on which this declaration can be found.
The internal definition of a ConfigVariable.
void set_flags(int flags)
Specifies the trust level of this variable.
get_trusted_reference
Returns the nth declaration in a trusted prc file that references this variable.
bool has_local_value() const
Returns true if this variable's value has been shadowed by a local assignment (as created via make_lo...
get_num_trusted_references
Returns the number of trusted prc files that reference this variable.
get_declaration
Returns the nth declarations that contributes to this variable's value.
get_value_type
Returns the stated type of this variable.
set_default_value
Specifies the default value for this variable if it is not defined in any prc file.
get_default_value
Returns the default variable specified for this variable.
get_reference
Returns the nth declaration in a prc file that references this variable.
is_dynamic
Returns true if the variable was indicated as "dynamic" by its constructor, indicating that its name ...
void set_used()
Marks that the variable has been "declared" by a ConfigVariable.
set_description
Specifies the one-line description of this variable.
get_num_references
Returns the number of prc files that reference this variable.
get_description
Returns the brief description of this variable, if it has been defined.
get_name
Returns the name of the variable.
set_value_type
Specifies the type of this variable.
is_used
Returns true if the variable has been referenced by a ConfigVariable somewhere in code,...
A global object that maintains the set of ConfigVariables (actually, ConfigVariableCores) everywhere ...
bool is_variable_used(size_t n) const
Returns true if the nth active ConfigVariable in the list has been used by code, false otherwise.
void list_unused_variables() const
Writes a list of all the variables that have been defined in a prc file without having been declared ...
std::string get_variable_name(size_t n) const
Returns the name of the nth active ConfigVariable in the list.
ConfigVariableCore * make_variable_template(const std::string &pattern, ConfigFlags::ValueType type, const std::string &default_value, const std::string &description=std::string(), int flags=0)
Defines a variable "template" to match against dynamically-defined variables that may or may not be c...
void write_prc_variables(std::ostream &out) const
Writes all of the prc-set config variables, as they appear in a prc file somewhere,...
void list_variables() const
Writes a list of all the variables that have been declared somewhere in code, along with a brief desc...
void list_dynamic_variables() const
Writes a list of all the "dynamic" variables that have been declared somewhere in code,...
ConfigVariableCore * make_variable(const std::string &name)
Creates and returns a new, undefined ConfigVariableCore with the indicated name; or if a variable wit...
This class can be used to test for string matches against standard Unix- shell filename globbing conv...
Definition globPattern.h:32
bool matches(const std::string &candidate) const
Returns true if the candidate string matches the pattern, false otherwise.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
void init_memory_hook()
Any code that might need to use PANDA_MALLOC or PANDA_FREE, or any methods of the global memory_hook ...
Definition dtoolbase.cxx:38