Line data Source code
1 : // Copyright (c) 2006-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/advgetopt
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 :
21 : /** \file
22 : * \brief Implementation of the option_info class.
23 : *
24 : * This is the implementation of the class used to define one command
25 : * line option.
26 : */
27 :
28 : // self
29 : //
30 : #include "advgetopt/option_info.h"
31 :
32 : #include "advgetopt/validator_double.h"
33 : #include "advgetopt/validator_integer.h"
34 :
35 :
36 : // advgetopt lib
37 : //
38 : #include "advgetopt/exception.h"
39 :
40 :
41 : // cppthread lib
42 : //
43 : #include <cppthread/guard.h>
44 : #include <cppthread/log.h>
45 : #include <cppthread/mutex.h>
46 :
47 :
48 : // snapdev lib
49 : //
50 : #include <snapdev/not_used.h>
51 : #include <snapdev/tokenize_string.h>
52 :
53 :
54 : // libutf8 lib
55 : //
56 : #include <libutf8/libutf8.h>
57 : #include <libutf8/iterator.h>
58 :
59 :
60 : // boost lib
61 : //
62 : #include <boost/algorithm/string/replace.hpp>
63 :
64 :
65 : // last include
66 : //
67 : #include <snapdev/poison.h>
68 :
69 :
70 :
71 :
72 : namespace advgetopt
73 : {
74 :
75 :
76 : namespace
77 : {
78 :
79 :
80 : /** \brief The library trace mode.
81 : *
82 : * This flag is used to determine whether the source of each option should
83 : * be traced. Very often, I have a problem where I'm not so sure where a
84 : * certain option was defined and how to fix the value of that option.
85 : * This flag allows us to debug that information at run time.
86 : *
87 : * When the flag is set to true (automatically done by the getopt object
88 : * when argv includes the "--show-sources" command line option), the sources
89 : * start to be traced. Once all the parsing is done, getopt again will check
90 : * whether it has the "--show-sources" command line option specified and if
91 : * so, it prints out all the options current values and the various sources
92 : * that were involved.
93 : */
94 : bool g_trace_sources = false;
95 :
96 :
97 : /** \brief The filename of the configuration being processed.
98 : *
99 : * This variable holds the filename of the configuration currently
100 : * being processed. This information is used to generate the trace
101 : * of the sources. That way it is possible to see where the current
102 : * value of a given variable comes from.
103 : *
104 : * This parameter is currently set from the
105 : * getopt::process_configuration_file() function.
106 : */
107 2 : std::string g_configuration_filename = std::string();
108 :
109 :
110 :
111 : } // no name namespace
112 :
113 :
114 :
115 : // from utils.cpp
116 : //
117 : // (it's here because we do not want to make cppthread public in
118 : // out header files--we could have an advgetopt_private.h, though)
119 : //
120 : cppthread::mutex & get_global_mutex();
121 :
122 :
123 :
124 :
125 : /** \brief Transform a string to a short name.
126 : *
127 : * This function transforms a string to a short name. The input string
128 : * can represent a UTF-8 character that can be used as a short name.
129 : *
130 : * An empty string is not considered to represent any name and thus
131 : * this function returns NO_SHORT_NAME when the input is an empty
132 : * string.
133 : *
134 : * \param[in] name The name to be checked.
135 : *
136 : * \return The short name character or NO_SHORT_NAME if it's not a match.
137 : */
138 2231149 : short_name_t string_to_short_name(std::string const & name)
139 : {
140 2231149 : if(!name.empty())
141 : {
142 2231148 : libutf8::utf8_iterator u8(name);
143 2231148 : short_name_t const short_name(*u8++);
144 2231148 : if(u8 == name.end())
145 : {
146 1112070 : return short_name;
147 : }
148 : }
149 :
150 1119079 : return NO_SHORT_NAME;
151 : }
152 :
153 :
154 : /** \brief Convert a short name to a UTF-8 string.
155 : *
156 : * This function is the opposite of the to_short_name() except that the
157 : * input is expected to be a valid short name or NO_SHORT_NAME.
158 : *
159 : * When the input is NO_SHORT_NAME, the function outputs an empty string.
160 : *
161 : * \note
162 : * There are other short names that are not really considered valid such
163 : * as control characters, the dash (-), and probably most other
164 : * punctuation, character codes which are not currently assigned to
165 : * any character in Unicode, etc. This function ignores all of those
166 : * potential problems.
167 : *
168 : * \param[in] short_name The short name to convert to UTF-8.
169 : *
170 : * \return The short name as a UTF-8 string or an empty string.
171 : */
172 2224181 : std::string short_name_to_string(short_name_t short_name)
173 : {
174 2224181 : if(short_name == NO_SHORT_NAME)
175 : {
176 1 : return std::string();
177 : }
178 2224180 : return libutf8::to_u8string(short_name);
179 : }
180 :
181 :
182 : /** \brief Create a new option_info object.
183 : *
184 : * This function creates a new option_info object with the specified \p name
185 : * and \p short_name. The \p short_name is optional.
186 : *
187 : * When adding options to a map of options, all the long and short names
188 : * must be unique. See the add_child() function for details.
189 : *
190 : * The \p short_name parameter is a UTF-32 character. To not offer a short
191 : * name for an option, use NO_SHORT_NAME as the value (which is the default
192 : * if not specified to the constructor.)
193 : *
194 : * \li Special Option Name: "--"
195 : *
196 : * The "--" long name is viewed as the separator between options and
197 : * \em filenames. When "--" is found by itself on the command line, then
198 : * it is viewed as a switch to go from having options to only having
199 : * \em filenames. Of course, these options may be used as any type of
200 : * values, not just filenames (it could be URLs, email addresses, numbers,
201 : * etc.)
202 : *
203 : * The "--" separator cannot be assigned a short name.
204 : *
205 : * \li Special Option Name: "*"
206 : *
207 : * The "*" long name is viewed as the \em accept \em all option. This
208 : * means all the options may not be defined in the list of options but
209 : * we still want to accept them. This is to allow dynamically defined
210 : * (supported) command options and especially to not have to declare
211 : * all the valid options found in a configuration file.
212 : *
213 : * \li Underscore and Dashes
214 : *
215 : * It is customary to support dashes between words in options appearing
216 : * on the command line (`--help-me`), however, it is unusual in
217 : * configuration files where underscores are used instead (`under_score`.)
218 : * When we compare option names, `'-' == '_'` is always considered true
219 : * so either dashes or underscore can be used in both cases.
220 : *
221 : * For this reason, the long name is saved with only dashes. That
222 : * means all the maps are indexed using the long name with dashes.
223 : *
224 : * \exception getopt_exception_logic
225 : * The constructor raises the invalid exception if the long name is an
226 : * empty string since this is not allowed. It will also raise that
227 : * exception if the name is the default option ("--") and a short name
228 : * is also defined. (i.e. no short name is allowed along the default
229 : * option.)
230 : *
231 : * \param[in] name The (long) name of this option.
232 : * \param[in] short_name The short name of this option (one character.)
233 : */
234 1517 : option_info::option_info(std::string const & name, short_name_t short_name)
235 : : f_name(boost::replace_all_copy(name, "_", "-"))
236 1525 : , f_short_name(short_name)
237 : {
238 1517 : if(f_name.empty())
239 : {
240 4 : if(short_name != NO_SHORT_NAME)
241 : {
242 : throw getopt_logic_error(
243 : "option_info::option_info(): all options must at least have a long name (short name: '"
244 4 : + libutf8::to_u8string(short_name)
245 6 : + "'.)");
246 : }
247 : throw getopt_logic_error(
248 2 : "option_info::option_info(): all options must at least have a long name.");
249 : }
250 :
251 1513 : if(f_name == "--")
252 : {
253 16 : if(short_name != NO_SHORT_NAME)
254 : {
255 : throw getopt_logic_error(
256 : "option_info::option_info(): the default parameter \"--\" cannot include a short name ('"
257 4 : + libutf8::to_u8string(short_name)
258 6 : + "'.)");
259 : }
260 :
261 14 : add_flag(GETOPT_FLAG_DEFAULT_OPTION);
262 : }
263 : else
264 : {
265 1497 : if(f_name[0] == '-')
266 : {
267 : throw getopt_logic_error(
268 : "option_info::option_info(): an option cannot start with a dash (-), \""
269 2 : + f_name
270 3 : + "\" is not valid.");
271 : }
272 :
273 1496 : if(short_name == '-')
274 : {
275 : throw getopt_logic_error(
276 1 : "option_info::option_info(): the short name of an option cannot be the dash (-).");
277 : }
278 : }
279 1509 : }
280 :
281 :
282 : /** \brief Get the long name of the option.
283 : *
284 : * This option retrieves the long name of the option.
285 : *
286 : * \note
287 : * Remember that the underscores in long names are converted to dashes.
288 : * This is because it makes more sense to look for command line parameters
289 : * with dashes. This function will return the name with only dashes.
290 : *
291 : * \note
292 : * The name is always defined. The creation of an option_info object
293 : * fails if the name is empty.
294 : *
295 : * \return The long name with dashes instead of underscores.
296 : */
297 3037 : std::string const & option_info::get_name() const
298 : {
299 3037 : return f_name;
300 : }
301 :
302 :
303 : /** \brief Assign a short name to an option.
304 : *
305 : * This function is used to assign a short name to an option.
306 : *
307 : * It can be changed to anything, including the NO_SHORT_NAME special
308 : * value.
309 : *
310 : * \warning
311 : * If you want this function to work as expected (i.e. for the option
312 : * to later be found using its short name), make sure to call the
313 : * getopt::set_short_name() on your getopt object and not directly this
314 : * function. This is because the getopt object needs to add the newly
315 : * named option to its map of options sorted by short name.
316 : *
317 : * \param[in] short_name The short name to assign to this option.
318 : *
319 : * \sa get_short_name()
320 : * \sa getopt::set_short_name()
321 : */
322 15 : void option_info::set_short_name(short_name_t short_name)
323 : {
324 15 : f_short_name = short_name;
325 15 : }
326 :
327 :
328 : /** \brief Get the short name of the option.
329 : *
330 : * This function returns the \p short_name of this option.
331 : *
332 : * The short name is a Unicode character (UTF-32).
333 : *
334 : * \return The short name character.
335 : */
336 1632 : short_name_t option_info::get_short_name() const
337 : {
338 1632 : return f_short_name;
339 : }
340 :
341 :
342 : /** \brief Retrieve the name of the option without any section names.
343 : *
344 : * The name of an option can include section names. These
345 : * are rarely used on the command line, but they are useful for
346 : * configuration files if you want to create multiple layers of
347 : * options (a.k.a. sections.)
348 : *
349 : * This function removes all the section names from the option name
350 : * and returns what's left.
351 : *
352 : * \return The base name without any section names.
353 : */
354 4 : std::string option_info::get_basename() const
355 : {
356 4 : std::string::size_type const pos(f_name.rfind("::"));
357 4 : if(pos == std::string::npos)
358 : {
359 1 : return f_name;
360 : }
361 :
362 3 : return f_name.substr(pos + 2);
363 : }
364 :
365 :
366 : /** \brief Retrieve the name of the sections.
367 : *
368 : * The name of an option can include section names. These
369 : * are rarely used on the command line, but they are useful for
370 : * configuration files if you want to create multiple layers of
371 : * options (a.k.a. sections.)
372 : *
373 : * This function returns all the section names found in this option
374 : * name. The last scope operator gets removed too.
375 : *
376 : * If the name does not include any sections, then this function returns
377 : * an empty string.
378 : *
379 : * \return The section names without the basename.
380 : */
381 4 : std::string option_info::get_section_name() const
382 : {
383 4 : std::string::size_type const pos(f_name.rfind("::"));
384 4 : if(pos == std::string::npos)
385 : {
386 1 : return std::string();
387 : }
388 :
389 3 : return f_name.substr(0, pos);
390 : }
391 :
392 :
393 : /** \brief Retrieve a list of section names.
394 : *
395 : * The name of an option can include section names. These
396 : * are rarely used on the command line, but they are useful for
397 : * configuration files if you want to create multiple layers of
398 : * options (a.k.a. sections.)
399 : *
400 : * This function returns a string_list_t of the section names found in
401 : * this option name.
402 : *
403 : * If the name does not include any sections, then this function returns
404 : * an empty list.
405 : *
406 : * \return The list of section name.
407 : */
408 4 : string_list_t option_info::get_section_name_list() const
409 : {
410 4 : std::string::size_type const pos(f_name.rfind("::"));
411 4 : if(pos == std::string::npos)
412 : {
413 1 : return string_list_t();
414 : }
415 :
416 6 : string_list_t section_list;
417 12 : snapdev::tokenize_string(section_list
418 6 : , f_name.substr(0, pos)
419 : , "::"
420 : , true
421 6 : , std::string()
422 : , &snapdev::string_predicate<string_list_t>);
423 3 : return section_list;
424 : }
425 :
426 :
427 : /** \brief Check whether this is the default option.
428 : *
429 : * This function checks whether this option represents the default option.
430 : * The default option is where non-options, generally filenames, are added
431 : * when not following an argument.
432 : *
433 : * The name of the default option is always "--". However, it is not
434 : * required. When no default option is defined, filenames can't be
435 : * specified and when such are found on the command line, an error
436 : * ensues.
437 : *
438 : * \return true if the name of the option is "--".
439 : */
440 1761 : bool option_info::is_default_option() const
441 : {
442 1761 : return has_flag(GETOPT_FLAG_DEFAULT_OPTION)
443 1761 : || (f_name.size() == 2 && f_name[0] == '-' && f_name[1] == '-');
444 : }
445 :
446 :
447 : /** \brief Get the flags.
448 : *
449 : * The options have flags determining various sub-options available
450 : * to them. Right now we have flags to tell how each option can be
451 : * used (on the command line, in an environment variable, or in
452 : * a configuration file.)
453 : *
454 : * \note
455 : * We have the GETOPT_FLAG_ALIAS flag which is used to define
456 : * an alias. That means values do not get set in an option which
457 : * is marked as an alias. Instead, they get set in the option
458 : * which is being aliased. This means your software does not have
459 : * to check both options. The setup function will actually call
460 : * the set_alias() function at some point to finalize aliases
461 : * so you do not really need the flag, except to know that no
462 : * value will be defined here because it will instead be saved
463 : * in the aliased option.
464 : *
465 : * \param[in] flags The new flags.
466 : */
467 67 : void option_info::set_flags(flag_t flags)
468 : {
469 67 : f_flags = flags;
470 67 : }
471 :
472 :
473 : /** \brief Make sure a given flag is set.
474 : *
475 : * This function adds the given flag from the set of flags being set.
476 : *
477 : * \param[in] flag The flag(s) to set.
478 : */
479 1667 : void option_info::add_flag(flag_t flag)
480 : {
481 1667 : f_flags |= flag;
482 1667 : }
483 :
484 :
485 : /** \brief Make sure a given flag is not set.
486 : *
487 : * This function removes the given flag from the set of flags being set.
488 : *
489 : * \param[in] flag The flag(s) to clear.
490 : */
491 46 : void option_info::remove_flag(flag_t flag)
492 : {
493 46 : f_flags &= ~flag;
494 46 : }
495 :
496 :
497 : /** \brief Retrieve the flags.
498 : *
499 : * This function retrieves all the flags defined in this option.
500 : *
501 : * To just check whether a flag is set or not, use the has_flag()
502 : * function instead.
503 : *
504 : * \return This option flags.
505 : */
506 1182 : flag_t option_info::get_flags() const
507 : {
508 1182 : return f_flags;
509 : }
510 :
511 :
512 : /** \brief Check whether a flag is set.
513 : *
514 : * This function is used to check whether a flag is set or not.
515 : *
516 : * \note
517 : * The \p flag parameter can be set to more than one flag in which case
518 : * the function returns true if any one of those flags is set.
519 : *
520 : * \return true if the flag is set, false otherwise.
521 : */
522 17703 : bool option_info::has_flag(flag_t flag) const
523 : {
524 17703 : return (f_flags & flag) != 0;
525 : }
526 :
527 :
528 : /** \brief Check whether this option has a default value.
529 : *
530 : * Whenever an option is given a default value, the GETOPT_FLAG_HAS_DEFAULT
531 : * flag gets set. This allows us to distinguish between an option with a
532 : * default which is the empty string and an option without a default.
533 : *
534 : * The set_default() forces the flag to be set.
535 : *
536 : * The remove_default() clears the flag.
537 : *
538 : * \return true if the flag is set, false otherwise.
539 : *
540 : * \sa set_default()
541 : * \sa remove_default()
542 : * \sa get_default()
543 : */
544 384 : bool option_info::has_default() const
545 : {
546 384 : return has_flag(GETOPT_FLAG_HAS_DEFAULT);
547 : }
548 :
549 :
550 : /** \brief Set the default value.
551 : *
552 : * This function sets the default value for this option.
553 : *
554 : * The default value is always defined as a string, but it can later be
555 : * converted to a different type using the option validator.
556 : *
557 : * Often, though, the default value is not compatible with the validator.
558 : * For example, you may have a parameter which is set to a percentage
559 : * from -100% to +100% and the default may be the string "off".
560 : *
561 : * \note
562 : * After calling this function, the option is viewed as having a default
563 : * even if that's the empty string.
564 : *
565 : * \param[in] default_value The new default value for this option.
566 : *
567 : * \sa remove_default()
568 : * \sa has_default()
569 : * \sa get_default()
570 : */
571 111 : void option_info::set_default(std::string const & default_value)
572 : {
573 111 : f_default_value = default_value;
574 111 : add_flag(GETOPT_FLAG_HAS_DEFAULT);
575 111 : }
576 :
577 :
578 : /** \brief Set the default value of this option.
579 : *
580 : * This function is an overload which allows us to call set_default()
581 : * with a nullptr.
582 : *
583 : * \param[in] default_value The new default value for this option.
584 : *
585 : * \sa remove_default()
586 : * \sa has_default()
587 : * \sa get_default()
588 : */
589 1389 : void option_info::set_default(char const * default_value)
590 : {
591 1389 : if(default_value != nullptr)
592 : {
593 97 : set_default(std::string(default_value));
594 : }
595 1389 : }
596 :
597 :
598 : /** \brief Remove the default value.
599 : *
600 : * Call this function remove the default value. The default string gets
601 : * cleared and the GETOPT_FLAG_NO_DEFAULT flag gets set.
602 : *
603 : * \sa set_default()
604 : * \sa has_default()
605 : * \sa get_default()
606 : */
607 4 : void option_info::remove_default()
608 : {
609 4 : f_default_value.clear();
610 4 : remove_flag(GETOPT_FLAG_HAS_DEFAULT);
611 4 : }
612 :
613 :
614 : /** \brief Retrieve the default value.
615 : *
616 : * This function returns the default value.
617 : *
618 : * \return The default string value.
619 : */
620 726 : std::string const & option_info::get_default() const
621 : {
622 726 : return f_default_value;
623 : }
624 :
625 :
626 : /** \brief Set the help string for this option.
627 : *
628 : * The usage() function prints this string whenever the command
629 : * line includes the help command line option (such as `-h` or
630 : * `--help`.)
631 : *
632 : * The string can include various flags such as `%p` to include
633 : * dynamically defined parameters. See the process_help_string()
634 : * function for additional details about these parameters.
635 : *
636 : * \note
637 : * When using a special flag (i.e. GETOPT_FLAG_HELP), the help value
638 : * string is used as the value used by that special feature:
639 : *
640 : * \li GETOPT_FLAG_HELP
641 : *
642 : * It represents a string to print out by the usage() function. The option
643 : * purpose is solaly for adding a string of help in the output.
644 : *
645 : * \li GETOPT_FLAG_EXTERNAL_OPTIONS
646 : *
647 : * It represents the filename to read additional advgetopt options. In
648 : * some cases, your static array of option structures is to define this
649 : * special flag.
650 : *
651 : * \li GETOPT_FLAG_LICENSE
652 : *
653 : * It represents the program license.
654 : *
655 : * \li GETOPT_FLAG_COPYRIGHT
656 : *
657 : * It represents the program copyright notice.
658 : *
659 : * \param[in] help The help string for this option.
660 : */
661 1414 : void option_info::set_help(std::string const & help)
662 : {
663 1414 : f_help = help;
664 1414 : }
665 :
666 :
667 : /** \brief Set the help string for this option.
668 : *
669 : * This function is an overload which allows us to call set_help() with
670 : * a nullptr and not crash. We just ignore the call when that happens.
671 : *
672 : * \param[in] help The help string for this option or nullptr.
673 : */
674 1397 : void option_info::set_help(char const * help)
675 : {
676 1397 : if(help != nullptr)
677 : {
678 1387 : set_help(std::string(help));
679 : }
680 1397 : }
681 :
682 :
683 : /** \brief Get the help string.
684 : *
685 : * This function returns the help string for this command line option.
686 : *
687 : * \warning
688 : * Note that when a special flag is set, this string may represent something
689 : * else that a help string.
690 : *
691 : * \return The help string of this argument.
692 : */
693 299 : std::string const & option_info::get_help() const
694 : {
695 299 : return f_help;
696 : }
697 :
698 :
699 : /** \brief Set the validator for this option.
700 : *
701 : * This function parses the specified name and optional parameters and
702 : * create a corresponding validator for this option.
703 : *
704 : * The \p name_and_params string can be defined as one of:
705 : *
706 : * \code
707 : * <validator-name>
708 : * <validator-name>()
709 : * <validator-name>(<param1>)
710 : * <validator-name>(<param1>, <param2>, ...)
711 : * \endcode
712 : *
713 : * The list of parameters is optional. There may be no, just one,
714 : * or any number of parameters. How the parameters are parsed is left
715 : * to the validator to decide.
716 : *
717 : * If the input string is empty, the current validator, if one is
718 : * installed, gets removed.
719 : *
720 : * \note
721 : * If the option_info already has a set of values, they get validated
722 : * against the new validator. Any value which does not validate gets
723 : * removed at once. The validation process also generates an error
724 : * when an invalid error is found. Note that it is expected that you
725 : * will setup a validator before you start parsing data so this feature
726 : * should seldom be used.
727 : *
728 : * \param[in] name_and_params The validator name and parameters.
729 : *
730 : * \return true if the validator was installed and all existing values were
731 : * considered valid.
732 : */
733 28 : bool option_info::set_validator(std::string const & name_and_params)
734 : {
735 28 : return set_validator(validator::create(name_and_params));
736 : }
737 :
738 :
739 : /** \brief Set the validator for this option.
740 : *
741 : * Options may be assigned a validator. Without a validator, any value
742 : * is considered valid.
743 : *
744 : * A value is checked when you call the validates() function. The function
745 : * returns true if the value is considered valid. False in all other cases.
746 : *
747 : * You can define your own validators and add them to the library list of
748 : * available validators before using the library in order to get your
749 : * options to use said validators.
750 : *
751 : * \note
752 : * If the option_info already has a set of values, they get validated
753 : * against the new validator. Any value which does not validate gets
754 : * removed at once. The validation process also generates an error
755 : * when an invalid error is found. Note that it is expected that you
756 : * will setup a validator before you start parsing data so this feature
757 : * should seldom be used.
758 : *
759 : * \param[in] validator A pointer to a validator.
760 : *
761 : * \return true if the validator was installed and all existing values were
762 : * considered valid.
763 : */
764 28 : bool option_info::set_validator(validator::pointer_t validator)
765 : {
766 28 : f_validator = validator;
767 :
768 : // make sure that all existing values validate against this
769 : // new validator
770 : //
771 28 : std::size_t const size(f_value.size());
772 28 : bool const r(validate_all_values());
773 28 : if(size != f_value.size())
774 : {
775 3 : value_changed(0);
776 : }
777 28 : return r;
778 : }
779 :
780 :
781 : /** \brief Clear the validator.
782 : *
783 : * This function removes the existing validator by resetting the pointer
784 : * back to nullptr.
785 : *
786 : * \param[in] null_ptr Ignored.
787 : *
788 : * \return Always true since no validator means any existing values would
789 : * be considered valid.
790 : */
791 5 : bool option_info::set_validator(std::nullptr_t null_ptr)
792 : {
793 5 : snapdev::NOT_USED(null_ptr);
794 :
795 5 : f_validator.reset();
796 :
797 5 : return true;
798 : }
799 :
800 :
801 : /** \brief Check a value validity.
802 : *
803 : * This function us used internally to verify values that get added at
804 : * the time they get added. It runs the validator::validate() function
805 : * and returns true if the value is considered valid. When the value
806 : * does not validate, it returns false and removes the value from the
807 : * f_value vector. This means no invalid values are ever kept in an
808 : * option_info object.
809 : *
810 : * An option without a validator has values that are always valid.
811 : * Also, an empty value is always considered valid.
812 : *
813 : * \note
814 : * This function is private since there is no need for the user of
815 : * the option_info to ever call it (i.e. it automatically gets called
816 : * any time a value gets added to the f_value vector.)
817 : *
818 : * \param[in] idx The value to check.
819 : *
820 : * \return true if the value is considered valid, false otherwise.
821 : */
822 664 : bool option_info::validates(int idx)
823 : {
824 664 : if(static_cast<size_t>(idx) >= f_value.size())
825 : {
826 : throw getopt_undefined( // LCOV_EXCL_LINE
827 : "option_info::get_value(): no value at index " // LCOV_EXCL_LINE
828 : + std::to_string(idx) // LCOV_EXCL_LINE
829 : + " (idx >= " // LCOV_EXCL_LINE
830 : + std::to_string(f_value.size()) // LCOV_EXCL_LINE
831 : + ") for --" // LCOV_EXCL_LINE
832 : + f_name // LCOV_EXCL_LINE
833 : + " so you can't get this value."); // LCOV_EXCL_LINE
834 : }
835 :
836 : // the value is considered valid when:
837 : // * there is no validator
838 : // * if the value is empty
839 : // * when the value validate against the specified validator
840 : //
841 1328 : if(f_validator == nullptr
842 67 : || f_value[idx].empty()
843 723 : || f_validator->validate(f_value[idx]))
844 : {
845 646 : return true;
846 : }
847 :
848 36 : cppthread::log << cppthread::log_level_t::error
849 18 : << "input \""
850 18 : << f_value[idx]
851 18 : << "\" given to parameter --"
852 18 : << f_name
853 18 : << " is not considered valid."
854 36 : << cppthread::end;
855 :
856 : // get rid of that value since it does not validate
857 : //
858 18 : f_value.erase(f_value.begin() + idx);
859 18 : if(f_value.empty())
860 : {
861 10 : f_source = option_source_t::SOURCE_UNDEFINED;
862 : }
863 :
864 18 : return false;
865 : }
866 :
867 :
868 : /** \brief Retrieve a pointer to the validator.
869 : *
870 : * The validator of an option may be used for additional tasks such as
871 : * converting the value to a specific type (i.e. a string to an
872 : * integer, for example.)
873 : *
874 : * This function allows you to retrieve the validator to be able to
875 : * make use of those functions. You will have to use
876 : * std::dynamic_cast_pointer<>() to change the type of validator to
877 : * the specialized validator of this option. If that returns a null
878 : * pointer, then the option is not using that type of validator.
879 : *
880 : * \todo
881 : * Add a template function that does the cast for the caller.
882 : *
883 : * \return A pointer to this option validator.
884 : */
885 19 : validator::pointer_t option_info::get_validator() const
886 : {
887 19 : return f_validator;
888 : }
889 :
890 :
891 : /** \brief Set the alias option.
892 : *
893 : * After loading all the options, we run the link_aliases() function which
894 : * makes sure that all the options that are marked as an alias are
895 : * properly linked.
896 : *
897 : * \param[in] alias The final destination of this option.
898 : */
899 20 : void option_info::set_alias_destination(option_info::pointer_t destination)
900 : {
901 20 : if(destination->has_flag(GETOPT_FLAG_ALIAS))
902 : {
903 : throw getopt_invalid(
904 : "option_info::set_alias(): you can't set an alias as"
905 1 : " an alias of another option.");
906 : }
907 :
908 19 : f_alias_destination = destination;
909 19 : }
910 :
911 :
912 : /** \brief Get a link to the destination alias.
913 : *
914 : * This function returns a pointer to the aliased option.
915 : *
916 : * \return The alias or a nullptr.
917 : */
918 95 : option_info::pointer_t option_info::get_alias_destination() const
919 : {
920 95 : return f_alias_destination;
921 : }
922 :
923 :
924 : /** \brief Set the list of separators.
925 : *
926 : * Options marked with the GETOPT_FLAG_MULTIPLE flag
927 : * get their value cut by separators when such is found in an
928 : * environment variable or a configuration file.
929 : *
930 : * This function saves the list of separators in a vector.
931 : *
932 : * \param[in] separators The list of separators to be used for this argument.
933 : */
934 1390 : void option_info::set_multiple_separators(char const * const * separators)
935 : {
936 1390 : f_multiple_separators.clear();
937 1390 : if(separators == nullptr)
938 : {
939 1371 : return;
940 : }
941 :
942 73 : for(; *separators != nullptr; ++separators)
943 : {
944 27 : f_multiple_separators.push_back(*separators);
945 : }
946 : }
947 :
948 :
949 : /** \brief Set the list of separators.
950 : *
951 : * Options marked with the GETOPT_FLAG_MULTIPLE flag
952 : * get their value cut by separators when such is found in an
953 : * environment variable or a configuration file.
954 : *
955 : * This function saves the specified list of separators.
956 : *
957 : * \param[in] separators The list of separators to be used for this argument.
958 : */
959 7 : void option_info::set_multiple_separators(string_list_t const & separators)
960 : {
961 7 : f_multiple_separators = separators;
962 7 : }
963 :
964 :
965 : /** \brief Retrieve the list of separators for this argument.
966 : *
967 : * This function returns a reference to the list of separators of this
968 : * option. It is expected to be used when a value is found in a
969 : * configuration file or a command line in an environment variable.
970 : * Parameters on the command line are already broken down by the
971 : * shell and we do not do any further manipulation with those.
972 : *
973 : * \return A reference to the list of separators used to cut multiple
974 : * arguments found in a configuration file or an environment
975 : * variable.
976 : */
977 9 : string_list_t const & option_info::get_multiple_separators() const
978 : {
979 9 : return f_multiple_separators;
980 : }
981 :
982 :
983 : /** \brief Assign variables to this option info.
984 : *
985 : * The getopt object holds a set of variables which is can pass down to
986 : * the option info. If defined, then the get_value() function returns
987 : * a processed value (a.k.a. the `${...}` references in that value are
988 : * replaced by their corresponding value).
989 : *
990 : * \param[in] vars A pointer to a list of variables.
991 : */
992 1455 : void option_info::set_variables(variables::pointer_t vars)
993 : {
994 1455 : f_variables = vars;
995 1455 : }
996 :
997 :
998 : /** \brief Retrieve the list of variables held by this option info.
999 : *
1000 : * This option info object may replace variables in values (see get_value()
1001 : * for details) using this list of variables. Option info objects created
1002 : * by the getopt class always have this pointer set, although the list of
1003 : * variables may be empty.
1004 : *
1005 : * \return A pointer to the list of variables found in the option info object.
1006 : */
1007 0 : variables::pointer_t option_info::get_variables() const
1008 : {
1009 0 : return f_variables;
1010 : }
1011 :
1012 :
1013 : /** \brief Check whether one of the values matches the input.
1014 : *
1015 : * This function searches the set of existing values in this option_info
1016 : * and if found returns true.
1017 : *
1018 : * \note
1019 : * It is possible to add the same value multiple times. However, there are
1020 : * cases where you may not want to have the same value more than once.
1021 : * This function can be used to try to not do that.
1022 : *
1023 : * \param[in] value The value to search in this option.
1024 : *
1025 : * \return true if the value is already defined in this option_info.
1026 : *
1027 : * \sa set_value()
1028 : */
1029 9 : bool option_info::has_value(std::string const & value) const
1030 : {
1031 9 : auto const it(std::find(f_value.begin(), f_value.end(), value));
1032 9 : return it != f_value.end();
1033 : }
1034 :
1035 :
1036 : /** \brief Add a value to this option.
1037 : *
1038 : * Whenever an option is found it may be followed by one or more values.
1039 : * This function is used to add these values to this option.
1040 : *
1041 : * Later you can use the size() function to know how many values were
1042 : * added and the get_value() to retrieve any one of these values.
1043 : *
1044 : * \warning
1045 : * This function sets the value at offset 0 if it is already defined and
1046 : * the GETOPT_FLAG_MULTIPLE flag is not set in this option. In other words,
1047 : * you can't use this function to add multiple values if this option does
1048 : * not support that feature.
1049 : *
1050 : * \param[in] value The value to add to this option.
1051 : * \param[in] source Where the value comes from.
1052 : *
1053 : * \return true when the value was accepted (no error occurred).
1054 : *
1055 : * \sa set_value()
1056 : */
1057 463 : bool option_info::add_value(std::string const & value, option_source_t source)
1058 : {
1059 589 : return set_value(
1060 463 : has_flag(GETOPT_FLAG_MULTIPLE)
1061 126 : ? f_value.size()
1062 : : 0
1063 : , value
1064 463 : , source);
1065 : }
1066 :
1067 :
1068 : /** \brief Replace a value.
1069 : *
1070 : * This function is generally used to replace an existing value. If the
1071 : * index is set to the size of the existing set of values, then a new
1072 : * value is saved in the vector.
1073 : *
1074 : * This is particularly useful if you want to edit a configuration file.
1075 : *
1076 : * If the option comes with a validator, then the value gets checked
1077 : * against that validator. If that results in an error, the value is
1078 : * not added to the vector so an invalid value will never be returned
1079 : * by the option_info class.
1080 : *
1081 : * The value does not get added when it currently is locked or when
1082 : * it does not validate as per the validator of this option_info.
1083 : *
1084 : * \exception getopt_exception_undefined
1085 : * If the index is out of range (too large or negative), then this
1086 : * exception is raised.
1087 : *
1088 : * \param[in] idx The position of the value to update.
1089 : * \param[in] value The new value.
1090 : * \param[in] source Where the value comes from.
1091 : *
1092 : * \return true if the set_value() added the value.
1093 : *
1094 : * \sa add_value()
1095 : * \sa validates()
1096 : * \sa lock()
1097 : * \sa unlock()
1098 : */
1099 680 : bool option_info::set_value(int idx, std::string const & value, option_source_t source)
1100 : {
1101 680 : if(source == option_source_t::SOURCE_UNDEFINED)
1102 : {
1103 : throw getopt_logic_error(
1104 : "option_info::set_value(): called with SOURCE_UNDEFINED ("
1105 2 : + std::to_string(static_cast<int>(source))
1106 3 : + ").");
1107 : }
1108 :
1109 679 : if(has_flag(GETOPT_FLAG_LOCK))
1110 : {
1111 8 : return false;
1112 : }
1113 :
1114 671 : if(source == option_source_t::SOURCE_DIRECT
1115 671 : && !has_flag(GETOPT_FLAG_DYNAMIC_CONFIGURATION))
1116 : {
1117 2 : cppthread::log << cppthread::log_level_t::error
1118 1 : << "option \"--"
1119 1 : << f_name
1120 1 : << "\" can't be directly updated."
1121 2 : << cppthread::end;
1122 1 : return false;
1123 : }
1124 :
1125 670 : if(has_flag(GETOPT_FLAG_MULTIPLE))
1126 : {
1127 142 : if(static_cast<size_t>(idx) > f_value.size())
1128 : {
1129 : throw getopt_logic_error(
1130 : "option_info::set_value(): no value at index "
1131 4 : + std::to_string(idx)
1132 6 : + " and it is not the last available index + 1 (idx > "
1133 8 : + std::to_string(f_value.size())
1134 6 : + ") so you can't set this value (try add_value() maybe?).");
1135 : }
1136 : }
1137 : else
1138 : {
1139 528 : if(idx != 0)
1140 : {
1141 : throw getopt_logic_error(
1142 : "option_info::set_value(): single value option \"--"
1143 4 : + f_name
1144 6 : + "\" does not accepts index "
1145 8 : + std::to_string(idx)
1146 6 : + " which is not 0.");
1147 : }
1148 : }
1149 :
1150 666 : f_source = source;
1151 666 : if(static_cast<size_t>(idx) == f_value.size())
1152 : {
1153 510 : f_value.push_back(value);
1154 : }
1155 : else
1156 : {
1157 156 : if(f_value[idx] == value)
1158 : {
1159 : // no change, we can return as is
1160 : //
1161 20 : return true;
1162 : }
1163 136 : f_value[idx] = value;
1164 : }
1165 646 : f_integer.clear();
1166 646 : f_double.clear();
1167 :
1168 646 : bool const r(validates(idx));
1169 :
1170 646 : value_changed(idx);
1171 :
1172 646 : return r;
1173 : }
1174 :
1175 :
1176 : /** \brief Set a multi-value at once.
1177 : *
1178 : * This function views the \p value parameter as a multi-value parameter
1179 : * which it breaks down in multiple parameters and add the results to this
1180 : * option_info object as the current value(s).
1181 : *
1182 : * To separate the values, the function makes use of the separators as
1183 : * set by one the set_multiple_separators() functions.
1184 : *
1185 : * The resulting values must not be the empty string. Empty strings are
1186 : * ignored. So if the separator is a comma and you write:
1187 : *
1188 : * \code
1189 : * foo,,,bar
1190 : * \endcode
1191 : *
1192 : * The result includes "foo" and "bar" and no empty strings.
1193 : *
1194 : * \note
1195 : * The function has the side effect of clearing any existing parameters
1196 : * first. So only the newly defined parameters in \p value will be set
1197 : * in the option once the function returns.
1198 : *
1199 : * \todo
1200 : * Add support for quoted values
1201 : *
1202 : * \param[in] value The multi-value to save in this option.
1203 : * \param[in] source Where the value comes from.
1204 : *
1205 : * \return true if all the values in \p value were considered valid.
1206 : *
1207 : * \sa add_value()
1208 : * \sa set_value()
1209 : */
1210 33 : bool option_info::set_multiple_values(std::string const & value, option_source_t source)
1211 : {
1212 33 : if(source == option_source_t::SOURCE_UNDEFINED)
1213 : {
1214 : throw getopt_logic_error(
1215 : "option_info::set_multiple_values(): called with SOURCE_UNDEFINED ("
1216 2 : + std::to_string(static_cast<int>(source))
1217 3 : + ").");
1218 : }
1219 :
1220 64 : string_list_t result;
1221 32 : split_string(unquote(value, "[]"), result, f_multiple_separators);
1222 :
1223 64 : if(!has_flag(GETOPT_FLAG_MULTIPLE)
1224 32 : && result.size() > 1)
1225 : {
1226 : throw getopt_logic_error(
1227 : "option_info::set_multiple_value(): parameter --"
1228 2 : + f_name
1229 3 : + " expects zero or one parameter. The set_multiple_value() function should not be called with parameters that only accept one value.");
1230 : }
1231 :
1232 31 : f_source = source;
1233 31 : f_value.swap(result);
1234 31 : f_integer.clear();
1235 31 : f_double.clear();
1236 :
1237 31 : bool const r(validate_all_values());
1238 :
1239 31 : if(f_value != result)
1240 : {
1241 : // TBD: should we not call this function with all instances?
1242 : // i.e. for(int idx(0); idx < f_value.size(); ++idx) ...
1243 : // and check each value in f_value with the old value in
1244 : // the result variable (knowing that result may be smaller)
1245 : //
1246 29 : value_changed(0);
1247 : }
1248 :
1249 62 : return r;
1250 : }
1251 :
1252 :
1253 : /** \brief Validate all the values of this option_info object.
1254 : *
1255 : * Whenever you change the validator of an option_info, or change
1256 : * all the values with set_multiple_value(), all the values get
1257 : * verified using this function. The function removes any value
1258 : * which does not validate according to the current validator.
1259 : *
1260 : * \note
1261 : * Keep in mind that an empty value is always considered valid,
1262 : * no matter what the validator is. This is because when you
1263 : * use an option without a value (i.e. `--order` instead of
1264 : * `--order asc`) the value is set to the empty string unless
1265 : * there is a default. This allows you to know that the
1266 : * option was used without a value, which is useful for some
1267 : * options.
1268 : *
1269 : * \return true if all the values were considered valid.
1270 : */
1271 59 : bool option_info::validate_all_values()
1272 : {
1273 59 : bool all_valid(true);
1274 59 : if(f_validator != nullptr)
1275 : {
1276 35 : for(size_t idx(0); idx < f_value.size(); )
1277 : {
1278 18 : if(!validates(idx))
1279 : {
1280 : // the value was removed, so do not increment `idx`
1281 : //
1282 9 : all_valid = false;
1283 : }
1284 : else
1285 : {
1286 9 : ++idx;
1287 : }
1288 : }
1289 : }
1290 :
1291 59 : return all_valid;
1292 : }
1293 :
1294 :
1295 : /** \brief Check whether a value is defined.
1296 : *
1297 : * When parsing the options on the command line or a configuration file,
1298 : * values get added to the various existing option_info. If a special
1299 : * "*" option is also defined, then any value found on the command line
1300 : * or the configuration file are returned.
1301 : *
1302 : * To know whether this or that option was defined with a value, use
1303 : * this function. Even an option which doesn't come with a parameter
1304 : * will get an is_defined() returning true once it was found on the
1305 : * command line. The value will be the empty string.
1306 : *
1307 : * \return true if that option was found on the command line, in the
1308 : * environment variable, or in the configuration file.
1309 : */
1310 2312 : bool option_info::is_defined() const
1311 : {
1312 2312 : return !f_value.empty();
1313 : }
1314 :
1315 :
1316 : /** \brief Return the source of this option info.
1317 : *
1318 : * This function returns the source of this option, i.e. whether it came
1319 : * from the command line, the environment variable, a configuration file,
1320 : * or some other source that you can define.
1321 : *
1322 : * The source is similar to a priority in the sense that a source with a
1323 : * higher number cannot overwrite the value of a smaller source. The source
1324 : * is set at the same time as you set the option. The mechanism may not be
1325 : * working exactly as expected when trying to add options from different
1326 : * sources.
1327 : *
1328 : * \note
1329 : * In the old version, the value would be the value set with the last
1330 : * set_value() command. That worked because we did not try to support
1331 : * fully dynamic options. Now we want to have the ability to set an
1332 : * option on the command line and that has to prevent the set from
1333 : * a dynamic source. Since the dynamic source would do the set_value()
1334 : * at a later time, just the order is not enough to know whether the
1335 : * dynamic source has permission to overwrite that value.
1336 : *
1337 : * \return The source of the option info.
1338 : */
1339 5 : option_source_t option_info::source() const
1340 : {
1341 5 : return f_source;
1342 : }
1343 :
1344 :
1345 : /** \brief Whether the sources should be traced.
1346 : *
1347 : * This is a global flag that you can set before calling any getopt functions
1348 : * so that way you can make sure that you get a full trace of all the
1349 : * sources for all your options. Then you can use the --show-sources
1350 : * command line options to see the resulting data.
1351 : *
1352 : * \note
1353 : * This option is costly since it saves a lot of data, which is why we have
1354 : * it as an option. If the getopt() function detects in the argv passed to
1355 : * it a "--show-sources" option, then it will automatically call this
1356 : * function with true, even before it starts parsing anything. The flag is
1357 : * false by default.
1358 : *
1359 : * \param[in] trace Whether the sources should be traced.
1360 : */
1361 1 : void option_info::set_trace_sources(bool trace)
1362 : {
1363 1 : g_trace_sources = trace;
1364 1 : }
1365 :
1366 :
1367 : /** \brief Get the trace of this option.
1368 : *
1369 : * An option can be marked for tracing. This allows you to see exactly
1370 : * which value came from which source. We currently support multiple
1371 : * sources such as the command line, environment variable, direct,
1372 : * dynamic, configuration files.
1373 : *
1374 : * \return An array of strings representing the source of each value
1375 : * in the order they were set in this option_info.
1376 : */
1377 89 : string_list_t const & option_info::trace_sources() const
1378 : {
1379 89 : return f_trace_sources;
1380 : }
1381 :
1382 :
1383 : /** \brief Save the filename of the current configuration file.
1384 : *
1385 : * While parsing a configuration file, this function gets called to
1386 : * set the name which is used to generate the trace of the source
1387 : * of all the configuration data.
1388 : */
1389 267 : void option_info::set_configuration_filename(std::string const & filename)
1390 : {
1391 267 : g_configuration_filename = filename;
1392 267 : }
1393 :
1394 :
1395 : /** \brief Retrieve the number of values defined for this option.
1396 : *
1397 : * This function returns the number of values that were found for this
1398 : * option.
1399 : *
1400 : * If the option is marked as GETOPT_FLAG_MULTIPLE, then this function
1401 : * may return 0 or more. Without that flag, this function only returns
1402 : * 0 or 1.
1403 : *
1404 : * You must use the size() parameter to know how many items are defined
1405 : * and call the get_value() with a correct `idx` parameter (i.e. a value
1406 : * between 0 and `size() - 1`.)
1407 : *
1408 : * \return The number of values defined in this option.
1409 : */
1410 488 : size_t option_info::size() const
1411 : {
1412 488 : return f_value.size();
1413 : }
1414 :
1415 :
1416 : /** \brief Retrieve the value.
1417 : *
1418 : * This function returns the value for this option. By default, set the
1419 : * \p idx parameter to zero.
1420 : *
1421 : * The number of values is defined by the size() function.
1422 : *
1423 : * The is_defined() function returns true if at least one value is defined.
1424 : * It is a good idea to check first otherwise you will get an exception.
1425 : *
1426 : * If the parameter is marked as one that can be processed through the
1427 : * variables::process_value() function and the variables were defined
1428 : * with set_variables(), then the value will be processed for variables
1429 : * unless you set the \p raw parameter to true.
1430 : *
1431 : * \exception getopt_exception_undefined
1432 : * If the \p idx parameter is too large or no value was found for this
1433 : * option, then this function raises an invalid error.
1434 : *
1435 : * \param[in] idx The index of the parameter to retrieve.
1436 : * \param[in] raw Whether to allow the variable processing or not.
1437 : *
1438 : * \return The value at \p idx.
1439 : */
1440 1237 : std::string option_info::get_value(int idx, bool raw) const
1441 : {
1442 1237 : if(static_cast<size_t>(idx) >= f_value.size())
1443 : {
1444 : throw getopt_undefined(
1445 : "option_info::get_value(): no value at index "
1446 4 : + std::to_string(idx)
1447 6 : + " (idx >= "
1448 8 : + std::to_string(f_value.size())
1449 6 : + ") for --"
1450 6 : + f_name
1451 6 : + " so you can't get this value.");
1452 : }
1453 :
1454 2470 : if(!raw
1455 1235 : && f_variables != nullptr
1456 1366 : && has_flag(GETOPT_FLAG_PROCESS_VARIABLES))
1457 : {
1458 0 : return f_variables->process_value(f_value[idx]);
1459 : }
1460 : else
1461 : {
1462 1235 : return f_value[idx];
1463 : }
1464 : }
1465 :
1466 :
1467 : /** \brief Get the value as a long.
1468 : *
1469 : * This function returns the value converted to a `long`.
1470 : *
1471 : * If the value does not represent a valid long value, an error is
1472 : * emitted through the logger.
1473 : *
1474 : * The value will be parsed through the variables if defined and this
1475 : * parameter allows it. This means the value may be a variable reference
1476 : * instead of an actually value (i.e. `${one}`)
1477 : *
1478 : * \note
1479 : * The function will transform all the values in case this is a
1480 : * GETOPT_FLAG_MULTIPLE option and cache the results.
1481 : * Calling the function many times with the same index is very fast
1482 : * after the first time.
1483 : *
1484 : * \exception getopt_exception_undefined
1485 : * If the value was not defined, the function raises this exception.
1486 : *
1487 : * \param[in] idx The index of the value to retrieve as a long.
1488 : *
1489 : * \return The value at \p idx converted to a long or -1 on error.
1490 : */
1491 157 : long option_info::get_long(int idx) const
1492 : {
1493 157 : if(static_cast<size_t>(idx) >= f_value.size())
1494 : {
1495 : throw getopt_undefined(
1496 : "option_info::get_long(): no value at index "
1497 2 : + std::to_string(idx)
1498 3 : + " (idx >= "
1499 4 : + std::to_string(f_value.size())
1500 3 : + ") for --"
1501 3 : + f_name
1502 3 : + " so you can't get this value.");
1503 : }
1504 :
1505 : // since we may change the f_integer vector between threads,
1506 : // add protection (i.e. most everything else is created at the
1507 : // beginning so in the main thread)
1508 : //
1509 312 : cppthread::guard lock(get_global_mutex());
1510 :
1511 156 : if(f_integer.size() != f_value.size())
1512 : {
1513 : // we did not yet convert to integers do that now
1514 : //
1515 88 : size_t const max(f_value.size());
1516 180 : for(size_t i(f_integer.size()); i < max; ++i)
1517 : {
1518 102 : std::int64_t v;
1519 102 : if(!validator_integer::convert_string(get_value(i), v))
1520 : {
1521 10 : f_integer.clear();
1522 :
1523 20 : cppthread::log << cppthread::log_level_t::error
1524 10 : << "invalid number ("
1525 10 : << f_value[i]
1526 10 : << ") in parameter --"
1527 10 : << f_name
1528 10 : << " at offset "
1529 10 : << i
1530 10 : << "."
1531 20 : << cppthread::end;
1532 10 : return -1;
1533 : }
1534 92 : f_integer.push_back(v);
1535 : }
1536 : }
1537 :
1538 146 : return f_integer[idx];
1539 : }
1540 :
1541 :
1542 : /** \brief Get the value as a double.
1543 : *
1544 : * This function returns the value converted to a `double`.
1545 : *
1546 : * If the value does not represent a valid double value, an error is
1547 : * emitted through the logger.
1548 : *
1549 : * The value will be parsed through the variables if defined and this
1550 : * parameter allows it. This means the value may be a variable reference
1551 : * instead of an actually value (i.e. `${pi}`)
1552 : *
1553 : * \note
1554 : * The function will transform all the values in case this is a
1555 : * GETOPT_FLAG_MULTIPLE option and cache the results.
1556 : * Calling the function many times with the same index is very fast
1557 : * after the first time.
1558 : *
1559 : * \exception getopt_exception_undefined
1560 : * If the value was not defined, the function raises this exception.
1561 : *
1562 : * \param[in] idx The index of the value to retrieve as a double.
1563 : *
1564 : * \return The value at \p idx converted to a double or -1.0 on error.
1565 : */
1566 0 : double option_info::get_double(int idx) const
1567 : {
1568 0 : if(static_cast<size_t>(idx) >= f_value.size())
1569 : {
1570 : throw getopt_undefined(
1571 : "option_info::get_double(): no value at index "
1572 0 : + std::to_string(idx)
1573 0 : + " (idx >= "
1574 0 : + std::to_string(f_value.size())
1575 0 : + ") for --"
1576 0 : + f_name
1577 0 : + " so you can't get this value.");
1578 : }
1579 :
1580 : // since we may change the f_integer vector between threads,
1581 : // add protection (i.e. most everything else is created at the
1582 : // beginning so in the main thread)
1583 : //
1584 0 : cppthread::guard lock(get_global_mutex());
1585 :
1586 0 : if(f_double.size() != f_value.size())
1587 : {
1588 : // we did not yet convert to doubles do that now
1589 : //
1590 0 : size_t const max(f_value.size());
1591 0 : for(size_t i(f_double.size()); i < max; ++i)
1592 : {
1593 0 : double v;
1594 0 : if(!validator_double::convert_string(get_value(i), v))
1595 : {
1596 0 : f_double.clear();
1597 :
1598 0 : cppthread::log << cppthread::log_level_t::error
1599 0 : << "invalid number ("
1600 0 : << f_value[i]
1601 0 : << ") in parameter --"
1602 0 : << f_name
1603 0 : << " at offset "
1604 0 : << i
1605 0 : << "."
1606 0 : << cppthread::end;
1607 0 : return -1;
1608 : }
1609 0 : f_double.push_back(v);
1610 : }
1611 : }
1612 :
1613 0 : return f_double[idx];
1614 : }
1615 :
1616 :
1617 : /** \brief Lock this value.
1618 : *
1619 : * This function allows for locking a value so further reading of data
1620 : * will not overwrite it.
1621 : *
1622 : * When parsing the data we have multiple levels. Here are these levels
1623 : * in priority order (first option found is the one we keep):
1624 : *
1625 : * \li Command line options
1626 : * \li Environment Variables
1627 : * \li Configuration File: Local (`./\<name>.conf`)
1628 : * \li Configuration File: User's (`~/.config/\<proc>/\<name>.conf`)
1629 : * \li Configuration File: Project sub-folder (`/etc/\<proc>/\<proc>.d/\<ohter-name>.conf`)
1630 : * \li Configuration File: Project folder (`/etc/\<proc>/\<other-name>.conf`)
1631 : * \li Configuration File: System sub-folder (`/etc/\<proc>/\<name>.conf`)
1632 : * \li Configuration File: System folder (`/etc/\<proc>/\<name>.conf`)
1633 : *
1634 : * \note
1635 : * Most of our packages do not have a Project and a System set of
1636 : * configuration files. Often they will have just the System files.
1637 : *
1638 : * We use this lock because we want to support multiple values so just
1639 : * detecting that a value is set to not add more options is not a good
1640 : * test. Instead we lock the values that are set before moving to the
1641 : * next level.
1642 : *
1643 : * \param[in] always Always lock that option, whether it is defined or not.
1644 : */
1645 6 : void option_info::lock(bool always)
1646 : {
1647 6 : if(!always)
1648 : {
1649 4 : if(!is_defined())
1650 : {
1651 2 : return;
1652 : }
1653 : }
1654 :
1655 4 : add_flag(GETOPT_FLAG_LOCK);
1656 : }
1657 :
1658 :
1659 : /** \brief Unlock this value.
1660 : *
1661 : * This function does the opposite of the lock() function. It allows for
1662 : * the value to be updated again.
1663 : *
1664 : * Once the getpot object is done parsing all the input, it unlocks all
1665 : * the values using this function. The unlock is always unconditional.
1666 : */
1667 4 : void option_info::unlock()
1668 : {
1669 4 : remove_flag(GETOPT_FLAG_LOCK);
1670 4 : }
1671 :
1672 :
1673 : /** \brief Reset this value.
1674 : *
1675 : * This function clears the value so it is marked as undefined again.
1676 : *
1677 : * To reuse the same getopt object multiple times, you can use the
1678 : * reset() function which clears the values. Then you can parse a
1679 : * new set of argc/argv parameters.
1680 : */
1681 25 : void option_info::reset()
1682 : {
1683 25 : if(is_defined())
1684 : {
1685 23 : f_source = option_source_t::SOURCE_UNDEFINED;
1686 23 : f_value.clear();
1687 23 : f_integer.clear();
1688 23 : f_double.clear();
1689 :
1690 23 : value_changed(0);
1691 : }
1692 25 : }
1693 :
1694 :
1695 : /** \brief Add a callback to call on a change to this value.
1696 : *
1697 : * Since we now officially support dynamically setting option values, we
1698 : * decided to add a callback mechanism that lets you know that an option
1699 : * changed. That way you can react to the change as soon as possible instead
1700 : * of having to poll for the value once in a while.
1701 : *
1702 : * \param[in] c The callback. Usually an std::bind() call.
1703 : *
1704 : * \return The new callback identifier.
1705 : */
1706 2 : option_info::callback_id_t option_info::add_callback(callback_t const & c)
1707 : {
1708 4 : cppthread::guard lock(get_global_mutex());
1709 :
1710 2 : ++f_next_callback_id;
1711 2 : f_callbacks.emplace_back(f_next_callback_id, c);
1712 4 : return f_next_callback_id;
1713 : }
1714 :
1715 :
1716 : /** \brief Remove a callback.
1717 : *
1718 : * This function is the opposite of the add_callback(). It removes a callback
1719 : * that you previously added. This is useful if you are interested in hearing
1720 : * about the value when set but are not interested at all about future
1721 : * changes.
1722 : *
1723 : * \param[in] id The id returned by the add_callback() function.
1724 : */
1725 3 : void option_info::remove_callback(callback_id_t id)
1726 : {
1727 6 : cppthread::guard lock(get_global_mutex());
1728 :
1729 3 : auto it(std::find_if(
1730 : f_callbacks.begin()
1731 : , f_callbacks.end()
1732 4 : , [id](auto e)
1733 4 : {
1734 4 : return e.f_id == id;
1735 7 : }));
1736 3 : if(it != f_callbacks.end())
1737 : {
1738 2 : f_callbacks.erase(it);
1739 : }
1740 3 : }
1741 :
1742 :
1743 : /** \brief Call whenever the value changed so we can handle callbacks.
1744 : *
1745 : * This function is called on a change of the internal values.
1746 : *
1747 : * The function is used to call the callbacks that were added to this
1748 : * option_info object. The function first copies the existing list of
1749 : * callbacks so you can safely update the list from within a callback.
1750 : *
1751 : * \warning
1752 : * Destroying your advgetopt::getopt option is not safe while a callback
1753 : * is running.
1754 : *
1755 : * \param[in] idx This represents the index of the value that last changed
1756 : * (currently poor attempt to fix this issue).
1757 : */
1758 701 : void option_info::value_changed(int idx)
1759 : {
1760 701 : trace_source(idx);
1761 :
1762 1402 : callback_vector_t callbacks;
1763 701 : callbacks.reserve(f_callbacks.size());
1764 :
1765 : {
1766 1402 : cppthread::guard lock(get_global_mutex());
1767 701 : callbacks = f_callbacks;
1768 : }
1769 :
1770 707 : for(auto e : callbacks)
1771 : {
1772 6 : e.f_callback(*this);
1773 : }
1774 701 : }
1775 :
1776 :
1777 :
1778 : /** \brief Remember the source information at of this last change.
1779 : *
1780 : * The getopt class supports a flag which turns on the trace mode. This
1781 : * allows it to memorize where the values came fram. This includes the
1782 : * source and if the source is a configuration file, the path to that
1783 : * configuration file.
1784 : */
1785 701 : void option_info::trace_source(int idx)
1786 : {
1787 701 : if(!g_trace_sources)
1788 : {
1789 521 : return;
1790 : }
1791 :
1792 359 : std::string s;
1793 180 : switch(f_source)
1794 : {
1795 83 : case option_source_t::SOURCE_COMMAND_LINE:
1796 83 : s = "command-line";
1797 83 : break;
1798 :
1799 77 : case option_source_t::SOURCE_CONFIGURATION:
1800 77 : s = "configuration=\"" + g_configuration_filename + "\"";
1801 77 : break;
1802 :
1803 1 : case option_source_t::SOURCE_DIRECT:
1804 1 : s = "direct";
1805 1 : break;
1806 :
1807 1 : case option_source_t::SOURCE_DYNAMIC:
1808 1 : s = "dynamic";
1809 1 : break;
1810 :
1811 17 : case option_source_t::SOURCE_ENVIRONMENT_VARIABLE:
1812 17 : s = "environment-variable";
1813 17 : break;
1814 :
1815 1 : case option_source_t::SOURCE_UNDEFINED:
1816 : // this happens on a reset or all the values were invalid
1817 : //
1818 1 : f_trace_sources.push_back(f_name + " [*undefined-source*]");
1819 1 : return;
1820 :
1821 : }
1822 :
1823 179 : if(f_value.empty())
1824 : {
1825 : // this should never ever happen
1826 : // (if f_value is empty then f_source == SOURCE_UNDEFINED)
1827 : //
1828 : f_trace_sources.push_back(f_name + " [*undefined-value*]"); // LCOV_EXCL_LINE
1829 : }
1830 : else
1831 : {
1832 : // TODO: change the algorithm, if the option supports
1833 : //
1834 358 : if(!has_flag(GETOPT_FLAG_MULTIPLE)
1835 179 : || static_cast<std::size_t>(idx) >= f_value.size())
1836 : {
1837 164 : f_trace_sources.push_back(f_name + "=" + f_value[0] + " [" + s + "]");
1838 : }
1839 : else
1840 : {
1841 15 : f_trace_sources.push_back(f_name + "[" + std::to_string(idx) + "]=" + f_value[idx] + " [" + s + "]");
1842 : }
1843 : }
1844 : }
1845 :
1846 :
1847 6 : } // namespace advgetopt
1848 : // vim: ts=4 sw=4 et
|