ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
config/plugins.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_config of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_CONFIG_PLUGINS
9#define HPP_ALIB_CONFIG_PLUGINS 1
10
11#if !defined (HPP_ALIB_CONFIG_VARIABLE)
13#endif
14
15#if !defined (HPP_ALIB_STRINGS_SUBSTRING)
17#endif
18
19#if !defined (_GLIBCXX_VECTOR) && !defined(_VECTOR_)
20# include <vector>
21#endif
22
23namespace alib { namespace config {
24
25
26// #################################################################################################
27// class XTernalizer
28// #################################################################################################
29
30/** ************************************************************************************************
31 * This virtual class is used by classes derived from
32 * \ref alib::config::ConfigurationPlugin "ConfigurationPlugin"
33 * to convert external string to internal values and vice versa, and for parsing lists of values
34 * from an external string.
35 *
36 * Class \b %ConfigurationPlugin owns a default object with field
37 * \alib{config::ConfigurationPlugin;defaultStringConverter} which by default points to field
38 * \alib{config::ConfigurationPlugin;StringConverter}.
39 *
40 * \note
41 * Replacing the converters is deemed to be an advanced usage of \alib. Consult the source code
42 * for detailed information about how to implement an application specific converter.
43 *
44 * This default implementation proceeds as follows:
45 * - "Externalizing" a value:
46 * - Value is surrounded by quotes if it starts or ends with spaces or if it includes
47 * the delimiter token.
48 * - A few characters are escaped using \c '\\'. Those are
49 * \c \\n, \c \\r, \c \\t , \c \\a, \c \\b, \c \\v, \c \\f, \c \\e and also
50 * the double quotation marks \c \\" and the backslash itself (\c \\\\‍).
51 *
52 * - "Internalizing" a value:
53 * - If (non-escaped) quote \c " characters are found, those are removed and whitespaces
54 * within such quotes are kept.
55 * - Escaped characters are converted to their original value.
56 *
57 * - Loading variables from external strings:
58 * - If provided variable has a valid delimiter set, this character is used to tokenize
59 * the external string.
60 * - Values are trimmed, unless quoted. Quotes characters themselves are removed.
61 * - Delimiters found within a pair of quotes are ignored.
62 * - Each value found is internalized separately
63 **************************************************************************************************/
65{
66 public:
67
68 /** ****************************************************************************************
69 * Virtual destructor
70 *****************************************************************************************/
71 virtual ~XTernalizer() {}
72
73 /** ********************************************************************************************
74 * If field \alib{config;Variable::Delim} is <c>'\0'</c>, just invokes #InternalizeValue.
75 * Otherwise, parses values using the delimiter. Quotes are removed and parts within quotes
76 * are kept as is. Also, delimiters in quotes are ignored.
77 *
78 * @param variable The destination variable.
79 * @param src The source string
80 **********************************************************************************************/
82 virtual
83 void LoadFromString( Variable& variable, const String& src );
84
85 /** ********************************************************************************************
86 * Trims \p{src}, removes surrounding quotes and , un-escapes characters.
87 *
88 * @param src The source string
89 * @param dest The destination string
90 **********************************************************************************************/
92 virtual
93 void InternalizeValue( const String& src, AString& dest );
94
95 /** ********************************************************************************************
96 * Converts the given \p{src} string to an external representation.
97 *
98 * @param src The source string
99 * @param dest The destination string
100 * @param delim If this character is found in the string, the value is quoted
101 **********************************************************************************************/
103 virtual
104 void ExternalizeValue( const String& src, AString& dest, character delim );
105};
106
107/** ************************************************************************************************
108 * Abstract class that represents a plug in for class
109 * \ref alib::config::Configuration "Configuration"
110 * to provide configuration data from specific configuration data source.
111 *
112 * See documentation of namespace #alib::config for more information on \alib
113 * external configuration variables.
114 *
115 * The plug-in also may have the ability to write data. The default implementation for writing
116 * configuration data returns constant false, indicating that this plug-in never writes
117 * anything (e.g. command line parameter plug-in, environment variable plug-in).
118 *
119 * Category and Variable names are character case insensitive for the plug-ins predefined
120 * with \alib.
121 * It is recommended to ignore character case in custom specializations of this class
122 * as well.
123 **************************************************************************************************/
125{
126 // #############################################################################################
127 // internal fields
128 // #############################################################################################
129 protected:
130 /** The default external string converter. */
132
133
134 // #############################################################################################
135 // public fields
136 // #############################################################################################
137 public:
138 /** The external string converter.
139 * By default this points to field #defaultStringConverter. */
141
142 // #############################################################################################
143 // protected constructor, public destructor
144 // #############################################################################################
145 protected:
146 /** ****************************************************************************************
147 * Constructor which is protected, as this is an abstract class.
148 ******************************************************************************************/
153
154 /** ****************************************************************************************
155 * Virtual Destructor.
156 ******************************************************************************************/
157 public:
159
160 // #############################################################################################
161 // abstract/virtual interface
162 // #############################################################################################
163 public:
164 /** ****************************************************************************************
165 * Abstract method to return a plug-in name. The name may be used in human readable
166 * output, e.g. log-files or exception messages to tell a user for example, which plug-in
167 * loaded a variable containing a syntax error.
168 * @return The name of the plug-in.
169 ******************************************************************************************/
170 virtual String Name() const =0;
171
172
173 /** ****************************************************************************************
174 * Abstract method that has to be overwritten by descendants.
175 * Searches and by default retrieves the value of a configuration variable.
176 * If \p{searchOnly} is \c true, then the variable value is not read.
177 *
178 * @param variable The variable to retrieve.
179 * @param searchOnly If \c true, the variable must not be set. Defaults to \c false.
180 * @return \c true if variable was found within this configuration source, \c false if not.
181 ******************************************************************************************/
183 virtual bool Load( Variable& variable, bool searchOnly= false ) =0;
184
185 /** ****************************************************************************************
186 * Writes a variable to the configuration.
187 * This default implementation just returns \c false. If this method is not overwritten
188 * in descendants, those descendants are not designed to write data.
189 *
190 * @param variable The variable to store.
191 *
192 * @return \c true if the variable was written, \c false if not which typically indicates
193 * that this plug-in is not able to write values.
194 ******************************************************************************************/
195 virtual bool Store( Variable& variable )
196 {
197 (void) variable;
198 return false;
199 }
200
201
202 /** ****************************************************************************************
203 * Convenience method that parses the values from the given string using field
204 * #StringConverter and then invokes \ref Store(Variable&) "Store".
205 *
206 * @param variable The variable to store.
207 * @param externalizedValue The value to parse into the variable before storing
208 *
209 * @return \c true if the variable was written, \c false if not which typically indicates
210 * that this plug-in is not able to write values.
211 ******************************************************************************************/
212 virtual bool Store( Variable& variable, const String& externalizedValue )
213 {
214 if( externalizedValue.IsNotNull() )
215 StringConverter->LoadFromString( variable, externalizedValue );
216 return Store( variable );
217 }
218
219 // #############################################################################################
220 // Iteration.
221 // #############################################################################################
222 public:
223 /** ****************************************************************************************
224 * Iterator interface class returned by #GetIterator.
225 *
226 * \note Method \alib{config;Configuration::GetIterator} returns an iterator that allows
227 * to iterate across all variables of a section found in all plug-ins
228 ******************************************************************************************/
230 {
231 public:
232
233 /** Virtual destructor. */
234 virtual ~Iterator()
235 {}
236
237 /**
238 * Searches and loads the next variable from the iterated section. On success, the
239 * variable data is stored in \p{variable}.
240 *
241 * @param variable The variable to load from this plug-in on success.
242 * @return \c true, if a next variable was found. \c false otherwise.
243 */
244 virtual bool Next( Variable& variable ) = 0;
245 };
246
247 /** ****************************************************************************************
248 * Creates an iterator object to return all variables within a section.
249 * The iterator object returned, needs to be deleted by the caller.
250 *
251 * If a plug-in can not perform iteration, it will return \c nullptr. This is for example
252 * true for plug-in class \alib{config;Environment}.
253 *
254 * \note Method \alib{config;Configuration::GetIterator} returns an iterator that allows
255 * to iterate across all variables of a section found in all plug-ins
256 *
257 * @param sectionName The name of the section to iterate.
258 *
259 * @returns The iterator requested or \c nullptr if the plug-in does not support section
260 * iteration.
261 ******************************************************************************************/
262 virtual Iterator* GetIterator( const String& sectionName )
263 {
264 (void) sectionName;
265 return nullptr;
266 }
267};
268
269
270class CLIArgs;
271
272/**
273 * Internal details of namespace #alib::config.
274 */
275namespace detail
276{
277 /**
278 * Internal friend function of \alib{config;CLIArgs} used for iteration.
279 * @param cliArgs The command line args plug-in.
280 * @param nextArgNo The argument to continue the search with.
281 * @param sectionName The name of the section to search for.
282 * @param variable The variable to load
283 * @return \c true on success, otherwise \c false.
284 */
285 bool nextCLIArg( CLIArgs& cliArgs, size_t& nextArgNo, const String& sectionName,
286 Variable& variable );
287}
288
289/** ************************************************************************************************
290 * Specialization of abstract interface class #ConfigurationPlugin, which takes all command line
291 * parameters in the constructor and reads variable values from those parameters on request.
292 * Its priority value usually is \alib{config;Priorities;Priorities::CLI}, which is higher
293 * than all other default plug-ins provided.
294 *
295 * Variable categories are used as a prefix together with an underscore \c '_'.
296 * This means, if variable <em>LOCALE</em> in category <em>ALIB</em> is accessed, the command line
297 * parameter <em>--ALIB_LOCALE=xyz</em> is read.
298 *
299 * Category and Variable names are insensitive in respect to character case.
300 *
301 * Command line variables may be passed with either one hyphen ('-') or two ('--').
302 * Both are accepted.
303 *
304 * An application can specify one or more "default categories" by adding their string names to
305 * public field #DefaultCategories. Variables of these categories are recognized by the plug-in
306 * also when given without the prefix of category name and underscore \c '_'.
307 *
308 * Furthermore, an application may set public field #AllowedMinimumShortCut to a value greater than
309 * \c 0. In this case, the plug-in recognizes variables in CLI arguments already when at least
310 * this amount of characters is provided. In other words, when reading an argument as many
311 * characters of the variable name as possible are 'consumed' and if a minimum number is given with
312 * #AllowedMinimumShortCut, such minimum is sufficient. If the remaining part of the argument
313 * string is either empty or continues with an equal sign \c '=', then the variable is recognized
314 * (with an empty value or the value after the equal sign).<br>
315 * Fields #AllowedMinimumShortCut and #DefaultCategories may also be used in combination.
316 *
317 * ## Friends ##
318 * class \alib{config;detail::nextCLIArg} (Used for implementation of iterator.)
319 **************************************************************************************************/
321{
322 #if !defined(ALIB_DOX)
323 // Friend detail function used for implementation of iterator.
324 friend bool detail::nextCLIArg( CLIArgs&, size_t&, const String&, Variable&);
325 #endif
326
327 protected:
328 size_t argCount = 0; ///< The number of command line arguments
329 const void** argVector = nullptr; ///< The list of command line arguments
330 bool wArgs = false; ///< Determines if argv is of type '<em>wchar **</em>'
331 ///< or '<em>nchar **</em>'
332
333 public:
334
335 /**
336 * If any value is added to this vector, its values are used as the source of command line
337 * arguments instead of using fields #argCount and #argVector.<br>
338 * This mechanic provides an alternative method to set the command line argument list.
339 *
340 * Applications that have a dedicated (more sophisticated) CLI interface which performs
341 * more complex processing of CLI arguments, may collect any unrecognized
342 * CLI argument here to be duly recognized as a configuration variable instead
343 *
344 */
345 std::vector<AString> AlternativeArgs;
346
347 /**
348 * An application can specify one or more "default categories" by adding the category names
349 * here. Variables of these categories are recognized by the plug-in
350 * also when given without the prefix of <c>category_</c>.
351 *
352 * \note This list uses the global allocator.
353 * Additions may only be made during bootstrap.
354 */
355 std::vector<AString> DefaultCategories;
356
357 /**
358 * If this field is set to a value greater than \c 0, this plug-in recognizes variables in
359 * CLI arguments already when at least this amount of characters is provided.
360 * If the remaining part of the argument string is either empty or continues with an equal
361 * sign \c '=', then the variable is recognized.
362 */
364
365 /** ****************************************************************************************
366 * Constructor. After creation, method #SetArgs should be called to equip this instance
367 * with the command line arguments.
368 ******************************************************************************************/
371 {}
372
373 /** ****************************************************************************************
374 * Virtual Destructor.
375 ******************************************************************************************/
376 virtual ~CLIArgs() override {}
377
378 /** ****************************************************************************************
379 * Sets the command line argument list. Needs to be called once after construction.
380 * Should not be invoked directly. Rather use method
381 * \alib{config;Configuration::SetCommandLineArgs}.
382 *
383 *\note
384 * In standard application scenarios, this method is invoked with corresponding
385 * module initialization during \ref alib_manual_bootstrapping "library bootstrap".
386 *
387 * <p>
388 *\note On the Windows platform, the Microsoft compiler provides the global variables
389 * <em>__argc</em> and <em>__argv</em> (respectively <em>__wargv</em> for wide
390 * character binaries. These variables a can be used if this method is invoked
391 * outside of the <em>main()</em> method.
392 *
393 * @param argc The number of arguments in argv
394 * @param argv The list of command line arguments.
395 * @param areWideChar If \c true, parameter \p{argv} is of type <c>wchar_t **</c>',
396 * otherwise of type <c>char **</c>.
397 * Defaults to \c false.
398 ******************************************************************************************/
399 void SetArgs( int argc, const void** argv= nullptr, bool areWideChar= false )
400 {
401 this->argCount= static_cast<size_t>( argc );
402 this->argVector= argv;
403 this->wArgs= areWideChar;
404 }
405
406 /** ****************************************************************************************
407 * Return the plug-in name, in this case, we read resource variable "CfgPlgCLI".
408 * @return The name of the plug-in.
409 ******************************************************************************************/
411 virtual String Name() const override;
412
413 /** ****************************************************************************************
414 * Searches the variable in the command line parameters.
415 *
416 * @param variable The variable to retrieve.
417 * @param searchOnly If \c true, the variable is not set. Defaults to \c false.
418 * @return \c true if variable was found, \c false if not.
419 ******************************************************************************************/
421 virtual bool Load( Variable& variable, bool searchOnly= false ) override;
422
423 /** ****************************************************************************************
424 * Creates an iterator object to return all variables within a section.
425 *
426 * The iterator object returned, needs to be deleted by the caller.
427 *
428 * \note Method \alib{config;Configuration::GetIterator} returns an iterator that allows
429 * to iterate across all variables of a section found in all plug-ins
430 *
431 * @param sectionName The name of the section to iterate.
432 *
433 * @returns The iterator requested.
434 ******************************************************************************************/
436 virtual Iterator* GetIterator( const String& sectionName ) override;
437};
438
439/** ************************************************************************************************
440 * Specialization of abstract interface class #ConfigurationPlugin, retrieves configuration
441 * data from the system environment.
442 *
443 * Its priority value usually is \alib{config;Priorities;Priorities::Environment}, which is higher
444 * than \alib{config;Priorities;Priorities::Standard} but lower than \alib{config;Priorities;Priorities::CLI}.
445 *
446 * Variable categories are used as a prefix together with an underscore '_'.
447 * This means, if variable <em>LOCALE</em> in category <em>ALIB</em> is accessed, the environment
448 * variable <em>ALIB_LOCALE</em> is read.
449 *
450 * Category and Variable names are insensitive in respect to character case.
451**************************************************************************************************/
453{
454 protected:
455
456 public:
457
458 /** ****************************************************************************************
459 * Constructor.
460 ******************************************************************************************/
461 Environment();
462
463 /** ****************************************************************************************
464 * Virtual Destructor.
465 ******************************************************************************************/
466 virtual ~Environment() override {}
467
468 /** ****************************************************************************************
469 * Return the plug-in name, in this case, we read resource variable CfgPlgEnv.
470 * @return The name of the plug-in.
471 ******************************************************************************************/
473 virtual String Name() const override;
474
475 /** ****************************************************************************************
476 * Searches the variable in the environment.
477 *
478 * @param variable The variable to retrieve.
479 * @param searchOnly If \c true, the variable is not set. Defaults to \c false.
480 * @return \c true if variable was found, \c false if not.
481 ******************************************************************************************/
482 ALIB_API virtual bool Load( Variable& variable, bool searchOnly= false ) override;
483};
484
485}} // namespace [alib::config]
486
487#endif // HPP_ALIB_CONFIG_PLUGINS
virtual ~CLIArgs() override
size_t argCount
The number of command line arguments.
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false) override
Definition plugins.cpp:178
const void ** argVector
The list of command line arguments.
virtual ALIB_API Iterator * GetIterator(const String &sectionName) override
virtual ALIB_API String Name() const override
Definition plugins.cpp:173
std::vector< AString > AlternativeArgs
std::vector< AString > DefaultCategories
void SetArgs(int argc, const void **argv=nullptr, bool areWideChar=false)
virtual bool Next(Variable &variable)=0
virtual bool Store(Variable &variable, const String &externalizedValue)
virtual bool Store(Variable &variable)
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false)=0
virtual String Name() const =0
virtual Iterator * GetIterator(const String &sectionName)
virtual ALIB_API bool Load(Variable &variable, bool searchOnly=false) override
Definition plugins.cpp:421
virtual ALIB_API String Name() const override
Definition plugins.cpp:416
virtual ~Environment() override
virtual ALIB_API void ExternalizeValue(const String &src, AString &dest, character delim)
Definition plugins.cpp:76
virtual ALIB_API void InternalizeValue(const String &src, AString &dest)
Definition plugins.cpp:32
virtual ALIB_API void LoadFromString(Variable &variable, const String &src)
Definition plugins.cpp:112
constexpr bool IsNotNull() const
Definition string.hpp:402
#define ALIB_API
Definition alib.hpp:538
bool nextCLIArg(CLIArgs &cliArgs, size_t &nextArgNo, const String &sectionName, Variable &variable)
Definition alib.cpp:57
characters::character character
Type alias in namespace alib.