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