Line data Source code
1 : /** \file appConfigurator.hpp
2 : * \author Jared R. Males
3 : * \brief An application configuration manager
4 : *
5 : * \ingroup mxApp_files
6 : *
7 : */
8 :
9 : //***********************************************************************//
10 : // Copyright 2015, 2016, 2017, 2018 Jared R. Males (jaredmales@gmail.com)
11 : //
12 : // This file is part of mxlib.
13 : //
14 : // mxlib is free software: you can redistribute it and/or modify
15 : // it under the terms of the GNU General Public License as published by
16 : // the Free Software Foundation, either version 3 of the License, or
17 : // (at your option) any later version.
18 : //
19 : // mxlib is distributed in the hope that it will be useful,
20 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
21 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 : // GNU General Public License for more details.
23 : //
24 : // You should have received a copy of the GNU General Public License
25 : // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
26 : //***********************************************************************//
27 :
28 : #ifndef app_appConfigurator_hpp
29 : #define app_appConfigurator_hpp
30 :
31 : #include <list>
32 : #include <fstream>
33 : #include <format>
34 :
35 : #include "../mxlib.hpp"
36 :
37 : #include "clOptions.hpp"
38 : #include "iniFile.hpp"
39 : #include "configTarget.hpp"
40 :
41 : namespace mx
42 : {
43 : namespace app
44 : {
45 :
46 : namespace detail
47 : {
48 :
49 : /// Optional parser override used to deterministically test appConfigurator parser failures.
50 : inline int ( *appConfiguratorParser )( iniFile &parser /**< [in,out] parser receiving file contents. */,
51 : const std::string &filename /**< [in] file requested by readConfig. */ ) =
52 : nullptr;
53 :
54 : } // namespace detail
55 :
56 : /// Class to manage a set of configurable values, and read their values from config/ini files and the command line.
57 : /**
58 : * The configuration files are TOML/ini-style, with sections. That is
59 : \verbatim
60 : key1=value1
61 : key2=value2
62 :
63 : [section1]
64 : key3=value3
65 : key4=value4,value4.1, value4.2, value4.3
66 :
67 : [section2]
68 : key3=value5
69 : key3=value5.1
70 : key4=value6_over_
71 : multiple_lines
72 :
73 : \endverbatim
74 : * such that section1.key3 is distinct from section2.key3 (they must have different config-target names though).
75 : *
76 : * Additional syntax rules:
77 : * - Leading whitespace is stripped from the value, so `key=val` and `key= val` are equivalent.
78 : * - Additional entries within one file with the same section and key are appended to the previous entry.
79 : * So the value of section2.key3 is "value5value5.1".
80 : * - Multi-line values are handled such that in the above example the result is key4=value6_over_multiple_lines.
81 : * - Vectors are input as comma separated lists, as in section1.key4 above. Leading whitespace is stripped from each
82 : * component of the vector.
83 : *
84 : * \todo add handling of += in subsequent files.
85 : * \todo should just swith to strict TOML
86 : *
87 : * The command line parser handles both short-opt ("-h -vArg -n Arg") and long-opt ("--help --value=Arg --number=Arg")
88 : styles.
89 : *
90 : *
91 : * \bug a config=value pair listed in a conf file twice seems to cause a failure, even if they are the same value.
92 : *
93 : * \ingroup mxApp
94 : *
95 : */
96 : struct appConfigurator
97 : {
98 : /// Iterator for the targets unordered_map
99 : typedef std::unordered_map<std::string, configTarget>::iterator targetIterator;
100 :
101 : /// Iterator for the clOnlyTargets list.
102 : typedef std::list<configTarget>::iterator clOnlyTargetIterator;
103 :
104 : /// The targets are stored in an unordered_map for fast access by key.
105 : std::unordered_map<std::string, configTarget> m_targets;
106 :
107 : /// Config file entries present in the file(s), but not corresponding to a target when parsed. Set aside for
108 : /// possible analysis.
109 : std::unordered_map<std::string, configTarget> m_unusedConfigs;
110 :
111 : /// Targets which are only for the command line are stored separately in a list.
112 : std::list<configTarget> clOnlyTargets;
113 :
114 : /// Non-option arguments from the command line.
115 : std::vector<std::string> nonOptions;
116 :
117 : /// Running count of options added, used to track order.
118 : int nAdded{ 0 };
119 :
120 : /// Flag controlling whether or not to record config sources
121 : bool m_sources{ false };
122 :
123 : /// Clear the containers and free up the associated memory.
124 : void clear();
125 :
126 : /// Add a configTarget
127 : /** Note that if name is a duplicate but the section and keyword are empty, it is handled as command-line only.
128 : */
129 : void add( const configTarget &tgt /**< [in] The configuration target to add */ );
130 :
131 : /// Add a configTarget
132 : /**
133 : * \overload
134 : */
135 : void add( const std::string &n, /**< [in] The name of the target */
136 : const std::string &so, /**< [in] The command-line short option (e.g. "f" for -f) */
137 : const std::string &lo, /**< [in] The command-line long option (e.g. "file" for --file) */
138 : int clt, /**< [in] The command-line option type, argType::false,
139 : argType::true, argType::optional, argType::required */
140 : const std::string &s, /**< [in] The config file section name, can be empty "" */
141 : const std::string &kw, /**< [in] The config file keyword, read in a "keyword=value" pair */
142 : bool isReq = false, /**< [in] Whether or not this option is required to be set */
143 22 : const std::string &ht = "", /**< [in] The type to display in the help message */
144 33 : const std::string &he = "" /**< [in] The explanation to display in the help message */
145 : );
146 :
147 : /// Parse the command line, updating the targets
148 : void parseCommandLine( int argc, /**< [in] standard command line result specifying number
149 : of argumetns in argv */
150 : char **argv, /**< [in] standard command line result containing the
151 : arguments. */
152 30 : const std::string &oneTarget = "" /**< [in] [optional] if not empty, then only this target
153 : is extracted by the parser. */
154 : );
155 :
156 : /// Read and parse a config/ini file, updating the targets
157 : /** \todo handle += here, by appending to the last value as if a vector.
158 : */
159 : int readConfig( const std::string &fname, ///< [in] the config file name
160 : bool reportFileNotFound = true ///< [in] [optiona] control whether a file not found is reported.
161 : );
162 :
163 : /// Check if a target has been set by the configuration
164 : /**
165 : * \returns true if the configuration set at least one value for this target
166 : * \returns false if no value was set.
167 : */
168 : bool isSet( const std::string &name, ///< [in] the target name
169 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
170 : );
171 :
172 : /// Check if a target has been set by the configuration
173 : /**
174 : * \overload
175 : *
176 : * \returns true if the configuration set at least one value for this target
177 : * \returns false if no value was set.
178 : */
179 : bool isSet( const std::string &name /**< [in] the target name */ );
180 :
181 : /// Get the number of different values set for the specified config target
182 : /**
183 : * \returns the number of different values set for name.
184 : */
185 : int count( const std::string &name, ///< [in] the target name
186 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
187 : );
188 :
189 : /// Get the number of different values set for the specified config target
190 : /**
191 : * \overload
192 : *
193 : * \returns the number of different values set for name.
194 : */
195 : int count( const std::string &name /**< [in] the target name */ );
196 :
197 : /// Get the command line verbosity count for this option.
198 : /** E.g., -v ==> 1, -vv ==> 2, -vvv ==> 3, etc. Note that for this to work
199 : * properly, this must be of type mx::argType::True.
200 : *
201 : * \returns the verbosity count.
202 : */
203 : int verbosity( const std::string &name, ///< [in] the target name
204 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
205 : );
206 :
207 : /// Get the command line verbosity count for this option.
208 : /** E.g., -v ==> 1, -vv ==> 2, -vvv ==> 3, etc. Note that for this to work
209 : * properly, this must be of type mx::argType::True.
210 : *
211 : * \overload
212 : *
213 : * \returns the verbosity count.
214 : */
215 : int verbosity( const std::string &name /**< [in] the target name */ );
216 :
217 : /// Get the i-th value of the target, converted to the specified type
218 : /** The supplied value is only altered if the config target was set, which preserves.
219 : * default values.
220 : *
221 : * \retval 0 on success
222 : * \retval -1 on error
223 : */
224 : template <typename typeT>
225 : int get( typeT &v, ///< [out] the variable to store the value in, unaltered if not set.
226 : const std::string &name, ///< [in] the config target name
227 : size_t i, ///< [in] the number of config specification to get.
228 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
229 : );
230 :
231 : /// Get the i-th value of the target from the used set, converted to the specified type
232 : /** The supplied value is only altered if the config target was set, which preserves.
233 : * default values.
234 : *
235 : * \overload
236 : *
237 : * \retval 0 on success
238 : * \retval -1 on error
239 : */
240 : template <typename typeT>
241 : int get( typeT &v, ///< [out] the variable to store the value in
242 : const std::string &name, ///< [in] the config target name
243 : size_t i ///< [in] the number of config specification to get.
244 : );
245 :
246 : /// Get the final value of the target, converted to the specified type
247 : /** The supplied value is only altered if the config target was set, which preserves.
248 : * default values.
249 : *
250 : * \overload
251 : *
252 : * \retval 0 on success.
253 : * \retval -1 on error.
254 : */
255 : template <typename typeT>
256 : int get( typeT &v, ///< [out] the variable to store the value in
257 : const std::string &name, ///< [in] the config target name
258 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
259 : );
260 :
261 : /// Get the final value of the target from the used set, converted to the specified type
262 : /** The supplied value is only altered if the config target was set, which preserves.
263 : * default values.
264 : *
265 : * \overload
266 : *
267 : * \retval 0 on success.
268 : * \retval -1 on error.
269 : */
270 : template <typename typeT>
271 : int get( typeT &v, ///< [out] the variable to store the value in
272 : const std::string &name ///< [in] the config target name
273 : );
274 :
275 : /// Get the i-th value of the target, converted to the specified config target
276 : /** The vector is only populated if the config target was set. If it is populated,
277 : * it is cleared first. Thus if a vector filled with default values is passed
278 : * in, it will only be overwritten if the user specified new values.
279 : *
280 : * \returns 0 on success
281 : * \returns -1 on error
282 : */
283 : template <typename typeT>
284 : int get( std::vector<typeT> &v, ///< [out] the vector to populate
285 : const std::string &name, ///< [in] the config target name.
286 : size_t i, ///< [in] the number of config specification to get.
287 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
288 : );
289 :
290 : /// Get the i-th value of the target, converted to the specified config target
291 : /** The vector is only populated if the config target was set. If it is populated,
292 : * it is cleared first. Thus if a vector filled with default values is passed
293 : * in, it will only be overwritten if the user specified new values.
294 : *
295 : * \returns 0 on success
296 : * \returns -1 on error
297 : */
298 : template <typename typeT>
299 : int get( std::vector<typeT> &v, ///< [out] the vector to populate
300 : const std::string &name, ///< [in] the config target name.
301 : size_t i ///< [in] the number of config specification to get.
302 : );
303 :
304 : /// Get the i-th value of the target as a vector containing the specified type.
305 : /** The vector is only populated if the config target was set. If it is populated,
306 : * it is cleared first. Thus if a vector filled with default values is passed
307 : * in, it will only be overwritten if the user specified new values.
308 : *
309 : * \retval 0 on success.
310 : * \retval -1 on error.
311 : */
312 : template <typename typeT>
313 : int get( std::vector<typeT> &v, ///< [out] the vector to populate
314 : const std::string &name, ///< [in] the config target name.
315 : std::unordered_map<std::string, configTarget> &targets ///< [in] the map of config targets to use
316 : );
317 :
318 : /// Get the final value of the target in the used set, as a vector containing the specified type.
319 : /** The vector is only populated if the config target was set. If it is populated,
320 : * it is cleared first. Thus if a vector filled with default values is passed
321 : * in, it will only be overwritten if the user specified new values.
322 : *
323 : * \retval 0 on success.
324 : * \retval -1 on error.
325 : */
326 : template <typename typeT>
327 : int get( std::vector<typeT> &v, ///< [out] the vector to populate
328 : const std::string &name ///< [in] the config target name.
329 : );
330 :
331 : /// Access operator, configures a value by calling get.
332 : /**
333 : * \retval 0 on success
334 : * \retval -1 on error
335 : */
336 : template <typename typeT>
337 : int
338 : operator()( typeT &v, ///< [out] the variable to populate (either scalar or vector), will be unaltered if not set.
339 : const std::string &name ///< [in] the config target name.
340 : );
341 :
342 : /// Configure a value from the unused map, using the iniFile key.
343 : /**
344 : * \retval 0 on success
345 : * \retval -1 on error
346 : */
347 : template <typename typeT>
348 : int
349 : configUnused( typeT &v, ///< [out] the variable to populate (either scalar or vector), will be unaltered if not set.
350 : const std::string &key ///< [in] the iniFile key for this target.
351 : );
352 :
353 : /// Configure a value from the unused map, using the section and keyword.
354 : /**
355 : * \retval 0 on success
356 : * \retval -1 on error
357 : */
358 : template <typename typeT>
359 : int
360 : configUnused( typeT &v, ///< [out] the variable to populate (either scalar or vector), will be unaltered if not set.
361 : const std::string §ion, ///< [in] the section name for this target
362 : const std::string &keyword ///< [in] the keyword for this target.
363 : );
364 :
365 : /// Get the unique sections in the unused config targets.
366 : /**
367 : * \retval 0 on success
368 : * \retval -1 on error
369 : */
370 : int unusedSections( std::vector<std::string> §ions );
371 :
372 : /// Check if a target has been set in the unused configuration
373 : /**
374 : * \returns true if the unused configuration set at least one value for this target
375 : * \returns false if no value was set.
376 : */
377 : int isSetUnused( const std::string &name /**< [in] the target name */ );
378 :
379 : /// Call an external logging function whenever a config value is accessed by get or operator().
380 : /** Only called if this is not a nullptr (the default), otherwise no logging or reporting is done.
381 : */
382 : void ( *configLog )(
383 : const std::string &name, ///< [in] The name of the config target.
384 : const int &code, ///< [in] The type code from mx::typeDescription
385 : const std::string &valueStr, ///< [in] The value in its string form as found in the configuration
386 : const std::string &source ///< [in] The source of the value, either default, command line, or a path.
387 : ){ nullptr };
388 :
389 : /// Get the number of unknown options found during config processing.
390 : int numUnknownOptions();
391 : };
392 :
393 : template <typename typeT>
394 118 : int appConfigurator::get( typeT &v,
395 : const std::string &name,
396 : size_t i,
397 : std::unordered_map<std::string, configTarget> &targets )
398 : {
399 118 : targets[name].used = true; // This means this was checked.
400 :
401 118 : if( !isSet( name, targets ) )
402 : {
403 1 : if( configLog )
404 : {
405 3 : configLog( name, meta::typeDescription<typeT>::code(), std::format( "{}", v ), "default" );
406 : }
407 :
408 1 : return 0;
409 : }
410 :
411 117 : if( targets[name].values.size() <= i )
412 : {
413 2 : return -1;
414 : }
415 :
416 115 : v = ioutils::stoT<typeT>( targets[name].values[i] );
417 :
418 : // Log it here.
419 115 : if( configLog )
420 : {
421 6 : if( m_sources )
422 : {
423 1 : configLog( name, meta::typeDescription<typeT>::code(), targets[name].values[i], targets[name].sources[i] );
424 : }
425 : else
426 : {
427 15 : configLog( name, meta::typeDescription<typeT>::code(), targets[name].values[i], "" );
428 : }
429 : }
430 :
431 115 : return 0;
432 : }
433 : // explicits
434 : extern template int appConfigurator::get<char>( char &v,
435 : const std::string &name,
436 : size_t i,
437 : std::unordered_map<std::string, configTarget> &targets );
438 :
439 : extern template int appConfigurator::get<signed char>( signed char &v,
440 : const std::string &name,
441 : size_t i,
442 : std::unordered_map<std::string, configTarget> &targets );
443 :
444 : extern template int appConfigurator::get<short>( short &v,
445 : const std::string &name,
446 : size_t i,
447 : std::unordered_map<std::string, configTarget> &targets );
448 :
449 : extern template int appConfigurator::get<int>( int &v,
450 : const std::string &name,
451 : size_t i,
452 : std::unordered_map<std::string, configTarget> &targets );
453 :
454 : extern template int appConfigurator::get<long>( long &v,
455 : const std::string &name,
456 : size_t i,
457 : std::unordered_map<std::string, configTarget> &targets );
458 :
459 : extern template int appConfigurator::get<long long>( long long &v,
460 : const std::string &name,
461 : size_t i,
462 : std::unordered_map<std::string, configTarget> &targets );
463 :
464 : extern template int appConfigurator::get<unsigned char>( unsigned char &v,
465 : const std::string &name,
466 : size_t i,
467 : std::unordered_map<std::string, configTarget> &targets );
468 :
469 : extern template int appConfigurator::get<unsigned short>( unsigned short &v,
470 : const std::string &name,
471 : size_t i,
472 : std::unordered_map<std::string, configTarget> &targets );
473 :
474 : extern template int appConfigurator::get<unsigned int>( unsigned int &v,
475 : const std::string &name,
476 : size_t i,
477 : std::unordered_map<std::string, configTarget> &targets );
478 :
479 : extern template int appConfigurator::get<unsigned long>( unsigned long &v,
480 : const std::string &name,
481 : size_t i,
482 : std::unordered_map<std::string, configTarget> &targets );
483 :
484 : extern template int appConfigurator::get<unsigned long long>( unsigned long long &v,
485 : const std::string &name,
486 : size_t i,
487 : std::unordered_map<std::string, configTarget> &targets );
488 :
489 : extern template int appConfigurator::get<float>( float &v,
490 : const std::string &name,
491 : size_t i,
492 : std::unordered_map<std::string, configTarget> &targets );
493 :
494 : extern template int appConfigurator::get<double>( double &v,
495 : const std::string &name,
496 : size_t i,
497 : std::unordered_map<std::string, configTarget> &targets );
498 :
499 : extern template int appConfigurator::get<long double>( long double &v,
500 : const std::string &name,
501 : size_t i,
502 : std::unordered_map<std::string, configTarget> &targets );
503 :
504 : #ifdef HASQUAD
505 : extern template int appConfigurator::get<__float128>( __float128 &v,
506 : const std::string &name,
507 : size_t i,
508 : std::unordered_map<std::string, configTarget> &targets );
509 : #endif
510 :
511 : extern template int appConfigurator::get<bool>( bool &v,
512 : const std::string &name,
513 : size_t i,
514 : std::unordered_map<std::string, configTarget> &targets );
515 :
516 : extern template int appConfigurator::get<std::string>( std::string &v,
517 : const std::string &name,
518 : size_t i,
519 : std::unordered_map<std::string, configTarget> &targets );
520 :
521 : //+++++++++++++++++++++++++++++++++++++
522 :
523 : template <typename typeT>
524 5 : int appConfigurator::get( typeT &v, const std::string &name, size_t i )
525 : {
526 5 : return get( v, name, i, m_targets );
527 : }
528 :
529 : // explicits
530 : extern template int appConfigurator::get<char>( char &v, const std::string &name, size_t i );
531 :
532 : extern template int appConfigurator::get<signed char>( signed char &v, const std::string &name, size_t i );
533 :
534 : extern template int appConfigurator::get<short>( short &v, const std::string &name, size_t i );
535 :
536 : extern template int appConfigurator::get<int>( int &v, const std::string &name, size_t i );
537 :
538 : extern template int appConfigurator::get<long>( long &v, const std::string &name, size_t i );
539 :
540 : extern template int appConfigurator::get<long long>( long long &v, const std::string &name, size_t i );
541 :
542 : extern template int appConfigurator::get<unsigned char>( unsigned char &v, const std::string &name, size_t i );
543 :
544 : extern template int appConfigurator::get<unsigned short>( unsigned short &v, const std::string &name, size_t i );
545 :
546 : extern template int appConfigurator::get<unsigned int>( unsigned int &v, const std::string &name, size_t i );
547 :
548 : extern template int appConfigurator::get<unsigned long>( unsigned long &v, const std::string &name, size_t i );
549 :
550 : extern template int
551 : appConfigurator::get<unsigned long long>( unsigned long long &v, const std::string &name, size_t i );
552 :
553 : extern template int appConfigurator::get<float>( float &v, const std::string &name, size_t i );
554 :
555 : extern template int appConfigurator::get<double>( double &v, const std::string &name, size_t i );
556 :
557 : extern template int appConfigurator::get<long double>( long double &v, const std::string &name, size_t i );
558 :
559 : #ifdef HASQUAD
560 : extern template int appConfigurator::get<__float128>( __float128 &v, const std::string &name, size_t i );
561 : #endif
562 :
563 : extern template int appConfigurator::get<bool>( bool &v, const std::string &name, size_t i );
564 :
565 : extern template int appConfigurator::get<std::string>( std::string &v, const std::string &name, size_t i );
566 :
567 : //+++++++++++++++++++++++++++++++++++++
568 :
569 : template <typename typeT>
570 484 : int appConfigurator::get( typeT &v, const std::string &name, std::unordered_map<std::string, configTarget> &targets )
571 : {
572 484 : targets[name].used = true; // This means this was checked.
573 :
574 484 : if( !isSet( name, targets ) )
575 : {
576 370 : if( configLog )
577 : {
578 3 : configLog( name, meta::typeDescription<typeT>::code(), std::format( "{}", v ), "default" );
579 : }
580 :
581 370 : return 0;
582 : }
583 :
584 114 : int i = targets[name].values.size() - 1;
585 :
586 114 : if( i < 0 )
587 1 : return -1;
588 :
589 113 : return get( v, name, i, targets );
590 : }
591 : // explicits:
592 :
593 : extern template int
594 : appConfigurator::get<char>( char &v, const std::string &name, std::unordered_map<std::string, configTarget> &targets );
595 :
596 : extern template int appConfigurator::get<signed char>( signed char &v,
597 : const std::string &name,
598 : std::unordered_map<std::string, configTarget> &targets );
599 :
600 : extern template int appConfigurator::get<short>( short &v,
601 : const std::string &name,
602 : std::unordered_map<std::string, configTarget> &targets );
603 :
604 : extern template int
605 : appConfigurator::get<int>( int &v, const std::string &name, std::unordered_map<std::string, configTarget> &targets );
606 :
607 : extern template int
608 : appConfigurator::get<long>( long &v, const std::string &name, std::unordered_map<std::string, configTarget> &targets );
609 :
610 : extern template int appConfigurator::get<long long>( long long &v,
611 : const std::string &name,
612 : std::unordered_map<std::string, configTarget> &targets );
613 :
614 : extern template int appConfigurator::get<unsigned char>( unsigned char &v,
615 : const std::string &name,
616 : std::unordered_map<std::string, configTarget> &targets );
617 :
618 : extern template int appConfigurator::get<unsigned short>( unsigned short &v,
619 : const std::string &name,
620 : std::unordered_map<std::string, configTarget> &targets );
621 :
622 : extern template int appConfigurator::get<unsigned int>( unsigned int &v,
623 : const std::string &name,
624 : std::unordered_map<std::string, configTarget> &targets );
625 :
626 : extern template int appConfigurator::get<unsigned long>( unsigned long &v,
627 : const std::string &name,
628 : std::unordered_map<std::string, configTarget> &targets );
629 :
630 : extern template int appConfigurator::get<unsigned long long>( unsigned long long &v,
631 : const std::string &name,
632 : std::unordered_map<std::string, configTarget> &targets );
633 :
634 : extern template int appConfigurator::get<float>( float &v,
635 : const std::string &name,
636 : std::unordered_map<std::string, configTarget> &targets );
637 :
638 : extern template int appConfigurator::get<double>( double &v,
639 : const std::string &name,
640 : std::unordered_map<std::string, configTarget> &targets );
641 :
642 : extern template int appConfigurator::get<long double>( long double &v,
643 : const std::string &name,
644 : std::unordered_map<std::string, configTarget> &targets );
645 :
646 : #ifdef HASQUAD
647 : extern template int appConfigurator::get<__float128>( __float128 &v,
648 : const std::string &name,
649 : std::unordered_map<std::string, configTarget> &targets );
650 : #endif
651 :
652 : extern template int
653 : appConfigurator::get<bool>( bool &v, const std::string &name, std::unordered_map<std::string, configTarget> &targets );
654 :
655 : extern template int appConfigurator::get<std::string>( std::string &v,
656 : const std::string &name,
657 : std::unordered_map<std::string, configTarget> &targets );
658 :
659 : //+++++++++++++++++++++++++++++++++++++
660 :
661 : template <typename typeT>
662 2 : int appConfigurator::get( typeT &v, const std::string &name )
663 : {
664 2 : return get( v, name, m_targets );
665 : }
666 : // explicits:
667 :
668 : extern template int appConfigurator::get<char>( char &v, const std::string &name );
669 :
670 : extern template int appConfigurator::get<signed char>( signed char &v, const std::string &name );
671 :
672 : extern template int appConfigurator::get<short>( short &v, const std::string &name );
673 :
674 : extern template int appConfigurator::get<int>( int &v, const std::string &name );
675 :
676 : extern template int appConfigurator::get<long>( long &v, const std::string &name );
677 :
678 : extern template int appConfigurator::get<long long>( long long &v, const std::string &name );
679 :
680 : extern template int appConfigurator::get<unsigned char>( unsigned char &v, const std::string &name );
681 :
682 : extern template int appConfigurator::get<unsigned short>( unsigned short &v, const std::string &name );
683 :
684 : extern template int appConfigurator::get<unsigned int>( unsigned int &v, const std::string &name );
685 :
686 : extern template int appConfigurator::get<unsigned long>( unsigned long &v, const std::string &name );
687 :
688 : extern template int appConfigurator::get<unsigned long long>( unsigned long long &v, const std::string &name );
689 :
690 : extern template int appConfigurator::get<float>( float &v, const std::string &name );
691 :
692 : extern template int appConfigurator::get<double>( double &v, const std::string &name );
693 :
694 : extern template int appConfigurator::get<long double>( long double &v, const std::string &name );
695 :
696 : #ifdef HASQUAD
697 : extern template int appConfigurator::get<__float128>( __float128 &v, const std::string &name );
698 : #endif
699 :
700 : extern template int appConfigurator::get<bool>( bool &v, const std::string &name );
701 :
702 : extern template int appConfigurator::get<std::string>( std::string &v, const std::string &name );
703 :
704 : //+++++++++++++++++++++++++++++++++++++
705 : template <typename typeT>
706 30 : int appConfigurator::get( std::vector<typeT> &v,
707 : const std::string &name,
708 : size_t i,
709 : std::unordered_map<std::string, configTarget> &targets )
710 : {
711 30 : targets[name].used = true; // This means this was checked.
712 :
713 30 : if( !isSet( name, targets ) )
714 : {
715 1 : if( configLog )
716 : {
717 5 : configLog( name, meta::typeDescription<typeT>::code(), "[need a vector to string]", "default" );
718 : }
719 :
720 1 : return 0;
721 : }
722 :
723 29 : if( targets[name].values.size() <= i )
724 1 : return -1;
725 :
726 28 : std::string s;
727 :
728 28 : s = ioutils::stoT<std::string>( targets[name].values[i] );
729 :
730 : // if( get<std::string>(s, name, i, targets) < 0) return -1;
731 :
732 : // Case that s was set to be empty.
733 28 : if( s.size() == 0 )
734 : {
735 2 : if( configLog )
736 : {
737 2 : if( m_sources )
738 : {
739 3 : configLog( name, meta::typeDescription<typeT>::code(), "", targets[name].sources[i] );
740 : }
741 : else
742 : {
743 5 : configLog( name, meta::typeDescription<typeT>::code(), "", "" );
744 : }
745 : }
746 :
747 2 : v.clear(); // We clear the vector passed as default
748 2 : return 0;
749 : }
750 :
751 : size_t st;
752 : size_t com;
753 :
754 26 : st = 0;
755 :
756 27 : while( st < s.size() && ::isspace( static_cast<unsigned char>( s[st] ) ) )
757 1 : ++st;
758 :
759 26 : com = s.find( ',', st );
760 :
761 26 : v.clear();
762 :
763 62 : while( com != std::string::npos )
764 : {
765 36 : v.push_back( ioutils::stoT<typeT>( s.substr( st, com - st ) ) );
766 36 : st = com + 1;
767 40 : while( st < s.size() && ::isspace( static_cast<unsigned char>( s[st] ) ) )
768 4 : ++st;
769 :
770 36 : com = s.find( ',', st );
771 : }
772 26 : v.push_back( ioutils::stoT<typeT>( s.substr( st, s.size() - st ) ) );
773 :
774 : // Log it here.
775 26 : if( configLog )
776 : {
777 4 : if( m_sources )
778 : {
779 1 : configLog( name, meta::typeDescription<typeT>::code(), targets[name].values[i], targets[name].sources[i] );
780 : }
781 : else
782 : {
783 9 : configLog( name, meta::typeDescription<typeT>::code(), targets[name].values[i], "" );
784 : }
785 : }
786 :
787 26 : return 0;
788 28 : }
789 : // explicits:
790 :
791 : extern template int appConfigurator::get<char>( std::vector<char> &v,
792 : const std::string &name,
793 : size_t i,
794 : std::unordered_map<std::string, configTarget> &targets );
795 :
796 : extern template int appConfigurator::get<signed char>( std::vector<signed char> &v,
797 : const std::string &name,
798 : size_t i,
799 : std::unordered_map<std::string, configTarget> &targets );
800 :
801 : extern template int appConfigurator::get<short>( std::vector<short> &v,
802 : const std::string &name,
803 : size_t i,
804 : std::unordered_map<std::string, configTarget> &targets );
805 :
806 : extern template int appConfigurator::get<int>( std::vector<int> &v,
807 : const std::string &name,
808 : size_t i,
809 : std::unordered_map<std::string, configTarget> &targets );
810 :
811 : extern template int appConfigurator::get<long>( std::vector<long> &v,
812 : const std::string &name,
813 : size_t i,
814 : std::unordered_map<std::string, configTarget> &targets );
815 :
816 : extern template int appConfigurator::get<long long>( std::vector<long long> &v,
817 : const std::string &name,
818 : size_t i,
819 : std::unordered_map<std::string, configTarget> &targets );
820 :
821 : extern template int appConfigurator::get<unsigned char>( std::vector<unsigned char> &v,
822 : const std::string &name,
823 : size_t i,
824 : std::unordered_map<std::string, configTarget> &targets );
825 :
826 : extern template int appConfigurator::get<unsigned short>( std::vector<unsigned short> &v,
827 : const std::string &name,
828 : size_t i,
829 : std::unordered_map<std::string, configTarget> &targets );
830 :
831 : extern template int appConfigurator::get<unsigned int>( std::vector<unsigned int> &v,
832 : const std::string &name,
833 : size_t i,
834 : std::unordered_map<std::string, configTarget> &targets );
835 :
836 : extern template int appConfigurator::get<unsigned long>( std::vector<unsigned long> &v,
837 : const std::string &name,
838 : size_t i,
839 : std::unordered_map<std::string, configTarget> &targets );
840 :
841 : extern template int appConfigurator::get<unsigned long long>( std::vector<unsigned long long> &v,
842 : const std::string &name,
843 : size_t i,
844 : std::unordered_map<std::string, configTarget> &targets );
845 :
846 : extern template int appConfigurator::get<float>( std::vector<float> &v,
847 : const std::string &name,
848 : size_t i,
849 : std::unordered_map<std::string, configTarget> &targets );
850 :
851 : extern template int appConfigurator::get<double>( std::vector<double> &v,
852 : const std::string &name,
853 : size_t i,
854 : std::unordered_map<std::string, configTarget> &targets );
855 :
856 : extern template int appConfigurator::get<long double>( std::vector<long double> &v,
857 : const std::string &name,
858 : size_t i,
859 : std::unordered_map<std::string, configTarget> &targets );
860 :
861 : #ifdef HASQUAD
862 : extern template int appConfigurator::get<__float128>( std::vector<__float128> &v,
863 : const std::string &name,
864 : size_t i,
865 : std::unordered_map<std::string, configTarget> &targets );
866 : #endif
867 :
868 : extern template int appConfigurator::get<bool>( std::vector<bool> &v,
869 : const std::string &name,
870 : size_t i,
871 : std::unordered_map<std::string, configTarget> &targets );
872 :
873 : extern template int appConfigurator::get<std::string>( std::vector<std::string> &v,
874 : const std::string &name,
875 : size_t i,
876 : std::unordered_map<std::string, configTarget> &targets );
877 :
878 : //+++++++++++++++++++++++++++++++++++++
879 :
880 : template <typename typeT>
881 5 : int appConfigurator::get( std::vector<typeT> &v, const std::string &name, size_t i )
882 : {
883 5 : return get( v, name, i, m_targets );
884 : }
885 :
886 : // explicits:
887 :
888 : extern template int appConfigurator::get<char>( std::vector<char> &v, const std::string &name, size_t i );
889 :
890 : extern template int appConfigurator::get<signed char>( std::vector<signed char> &v, const std::string &name, size_t i );
891 :
892 : extern template int appConfigurator::get<short>( std::vector<short> &v, const std::string &name, size_t i );
893 :
894 : extern template int appConfigurator::get<int>( std::vector<int> &v, const std::string &name, size_t i );
895 :
896 : extern template int appConfigurator::get<long>( std::vector<long> &v, const std::string &name, size_t i );
897 :
898 : extern template int appConfigurator::get<long long>( std::vector<long long> &v, const std::string &name, size_t i );
899 :
900 : extern template int
901 : appConfigurator::get<unsigned char>( std::vector<unsigned char> &v, const std::string &name, size_t i );
902 :
903 : extern template int
904 : appConfigurator::get<unsigned short>( std::vector<unsigned short> &v, const std::string &name, size_t i );
905 :
906 : extern template int
907 : appConfigurator::get<unsigned int>( std::vector<unsigned int> &v, const std::string &name, size_t i );
908 :
909 : extern template int
910 : appConfigurator::get<unsigned long>( std::vector<unsigned long> &v, const std::string &name, size_t i );
911 :
912 : extern template int
913 : appConfigurator::get<unsigned long long>( std::vector<unsigned long long> &v, const std::string &name, size_t i );
914 :
915 : extern template int appConfigurator::get<float>( std::vector<float> &v, const std::string &name, size_t i );
916 :
917 : extern template int appConfigurator::get<double>( std::vector<double> &v, const std::string &name, size_t i );
918 :
919 : extern template int appConfigurator::get<long double>( std::vector<long double> &v, const std::string &name, size_t i );
920 :
921 : #ifdef HASQUAD
922 : extern template int appConfigurator::get<__float128>( std::vector<__float128> &v, const std::string &name, size_t i );
923 : #endif
924 :
925 : extern template int appConfigurator::get<bool>( std::vector<bool> &v, const std::string &name, size_t i );
926 :
927 : extern template int appConfigurator::get<std::string>( std::vector<std::string> &v, const std::string &name, size_t i );
928 :
929 : //+++++++++++++++++++++++++++++++++++++
930 : template <typename typeT>
931 230 : int appConfigurator::get( std::vector<typeT> &v,
932 : const std::string &name,
933 : std::unordered_map<std::string, configTarget> &targets )
934 : {
935 230 : targets[name].used = true; // This means this was checked.
936 :
937 230 : if( !isSet( name, targets ) )
938 : {
939 204 : if( configLog )
940 : {
941 5 : configLog( name, meta::typeDescription<typeT>::code(), "[need a vector to string]", "default" );
942 : }
943 204 : return 0;
944 : }
945 26 : int i = targets[name].values.size() - 1;
946 :
947 26 : if( i < 0 )
948 1 : return -1;
949 :
950 25 : return get( v, name, i, targets );
951 : }
952 : // explicits:
953 :
954 : extern template int appConfigurator::get<char>( std::vector<char> &v,
955 : const std::string &name,
956 : std::unordered_map<std::string, configTarget> &targets );
957 :
958 : extern template int appConfigurator::get<signed char>( std::vector<signed char> &v,
959 : const std::string &name,
960 : std::unordered_map<std::string, configTarget> &targets );
961 :
962 : extern template int appConfigurator::get<short>( std::vector<short> &v,
963 : const std::string &name,
964 : std::unordered_map<std::string, configTarget> &targets );
965 :
966 : extern template int appConfigurator::get<int>( std::vector<int> &v,
967 : const std::string &name,
968 : std::unordered_map<std::string, configTarget> &targets );
969 :
970 : extern template int appConfigurator::get<long>( std::vector<long> &v,
971 : const std::string &name,
972 : std::unordered_map<std::string, configTarget> &targets );
973 :
974 : extern template int appConfigurator::get<long long>( std::vector<long long> &v,
975 : const std::string &name,
976 : std::unordered_map<std::string, configTarget> &targets );
977 :
978 : extern template int appConfigurator::get<unsigned char>( std::vector<unsigned char> &v,
979 : const std::string &name,
980 : std::unordered_map<std::string, configTarget> &targets );
981 :
982 : extern template int appConfigurator::get<unsigned short>( std::vector<unsigned short> &v,
983 : const std::string &name,
984 : std::unordered_map<std::string, configTarget> &targets );
985 :
986 : extern template int appConfigurator::get<unsigned int>( std::vector<unsigned int> &v,
987 : const std::string &name,
988 : std::unordered_map<std::string, configTarget> &targets );
989 :
990 : extern template int appConfigurator::get<unsigned long>( std::vector<unsigned long> &v,
991 : const std::string &name,
992 : std::unordered_map<std::string, configTarget> &targets );
993 :
994 : extern template int appConfigurator::get<unsigned long long>( std::vector<unsigned long long> &v,
995 : const std::string &name,
996 : std::unordered_map<std::string, configTarget> &targets );
997 :
998 : extern template int appConfigurator::get<float>( std::vector<float> &v,
999 : const std::string &name,
1000 : std::unordered_map<std::string, configTarget> &targets );
1001 :
1002 : extern template int appConfigurator::get<double>( std::vector<double> &v,
1003 : const std::string &name,
1004 : std::unordered_map<std::string, configTarget> &targets );
1005 :
1006 : extern template int appConfigurator::get<long double>( std::vector<long double> &v,
1007 : const std::string &name,
1008 : std::unordered_map<std::string, configTarget> &targets );
1009 :
1010 : #ifdef HASQUAD
1011 : extern template int appConfigurator::get<__float128>( std::vector<__float128> &v,
1012 : const std::string &name,
1013 : std::unordered_map<std::string, configTarget> &targets );
1014 : #endif
1015 :
1016 : extern template int appConfigurator::get<bool>( std::vector<bool> &v,
1017 : const std::string &name,
1018 : std::unordered_map<std::string, configTarget> &targets );
1019 :
1020 : extern template int appConfigurator::get<std::string>( std::vector<std::string> &v,
1021 : const std::string &name,
1022 : std::unordered_map<std::string, configTarget> &targets );
1023 :
1024 : //+++++++++++++++++++++++++++++++++++++
1025 :
1026 : template <typename typeT>
1027 2 : int appConfigurator::get( std::vector<typeT> &v, const std::string &name )
1028 : {
1029 2 : return get( v, name, m_targets );
1030 : }
1031 : // explicits:
1032 :
1033 : extern template int appConfigurator::get<char>( std::vector<char> &v, const std::string &name );
1034 :
1035 : extern template int appConfigurator::get<signed char>( std::vector<signed char> &v, const std::string &name );
1036 :
1037 : extern template int appConfigurator::get<short>( std::vector<short> &v, const std::string &name );
1038 :
1039 : extern template int appConfigurator::get<int>( std::vector<int> &v, const std::string &name );
1040 :
1041 : extern template int appConfigurator::get<long>( std::vector<long> &v, const std::string &name );
1042 :
1043 : extern template int appConfigurator::get<long long>( std::vector<long long> &v, const std::string &name );
1044 :
1045 : extern template int appConfigurator::get<unsigned char>( std::vector<unsigned char> &v, const std::string &name );
1046 :
1047 : extern template int appConfigurator::get<unsigned short>( std::vector<unsigned short> &v, const std::string &name );
1048 :
1049 : extern template int appConfigurator::get<unsigned int>( std::vector<unsigned int> &v, const std::string &name );
1050 :
1051 : extern template int appConfigurator::get<unsigned long>( std::vector<unsigned long> &v, const std::string &name );
1052 :
1053 : extern template int appConfigurator::get<unsigned long long>( std::vector<unsigned long long> &v,
1054 : const std::string &name );
1055 :
1056 : extern template int appConfigurator::get<float>( std::vector<float> &v, const std::string &name );
1057 :
1058 : extern template int appConfigurator::get<double>( std::vector<double> &v, const std::string &name );
1059 :
1060 : extern template int appConfigurator::get<long double>( std::vector<long double> &v, const std::string &name );
1061 :
1062 : #ifdef HASQUAD
1063 : extern template int appConfigurator::get<__float128>( std::vector<__float128> &v, const std::string &name );
1064 : #endif
1065 :
1066 : extern template int appConfigurator::get<bool>( std::vector<bool> &v, const std::string &name );
1067 :
1068 : extern template int appConfigurator::get<std::string>( std::vector<std::string> &v, const std::string &name );
1069 :
1070 : //+++++++++++++++++++++++++++++++++++++
1071 :
1072 : template <typename typeT>
1073 706 : int appConfigurator::operator()( typeT &v, const std::string &name )
1074 : {
1075 706 : return get( v, name, m_targets );
1076 : }
1077 :
1078 : // explicits:
1079 :
1080 : extern template int appConfigurator::operator()<char>( char &v, const std::string &name );
1081 :
1082 : extern template int appConfigurator::operator()<signed char>( signed char &v, const std::string &name );
1083 :
1084 : extern template int appConfigurator::operator()<short>( short &v, const std::string &name );
1085 :
1086 : extern template int appConfigurator::operator()<int>( int &v, const std::string &name );
1087 :
1088 : extern template int appConfigurator::operator()<long>( long &v, const std::string &name );
1089 :
1090 : extern template int appConfigurator::operator()<long long>( long long &v, const std::string &name );
1091 :
1092 : extern template int appConfigurator::operator()<unsigned char>( unsigned char &v, const std::string &name );
1093 :
1094 : extern template int appConfigurator::operator()<unsigned short>( unsigned short &v, const std::string &name );
1095 :
1096 : extern template int appConfigurator::operator()<unsigned int>( unsigned int &v, const std::string &name );
1097 :
1098 : extern template int appConfigurator::operator()<unsigned long>( unsigned long &v, const std::string &name );
1099 :
1100 : extern template int appConfigurator::operator()<unsigned long long>( unsigned long long &v, const std::string &name );
1101 :
1102 : extern template int appConfigurator::operator()<float>( float &v, const std::string &name );
1103 :
1104 : extern template int appConfigurator::operator()<double>( double &v, const std::string &name );
1105 :
1106 : extern template int appConfigurator::operator()<long double>( long double &v, const std::string &name );
1107 :
1108 : #ifdef HASQUAD
1109 : extern template int appConfigurator::operator()<__float128>( __float128 &v, const std::string &name );
1110 : #endif
1111 :
1112 : extern template int appConfigurator::operator()<bool>( bool &v, const std::string &name );
1113 :
1114 : extern template int appConfigurator::operator()<std::string>( std::string &v, const std::string &name );
1115 :
1116 : //+++++++++++++++++++++++++++++++++++++
1117 :
1118 : template <typename typeT>
1119 4 : int appConfigurator::configUnused( typeT &v, const std::string &key )
1120 : {
1121 4 : return get( v, key, m_unusedConfigs );
1122 : }
1123 :
1124 : extern template int appConfigurator::configUnused<char>( char &v, const std::string &key );
1125 :
1126 : extern template int appConfigurator::configUnused<signed char>( signed char &v, const std::string &key );
1127 :
1128 : extern template int appConfigurator::configUnused<short>( short &v, const std::string &key );
1129 :
1130 : extern template int appConfigurator::configUnused<int>( int &v, const std::string &key );
1131 :
1132 : extern template int appConfigurator::configUnused<long>( long &v, const std::string &key );
1133 :
1134 : extern template int appConfigurator::configUnused<long long>( long long &v, const std::string &key );
1135 :
1136 : extern template int appConfigurator::configUnused<unsigned char>( unsigned char &v, const std::string &key );
1137 :
1138 : extern template int appConfigurator::configUnused<unsigned short>( unsigned short &v, const std::string &key );
1139 :
1140 : extern template int appConfigurator::configUnused<unsigned int>( unsigned int &v, const std::string &key );
1141 :
1142 : extern template int appConfigurator::configUnused<unsigned long>( unsigned long &v, const std::string &key );
1143 :
1144 : extern template int appConfigurator::configUnused<unsigned long long>( unsigned long long &v, const std::string &key );
1145 :
1146 : extern template int appConfigurator::configUnused<float>( float &v, const std::string &key );
1147 :
1148 : extern template int appConfigurator::configUnused<double>( double &v, const std::string &key );
1149 :
1150 : extern template int appConfigurator::configUnused<long double>( long double &v, const std::string &key );
1151 :
1152 : #ifdef HASQUAD
1153 : extern template int appConfigurator::configUnused<__float128>( __float128 &v, const std::string &key );
1154 : #endif
1155 :
1156 : extern template int appConfigurator::configUnused<bool>( bool &v, const std::string &key );
1157 :
1158 : extern template int appConfigurator::configUnused<std::string>( std::string &v, const std::string &key );
1159 : //+++++++++++++++++++++++++++++++++++++
1160 :
1161 : template <typename typeT>
1162 4 : int appConfigurator::configUnused( typeT &v, const std::string §ion, const std::string &keyword )
1163 : {
1164 4 : return configUnused( v, iniFile::makeKey( section, keyword ) );
1165 : }
1166 :
1167 : extern template int
1168 : appConfigurator::configUnused<char>( char &v, const std::string §ion, const std::string &keyword );
1169 :
1170 : extern template int
1171 : appConfigurator::configUnused<signed char>( signed char &v, const std::string §ion, const std::string &keyword );
1172 :
1173 : extern template int
1174 : appConfigurator::configUnused<short>( short &v, const std::string §ion, const std::string &keyword );
1175 :
1176 : extern template int
1177 : appConfigurator::configUnused<int>( int &v, const std::string §ion, const std::string &keyword );
1178 :
1179 : extern template int
1180 : appConfigurator::configUnused<long>( long &v, const std::string §ion, const std::string &keyword );
1181 :
1182 : extern template int
1183 : appConfigurator::configUnused<long long>( long long &v, const std::string §ion, const std::string &keyword );
1184 :
1185 : extern template int appConfigurator::configUnused<unsigned char>( unsigned char &v,
1186 : const std::string §ion,
1187 : const std::string &keyword );
1188 :
1189 : extern template int appConfigurator::configUnused<unsigned short>( unsigned short &v,
1190 : const std::string §ion,
1191 : const std::string &keyword );
1192 :
1193 : extern template int
1194 : appConfigurator::configUnused<unsigned int>( unsigned int &v, const std::string §ion, const std::string &keyword );
1195 :
1196 : extern template int appConfigurator::configUnused<unsigned long>( unsigned long &v,
1197 : const std::string §ion,
1198 : const std::string &keyword );
1199 :
1200 : extern template int appConfigurator::configUnused<unsigned long long>( unsigned long long &v,
1201 : const std::string §ion,
1202 : const std::string &keyword );
1203 :
1204 : extern template int
1205 : appConfigurator::configUnused<float>( float &v, const std::string §ion, const std::string &keyword );
1206 :
1207 : extern template int
1208 : appConfigurator::configUnused<double>( double &v, const std::string §ion, const std::string &keyword );
1209 :
1210 : extern template int
1211 : appConfigurator::configUnused<long double>( long double &v, const std::string §ion, const std::string &keyword );
1212 :
1213 : #ifdef HASQUAD
1214 : extern template int
1215 : appConfigurator::configUnused<__float128>( __float128 &v, const std::string §ion, const std::string &keyword );
1216 : #endif
1217 :
1218 : extern template int
1219 : appConfigurator::configUnused<bool>( bool &v, const std::string §ion, const std::string &keyword );
1220 :
1221 : extern template int
1222 : appConfigurator::configUnused<std::string>( std::string &v, const std::string §ion, const std::string &keyword );
1223 :
1224 : //+++++++++++++++++++++++++++++++++++++
1225 :
1226 : /// A simple config file writing function, useful for testing.
1227 : /** Write a config file to the path specified by `fname`. Each of the parameters
1228 : * is a vector, and each component is required of each vector.
1229 : *
1230 : * Example:
1231 : *\code
1232 : writeConfigFile( "/tmp/test.conf", {"", "", "sect1", "sect1", "sect2", "sect2"},
1233 : {"key0", "key1", "key2", "key3", "key4", "key5"},
1234 : {"val0", "val1", "val2", "val3", "val4", "val5"} );
1235 :
1236 : *\endcode
1237 : * results in the file `/tmp/test.conf` containing
1238 : * \verbatim
1239 : key0=val0
1240 : key1=val1
1241 :
1242 : [sect1]
1243 : key2=val2
1244 : key3=val3
1245 :
1246 : [sect2]
1247 : key4=val4
1248 : key5=val5
1249 :
1250 : * \endverbatim
1251 : *
1252 : * No error checking is done.
1253 : */
1254 : void writeConfigFile( const std::string &fname, ///< [in] the complete path for the output file.
1255 : const std::vector<std::string> §ions, ///< [in] sections, one per config value
1256 : const std::vector<std::string> &keywords, ///< [in] keywords, one per config value
1257 : const std::vector<std::string> &values ///< [in] the values
1258 : );
1259 :
1260 : } // namespace app
1261 : } // namespace mx
1262 :
1263 : #endif // app_appConfigurator_hpp
|