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