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