ALib C++ Library
Library Version: 2511 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
configuration.inl
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header-file is part of module \alib_variables of the \aliblong.
4///
5/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace variables {
9
10class Configuration;
12class Variable;
13class Configuration;
14
15namespace detail {
17
18//==================================================================================================
19/// This is the entry element type of the \alib{containers;StringTree} of class
20/// \alib{variables;Configuration}.
21//==================================================================================================
22class Entry
23{
24 friend class alib::variables::Variable;
27
28 protected:
29 VDATA* data = nullptr; ///< The list hook of values.
30 VMeta* meta ; ///< The virtual handler instance for this variable.
31 const Declaration* declaration; ///< Declaration information. Can be \c nullptr in case
32 ///< a variable was not declared using a record.
33 Priority priority ; ///< The priority level of this data element.
34
35 public:
36 /// Deleted copy-constructor.
37 Entry(const Entry&) =delete;
38
39 /// Deleted move-constructor.
40 Entry(Entry&&) =delete;
41
42 /// Defaulted default constructor.
43 Entry() : data(nullptr), meta{nullptr}, declaration{nullptr}, priority{Priority::NONE} {}
44}; // class Entry
45
46
47/// A shortcut to the base class of the base class of class \alib{variables;Configuration}.
49 Recycling::Private >;
50
51/// Specialized \ref alib_ns_containers_stringtree_referencedoc "TNodeHandler" for class
52/// \alib{variables;Configuration} which recycles variables and their extended information objects.
53///
54/// In respect to the node name allocation, this type behaves like
55/// default handler \alib{containers;StringTreeNamesDynamic}. In debug compilations,
56/// statistics variables \alib{containers;DBG_STATS_STRINGTREE_NAMES} and
57/// \alib{containers;DBG_STATS_STRINGTREE_NAME_OVERFLOWS} are increased, just like the original
58/// does.
60{
61 /// The character type that the \b StringTree uses for child name and path strings.
63
64 /// The string-type of a node's name. This is a simple static string, allocated with the
65 /// pool allocator.
67
68 /// Copies the node's name to the local string.
69 /// @param node The node that was just created. Allows access to the key and
70 /// custom value data. While the parent and sibling nodes are likewise accessible,
71 /// it is strictly forbidden to modify those.
72 /// @param tree The instance of struct \alib{containers;detail::StringTreeBase} that invokes
73 /// this method. Any member may be accessed, including
74 /// \alib{containers::detail::StringTreeBase;nodeTable} which contains the
75 /// \alib{MonoAllocator} that the tree uses for the allocation of nodes.
76 inline static
77 void InitializeNode( TTree::Node& node, TTree& tree );
78
79
80 /// This implementation frees any dynamically allocated memory of the node's name and in
81 /// addition recycles any extended information object attached to the \alib{variables;Variable}
82 /// object.
83 /// @param tree The instance of struct \alib{containers;detail::StringTreeBase} that invokes
84 /// this method. Any member may be accessed, including
85 /// \alib{containers::detail::StringTreeBase;nodeTable} which contains the
86 /// \alib{MonoAllocator} that the tree uses for the allocation of nodes.
87 /// @param node The node that is to be removed. Allows access to the key and
88 /// custom value data. While the parent and sibling nodes are likewise accessible,
89 /// it is strictly forbidden to modify those.
90 static ALIB_DLL
91 void FreeNode( TTree::Node& node, TTree& tree ); // inline implementation is below
92}; // struct ConfigNodeHandler
93
94} // namespace detail
95
96
97
98//==================================================================================================
99/// Abstract virtual interface type to implement types observing configuration changes.
100/// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
101//==================================================================================================
103{
104 /// The type of change that imposes the notification of a listener.
105 enum class Event
106 {
107 Creation, ///< A variable was declared for the first time.
108 Definition, ///< A variable was defined or re-defined with the same or a higher priority.
109 Deletion, ///< A variable is deleted. Note that the variable is still valid
110 ///< when method #Notify is invoked and will be deleted right after
111 ///< the invocation of all listeners in question.
112 };
113
114 /// Virtual destructor.
116
117 /// The virtual notification method.
118 /// @param variable The variable that was modified.
119 /// @param event The type of modification.
120 /// @param previousPriority The priority of the variable before event type
121 /// \alib{variables;ConfigurationListener::Event;Event::Definition}.<p>
122 /// With other events, this parameter is undefined.
123 virtual void Notify( const Variable& variable, Event event, Priority previousPriority ) =0;
124
125}; // struct ConfigurationListener
126
127//==================================================================================================
128/// Abstract class that defines the plug-in interface for class \alib{variables;Configuration}.
129/// Plug-ins provide configuration data (variables) from external configuration data sources
130/// at the moment those are requested.
131///
132/// The rationale for this concept is that some external configuration sources may provide a lot of
133/// data that is not related to an application. This is, for example, true for environment
134/// variables, the windows registry or the Gnome variable systems <em>gconf/dconf</em>.
135/// In these cases, variables have to be read into the \alib variable system only at the moment
136/// they are declared.
137///
138/// With other sources, like dedicated INI-files, a different technique is usually preferred:
139/// Here, all data is read and imported into the configuration system with an application's
140/// bootstrap and variables (respectively whole subtrees of variables) may be exported when an
141/// application exits, just to populate empty INI-files with default values or to add new variables
142/// which occur with a new software version.
143///
144/// Category and Variable names are character case-insensitive for the plug-ins predefined
145/// with \alib. It is up to a custom implementation to decide to ignore character case in custom
146/// specializations of this class as well.
147//==================================================================================================
148class ConfigurationPlugin : public lang::Plugin<Configuration, Priority>
149{
150 protected:
151 /// A default string escaper instance. This is used with all plugins provided with \alib.
152 /// (Namely \alib{variables;CLIVariablesPlugin} and \alib{variables;EnvironmentVariablesPlugin}.)
154
155 /// Constructor which is protected, as this is an abstract class.
156 /// @param pPriority The priority that this plug-in uses.
158 : Plugin(pPriority) {}
159
160 public:
161 /// Virtual Destructor.
163
164 /// Derived types may return a different, customized implementation specific to their needs.
165 /// This default implementation returns field #stringEscaper.
166 /// @return An escaper used to convert string values from and to escaped sequences as provided
167 /// by a configuration source that is based on serialization of variable values to and
168 /// from ASCII/unicode strings which are human-readable and placeable in text files,
169 /// command line parameters, etc.
170 virtual const StringEscaper& GetEscaper() const { return stringEscaper; }
171
172 /// Abstract method. Descendents need to return a plug-in name. The name may be used in human
173 /// readable output, e.g., log-files or exception messages to tell a user for example, which
174 /// plug-in loaded a variable containing a syntax error.
175 /// @return The name of the plug-in.
176 virtual String Name() const =0;
177
178 /// Abstract method that has to be overwritten by descendants.
179 /// Searches and retrieves the value of a configuration variable.
180 /// @param name The name of the variable to retrieve.
181 /// @param[out] target A reference to the buffer to write the variable's exported value to.
182 /// @return \c true if variable was found within this configuration source, \c false if not.
184 virtual bool Get( const String& name, AString& target ) =0;
185};
186
187
188//==================================================================================================
189/// This class is the container for \alib variables.<br>
190/// The use of this type is documented with the \ref alib_mod_variables "Programmer's Manual" of
191/// camp \alib_variables_nl.
192///
193/// Beside the interface that this class provides, publicly inherited interfaces of base types
194/// \alib{containers;StringTree} and \alib{lang;PluginContainer} are available for use.
195///
196/// @see
197/// Note that a general configuration object is provided with \alibcamps.
198/// Usually one instance is shared between all \alibcamps_nl.
199/// By \ref alib_mod_bs_customize "customizing the bootstrap process",
200/// dedicated configuration instances for built-in or custom \alibcamps_nl can be created.
201//==================================================================================================
202class Configuration : public StringTree<MonoAllocator,detail::Entry, detail::ConfigNodeHandler>
203 , public lang::PluginContainer<ConfigurationPlugin, Priority>
204{
205 /// Alias to the StringTree-parent.
207
208 // friends
209 friend class Variable;
210 friend class detail::Entry;
211 friend struct detail::ConfigNodeHandler;
212
213 public:
214 /// An object pool for recycling variable values as well as the hashtable entries.
215 /// It is \ref alib_contmono_chaining "chained" to the allocator provided with construction.
216 ///
217 /// The pool may be used in accordance with the general rules imposed by camp \alib_monomem.
218 /// If so, in multithreaded environments, this configuration has to be locked (in addition
219 /// to all other custom locks when interfacing this type), when using this pool from custom
220 /// code.
222
223 protected:
224 /// Record used to manage registered listeners.
226 {
227 ConfigurationListener* listener; ///< The listener to register or dispose.
228 int event; ///< The event to listen to.
229 ConstCursorHandle variable; ///< If given, the variable to listen to.
230 ConstCursorHandle subTree; ///< If given, the subtree of variables to listen to.
231 AStringPA variableName; ///< If given, the variable's name to listen to.
232 AStringPA pathPrefix; ///< If given, the start string of the file path to monitor.
233 AStringPA pathSubstring; ///< If given, the substring to match in the path
234 ///< (including the variable name) of files to monitor.
235 };
236
237 /// A default plugin created and inserted with construction.
239
240 /// A default plugin created and inserted with construction.
242
243 /// Helper-struct used for implementing field #types.
245 {
246 /// Returns the name of the type.
247 /// @param src The value of the element to hash.
248 /// @return The key-portion of the stored value.
249 const String Key(const VMeta* src) const { return src->typeName(); }
250 };
251
252
253 /// A hashtable for the registered types. Key is the type name, value is the VMeta singleton.
256 std::hash<String> ,
257 std::equal_to<String> ,
259 Recycling::None >;
260
261 /// A hashtable for the registered types. Key is the type name, value is the VMeta singleton.
263
264
265 /// Helper-struct used for implementing field #replacementDeclarations.
266 struct ValueDescriptorRD : containers::TSubsetKeyDescriptor<Declaration*, const String&>
267 {
268 /// Returns the name of the declaration.
269 /// @param src The value of the element to hash.
270 /// @return The key-portion of the stored value.
271 const String& Key(const Declaration* src) const { return src->Name(); }
272 };
273
274 /// Type definition of the container that stores declarations allocated with method
275 /// \alib{variables;Configuration::StoreDeclaration}.
276 using RDHashTable= HashTable< MonoAllocator , // TAllocator
277 ValueDescriptorRD , // TValueDescriptor
278 std::hash <String> , // THash
279 std::equal_to<String> , // TEqual
280 lang::Caching::Disabled , // THashCaching
281 Recycling::None >; // TRecycling
282
283
284 /// A hashtable for declarations allocated with method
285 /// \alib{variables;Configuration::StoreDeclaration}.
287
288 /// The list of registered listeners.
290
291 //======================================= Protected Methods ======================================
292 /// Implementation of \alib{variables;Configuration::RegisterType}.
293 /// @tparam TVMeta The meta-information type of the type to register.
294 template<typename TVMeta>
296 {
297 auto* meta= GetAllocator()().New<TVMeta>();
298 types.EmplaceUnique( meta );
299 }
300
301 /// Stores the given information as a default value, which is imported to a variable
302 /// as soon as it becomes declared.
303 /// @see Overloaded public methods \alib{variables;Configuration::PresetImportString}.
304 /// @param name The name of the variable.
305 /// @param value The value to import.
306 /// @param escaper The escaper to use for importing.
307 /// @param priority The priority to set for the value.
308 ALIB_DLL void presetImportString(const String& name, const String& value,
309 const StringEscaper* escaper, Priority priority);
310
311 /// Implements the various overloaded listener registration methods.
312 /// @param listener The listener to register or dispose.
313 /// @param insertOrRemove Denotes registration or disposal of a listener.
314 /// @param event The event to listen to.
315 /// @param variable If given, the exported value of the variable to listen to.
316 /// @param subTree If given, the exported value of the subtree of variables to listen to.
317 /// @param variableName If given, the variable's name to listen to.
318 /// @param pathPrefix If given, the start string of the path of the variables to monitor.
319 /// @param pathSubstring If given, the substring to match in the path (including the variable name)
320 /// of the variables to monitor.
322 lang::ContainerOp insertOrRemove,
323 int event,
324 const Variable* variable,
325 const StringTree::Cursor* subTree,
326 const String& variableName,
327 const String& pathPrefix,
328 const String& pathSubstring );
329
330 /// Notifies registered listeners on events.
331 /// @param event The event that occurred.
332 /// @param variable The variable.
333 /// @param variablePath The full path of the variable. Might be nulled if not available, yet.
334 /// @param previousPriority The priority of the variable before the event.
335 ALIB_DLL void notifyListeners( int event,
336 const Variable& variable,
337 const String& variablePath,
338 Priority previousPriority );
339
340 //========================================= Public Members =======================================
341 public:
342 /// Number format definition used to read and write int and float values.
343 /// Can be tweaked to change the way external information is parsed.
345
346 /// A standard string escaper that can be used to set preset values received from external
347 /// escaped strings.
349
350 /// The start string to identify substitution variables.
351 /// Defaults to single character \c '$'. If a string is set, i.e., \c "${", then field
352 /// #SubstitutionVariableEnd may be set accordingly, i.e., \c "}"
354
355 /// The end of a substitution variables.
356 /// If this field is set, then field #SubstitutionVariableDelimiters is ignored. If this
357 /// field is nullptr (the default) or empty, it is ignored and characters in field
358 /// #SubstitutionVariableDelimiters are used to identify the end of the variable.
360
361 /// The delimiters used to identify the end of a substitutable variable.
362 /// If field #SubstitutionVariableEnd is not empty, this field is ignored. Otherwise, all
363 /// characters defined in this string are used to identify the end of a substitution
364 /// variable.
365 CString SubstitutionVariableDelimiters =A_CHAR(" $@,.;:\"\'+-*\\§%&()[]{}<>=?'`~#");
366
367 /// This is a list that holds pairs of type \alib{strings::util::Token} which is used by the
368 /// built-in boolean variable type (type name "B").
369 /// The list defines how extern string data (for example, from command line args, environment
370 /// variables, or INI-files) is converted to boolean values.
371 ///
372 /// When parsed from outside, the index of the pair that had the match is stored and
373 /// in the case of writing back (e.g., to the INI-file), the corresponding representation of
374 /// this pair will be written out. (For example, if a user used "On" in the configuration file,
375 /// and the software switched it to \c false, the word "Off" is to be written.
376 ///
377 /// During bootstrap, this list might be modified, but before any variable was read. Otherwise
378 /// the indices would become invalid. However, the preferred way of changing the accepted
379 /// tokens is to modify the resources. This allows having localization of terms, in case
380 /// this should be needed some day.
381 ///
382 /// If even with modification of the predefined list,
383 /// some other needs or flexibility is wanted, then the definition of an alternative
384 /// boolean configuration variable type is the way to go.
385 ///
386 /// The list of resourced predefined tokens after construction of a configuration is:
387 ///
388 /// Index | True Token | False Token
389 /// --------|---------------------|--------------------
390 /// 0 | <c>false I 1</c> | <c>true I 1</c>
391 /// 1 | <c>0 I 1</c> | <c>1 I 1</c>
392 /// 2 | <c>no I 1</c> | <c>yes I 1</c>
393 /// 3 | <c>off I 3</c> | <c>on I 2</c>
394 /// 4 | <c>--- I 1</c> | <c>OK I 2</c>
395 ///
396 /// @see Methods #ParseBooleanToken and #WriteBooleanToken.
398
399
400 //===================================== Constructor/destructor ===================================
401 /// Constructs a Configuration.
402 ///
403 /// If \p{addDefaultPlugins} is \c true, registers the initial plug-ins as follows:
404 ///
405 /// Priority | Plug-in Type
406 /// -----------------------------------------------|------------------------------
407 /// \alib{variables;Priority;Priority::Environment} | \alib{variables;EnvironmentVariablesPlugin}
408 /// \alib{variables;Priority;Priority::CLI} | \alib{variables;CLIVariablesPlugin}
409 ///
410 /// Furthermore all \ref alib_variables_types_builtin "built-in variable types" are registered.
411 ///
412 /// Modifications (in respect to plug-ins and registered types) should
413 /// be performed during bootstrap, right after construction of this type (when no parallel
414 /// threads are active) or with prior locking the \alib{variables;Configuration} instance.
415 ///
416 /// @param allocator The allocator to use.
417 /// @param createDefaults Determines if default plug-ins are to be created.
418 /// Defaults to \c Yes.
420 Configuration( MonoAllocator& allocator,
422
423 /// Destructor.
425
426//============================================ Interface ===========================================
427 /// Registers a variable type with this configuration. The only parameter is the template
428 /// parameter \p{TVMeta}. The function will create the singleton of this type and store
429 /// it in a hash table of types. When a variable associated with this configuration object
430 /// is declared, this variable type is used as the key to this hash table.
431 /// Then this singleton object of the given type is responsible for construction, destruction
432 /// and import/export of variables of this type.
433 /// @tparam TVMeta The meta-information type of the type to register.
434 template<typename TVMeta>
436
437 /// Creates and stores a declaration. Placeholders \c "%1", \c "%2" ... \c "%N" found in
438 /// the fields (except \alib{variables::Declaration;typeName}) are replaced with the
439 /// replacement values given with boxed argument (list) \p{replacements}.
440 ///
441 /// \attention
442 /// This method creates a copy a new declaration instance within the monotonic allocator
443 /// of this \b Configuration object. This imposes a potential memory drain (leak).
444 /// To mitigate the problem and widen the use cases, this method uses a hashtable
445 /// to cache the resulting declarations. This means, that only for combinations of parameters
446 /// that result to a different variable name, a declaration is created.
447 ///
448 /// @see Chapter \ref alib_variables_names_placeholders of the Programmer's Manual of
449 /// camp \alib_variables_nl.
450 ///
451 /// @param orig The original, typically resourced declaration with placeholders.
452 /// @param replacements A list of replacement values. Must be of boxed types that are
453 /// \alib{strings,AppendableTraits,appendable} to class \b AString.
454 /// To provide more than one object, pass an object of class
455 /// \alib{boxing,Boxes} or a boxed array.
456 /// @return The allocated (or cached) copy of \p{orig}.
458 const Declaration* StoreDeclaration( const Declaration* orig, const Box& replacements );
459
460 /// Declares and defines all variables of the given enum type which do not contain
461 /// placeholders are contained in the variable's name.
462 ///
463 /// The purpose of this method is to fill the configuration system with variables
464 /// (usually during or right after bootstrap) regardless of their later use, which depends
465 /// on the concrete execution path of a run of software. The rationale to do this is
466 /// twofold:
467 /// 1. To allow external configuaration plug-ins to set all variable's values, which is not
468 /// possible if a variable is not declared, yet, and thus its type is not known. In
469 /// that case, an external source can only use method
470 /// \alib{variables;Configuration::PresetImportString}, which in the end leads to correctly
471 /// setting a variable's external value, but which creates a little overhead in respect
472 /// to execution time and memory consumption.
473 /// 2. To give external configuaration plug-ins the possibiltiy to "populate" their files
474 /// with all known variables, including their default values and comments, again
475 /// independently from a concrete excution path of a run of the software, which might
476 /// not declare certain variables and thus those would not be "known" to the external
477 /// source. Populating external configuration files (with the first run of software),
478 /// tremendously supports an end-user in learning about configuration options.<br>
479 /// For example, built-in class \alib{variables;IniFileFeeder} supports such "population"
480 /// of for INI-fles through its \b Export methods.
481 ///
482 /// Altogether, the use of this method does not impose much of an overhead, because:
483 /// - as explained above, the need of method \alib{variables;Configuration::PresetImportString}
484 /// is avoided for all variables that do not contain placeholders, and because
485 /// - most variables would anyhow be declared later during the run of software
486 /// and thus, this declaration is just performed earlier and the variable are already in
487 /// place when software later uses them.
488 ///
489 /// @see Chapter \ref alib_variables_external_ini of the Programmer's Manual of camp
490 /// \alib_variables.
491 ///
492 /// @tparam TEnum Enumeration type equipped with \ref alib_enums_records "ALib Enum Records"
493 /// of type \alib{variables;Declaration}.
494 template<typename TEnum>
495 requires ( EnumRecords<TEnum>::template AreOfType<Declaration>() )
497
498 /// Stores the given information as a default value, which will be assigned to a variable as
499 /// soon as it is declared. If a variable is deleted and later again declared, the given
500 /// \p{value} is again imported. In other words, a preset will not be removed with a first
501 /// declaration and use.<br>
502 /// To delete a previously set import string, a \e nulled string is to be passed with
503 /// for parameter \p{value}.
504 ///
505 /// This method is to be used in cases when a declaration of a variable is not possible,
506 /// i.e., when a variable's type is not known, which often is the case when external
507 /// configuration values are to be set.
508 ///
509 /// @see
510 /// - Overloaded public methods #PresetImportString.
511 /// - Chapter \ref alib_variables_external_ini of the Programmer's Manual of camp
512 /// \alib_variables.
513 /// @param name The name of the variable.
514 /// @param value The value to import. Will be 'unescaped' using \p{escaper}.
515 /// @param escaper The escaper to use for importing. Has to be still valid at the time(s)
516 /// the value read. A pointer to field #Escaper might be passed here.
517 /// @param priority The priority to set for the value.
518 /// Defaults to \alib{variables;Priority;Default}.
519 void PresetImportString(const String& name, const String& value, StringEscaper* escaper,
520 Priority priority= Priority::DefaultValues)
521 { presetImportString( name, value, escaper, priority); }
522
523 /// Same as overloaded version
524 /// #PresetImportString(const String&, const String&,StringEscaper*, Priority),
525 /// but does not accept an \alib{strings::util;StringEscaper} and thus expects the value is in
526 /// C++ internal string format (aka 'not escaped').
527 /// @param name The name of the variable.
528 /// @param value The value to import.
529 /// @param priority The priority to set for the value.
530 /// Defaults to \alib{variables;Priority;Default}.
531 void PresetImportString( const String& name, const String& value,
532 Priority priority= Priority::DefaultValues )
533 { presetImportString( name, value, nullptr, priority); }
534
535 /// Deletes the given variable \p{path}, respectively all variables under the given \p{path} as
536 /// well as the path node itself.
537 ///
538 /// This is a convenience method. Full access to the underlying \alib{containers;StringTree}
539 /// is provided by public inheritance, which offers many other ways of manipulating
540 /// variable data. As an example, consider the implementation of this method:
541 /// \snippet "variables/configuration.cpp" DOX_VARIABLES_DELETE_SAMPLE
542 ///
543 ///
544 /// @param path The path in the variable tree.
545 /// @return \c true on success, \c false, if the given \p{path} was not found.
547 bool DeletePath( const String& path );
548
549 /// Utility method that checks if a given value represents boolean \b true.
550 ///
551 /// @see Field #BooleanTokens, which is used by this function and sibling method
552 /// #WriteBooleanToken
553 ///
554 /// @param src The input string to check.
555 /// @return Returns the value found and the index of the pair of tokens that matched.
556 /// If no token matched <c>(false,-1)</c> is returned.
558 std::pair<bool,int8_t> ParseBooleanToken( const String& src );
559
560 /// Utility method that writes the given boolean value as specified with the token
561 /// found at \p{index} in #BooleanTokens.<br>
562 /// This method is used internally by the meta-information handler of variable type
563 /// <c>"B"</c>/<c>bool</c>.
564 /// @see Sibling method #ParseBooleanToken.
565 ///
566 /// @param value The boolean value to write.
567 /// @param index The token to use. If negative, this is corrected to \c 0.
568 /// @param dest The destination string.
569 /// @return \p{dest} to allow concatenated operations.
571 AString& WriteBooleanToken( bool value, int8_t index, AString& dest );
572
573
574 //===================================== Listener Registration ====================================
575
576 /// Inserts or removes a listener to a specific variable.
577 /// Note that this version of the method cannot be used to fetch declaration events,
578 /// because the given \p{variable} obviously is already declared and created.
579 /// @param insertOrRemove Denotes whether the listener should be inserted or removed.
580 /// (Only enum elements \b ContainerOp::Insert or \b ContainerOp::Remove
581 /// must be passed.)
582 /// @param listener The listener to register.
583 /// @param event The event to listen to.
584 /// @param variable The variable to listen to.
585 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
587 ConfigurationListener* listener,
589 const Variable& variable ) {
591 "Event::Creation will never be invoked with this listener-registration-type.")
592 registerListener( listener,
593 insertOrRemove,
594 int(event),
595 &variable, nullptr,
597 }
598
599 /// Inserts or removes a listener for all variables that share the given \p{variableName}.
600 /// @param insertOrRemove Denotes whether the listener should be inserted or removed.
601 /// (Only enum elements \b ContainerOp::Insert or \b ContainerOp::Remove
602 /// must be passed.)
603 /// @param listener The listener to register.
604 /// @param event The event to listen to.
605 /// @param variableName The name of one or more variables to listen to.
606 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
608 ConfigurationListener* listener,
610 const String& variableName ) {
611 ALIB_ASSERT_ERROR( variableName.IsNotEmpty(), "VARIABLES", "Empty variable name given.")
612 registerListener( listener, insertOrRemove, int(event),
613 nullptr, nullptr, variableName, NULL_STRING, NULL_STRING );
614 }
615
616
617 /// Inserts or removes a listener for all variables below subtree specified by the
618 /// given \p{cursor}.
619 /// @param insertOrRemove Denotes whether the listener should be inserted or removed.
620 /// (Only enum elements \b ContainerOp::Insert or \b ContainerOp::Remove
621 /// must be passed.)
622 /// @param listener The listener to register.
623 /// @param event The event to listen to.
624 /// @param cursor The parent node in the configuration variable tree of the variables
625 /// to monitor.
626 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
627 void MonitorPath( lang::ContainerOp insertOrRemove,
628 ConfigurationListener* listener,
630 const Configuration::Cursor& cursor ) {
631 registerListener( listener,
632 insertOrRemove,
633 int(event),
634 nullptr, &cursor,
636 }
637
638
639
640 /// Inserts or removes a listener for all variables below the subtree specified by the
641 /// given \p{startPath}.
642 /// @param insertOrRemove Denotes whether the listener should be inserted or removed.
643 /// (Only enum elements \b ContainerOp::Insert or \b ContainerOp::Remove
644 /// must be passed.)
645 /// @param listener The listener to register.
646 /// @param event The event to listen to.
647 /// @param pathPrefix The path prefix of the subtree of variables to monitor. Note that a
648 /// missing leading separator character <c>'/'</c> will be added.
649 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
651 ConfigurationListener* listener,
653 const String& pathPrefix ) {
654 ALIB_ASSERT_ERROR( pathPrefix.IsNotEmpty(), "VARIABLES", "Empty path prefix given.")
655 registerListener( listener,
656 insertOrRemove,
657 int(event),
658 nullptr, nullptr,
659 NULL_STRING, pathPrefix, NULL_STRING );
660 }
661
662 /// Inserts or removes a listener for all variables below the subtree specified by the
663 /// given \p{startPath}.
664 /// @param insertOrRemove Denotes whether the listener should be inserted or removed.
665 /// (Only enum elements \b ContainerOp::Insert or \b ContainerOp::Remove
666 /// must be passed.)
667 /// @param listener The listener to register.
668 /// @param event The event to listen to.
669 /// @param pathSubstring The substring to match in the path (including the variable name)
670 /// of the variables to monitor.
671 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
673 ConfigurationListener* listener,
675 const String& pathSubstring ) {
676 ALIB_ASSERT_ERROR( pathSubstring.IsNotEmpty(), "VARIABLES", "Empty path substring given.")
677 registerListener( listener,
678 insertOrRemove,
679 int(event),
680 nullptr, nullptr,
681 NULL_STRING, NULL_STRING, pathSubstring );
682 }
683
684 /// Removes all registrations of the given listener.
685 /// @param listener The listener to remove.
686 /// @return The number of registrations that have been removed.
687 /// @see Chapter \ref alib_variables_monitoring of the Programmer's Manual of camp \alib_variables_nl.
689 int MonitorStop( ConfigurationListener* listener );
690
691}; // struct Configuration
692
693void detail::ConfigNodeHandler::InitializeNode( typename TTree::Node& node, TTree& tree )
694{ node.name.storage.Allocate(static_cast<Configuration&>(tree).Pool, node.name.key ); }
695
696
697//==================================================================================================
698// Class Variable
699//==================================================================================================
700
701//==================================================================================================
702/// This is the central interface type into the module \alib_variables.
703/// The class is a very lightweight (size of two times <c>sizeof(void*)</c>) object, because
704/// it rather is a pointer to a variable instead of an implementation of its data structures.
705/// The types' true nature is inherited from class \alib{containers;StringTree::Cursor}
706/// which is the base of this class. The inheritance is defined <c>protected</c> and this class
707/// received its own dedicated interface reflecting the domain of <em>configuration variables</em>.
708/// Nevertheless, the protected base type is accessible with the explicit cast method #AsCursor.
709/// While a reader might think this is a contradiction, this was made by design: Casting to
710/// a <b>StringTree::Cursor</b> is only necessary for implementing \alib{variables;ConfigurationPlugin}
711/// or similar extraordinary things. For the common use, the dedicated interface is all that is
712/// needed.
713///
714/// @see
715/// - For a quick tutorial about using \alib variables, consult the tutorial-style
716/// \ref alib_mod_variables "Programmer's Manual" of camp \alib_variables_nl.
717/// - For this class, a \ref alibtools_debug_helpers_gdb "pretty printer" for the
718/// GNU debugger is provided.
719/// - Besides the constructors found with this class, with the inclusion of the module
720/// \alib_camp in the \alibbuild, and the inclusion of the header file \implude{Camp},
721/// a set of overloaded namespace functions \alib{variables;CampVariable} allow the construction
722/// of variables in the \b Configuration instance included in \alibcamps.
723//==================================================================================================
725{
727
728 /// The base cursor type of the internal \b StringTree. This type is used to perform
729 /// cursor operations on \b Configuration instances.
731
732 protected:
733 /// Called by declaration methods. Creates necessary internal data structs, searches
734 /// configuration plug-ins for data, and, in case not found, optionally applies the given
735 /// \p{defaultValue}
736 /// @param typeName The type name.
737 /// @param defaultValue A default value, if available.
738 void create(const String& typeName, const String& defaultValue );
739
740 /// Performs variable substitution. This method is called before any call to
741 /// \alib{variables;VMeta::imPort}.
742 /// @param importString The import string.
743 /// @param buf The substitution buffer.
744 /// @param escaper The escaper used to externalize substitution values.
745 /// @return Either the original import string, or a reference to the given buffer containing
746 /// the substituted copy.
747 const String& substitute(const String& importString, AString& buf,
748 const StringEscaper* escaper );
749
750 /// Returns the meta-information object.
751 /// @return The virtual meta handler.
752 inline VMeta* getMeta() const { return Cursor::Value().meta; }
753
754
755 //################################################################################################
756 // Constructors
757 //################################################################################################
758 public:
759 /// Default constructor.
760 /// \note
761 /// A variable that was default-constructed cannot be used later, without assigning
762 /// a configuration with declaration. If, for example, a field member of type variable
763 /// cannot be constructed with the provision of a corresponding \b Configuration, one of
764 /// the following options has to be taken:
765 /// - The variable value gets a newly constructed instance assigned at a later stage
766 /// when the configuration is known, or
767 /// - the configuration is provided with one of the overloaded #Declare methods that
768 /// accept a configuration.
769 Variable() =default;
770
771 /// Constructs an instance of this type from its base type.
772 /// This constructor is for advanced use when direct operations with class \b StringTree and
773 /// its cursor and iterator types are performed.<br>
774 /// Note that the variable has to be declared already, when this constructor is used.
775 /// @param cursor The \b StringTree cursor.
776 Variable(const Cursor& cursor )
777 : Cursor(cursor) {}
778
779 /// Constructs an instance of this type from its base type.
780 /// This constructor is for advanced use when direct operations with class \b StringTree and
781 /// its cursor and iterator types are performed.<br>
782 /// Note that the previous variable declaratin will be destroyed, in case a variable had been
783 /// declared at this cursor already.
784 /// @param cursor The \b StringTree cursor.
785 /// @param typeName The type name.
786 /// @param defaultValue A default value, if available. Defaults to \e nulled string.
787 Variable( const Cursor& cursor, const String& typeName, const String& defaultValue= NULL_STRING )
788 : Cursor(cursor) { Cursor::Value().declaration= nullptr; create( typeName, defaultValue); }
789
790 /// Constructs an undeclared variable "cursor" associated with the given configuration object.
791 /// \note The internal \alib{containers,StringTree::Cursor} equals
792 /// the root cursor received with \alib{containers,StringTree::Root} after this
793 /// construction.
794 /// @see Overloaded namespace functions \alib{variables;CampVariable} which become accessible
795 /// with the header file \implude{Camp}.
796 /// @param cfg The configuration to use.
797 explicit Variable(Configuration& cfg)
798 : Cursor(cfg.Root()) {}
799
800 /// Constructs and declares this variable, without using or allocating a declaration struct.
801 /// @see Overloaded namespace functions \alib{variables;CampVariable} which become accessible
802 /// with the header file \implude{Camp}.
803 /// @param cfg The configuration to use.
804 /// @param name The name of the variable.
805 /// @param typeName The type of the variable.
806 /// @param defaultValue An optional default value. Defaults to \e nulled string.
807 Variable( Configuration& cfg,
808 const String& name, const String& typeName,
809 const String& defaultValue= NULL_STRING )
810 : Cursor(cfg.Root()) { Declare( name, typeName, defaultValue ); }
811
812
813 /// Constructs and declares this variable.
814 /// @see Overloaded namespace functions \alib{variables;CampVariable} which become accessible
815 /// with the header file \implude{Camp}.
816 /// @param cfg The configuration to use.
817 /// @param decl The declaration to use.
818 Variable(Configuration& cfg, const Declaration* decl)
819 : Cursor(cfg.Root()) { Declare( decl ); }
820
821 /// Constructs and declares this variable.
822 /// @see Overloaded namespace functions \alib{variables;CampVariable} which become accessible
823 /// with the header file \implude{Camp}.
824 /// @tparam TEnum The type of parameter \p{Enum}
825 /// @param cfg The configuration to use.
826 /// @param Enum Element of an enum type that represents resourced configuration variables.
827 template<typename TEnum>
828 inline
829 Variable(Configuration& cfg, TEnum Enum )
830 : Cursor(cfg.Root()) { Declare( Declaration::Get(Enum) ); }
831
832 /// Constructs and declares this variable.
833 /// \attention This constructor might allocate a new record in the mono allocator of \p{cfg}.
834 /// To avoid memory drain, consult the documentation of the method
835 /// \alib{variables;Configuration::StoreDeclaration}.
836 /// @see Overloaded namespace functions \alib{variables;CampVariable} which become accessible
837 /// with the header file \implude{Camp}.
838 /// @tparam TEnum The type of parameter \p{Enum}
839 /// @param cfg The configuration to use.
840 /// @param Enum Element of an enum type that represents resourced configuration variables.
841 /// @param replacements Replacement values.
842 template<typename TEnum>
843 requires std::is_enum_v<TEnum>
844 Variable(Configuration& cfg, TEnum Enum, const Box replacements )
845 : Cursor(cfg.Root()) { Declare( StoreDeclaration( Declaration::Get( Enum ), replacements ) ); }
846
847 /// This is an explicit <c>cast operator</c> to the protected base class.
848 /// \note C++, for good reasons, does not allow implicit cast operators to protected base
849 /// classes, as this would undermine the protected nature of the inheritance.
850 /// Now, we undermine this explicitly. Why is this still good software design? Well,
851 /// class \b Variable restricts and changes the interface of class \b Cursor in a way that
852 /// it seems to be a very different entity. And this is right in the vast majority of use
853 /// cases. In the remaining cases such access to the cursor features is needed. For
854 /// example, when implementing a custom \alib{variables;ConfigurationPlugin}.<br>
855 /// By the same token, this class has explicit constructors that accept a \c Cursor.
856 /// @return This instance cast 'down' to its protected base class.
857 Cursor& AsCursor() { return static_cast<Cursor&>(*this); }
858
859 /// \c const version of the <c>cast operator</c> to the protected base class.
860 /// @see For details, see the mutable version of this operator.
861 /// @return This instance cast 'down' to its protected base class.
862 const Cursor& AsCursor() const { return static_cast<const Cursor&>(*this); }
863
864 //################################################################################################
865 // Declaration
866 //################################################################################################
867 public:
868 /// Declares this variable, without using or allocating a declaration struct.
869 ///
870 /// @param name The name of the variable.
871 /// @param typeName The type of the variable.
872 /// @param defaultValue An optional default value. Defaults to \e nulled string.
873 /// @return <c>*this</c> to allow concatenated operations.
875 Variable& Declare( const String& name, const String& typeName,
876 const String& defaultValue= NULL_STRING );
877
878 /// Moves this variable cursor (aka \alib{containers;StringTree::Cursor})
879 /// to represent the variable of the given declaration. If the variable does not exist, yet
880 /// it is created. If the variable exists, the given \p{decl} is ignored.
881 /// In debug compilations, an \ref alib_mod_assert "error is raised" in case the variable
882 /// existed but has a different declaration attached.
883 ///
884 /// If the variable is created and the \p{declaration} contains a default value, such value is
885 /// imported from the string. In this case, \alib{variables;Priority;DefaultValues} is returned.
886 ///
887 /// @param declaration The declaration singleton.
888 /// @return <c>*this</c> to allow concatenated operations.
890 Variable& Declare( const Declaration* declaration );
891
892 /// Declares this variable.
893 /// @tparam TEnum The type of parameter \p{Enum}
894 /// @param Enum Element of an enum type that represents resourced configuration variables.
895 /// @return The priority of the variable's data.
896 template<typename TEnum>
897 requires ( EnumRecords<TEnum>::template AreOfType<Declaration>() )
899
900
901 /// Declares this variable.
902 /// \attention
903 /// This method might allocate a new record in the mono allocator of \p{cfg}.
904 /// To avoid memory drain, consult the documentation of the method
905 /// \alib{variables;Configuration::StoreDeclaration}.
906 ///
907 /// @tparam TEnum The type of parameter \p{Enum}
908 /// @param Enum Element of an enum type that represents resourced configuration variables.
909 /// @param replacements Replacement values.
910 /// @return The priority of the variable's data.
911 template<typename TEnum>
912 requires ( EnumRecords<TEnum>::template AreOfType<Declaration>() )
913 Variable& Declare( TEnum Enum, const Box& replacements )
914 {
916 replacements ) );
917 }
918
919 /// Returns \c true if this variable is declared. If \c false is returned,
920 /// this is just a path node inside the \b StringTree of the \b Configuration.<br>
921 ///
922 /// \c false will be returned only if:
923 /// - An instance of a variable was created with the constructor that only accepts a
924 /// \b Configuration instance (an undeclared variable).
925 /// - An instance of a variable was created with the constructor that accepts a cursor
926 /// object of a \b Configuration, and this cursor does not point to a declared variable.
927 /// - Method #Try was called on an instance of this type, and the given variable name
928 /// did not represent a declared variable.
929 ///
930 /// @return \c true if the underlying \b StringTree::Cursor of the \b Configuration that this
931 /// variable is associated with, points to a declared variable.
932 /// Otherwise \c false is returned.
933 bool IsDeclared() const { return Cursor::Value().data != nullptr; }
934
935 /// Tries to move the underlying \b StringTree::Cursor of the \b Configuration that this
936 /// variable is associated with, to the given \p{path} (aka variable name).
937 /// If this succeeds, the result of #IsDeclared() is returned. Otherwise \c false.
938 ///
939 /// Note that this method still returns \c false if a
940 /// \alib{variables;Configuration::PresetImportString;preset value} exists for the variable,
941 /// because preset values can only be imported if a variable's type is known, hence when
942 /// a variable is declared. But this method explicitly avoids declarations.
943 ///
944 /// @see Overloaded versions, which declare and define a variable if a preset exists.
945 ///
946 /// @param name The name of the variable to try.
947 /// @return \c true if the variable name specified with the given \p{declaration} existed and
948 /// was declared. Otherwise \c false is returned and the variable's value is not allowed
949 /// to be accessed.
950 bool Try(const String& name)
951 { return Cursor::GoToRoot().GoTo( name ).IsEmpty() && IsDeclared(); }
952
953 /// Tries to move the underlying \b StringTree::Cursor of the \b Configuration that this
954 /// variable is associated with, to the given \p{path} (aka variable name).
955 ///
956 /// \note
957 /// This method automatically declares and defines variables, for which an
958 /// \alib{variables;Configuration::PresetImportString;preset value} is set.
959 ///
960 /// @param name The name of the variable.
961 /// @param typeName The type of the variable.
962 /// @return \c true if the variable name specified with the given \p{declaration} existed and
963 /// was declared. Otherwise \c false is returned and the variable's value is not allowed
964 /// to be accessed.
966 bool Try(const String& name, const String& typeName);
967
968 /// Tries to move the underlying \b StringTree::Cursor of the \b Configuration that this
969 /// variable is associated with, to the variable name found with given \p{declaration}.
970 /// If this succeeds, it is checked if the variable has no declaration record set, and if not,
971 /// the one given is stored with the variable.
972 ///
973 /// \note
974 /// This method automatically declares and defines variables, for which an
975 /// \alib{variables;Configuration::PresetImportString;preset value} is set.
976 ///
977 /// @param decl The declaration of the variable to use.
978 /// @return \c true if the variable name specified with the given \p{declaration} existed and
979 /// was declared, or if a preset value existed. Otherwise \c false is returned and
980 /// the variable's value is not allowed to be accessed.
982 bool Try(const Declaration* decl);
983
984 /// Deletes a variable. After this method is executed, the internal cursor will be
985 /// invalid and further operations on this variable instance can only be made after a next
986 /// declaration.
988 void Delete();
989
990 /// Assembles the variable's name from its path within the internal
991 /// \alib{containers;StringTree}.
992 /// @param target The string buffer to append this variable's name to.
993 /// @return The given \b AString to allow concatenated operations.
994 AString& Name(AString& target) const
995 { return AssemblePath(target, Tree().Root(), lang::CurrentData::Keep); }
996
997
998 //################################################################################################
999 // Get/Delete
1000 //################################################################################################
1001 public:
1002
1003 /// Increases the reported priority of this variable to the value given. If the current value
1004 /// is higher than the given one, it is not increased and \c false is returned.
1005 /// In this case, a program should not write the variable's value.
1006 ///
1007 /// \note
1008 /// A programmer can easily ignore the result of this method. However, the suggested
1009 /// usage is a contract to make the \alib variable system secure.
1010 /// For this reason, this method is attributed <c>[[nodiscard]]</c>.<br>
1011 ///
1012 /// \note
1013 /// If the return value is to be ignored for good reason (for example, if
1014 /// \alib{variables;Priority;Priority::Protected} is passed, add a simple <c>(void)</c> before
1015 /// the call.
1016 ///
1017 /// @see
1018 /// - Chapter \ref alib_variables_definition of the Programmer's Manual for more information.
1019 /// - Chapter \ref alib_variables_monitoring to learn about how to monitor changes of
1020 /// variables.
1021 ///
1022 /// @param requestedPriority The new, higher priority to set.
1023 /// @return \c true, if the current priority was lower or equal to the given one, \c false
1024 /// otherwise.
1025 ALIB_DLL
1026 [[nodiscard]]
1027 bool Define( Priority requestedPriority= Priority::Standard );
1028
1029 /// Returns the declaration struct of this variable, in case it was constructed or declared
1030 /// with an overloaded constructor or method #Declare, which accepts such struct.
1031 /// Otherwise, a nullptr is returned.
1032 ///
1033 /// \note If a variable is doubly declared by two or more code entities (which is the usual
1034 /// case), a first declaration given is stored and returned from now on.
1035 /// If a second, different declaration struct is passed for the same variable, an
1036 /// assertion is raised in debug compilation. Hence, once a declaration is given,
1037 /// it is always available for inspection.
1038 ///
1039 /// @return \c nullptr, if no declaration struct was given. Otherwise, the singleton declaration
1040 /// object provided.
1041 const Declaration* GetDeclaration() const { return Cursor::Value().declaration; }
1042
1043 /// Returns a \c reference to the configuration this variable resides in.
1044 /// @return The associated configuration instance.
1045 Configuration& GetConfiguration() const { return Tree<Configuration>(); }
1046
1047 /// The priority of a variable indicates "who" or "what" defined the variable and provided
1048 /// the current value. It may be defaulted values, values coming from external configuration
1049 /// files, from command line arguments, environment variables or from common code entities
1050 /// ('hard-coded' values). Besides the elements in enumeration \alib{variables;Priority},
1051 /// also any value in between may be given. Doing so, allows fine-tuning which entity exacly
1052 /// is allowed to write values. For example, if a variable's priority is set in code
1053 /// to \alib{variables;Priority;Environment}, then environment variables and CLI arguments may
1054 /// still overwrite a value. If set to \alib{variables;Priority;Environment + 1}, then
1055 /// environment variables would not overwrite, but still CLI arguments could.
1056 ///
1057 /// A priority of \alib{variables;Priority;Protected} disallows any code entity to make
1058 /// further changes, but those that again use this priority.
1059 ///
1060 /// @return The priority setting for this variable, given with the last successful call to
1061 /// #Define.
1062 Priority GetPriority() const { return Cursor::Value().priority; }
1063
1064 /// This is a shortcut to <c>Priority() != Priority::NONE</c> and thus, this method
1065 /// checks whether any data is defined.<br>
1066 /// Variables which are declared using a \alib{variables;Declaration} that
1067 /// contains a default value, will have this default value parsed and contain a data set of
1068 /// priority \alib{variables;Priority;DefaultValues}.
1069 ///
1070 /// @return \c true if data of any priority is available in this variable, \c false if not.
1071 inline
1072 bool IsDefined() const
1073 {
1074 ALIB_ASSERT_ERROR( IsDeclared(), "VARIABLES", "Variable not declared: ", this )
1075 return Cursor::Value().priority != Priority::NONE;
1076 }
1077
1078 /// This is the negation of method #IsDefined.
1079 ///
1080 /// @return \c false if data of any priority is available in this variable, \c true if not.
1081 inline
1082 bool IsNotDefined() const { return !IsDefined(); }
1083
1084 /// This is a shortcut to <c>Priority() > Priority::Standard</c> and thus, this method
1085 /// checks whether an explicit definition with a priority higher than \e Standard was performed,
1086 /// which - by contract - is done only when external data sources are read, for example
1087 /// configuration files, environment variables, or command line parameters.
1088 ///
1089 /// @return \c true if data contained has a higher priority than \alib{variables;Priority;Standard},
1090 /// \c false if not.
1091 inline
1092 bool IsDefinedExternally() const { return Priority() > Priority::Standard; }
1093
1094
1095 /// Imports a variable value from a serialized string representation. Internally, this is
1096 /// performed by calling \alib{variables;VMeta::imPort} on the virtual meta object
1097 /// associated with this variable's type.
1098 /// @param src The source string.
1099 /// @param priority The priority of the import. If the variable is already defined in a
1100 /// higher priority, nothing is done.
1101 /// @param escaper The \b StringEscaper to use for importing an escaped string. Defaults to
1102 /// \c nullptr which indicates that a programmatically defined C++ string is to
1103 /// be parsed. Usually, if a \alib{variables;ConfigurationPlugin} invokes this method
1104 /// it would pass its own suitable implementation here.
1105 ALIB_DLL
1106 void Import( const String& src, Priority priority,
1107 const StringEscaper* escaper= nullptr);
1108
1109
1110 /// Exports the contents of this variable to the given buffer.
1111 /// This is done by calling \alib{variables;VMeta::exPort} on the virtual meta object
1112 /// associated with this variable's type.
1113 ///
1114 /// @param dest The destination string. Must not be reset prior writing, but appended.
1115 /// @param escaper The \b StringEscaper to use for exporting a C++ string to a (probably)
1116 /// escaped string format. Defaults to \c nullptr which indicates that no
1117 /// conversion (aka 'escaping') has to be performed. Usually, if
1118 /// a \alib{variables;ConfigurationPlugin} invokes this method to write-back the
1119 /// contents of a variable, it would pass its own suitable implementation here.
1120 /// @return \p{dest} to allow concatenated operations.
1121 AString& Export(AString& dest, const StringEscaper* escaper= nullptr) const {
1122 StringEscaper nonEscaper;
1123 if( !escaper )
1124 escaper= &nonEscaper;
1125 getMeta()->exPort( Cursor::Value().data, GetConfiguration(), *escaper, dest );
1126 return dest;
1127 }
1128
1129 /// Returns a reference to the variable's value. To receive a value the variable has to be
1130 /// defined, which is either done, by
1131 /// - A provision of a default value with declaration,
1132 /// - A configuration plug-in like \alib{variables;CLIVariablesPlugin} or
1133 /// \alib{variables;EnvironmentVariablesPlugin},
1134 /// - Some bootstrap or other code entities like reading external configuration data from
1135 /// 3rd party sources,
1136 /// - or finally "hard coded" with method #Define.
1137 ///
1138 /// If this is not done, in debug-compilations an \ref alib_mod_assert "error is raised".
1139 /// In release-builds, it is defined (!) behavior: A default constructed value of \p{T} is
1140 /// returned.
1141 /// Hence, the whole concept of defining a variable and methods #IsDefined, etc. is
1142 /// rather a contract than a necessity. This is explained in section
1143 /// \ref alib_variables_definition of the Programmer's Manual of this \alibcamp.
1144 ///
1145 /// Template parameter \p{T} has to be specified
1146 /// in alignment with the declaration of the variable. It is the users responsibility to
1147 /// specify the right type, as internally a <c>reinterpret_cast</c> has to be performed.
1148 /// In other words, providing a wrong type is undefined behavior.
1149 ///
1150 /// In debug-compilations, an \ref alib_mod_assert "error is raised" if the type does not
1151 /// match the declaration.
1152 ///
1153 /// @tparam T The type to receive.
1154 /// @return A reference to the value of the variable.
1155 template<typename T> T& Get() {
1156 ALIB_ASSERT_ERROR( !Cursor::IsRoot(), "VARIABLES",
1157 "Requesting value from undeclared variable \"{}\"", this )
1158 ALIB_ASSERT_ERROR( IsDefined(), "VARIABLES",
1159 "Requesting value from undefined variable \"{}\".\n"
1160 "Use 'var.Define();' to mitigate this error.", this )
1161 ALIB_ASSERT_ERROR( getMeta()->dbgTypeID() == typeid(T), "VARIABLES",
1162 "Wrong variable type requested for variable: \"{}\".\n"
1163 " Stored : {}\n"
1164 " Requested: {}\n",
1165 this, &getMeta()->dbgTypeID(), &typeid(T) )
1166
1167 return Cursor::Value().data->As<T>();
1168 }
1169
1170 /// <c>const</c>-version of overloaded method.
1171 ///
1172 /// @tparam T The type to receive.
1173 /// @return A reference to the value of the variable.
1174 template<typename T> const T& Get() const {
1175 ALIB_ASSERT_ERROR( Cursor::Value().data != nullptr, "VARIABLES",
1176 "Requested value from unset variable: ", *this )
1177 ALIB_ASSERT_ERROR( IsDefined(), "VARIABLES",
1178 "Requesting value from undefined variable. Use 'var.Define();' to mitigate\n"
1179 "this error. Variable: ", *this )
1180 ALIB_ASSERT_ERROR( getMeta()->dbgTypeID() == typeid(T), "VARIABLES",
1181 "Wrong variable type requested for variable: \"{}\".\n"
1182 " Stored : {}\n"
1183 " Requested: {}\n",
1184 *this, getMeta()->dbgTypeID(), typeid(T) )
1185
1186 return Cursor::Value().data->As<T>();
1187 }
1188
1189 operator bool () { return Get<Bool >(); } ///< @return Calls and returns \ref Get "Get<Bool>()".
1190 operator integer () { return Get<integer >(); } ///< @return Calls and returns \ref Get "Get<integer>()".
1191 operator float () { return float(Get<double>()); } ///< @return Calls and returns \ref Get "Get<double>()" cast to \c float.
1192 operator double () { return Get<double >(); } ///< @return Calls and returns \ref Get "Get<double>()".
1193 operator const String& () { return Get<AStringPA>(); } ///< @return Calls and returns \ref Get "Get<AStringPA>()".
1194 operator const Substring () { return Get<AStringPA>(); } ///< @return Calls and returns \ref Get "Get<AStringPA>()".
1195
1196 bool GetBool() { return Get<Bool >(); } ///< @return Calls and returns \ref Get "Get<Bool>()".
1197 integer GetInt() { return Get<integer >(); } ///< @return Calls and returns \ref Get "Get<integer>()".
1198 float GetFloat() { return float(Get<double>()); } ///< @return Calls and returns \ref Get "Get<double>()" cast to \c float.
1199 double GetDouble() { return Get<double >(); } ///< @return Calls and returns \ref Get "Get<double>()".
1200 Box& GetBox() { return Get<Box >(); } ///< @return Calls and returns \ref Get "Get<AStringPA>()".
1201 AStringPA& GetString() { return Get<AStringPA>(); } ///< @return Calls and returns \ref Get "Get<AStringPA>()".
1202 StringVectorPA& GetStrings() { return Get<StringVectorPA>(); } ///< @return Calls and returns \ref Get "Get<StringVectorPA>()".
1203 String& GetString(int idx) { return Get<StringVectorPA>().at(size_t(idx)); } ///< @param idx The index of the requested string. @return Calls and returns \ref Get "Get<StringVectorPA>().Lines.at(idx)".
1204 int Size() { return int(Get<StringVectorPA>().size()); } ///< @return Calls and returns \ref Get "Get<StringVectorPA>().Lines.size()".
1205
1206 bool operator= (bool val) { return Get<Bool >()= val; } ///< Calls \ref Get "Get<Bool>()" and assigns \p{val}. @param val The value to assign. @return The \p{val} given.
1207 integer operator= (integer val) { return Get<integer >()= val; } ///< Calls \ref Get "Get<integer>()" and assigns \p{val}. @param val The value to assign. @return The \p{val} given.
1208 float operator= (float val) { Get<double>()= double(val); return val; } ///< Calls \ref Get "Get<double>()" and assigns \p{val}. @param val The value to assign. @return The \p{val} given.
1209 double operator= (double val) { return Get<double >()= val; } ///< Calls \ref Get "Get<double>()" and assigns \p{val}. @param val The value to assign. @return The \p{val} given.
1210 const String& operator= (const String& val) { return Get<AStringPA>().Reset(val); } ///< Calls \ref Get "Get<AStringPA>()" and resets the string to \p{val}. @param val The value to assign. @return The \p{val} given.
1211
1212
1213
1214 /// Convenience method. If #IsDefined returns \c true, the value of this variable is returned.
1215 /// Otherwise the variable gets defined with the given \p{priority} and \p{value} is imported.
1216 /// @param value The value to import in case the variable is not defined.
1217 /// @param priority The priority to set on import in case the variable is not defined.
1218 /// Defaults to \alib{variables;Priority;DefaultValues}.
1219 /// @return \c false if data of any priority is available in this variable, \c true if not.
1220 inline
1221 String& GetOrSetDefault( const String& value, Priority priority= Priority::DefaultValues ) {
1222 if(IsDefined())
1223 return Get<AStringPA>();
1224
1225 (void) Define(priority);
1226 return (Get<AStringPA>().Reset(value));
1227 }
1228
1229 /// Convenience method. If #IsDefined returns \c true, the value of this variable is returned.
1230 /// Otherwise the variable gets defined with the given \p{priority} and \p{value} is imported.
1231 /// @param value The value to import in case the variable is not defined.
1232 /// @param priority The priority to set on import in case the variable is not defined.
1233 /// Defaults to \alib{variables;Priority;DefaultValues}.
1234 /// @return \c false if data of any priority is available in this variable, \c true if not.
1235 inline
1236 bool GetOrSetDefault( bool value, Priority priority= Priority::DefaultValues ) {
1237 if(IsDefined())
1238 return Get<Bool>();
1239
1240 (void) Define(priority);
1241 return (Get<Bool>()= value);
1242 }
1243
1244 /// Convenience method. If #IsDefined returns \c true, the value of this variable is returned.
1245 /// Otherwise the variable gets defined with the given \p{priority} and \p{value} is imported.
1246 /// @param value The value to import in case the variable is not defined.
1247 /// @param priority The priority to set on import in case the variable is not defined.
1248 /// Defaults to \alib{variables;Priority;DefaultValues}.
1249 /// @return \c false if data of any priority is available in this variable, \c true if not.
1250 inline
1251 bool GetOrSetDefault( integer value, Priority priority= Priority::DefaultValues ) {
1252 if(IsDefined())
1253 return GetInt();
1254
1255 (void) Define(priority);
1256 return (Get<integer >()= value);
1257 }
1258
1259
1260}; // class Variable
1261
1262//==================================================================================================
1263// Definition of inline Configuration methods that deal with class Variable
1264//==================================================================================================
1265#if !DOXYGEN
1266template<typename TEnum>
1267requires ( EnumRecords<TEnum>::template AreOfType<Declaration>() )
1269 for( auto recordIt= EnumRecords<TEnum>::begin()
1270 ; recordIt!= EnumRecords<TEnum>::end ()
1271 ; ++ recordIt )
1272 {
1273 const Declaration* decl= Declaration::Get( recordIt.Enum() );
1274 if(decl->EnumElementName.IndexOf('%') < 0)
1275 Variable(*this, decl);
1276} }
1277#endif
1278
1279/// Utility type which implements \alib{monomem;TSharedMonoVal} with class
1280/// \alib{variables;Configuration}.
1281/// The result of combining both is an automatic pointer to a \b %Configuration that is
1282/// "self-contained" in the first buffer of a \alib{MonoAllocator} together with the allocator
1283/// itself.
1284/// All configuration variables are deleted and all associated memory is freed when the last copy
1285/// of the pointer goes out of scope.
1286///
1287/// Along with the \b Configuration, this shared object includes a \alib{threads;SharedLock}.
1288/// See chapter \ref alib_contmono_smv_locking of the Programmer's Manual of module \alib_monomem
1289/// for further information on how to protect the contents of this type against
1290/// thread-racing-conditions.
1291///
1292/// @tparam TLock The lock type passed to the template parameter of parent type
1293/// \alib{monomem;TSharedMonoVal} with the same name.<br>
1294/// With the inclusion of module \alib_threads in the \alibbuild, the type-alias
1295/// #alib::SharedConfiguration chooses type \alib{threads;SharedLock}.<br>
1296/// Otherwise, in case \alib is compiled without threading support, the alias chooses
1297/// <c>void</c>.<br>
1298/// If it is assured that no racing-conditions occur with shared instances in
1299/// multithreaded software, the using code may pass <c>void</c> here as well.
1300template<typename TLock>
1301class TSharedConfiguration : public monomem::TSharedMonoVal<Configuration, HeapAllocator, TLock>
1302{
1303 /// Exposed shortcut to the base type.
1305
1306 public:
1307 /// Constructs an empty instance, hence a cleared automatic pointer.
1309
1310 /// Constructs an empty instance from \c std::nullptr.
1311 /// This constructor is necessary to allow assignment of \c nullptr to values of this type,
1312 /// which clears the automatic pointer.
1313 TSharedConfiguration(std::nullptr_t) noexcept {}
1314
1315 /// Constructor.
1316 /// Calls the constructor of parent \b TSharedMonoVal and then invokes
1317 /// \alib{monomem;TSharedMonoVal::ConstructT} passing the mono allocator that the
1318 /// parent creates this instance in.<br>
1319 /// Furthermore calls DbgCriticalSections to enable assertions to locked usage.
1320 /// @param initialBufferSizeInKB The initial size of memory buffers.
1321 /// Passed to the allocator given with parent class
1322 /// \alib{monomem;TSharedMonoVal}.
1323 /// @param bufferGrowthInPercent Optional growth factor in percent, applied to the buffer size
1324 /// with each next buffer allocation.
1325 /// Should be set to \c 200, to double the size with each
1326 /// allocation.
1327 /// Defaults to \c 200.
1328 /// Passed to the allocator given with parent class
1329 /// \alib{monomem;TSharedMonoVal}.
1330 /// @param createDefaults Determines if default plug-ins are to be created.
1331 /// Defaults to \c Yes.
1332 TSharedConfiguration( size_t initialBufferSizeInKB,
1333 unsigned bufferGrowthInPercent = 200,
1335 : Base(initialBufferSizeInKB, bufferGrowthInPercent) {
1336 Base::ConstructT( Base::GetAllocator(), createDefaults );
1338 ALIB_DBG(Base::GetAllocator().DbgName= "Configuration";)
1339
1340 }
1341
1342 /// Defaulted copy-constructor.
1344
1345 /// Defaulted copy-assignment operator.
1346 /// @return A reference to <c>this</c>.
1348
1349
1350 /// Destructor.
1351 /// Calls #DbgCriticalSections to stop checking the integrated \p{TLock}.
1353
1354 #if DOXYGEN
1355 /// Enables or disables critical section checks between the contained \p{T} and the likewise
1356 /// contained \p{TLock}.<br>
1357 /// In case \p{TLock} equals <c>void</c> or if symbol \ref ALIB_DEBUG_CRITICAL_SECTIONS is not
1358 /// set, this method is empty (and its use is optimized out).
1359 /// @param onOff The switch.
1361 #else
1362 template<typename TRequires= typename Base::LockType>
1363 requires (!std::same_as<TRequires, void>)
1364 void DbgCriticalSections(lang::Switch onOff) {
1365 #if ALIB_DEBUG_CRITICAL_SECTIONS
1366 if ( !Base::IsNulled() ) {
1367 if( onOff == lang::Switch::On ) Base::Self().NodeTable().dcs.DCSLock= &Base::GetLock();
1368 else Base::Self().NodeTable().dcs.DCSLock= nullptr;
1369 }
1370 #else
1371 (void) onOff;
1372 #endif
1373 }
1374
1375 template<typename TRequires= typename Base::LockType>
1376 requires std::same_as<TRequires, void>
1377 void DbgCriticalSections(lang::Switch) {}
1378 #endif
1379
1380 /// Clears all data, plugins, type-registrations, etc., from this configuration.
1381 /// Then this object is reinitialized to its constructor defaults.<br>
1382 /// The \b MonoAllocator of the parent class is likewise reset.
1383 ///
1384 /// All shared instances remain valid (while, of course, their content is likewise reset).
1385 /// @param createDefaults Determines if default plug-ins are to be created.
1386 /// Defaults to \c Yes.
1392
1393
1394
1395}; //class Configuration
1396
1397
1398} // namespace alib[::config]
1399
1400
1401using Configuration = variables::Configuration; ///< Type alias in namespace \b alib.
1402#if !ALIB_SINGLE_THREADED || DOXYGEN
1403using SharedConfiguration = variables::TSharedConfiguration<SharedLock>; ///< Type alias in namespace \b alib.
1404#else
1406#endif
1407using ConfigurationListener= variables::ConfigurationListener; ///< Type alias in namespace \b alib.
1408using Variable = variables::Variable; ///< Type alias in namespace \b alib.
1409
1410} // namespace [alib]
1411
1412
1413
1414//##################################################################################################
1415// struct AppendableTraits<Variable>
1416//##################################################################################################
1417
1418// Faking all template specializations of namespace strings for doxygen into namespace
1419// strings::APPENDABLES to keep the documentation of namespace string clean!
1420namespace alib::strings {
1421#if DOXYGEN
1422namespace APPENDABLES {
1423#endif
1424
1425/// Specialization of functor \alib{strings;AppendableTraits} for type <c>Variable</c>.
1427{
1428 /// Writes the variable name represented by the given configuration cursor to the given AString.
1429 /// @param target The \b NAString that \b Append was invoked on.
1430 /// @param variable The variable (or section).
1432};
1433
1434/// Specialization of functor \alib{strings;AppendableTraits} for type <c>Variable</c>.
1436{
1437 /// Writes the variable name represented by the given configuration cursor to the given AString.
1438 /// @param target The \b WAString that \b Append was invoked on.
1439 /// @param variable The variable (or section).
1441};
1442
1443#if DOXYGEN
1444} // namespace alib::strings[APPENDABLES]
1445#endif
1446} // namespace [alib::strings]
1447
StringTree(AllocatorType &allocator, CharacterType pathSeparator)
bool IsNulled() const noexcept
void ConstructT(TArgs &&... args)
TLock & GetLock() const noexcept
void Reset(TArgs &&... args)
AllocatorType & GetAllocator() noexcept
integer IndexOf(TChar needle, integer startIdx=0) const
Definition string.inl:815
constexpr bool IsNotEmpty() const
Definition string.inl:369
virtual String Name() const =0
virtual const StringEscaper & GetEscaper() const
virtual ~ConfigurationPlugin()
Virtual Destructor.
virtual ALIB_DLL bool Get(const String &name, AString &target)=0
HashTable< MonoAllocator, ValueDescriptorTypes, std::hash< String >, std::equal_to< String >, lang::Caching::Enabled, Recycling::None > TypesHashTable
A hashtable for the registered types. Key is the type name, value is the VMeta singleton.
ALIB_DLL bool DeletePath(const String &path)
StringTree< MonoAllocator, detail::Entry, detail::ConfigNodeHandler > base
Alias to the StringTree-parent.
ALIB_DLL void notifyListeners(int event, const Variable &variable, const String &variablePath, Priority previousPriority)
ALIB_DLL AString & WriteBooleanToken(bool value, int8_t index, AString &dest)
ConfigurationPlugin * cliPlugin
A default plugin created and inserted with construction.
ListMA< std::pair< Token, Token >, Recycling::None > BooleanTokens
void PresetImportString(const String &name, const String &value, StringEscaper *escaper, Priority priority=Priority::DefaultValues)
TypesHashTable types
A hashtable for the registered types. Key is the type name, value is the VMeta singleton.
ALIB_DLL const Declaration * StoreDeclaration(const Declaration *orig, const Box &replacements)
void MonitorPath(lang::ContainerOp insertOrRemove, ConfigurationListener *listener, ConfigurationListener::Event event, const Configuration::Cursor &cursor)
void MonitorPathPrefix(lang::ContainerOp insertOrRemove, ConfigurationListener *listener, ConfigurationListener::Event event, const String &pathPrefix)
ALIB_DLL int MonitorStop(ConfigurationListener *listener)
void PresetImportString(const String &name, const String &value, Priority priority=Priority::DefaultValues)
void MonitorVariablesByName(lang::ContainerOp insertOrRemove, ConfigurationListener *listener, ConfigurationListener::Event event, const String &variableName)
ConfigurationPlugin * environmentPlugin
A default plugin created and inserted with construction.
friend class Variable
Type alias in namespace alib.
void MonitorDistinctVariable(lang::ContainerOp insertOrRemove, ConfigurationListener *listener, ConfigurationListener::Event event, const Variable &variable)
ListMA< ListenerRecord > listeners
The list of registered listeners.
ALIB_DLL ~Configuration()
Destructor.
ALIB_DLL void presetImportString(const String &name, const String &value, const StringEscaper *escaper, Priority priority)
void MonitorPathSubstring(lang::ContainerOp insertOrRemove, ConfigurationListener *listener, ConfigurationListener::Event event, const String &pathSubstring)
ALIB_DLL Configuration(MonoAllocator &allocator, lang::CreateDefaults createDefaults=lang::CreateDefaults::Yes)
ALIB_DLL std::pair< bool, int8_t > ParseBooleanToken(const String &src)
StringEscaperStandard Escaper
ALIB_DLL void registerListener(ConfigurationListener *listener, lang::ContainerOp insertOrRemove, int event, const Variable *variable, const StringTree::Cursor *subTree, const String &variableName, const String &pathPrefix, const String &pathSubstring)
HashTable< MonoAllocator, ValueDescriptorRD, std::hash< String >, std::equal_to< String >, lang::Caching::Disabled, Recycling::None > RDHashTable
static const Declaration * Get(TEnum element)
const String & Name() const
monomem::TSharedMonoVal< Configuration, HeapAllocator, TLock > Base
Exposed shortcut to the base type.
TSharedConfiguration(std::nullptr_t) noexcept
TSharedConfiguration & operator=(const TSharedConfiguration &)=default
TSharedConfiguration(const TSharedConfiguration &)=default
Defaulted copy-constructor.
void Reset(lang::CreateDefaults createDefaults=lang::CreateDefaults::Yes)
TSharedConfiguration()=default
Constructs an empty instance, hence a cleared automatic pointer.
TSharedConfiguration(size_t initialBufferSizeInKB, unsigned bufferGrowthInPercent=200, lang::CreateDefaults createDefaults=lang::CreateDefaults::Yes)
ALIB_DLL bool Define(Priority requestedPriority=Priority::Standard)
Definition variable.cpp:261
bool GetOrSetDefault(bool value, Priority priority=Priority::DefaultValues)
Variable(Configuration &cfg, const Declaration *decl)
AString & Export(AString &dest, const StringEscaper *escaper=nullptr) const
AString & Name(AString &target) const
Variable & Declare(TEnum Enum, const Box &replacements)
void create(const String &typeName, const String &defaultValue)
Definition variable.cpp:110
const Cursor & AsCursor() const
Variable(Configuration &cfg, TEnum Enum, const Box replacements)
String & GetOrSetDefault(const String &value, Priority priority=Priority::DefaultValues)
bool Try(const String &name)
Variable(Configuration &cfg, const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
ALIB_DLL Variable & Declare(const String &name, const String &typeName, const String &defaultValue=NULL_STRING)
Definition variable.cpp:187
Variable(const Cursor &cursor)
const Declaration * GetDeclaration() const
Configuration::Cursor Cursor
Variable(Configuration &cfg, TEnum Enum)
Variable(Configuration &cfg)
Variable(const Cursor &cursor, const String &typeName, const String &defaultValue=NULL_STRING)
StringVectorPA & GetStrings()
Configuration & GetConfiguration() const
bool GetOrSetDefault(integer value, Priority priority=Priority::DefaultValues)
const String & substitute(const String &importString, AString &buf, const StringEscaper *escaper)
Definition variable.cpp:26
Variable & Declare(TEnum Enum)
Entry(Entry &&)=delete
Deleted move-constructor.
VMeta * meta
The virtual handler instance for this variable.
const Declaration * declaration
Entry()
Defaulted default constructor.
VDATA * data
The list hook of values.
Priority priority
The priority level of this data element.
Entry(const Entry &)=delete
Deleted copy-constructor.
#define ALIB_DLL
Definition alib.inl:503
#define A_CHAR(STR)
#define ALIB_ASSERT_WARNING(cond, domain,...)
Definition alib.inl:1067
#define ALIB_BOXING_VTABLE_DECLARE(TMapped, Identifier)
#define ALIB_EXPORT
Definition alib.inl:497
#define ALIB_DBG(...)
Definition alib.inl:853
#define ALIB_ASSERT_ERROR(cond, domain,...)
Definition alib.inl:1066
ContainerOp
Denotes standard container operations.
Switch
Denotes if sth. is switched on or off.
@ On
Switch it on, switched on, etc.
@ Off
Switch it off, switched off, etc.
@ Keep
Chooses not no clear existing data.
CreateDefaults
Denotes whether default entities should be created or not.
@ Yes
Create default values.
@ Enabled
Caching is enabled.
@ Disabled
Caching is disabled.
VData< void * > VDATA
Definition vmeta.inl:45
containers::detail::StringTreeBase< MonoAllocator, Entry, ConfigNodeHandler, Recycling::Private > TTree
A shortcut to the base class of the base class of class Configuration.
strings::util::StringEscaper StringEscaper
Type alias in namespace alib.
Definition escaper.inl:183
variables::Declaration Declaration
Type alias in namespace alib.
constexpr String NULL_STRING
A nulled string of the default character type.
Definition string.inl:2271
strings::TAString< character, lang::HeapAllocator > AString
Type alias in namespace alib.
variables::Variable Variable
Type alias in namespace alib.
containers::HashTable< TAllocator, TValueDescriptor, THash, TEqual, THashCaching, TRecycling > HashTable
Type alias in namespace alib. See type definition alib::containers::HashSet.
containers::List< T, MonoAllocator, TRecycling > ListMA
Type alias in namespace alib.
Definition list.inl:693
variables::ConfigurationListener ConfigurationListener
Type alias in namespace alib.
variables::Configuration Configuration
Type alias in namespace alib.
strings::TCString< character > CString
Type alias in namespace alib.
Definition cstring.inl:475
characters::wchar wchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.inl:149
monomem::TPoolAllocator< MonoAllocator > PoolAllocator
strings::TNumberFormat< character > NumberFormat
Type alias in namespace alib.
strings::util::TStringVector< character, PoolAllocator > StringVectorPA
Type alias in namespace alib.
variables::TSharedConfiguration< SharedLock > SharedConfiguration
Type alias in namespace alib.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
enumrecords::EnumRecords< TEnum > EnumRecords
Type alias in namespace alib.
Definition records.inl:482
characters::nchar nchar
Type alias in namespace alib.
boxing::Enum Enum
Type alias in namespace alib.
Definition enum.inl:192
boxing::Box Box
Type alias in namespace alib.
Definition box.inl:1149
strings::TString< character > String
Type alias in namespace alib.
Definition string.inl:2189
strings::util::StringEscaperStandard StringEscaperStandard
Type alias in namespace alib.
Definition escaper.inl:186
strings::TAString< character, PoolAllocator > AStringPA
Type alias in namespace alib.
characters::character character
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
String EnumElementName
The name of the enum element.
Definition records.inl:430
static ForwardIterator begin()
Definition records.inl:378
static constexpr ForwardIterator end()
Definition records.inl:386
ALIB_DLL void operator()(TAString< nchar, lang::HeapAllocator > &target, const variables::Variable &variable)
ALIB_DLL void operator()(TAString< wchar, lang::HeapAllocator > &target, const variables::Variable &variable)
virtual ~ConfigurationListener()
Virtual destructor.
virtual void Notify(const Variable &variable, Event event, Priority previousPriority)=0
Event
The type of change that imposes the notification of a listener.
@ Definition
A variable was defined or re-defined with the same or a higher priority.
@ Creation
A variable was declared for the first time.
Record used to manage registered listeners.
ConstCursorHandle subTree
If given, the subtree of variables to listen to.
ConfigurationListener * listener
The listener to register or dispose.
AStringPA variableName
If given, the variable's name to listen to.
AStringPA pathPrefix
If given, the start string of the file path to monitor.
ConstCursorHandle variable
If given, the variable to listen to.
Helper-struct used for implementing field replacementDeclarations.
const String & Key(const Declaration *src) const
Helper-struct used for implementing field types.
virtual String typeName() const =0
static ALIB_DLL void FreeNode(TTree::Node &node, TTree &tree)
static void InitializeNode(TTree::Node &node, TTree &tree)
character CharacterType
The character type that the StringTree uses for child name and path strings.
strings::TString< character > NameStringType