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