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