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