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