Line data Source code
1 : /*
2 : * File:
3 : * advgetopt/option_info.cpp -- a replacement to the Unix getopt() implementation
4 : *
5 : * License:
6 : * Copyright (c) 2006-2019 Made to Order Software Corp. All Rights Reserved
7 : *
8 : * https://snapwebsites.org/
9 : * contact@m2osw.com
10 : *
11 : * This program is free software; you can redistribute it and/or modify
12 : * it under the terms of the GNU General Public License as published by
13 : * the Free Software Foundation; either version 2 of the License, or
14 : * (at your option) any later version.
15 : *
16 : * This program is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU General Public License along
22 : * with this program; if not, write to the Free Software Foundation, Inc.,
23 : * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 : *
25 : * Authors:
26 : * Alexis Wilke alexis@m2osw.com
27 : * Doug Barbieri doug@m2osw.com
28 : */
29 :
30 :
31 : /** \file
32 : * \brief Implementation of the option_info class.
33 : *
34 : * This is the implementation of the class used to define one command
35 : * line option.
36 : */
37 :
38 : // self
39 : //
40 : #include "advgetopt/option_info.h"
41 :
42 :
43 : // advgetopt lib
44 : //
45 : #include "advgetopt/exception.h"
46 : #include "advgetopt/log.h"
47 :
48 :
49 : // snapdev lib
50 : //
51 : #include <snapdev/not_used.h>
52 : #include <snapdev/tokenize_string.h>
53 :
54 :
55 : // libutf8 lib
56 : //
57 : #include <libutf8/libutf8.h>
58 : #include <libutf8/iterator.h>
59 :
60 :
61 : // boost lib
62 : //
63 : #include <boost/algorithm/string/replace.hpp>
64 :
65 :
66 : // last include
67 : //
68 : #include <snapdev/poison.h>
69 :
70 :
71 :
72 :
73 : namespace advgetopt
74 : {
75 :
76 :
77 :
78 : /** \brief Transform a string to a short name.
79 : *
80 : * This function transforms a string to a short name. The input string
81 : * can represent a UTF-8 character that can be used as a short name.
82 : *
83 : * An empty string is not considered to represent any name and thus
84 : * this function returns NO_SHORT_NAME when the input is an empty
85 : * string.
86 : *
87 : * \param[in] name The name to be checked.
88 : *
89 : * \return The short name character or NO_SHORT_NAME if it's not a match.
90 : */
91 2228883 : short_name_t string_to_short_name(std::string const & name)
92 : {
93 2228883 : if(!name.empty())
94 : {
95 2228882 : libutf8::utf8_iterator u8(name);
96 2228882 : short_name_t const short_name(*u8++);
97 2228882 : if(u8 == name.end())
98 : {
99 1112069 : return short_name;
100 : }
101 : }
102 :
103 1116814 : return NO_SHORT_NAME;
104 : }
105 :
106 :
107 : /** \brief Convert a short name to a UTF-8 string.
108 : *
109 : * This function is the opposite of the to_short_name() except that the
110 : * input is expected to be a valid short name or NO_SHORT_NAME.
111 : *
112 : * When the input is NO_SHORT_NAME, the function outputs an empty string.
113 : *
114 : * \note
115 : * There are other short names that are not really considered valid such
116 : * as control characters, the dash (-), and probably most other
117 : * punctuation, character codes which are not currently assigned to
118 : * any character in Unicode, etc. This function ignores all of those
119 : * potential problems.
120 : *
121 : * \param[in] short_name The short name to convert to UTF-8.
122 : *
123 : * \return The short name as a UTF-8 string or an empty string.
124 : */
125 2224175 : std::string short_name_to_string(short_name_t short_name)
126 : {
127 2224175 : if(short_name == NO_SHORT_NAME)
128 : {
129 1 : return std::string();
130 : }
131 2224174 : return libutf8::to_u8string(short_name);
132 : }
133 :
134 :
135 : /** \brief Create a new option_info object.
136 : *
137 : * This function creates a new option_info object with the specified \p name
138 : * and \p short_name. The \p short_name is optional.
139 : *
140 : * When adding options to a map of options, all the long and short names
141 : * must be unique. See the add_child() function for details.
142 : *
143 : * The \p short_name parameter is a UTF-32 character. To not offer a short
144 : * name for an option, use NO_SHORT_NAME as the value (which is the default
145 : * if not specified to the constructor.)
146 : *
147 : * \li Special Option Name: "--"
148 : *
149 : * The "--" long name is viewed as the separator between options and
150 : * \em filenames. When "--" is found by itself on the command line, then
151 : * it is viewed as a switch to go from having options to only having
152 : * \em filenames. Of course, these options may be used as any type of
153 : * values, not just filenames (it could be URLs, email addresses, numbers,
154 : * etc.)
155 : *
156 : * The "--" separator cannot be assigned a short name.
157 : *
158 : * \li Special Option Name: "*"
159 : *
160 : * The "*" long name is viewed as the \em accept \em all option. This
161 : * means all the options may not be defined in the list of options but
162 : * we still want to accept them. This is to allow dynamically defined
163 : * (supported) command options and especially to not have to declare
164 : * all the valid options found in a configuration file.
165 : *
166 : * \li Underscore and Dashes
167 : *
168 : * It is customary to support dashes between words in options appearing
169 : * on the command line (`--help-me`), however, it is unusual in
170 : * configuration files where underscores are used instead (`under_score`.)
171 : * When we compare option names, `'-' == '_'` is always considered true
172 : * so either dashes or underscore can be used in both cases.
173 : *
174 : * For this reason, the long name is saved with only dashes. That
175 : * means all the maps are indexed using the long name with dashes.
176 : *
177 : * \exception getopt_exception_logic
178 : * The constructor raises the invalid exception if the long name is an
179 : * empty string since this is not allowed. It will also raise that
180 : * exception if the name is the default option ("--") and a short name
181 : * is also defined. (i.e. no short name is allowed along the default
182 : * option.)
183 : *
184 : * \param[in] name The (long) name of this option.
185 : * \param[in] short_name The short name of this option (one character.)
186 : */
187 1082 : option_info::option_info(std::string const & name, short_name_t short_name)
188 : : f_name(boost::replace_all_copy(name, "_", "-"))
189 1090 : , f_short_name(short_name)
190 : {
191 1082 : if(name.empty())
192 : {
193 4 : if(short_name != NO_SHORT_NAME)
194 : {
195 : throw getopt_exception_logic(
196 : "option_info::option_info(): all options must at least have a long name (short name: '"
197 4 : + libutf8::to_u8string(short_name)
198 6 : + "'.)");
199 : }
200 : throw getopt_exception_logic(
201 2 : "option_info::option_info(): all options must at least have a long name.");
202 : }
203 :
204 1078 : if(name == "--")
205 : {
206 16 : if(short_name != NO_SHORT_NAME)
207 : {
208 : throw getopt_exception_logic(
209 : "option_info::option_info(): the default parameter \"--\" cannot include a short name ('"
210 4 : + libutf8::to_u8string(short_name)
211 6 : + "'.)");
212 : }
213 :
214 14 : add_flag(GETOPT_FLAG_DEFAULT_OPTION);
215 : }
216 : else
217 : {
218 1062 : if(name[0] == '-')
219 : {
220 : throw getopt_exception_logic(
221 : "option_info::option_info(): an option cannot start with a dash (-), \""
222 2 : + name
223 3 : + "\" is not valid.");
224 : }
225 :
226 1061 : if(short_name == '-')
227 : {
228 : throw getopt_exception_logic(
229 1 : "option_info::option_info(): the short name of an option cannot be the dash (-).");
230 : }
231 : }
232 1074 : }
233 :
234 :
235 : /** \brief Get the long name of the option.
236 : *
237 : * This option retrieves the long name of the option.
238 : *
239 : * \note
240 : * Remember that the underscores in long names are converted to dashes.
241 : * This is because it makes more sense to look for command line parameters
242 : * with dashes. This function will return the name with only dashes.
243 : *
244 : * \note
245 : * The name is always defined. The creation of an option_info object
246 : * fails if the name is empty.
247 : *
248 : * \return The long name with dashes instead of underscores.
249 : */
250 171 : std::string const & option_info::get_name() const
251 : {
252 171 : return f_name;
253 : }
254 :
255 :
256 : /** \brief Assign a short name to an option.
257 : *
258 : * This function is used to assign a short name to an option.
259 : *
260 : * \warning
261 : * If you want this function to function as expected (i.e. for the option
262 : * to later be found using its short name), make sure to call the
263 : * set_short_name() on your getopt object and not directly this function.
264 : * This is because the getopt object needs to add the newly named option
265 : * to its map of options sorted by short name.
266 : *
267 : * \exception getopt_exception_logic
268 : * Calling this function with an option which already has a short name
269 : * results in a logic exception. Also, \p short_name cannot be
270 : * NO_SHORT_NAME.
271 : *
272 : * \param[in] short_name The short name to assign to this option.
273 : */
274 5 : void option_info::set_short_name(short_name_t short_name)
275 : {
276 5 : if(short_name == NO_SHORT_NAME)
277 : {
278 : throw getopt_exception_logic("The short name of option \""
279 2 : + f_name
280 3 : + "\" cannot be set to NO_SHORT_NAME.");
281 : }
282 :
283 4 : if(f_short_name != NO_SHORT_NAME)
284 : {
285 : throw getopt_exception_logic("The short name of option \""
286 2 : + f_name
287 2 : + "\" cannot be changed from '"
288 4 : + short_name_to_string(f_short_name)
289 2 : + "' to '"
290 4 : + short_name_to_string(short_name)
291 3 : + "'.");
292 : }
293 :
294 3 : f_short_name = short_name;
295 3 : }
296 :
297 :
298 : /** \brief Get the short name of the option.
299 : *
300 : * This function returns the \p short_name of this option.
301 : *
302 : * The short name is a Unicode character (UTF-32).
303 : *
304 : * \return The short name character.
305 : */
306 206 : short_name_t option_info::get_short_name() const
307 : {
308 206 : return f_short_name;
309 : }
310 :
311 :
312 : /** \brief Retrieve the name of the option without any section names.
313 : *
314 : * The name of an option can include section names. These
315 : * are rarely used on the command line, but they are useful for
316 : * configuration files if you want to create multiple layers of
317 : * options (a.k.a. sections.)
318 : *
319 : * This function removes all the section names from the option name
320 : * and returns what's left.
321 : *
322 : * \return The base name without any section names.
323 : */
324 4 : std::string option_info::get_basename() const
325 : {
326 4 : std::string::size_type const pos(f_name.rfind("::"));
327 4 : if(pos == std::string::npos)
328 : {
329 1 : return f_name;
330 : }
331 :
332 3 : return f_name.substr(pos + 2);
333 : }
334 :
335 :
336 : /** \brief Retrieve the name of the sections.
337 : *
338 : * The name of an option can include section names. These
339 : * are rarely used on the command line, but they are useful for
340 : * configuration files if you want to create multiple layers of
341 : * options (a.k.a. sections.)
342 : *
343 : * This function returns all the section names found in this option
344 : * name. The last scope operator gets removed too.
345 : *
346 : * If the name does not include any sections, then this function returns
347 : * an empty string.
348 : *
349 : * \return The section names without the basename.
350 : */
351 4 : std::string option_info::get_section_name() const
352 : {
353 4 : std::string::size_type const pos(f_name.rfind("::"));
354 4 : if(pos == std::string::npos)
355 : {
356 1 : return std::string();
357 : }
358 :
359 3 : return f_name.substr(0, pos);
360 : }
361 :
362 :
363 : /** \brief Retrieve a list of 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 returns a string_list_t of the section names found in
371 : * this option name.
372 : *
373 : * If the name does not include any sections, then this function returns
374 : * an empty list.
375 : *
376 : * \return The list of section name.
377 : */
378 4 : string_list_t option_info::get_section_name_list() const
379 : {
380 4 : std::string::size_type const pos(f_name.rfind("::"));
381 4 : if(pos == std::string::npos)
382 : {
383 1 : return string_list_t();
384 : }
385 :
386 6 : string_list_t section_list;
387 6 : snap::tokenize_string(section_list
388 6 : , f_name.substr(0, pos)
389 : , "::"
390 : , true
391 : , std::string()
392 3 : , &snap::string_predicate<string_list_t>);
393 3 : return section_list;
394 : }
395 :
396 :
397 : /** \brief Check whether this is the default option.
398 : *
399 : * This function checks whether this option represents the default option.
400 : * The default option is where non-options, generally filenames, are added
401 : * when not following an argument.
402 : *
403 : * The name of the default option is always "--". However, it is not
404 : * required. When no default option is defined, filenames can't be
405 : * specified and when such are found on the command line, an error
406 : * ensues.
407 : *
408 : * \return true if the name of the option is "--".
409 : */
410 1304 : bool option_info::is_default_option() const
411 : {
412 1304 : return has_flag(GETOPT_FLAG_DEFAULT_OPTION)
413 1304 : || (f_name.size() == 2 && f_name[0] == '-' && f_name[1] == '-');
414 : }
415 :
416 :
417 : /** \brief Get the flags.
418 : *
419 : * The options have flags determining various sub-options available
420 : * to them. Right now we have flags to tell how each option can be
421 : * used (on the command line, in an environment variable, or in
422 : * a configuration file.)
423 : *
424 : * \note
425 : * We have the GETOPT_FLAG_ALIAS flag which is used to define
426 : * an alias. That means values do not get set in an option which
427 : * is marked as an alias. Instead, they get set in the option
428 : * which is being aliased. This means your software does not have
429 : * to check both options. The setup function will actually call
430 : * the set_alias() function at some point to finalize aliases
431 : * so you do not really need the flag, except to know that no
432 : * value will be defined here because it will instead be saved
433 : * in the aliased option.
434 : *
435 : * \param[in] flags The new flags.
436 : */
437 66 : void option_info::set_flags(flag_t flags)
438 : {
439 66 : f_flags = flags;
440 66 : }
441 :
442 :
443 : /** \brief Make sure a given flag is set.
444 : *
445 : * This function adds the given flag from the set of flags being set.
446 : *
447 : * \param[in] flag The flag(s) to set.
448 : */
449 1172 : void option_info::add_flag(flag_t flag)
450 : {
451 1172 : f_flags |= flag;
452 1172 : }
453 :
454 :
455 : /** \brief Make sure a given flag is not set.
456 : *
457 : * This function removes the given flag from the set of flags being set.
458 : *
459 : * \param[in] flag The flag(s) to clear.
460 : */
461 46 : void option_info::remove_flag(flag_t flag)
462 : {
463 46 : f_flags &= ~flag;
464 46 : }
465 :
466 :
467 : /** \brief Retrieve the flags.
468 : *
469 : * This function retrieves all the flags defined in this option.
470 : *
471 : * To just check whether a flag is set or not, use the has_flag()
472 : * function instead.
473 : *
474 : * \return This option flags.
475 : */
476 1161 : flag_t option_info::get_flags() const
477 : {
478 1161 : return f_flags;
479 : }
480 :
481 :
482 : /** \brief Check whether a flag is set.
483 : *
484 : * This function is used to check whether a flag is set or not.
485 : *
486 : * \note
487 : * The \p flag parameter can be set to more than one flag in which case
488 : * the function returns true if any one of those flags is set.
489 : *
490 : * \return true if the flag is set, false otherwise.
491 : */
492 15303 : bool option_info::has_flag(flag_t flag) const
493 : {
494 15303 : return (f_flags & flag) != 0;
495 : }
496 :
497 :
498 : /** \brief Check whether this option has a default value.
499 : *
500 : * Whenever an option is given a default value, the GETOPT_FLAG_HAS_DEFAULT
501 : * flag gets set. This allows us to distinguish between an option with a
502 : * default which is the empty string and an option without a default.
503 : *
504 : * The set_default() forces the flag to be set.
505 : *
506 : * The remove_default() clears the flag.
507 : *
508 : * \return true if the flag is set, false otherwise.
509 : *
510 : * \sa set_default()
511 : * \sa remove_default()
512 : */
513 296 : bool option_info::has_default() const
514 : {
515 296 : return has_flag(GETOPT_FLAG_HAS_DEFAULT);
516 : }
517 :
518 :
519 : /** \brief Set the default value.
520 : *
521 : * This function sets the default value for this option.
522 : *
523 : * The default value is always defined as a string, but it can later be
524 : * converted to a different type using the option validator.
525 : *
526 : * Often, though, the default value is not compatible with the validator.
527 : * For example, you may have a parameter which is set to a percentage
528 : * from -100% to +100% and the default may be the string "off".
529 : *
530 : * \note
531 : * After calling this function, the option is viewed as having a default
532 : * even if that's the empty string.
533 : *
534 : * \param[in] default_value The new default value for this option.
535 : *
536 : * \sa remove_default()
537 : */
538 101 : void option_info::set_default(std::string const & default_value)
539 : {
540 101 : f_default_value = default_value;
541 101 : add_flag(GETOPT_FLAG_HAS_DEFAULT);
542 101 : }
543 :
544 :
545 : /** \brief Set the default value of this option.
546 : *
547 : * This function is an overload which allows us to call set_default()
548 : * with a nullptr.
549 : *
550 : * \param[in] default_value The new default value for this option.
551 : *
552 : * \sa remove_default()
553 : */
554 960 : void option_info::set_default(char const * default_value)
555 : {
556 960 : if(default_value != nullptr)
557 : {
558 87 : set_default(std::string(default_value));
559 : }
560 960 : }
561 :
562 :
563 : /** \brief Remove the default value.
564 : *
565 : * Call this function remove the default value. The default string gets
566 : * cleared and the GETOPT_FLAG_NO_DEFAULT flag gets set.
567 : *
568 : * \sa set_default()
569 : */
570 4 : void option_info::remove_default()
571 : {
572 4 : f_default_value.clear();
573 4 : remove_flag(GETOPT_FLAG_HAS_DEFAULT);
574 4 : }
575 :
576 :
577 : /** \brief Retrieve the default value.
578 : *
579 : * This function returns the default value.
580 : *
581 : * \return The default string value.
582 : */
583 687 : std::string const & option_info::get_default() const
584 : {
585 687 : return f_default_value;
586 : }
587 :
588 :
589 : /** \brief Set the help string for this option.
590 : *
591 : * The usage() function prints this string whenever the command
592 : * line includes the help command line option (such as `-h` or
593 : * `--help`.)
594 : *
595 : * The string can include various flags such as `%p` to include
596 : * dynamically defined parameters. See the process_help_string()
597 : * function for additional details about these parameters.
598 : *
599 : * \note
600 : * When using a special flag (i.e. GETOPT_FLAG_HELP), the help value
601 : * string is used as the value used by that special feature:
602 : *
603 : * \li GETOPT_FLAG_HELP
604 : *
605 : * It represents a string to print out by the usage() function. The option
606 : * purpose is solaly for adding a string of help in the output.
607 : *
608 : * \li GETOPT_FLAG_EXTERNAL_OPTIONS
609 : *
610 : * It represents the filename to read additional advgetopt options. In
611 : * some cases, your static array of option structures is to define this
612 : * special flag.
613 : *
614 : * \li GETOPT_FLAG_LICENSE
615 : *
616 : * It represents the program license.
617 : *
618 : * \li GETOPT_FLAG_COPYRIGHT
619 : *
620 : * It represents the program copyright notice.
621 : *
622 : * \param[in] help The help string for this option.
623 : */
624 985 : void option_info::set_help(std::string const & help)
625 : {
626 985 : f_help = help;
627 985 : }
628 :
629 :
630 : /** \brief Set the help string for this option.
631 : *
632 : * This function is an overload which allows us to call set_help() with
633 : * a nullptr and not crash. We just ignore the call when that happens.
634 : *
635 : * \param[in] help The help string for this option or nullptr.
636 : */
637 966 : void option_info::set_help(char const * help)
638 : {
639 966 : if(help != nullptr)
640 : {
641 958 : set_help(std::string(help));
642 : }
643 966 : }
644 :
645 :
646 : /** \brief Get the help string.
647 : *
648 : * This function returns the help string for this command line option.
649 : *
650 : * \warning
651 : * Note that when a special flag is set, this string may represent something
652 : * else that a help string.
653 : *
654 : * \return The help string of this argument.
655 : */
656 290 : std::string const & option_info::get_help() const
657 : {
658 290 : return f_help;
659 : }
660 :
661 :
662 : /** \brief Set the validator for this option.
663 : *
664 : * This function parses the specified name and optional parameters and
665 : * create a corresponding validator for this option.
666 : *
667 : * The \p name_and_params string can be defined as one of:
668 : *
669 : * \code
670 : * <validator-name>
671 : * <validator-name>()
672 : * <validator-name>(<param1>)
673 : * <validator-name>(<param1>, <param2>, ...)
674 : * \endcode
675 : *
676 : * The list of parameters is optional. There may be no, just one,
677 : * or any number of parameters. How the parameters are parsed is left
678 : * to the validator to decide.
679 : *
680 : * If the input string is empty, the current validator, if one is
681 : * installed, gets removed.
682 : *
683 : * \note
684 : * If the option_info already has a set of values, they get validated
685 : * against the new validator. Any value which does not validate gets
686 : * removed at once. The validation process also generates an error
687 : * when an invalid error is found. Note that it is expected that you
688 : * will setup a validator before you start parsing data so this feature
689 : * should seldom be used.
690 : *
691 : * \param[in] name_and_params The validator name and parameters.
692 : *
693 : * \return true if the validator was installed and all existing values were
694 : * considered valid.
695 : */
696 28 : bool option_info::set_validator(std::string const & name_and_params)
697 : {
698 28 : f_validator = validator::create(name_and_params);
699 :
700 : // make sure that all existing values validate against this
701 : // new validator
702 : //
703 26 : return validate_all_values();
704 : }
705 :
706 :
707 : /** \brief Set the validator for this option.
708 : *
709 : * Options may be assigned a validator. Without a validator, any value
710 : * is considered valid.
711 : *
712 : * A value is checked when you call the validates() function. The function
713 : * returns true if the value is considered valid. False in all other cases.
714 : *
715 : * You can define your own validators and add them to the library list of
716 : * available validators before using the library in order to get your
717 : * options to use said validators.
718 : *
719 : * \note
720 : * If the option_info already has a set of values, they get validated
721 : * against the new validator. Any value which does not validate gets
722 : * removed at once. The validation process also generates an error
723 : * when an invalid error is found. Note that it is expected that you
724 : * will setup a validator before you start parsing data so this feature
725 : * should seldom be used.
726 : *
727 : * \param[in] validator A pointer to a validator.
728 : *
729 : * \return true if the validator was installed and all existing values were
730 : * considered valid.
731 : */
732 2 : bool option_info::set_validator(validator::pointer_t validator)
733 : {
734 2 : f_validator = validator;
735 :
736 : // make sure that all existing values validate against this
737 : // new validator
738 : //
739 2 : return validate_all_values();
740 : }
741 :
742 :
743 : /** \brief Clear the validator.
744 : *
745 : * This function removes the existing validator by resetting the pointer
746 : * back to nullptr.
747 : *
748 : * \param[in] null_ptr Ignored.
749 : *
750 : * \return Always true since no validator means any existing values would
751 : * be considered valid.
752 : */
753 5 : bool option_info::set_validator(std::nullptr_t null_ptr)
754 : {
755 5 : snap::NOTUSED(null_ptr);
756 :
757 5 : f_validator.reset();
758 :
759 5 : return true;
760 : }
761 :
762 :
763 : /** \brief Check a value validity.
764 : *
765 : * This function us used internally to verify values that get added at
766 : * the time they get added. It runs the validator::validate() function
767 : * and returns true if the value is considered valid. When the value
768 : * does not validate, it returns false and removes the value from the
769 : * f_value vector. This means no invalid values are ever kept in an
770 : * option_info object.
771 : *
772 : * An option without a validator has values that are always valid.
773 : * Also, an empty value is always considered valid.
774 : *
775 : * \note
776 : * This function is private since there is no need for the user of
777 : * the option_info to ever call it (i.e. it automatically gets called
778 : * any time a value gets added to the f_value vector.)
779 : *
780 : * \param[in] idx The value to check.
781 : *
782 : * \return true if the value is considered valid, false otherwise.
783 : */
784 551 : bool option_info::validates(int idx)
785 : {
786 551 : if(static_cast<size_t>(idx) >= f_value.size())
787 : {
788 : throw getopt_exception_undefined( // LCOV_EXCL_LINE
789 : "option_info::get_value(): no value at index " // LCOV_EXCL_LINE
790 : + std::to_string(idx) // LCOV_EXCL_LINE
791 : + " (idx >= " // LCOV_EXCL_LINE
792 : + std::to_string(f_value.size()) // LCOV_EXCL_LINE
793 : + ") for --" // LCOV_EXCL_LINE
794 : + f_name // LCOV_EXCL_LINE
795 : + " so you can't get this value."); // LCOV_EXCL_LINE
796 : }
797 :
798 : // the value is considered valid when:
799 : // * there is no validator
800 : // * if the value is empty
801 : // * when the value validate against the specified validator
802 : //
803 1102 : if(f_validator == nullptr
804 71 : || f_value[idx].empty()
805 614 : || f_validator->validate(f_value[idx]))
806 : {
807 533 : return true;
808 : }
809 :
810 36 : log << log_level_t::error
811 18 : << "input \""
812 36 : << f_value[idx]
813 18 : << "\" given to parameter --"
814 36 : << f_name
815 18 : << " is not considered valid."
816 18 : << end;
817 :
818 : // get rid of that value since it does not validate
819 : //
820 18 : f_value.erase(f_value.begin() + idx);
821 :
822 18 : return false;
823 : }
824 :
825 :
826 : /** \brief Retrieve a pointer to the validator.
827 : *
828 : * The validator of an option may be used for additional tasks such as
829 : * converting the value to a specific type (i.e. a string to an
830 : * integer, for example.)
831 : *
832 : * This function allows you to retrieve the validator to be able to
833 : * make use of those functions. You will have to use
834 : * std::dynamic_cast_pointer<>() to change the type of validator to
835 : * the specialized validator of this option. If that returns a null
836 : * pointer, then the option is not using that type of validator.
837 : *
838 : * \todo
839 : * Add a template function that does the cast for the caller.
840 : *
841 : * \return A pionter to this option validator.
842 : */
843 19 : validator::pointer_t option_info::get_validator() const
844 : {
845 19 : return f_validator;
846 : }
847 :
848 :
849 : /** \brief Set the alias option.
850 : *
851 : * After loading all the options, we run the link_aliases() function which
852 : * makes sure that all the options that are marked as an alias are
853 : * properly linked.
854 : *
855 : * \param[in] alias The final destination of this option.
856 : */
857 20 : void option_info::set_alias_destination(option_info::pointer_t destination)
858 : {
859 20 : if(destination->has_flag(GETOPT_FLAG_ALIAS))
860 : {
861 : throw getopt_exception_invalid(
862 : "option_info::set_alias(): you can't set an alias as"
863 1 : " an alias of another option.");
864 : }
865 :
866 19 : f_alias_destination = destination;
867 19 : }
868 :
869 :
870 : /** \brief Get a link to the destination alias.
871 : *
872 : * This function returns a pointer to the aliased option.
873 : *
874 : * \return The alias or a nullptr.
875 : */
876 95 : option_info::pointer_t option_info::get_alias_destination() const
877 : {
878 95 : return f_alias_destination;
879 : }
880 :
881 :
882 : /** \brief Set the list of separators.
883 : *
884 : * Options marked with the GETOPT_FLAG_CONFIGURATION_MULTIPLE flag
885 : * get their value cut by separators when such is found in an
886 : * environment variable or a configuration file.
887 : *
888 : * This function saves the list of separators in a vector.
889 : *
890 : * \param[in] separators The list of separators to be used for this argument.
891 : */
892 961 : void option_info::set_multiple_separators(char const * const * separators)
893 : {
894 961 : f_multiple_separators.clear();
895 961 : if(separators == nullptr)
896 : {
897 943 : return;
898 : }
899 :
900 68 : for(; *separators != nullptr; ++separators)
901 : {
902 25 : f_multiple_separators.push_back(*separators);
903 : }
904 : }
905 :
906 :
907 : /** \brief Set the list of separators.
908 : *
909 : * Options marked with the GETOPT_FLAG_CONFIGURATION_MULTIPLE flag
910 : * get their value cut by separators when such is found in an
911 : * environment variable or a configuration file.
912 : *
913 : * This function saves the specified list of separators.
914 : *
915 : * \param[in] separators The list of separators to be used for this argument.
916 : */
917 7 : void option_info::set_multiple_separators(string_list_t const & separators)
918 : {
919 7 : f_multiple_separators = separators;
920 7 : }
921 :
922 :
923 : /** \brief Retrieve the list of separators for this argument.
924 : *
925 : * This function returns a reference to the list of separators of this
926 : * option. It is expected to be used when a value is found in a
927 : * configuration file or a command line in an environment variable.
928 : * Parameters on the command line are already broken down by the
929 : * shell and we do not do any further manipulation with those.
930 : *
931 : * \return A reference to the list of separators used to cut multiple
932 : * arguments found in a configuration file or an environment
933 : * variable.
934 : */
935 9 : string_list_t const & option_info::get_multiple_separators() const
936 : {
937 9 : return f_multiple_separators;
938 : }
939 :
940 :
941 : /** \brief Add a value to this option.
942 : *
943 : * Whenever an option is found it may be followed by one or more values.
944 : * This function is used to add these values to this option.
945 : *
946 : * Later you can use the size() function to know how many values were
947 : * added and the get_value() to retrieve any one of these values.
948 : *
949 : * \warning
950 : * This function sets the value at offset 0 if it is already defined and
951 : * the GETOPT_FLAG_MULTIPLE flag is not set in this option. In other words,
952 : * you can't use this function to add multiple values if this option does
953 : * not support that feature.
954 : *
955 : * \return true when the value was accepted (no error occurred).
956 : *
957 : * \param[in] value The value to add to this option.
958 : *
959 : * \sa set_value()
960 : */
961 429 : bool option_info::add_value(std::string const & value)
962 : {
963 542 : return set_value(has_flag(GETOPT_FLAG_MULTIPLE)
964 113 : ? f_value.size()
965 : : 0
966 429 : , value);
967 : }
968 :
969 :
970 : /** \brief Replace a value.
971 : *
972 : * This function is generally used to replace an existing value. If the
973 : * index is set to the size of the existing set of values, then a new
974 : * value is saved in the vector.
975 : *
976 : * This is particularly useful if you want to edit a configuration file.
977 : *
978 : * If the option comes with a validator, then the value gets checked
979 : * against that validator. If that results in an error, the value is
980 : * not added to the vector so an invalid value will never be returned
981 : * by the option_info class.
982 : *
983 : * The value does not get added when it currently is locked or when
984 : * it does not validate as per the validator of this option_info.
985 : *
986 : * \exception getopt_exception_undefined
987 : * If the index is out of range (too large or negative), then this
988 : * exception is raised.
989 : *
990 : * \param[in] idx The position of the value to update.
991 : * \param[in] value The new value.
992 : *
993 : * \return true if the set_value() added the value.
994 : *
995 : * \sa add_value()
996 : * \sa validates()
997 : * \sa lock()
998 : * \sa unlock()
999 : */
1000 545 : bool option_info::set_value(int idx, std::string const & value)
1001 : {
1002 545 : if(has_flag(GETOPT_FLAG_LOCK))
1003 : {
1004 8 : return false;
1005 : }
1006 :
1007 537 : if(has_flag(GETOPT_FLAG_MULTIPLE))
1008 : {
1009 129 : if(static_cast<size_t>(idx) > f_value.size())
1010 : {
1011 : throw getopt_exception_logic(
1012 : "option_info::set_value(): no value at index "
1013 4 : + std::to_string(idx)
1014 4 : + " and it is not the last available index + 1 (idx > "
1015 8 : + std::to_string(f_value.size())
1016 6 : + ") so you can't set this value (try add_value() maybe?).");
1017 : }
1018 : }
1019 : else
1020 : {
1021 408 : if(idx != 0)
1022 : {
1023 : throw getopt_exception_logic(
1024 : "option_info::set_value(): single value option \"--"
1025 4 : + f_name
1026 4 : + "\" does not accepts index "
1027 8 : + std::to_string(idx)
1028 6 : + " which is not 0.");
1029 : }
1030 : }
1031 :
1032 533 : if(static_cast<size_t>(idx) == f_value.size())
1033 : {
1034 453 : f_value.push_back(value);
1035 : }
1036 : else
1037 : {
1038 80 : f_value[idx] = value;
1039 : }
1040 533 : f_integer.clear();
1041 :
1042 533 : return validates(idx);
1043 : }
1044 :
1045 :
1046 : /** \brief Set a multi-value at once.
1047 : *
1048 : * This function views the \p value parameter as a multi-value parameter
1049 : * which it breaks down in multiple parameters and add the results to this
1050 : * option_info object as the current value(s).
1051 : *
1052 : * To separate the values, the function makes use of the separators as
1053 : * set by one the set_multiple_separators() functions.
1054 : *
1055 : * The resulting values must not be the empty string. Empty strings are
1056 : * ignored. So if the separator is a comma and you write:
1057 : *
1058 : * \code
1059 : * foo,,,bar
1060 : * \endcode
1061 : *
1062 : * The result includes "foo" and "bar" and no empty strings.
1063 : *
1064 : * \note
1065 : * The function has the side effect of clearing any existing parameters
1066 : * first. So only the newly defined parameters in \p value will be set
1067 : * in the option once the function returns.
1068 : *
1069 : * \todo
1070 : * Add support for quoted values
1071 : *
1072 : * \param[in] value The multi-value to save in this option.
1073 : *
1074 : * \return true if all the values in \p value were considered valid.
1075 : *
1076 : * \sa add_value()
1077 : * \sa set_value()
1078 : */
1079 21 : bool option_info::set_multiple_value(std::string const & value)
1080 : {
1081 21 : f_value.clear();
1082 21 : f_integer.clear();
1083 :
1084 21 : split_string(value, f_value, f_multiple_separators);
1085 :
1086 42 : if(!has_flag(GETOPT_FLAG_MULTIPLE)
1087 21 : && f_value.size() > 1)
1088 : {
1089 1 : f_value.clear();
1090 : throw getopt_exception_logic(
1091 : "option_info::set_multiple_value(): parameter --"
1092 2 : + f_name
1093 3 : + " expects zero or one parameter. The set_multiple_value() function should not be called with parameters that only accept one value.");
1094 : }
1095 :
1096 20 : return validate_all_values();
1097 : }
1098 :
1099 :
1100 : /** \brief Validate all the values of this option_info object.
1101 : *
1102 : * Whenever you change the validator of an option_info, or change
1103 : * all the values with set_multiple_value(), all the values get
1104 : * verified using this function. The function removes any value
1105 : * which does not validate according to the current validator.
1106 : *
1107 : * \note
1108 : * Keep in mind that an empty value is always considered valid,
1109 : * no matter what the validator is. This is because when you
1110 : * use an option without a value (i.e. `--order` instead of
1111 : * `--order asc`) the value is set to the empty string unless
1112 : * there is a default. This allows you to know that the
1113 : * option was used without a value, which is useful for some
1114 : * options.
1115 : *
1116 : * \return true if all the values were considered valid.
1117 : */
1118 48 : bool option_info::validate_all_values()
1119 : {
1120 48 : bool all_valid(true);
1121 48 : if(f_validator != nullptr)
1122 : {
1123 35 : for(size_t idx(0); idx < f_value.size(); )
1124 : {
1125 18 : if(!validates(idx))
1126 : {
1127 : // the value was removed, so do not increment `idx`
1128 : //
1129 9 : all_valid = false;
1130 : }
1131 : else
1132 : {
1133 9 : ++idx;
1134 : }
1135 : }
1136 : }
1137 :
1138 48 : return all_valid;
1139 : }
1140 :
1141 :
1142 : /** \brief Check whether a value is defined.
1143 : *
1144 : * When parsing the options on the command line or a configuration file,
1145 : * values get added to the various existing option_info. If a special
1146 : * "*" option is also defined, then any value found on the command line
1147 : * or the configuration file are returned.
1148 : *
1149 : * To know whether this or that option was defined with a value, use
1150 : * this function. Even an option which doesn't come with a parameter
1151 : * will get an is_defined() returning true once it was found on the
1152 : * command line. The value will be the empty string.
1153 : *
1154 : * \return true if that option was found on the command line, in the
1155 : * environment variable, or in the configuration file.
1156 : */
1157 2052 : bool option_info::is_defined() const
1158 : {
1159 2052 : return !f_value.empty();
1160 : }
1161 :
1162 :
1163 : /** \brief Retrieve the number of values defined for this option.
1164 : *
1165 : * This function returns the number of values that were found for this
1166 : * option.
1167 : *
1168 : * If the option is marked as GETOPT_FLAG_MULTIPLE, then this function
1169 : * may return 0 or more. Without that flag, this function only returns
1170 : * 0 or 1.
1171 : *
1172 : * You must use the size() parameter to know how many items are defined
1173 : * and call the get_value() with a correct `idx` parameter (i.e. a value
1174 : * between 0 and `size() - 1`.)
1175 : *
1176 : * \return The number of values defined in this option.
1177 : */
1178 485 : size_t option_info::size() const
1179 : {
1180 485 : return f_value.size();
1181 : }
1182 :
1183 :
1184 : /** \brief Retrieve the value.
1185 : *
1186 : * This function returns the value for this option. By default, set the
1187 : * \p idx parameter to zero.
1188 : *
1189 : * The number of values is defined by the size() function.
1190 : *
1191 : * The is_defined() function returns true if at least one value is defined.
1192 : * It is a good idea to check first otherwise you will get an exception.
1193 : *
1194 : * \exception getopt_exception_undefined
1195 : * If the \p idx parameter is too large or no value was found for this
1196 : * option, then this function raises an invalid error.
1197 : *
1198 : * \return The value.
1199 : */
1200 1094 : std::string const & option_info::get_value(int idx) const
1201 : {
1202 1094 : if(static_cast<size_t>(idx) >= f_value.size())
1203 : {
1204 : throw getopt_exception_undefined(
1205 : "option_info::get_value(): no value at index "
1206 4 : + std::to_string(idx)
1207 4 : + " (idx >= "
1208 8 : + std::to_string(f_value.size())
1209 4 : + ") for --"
1210 6 : + f_name
1211 6 : + " so you can't get this value.");
1212 : }
1213 :
1214 1092 : return f_value[idx];
1215 : }
1216 :
1217 :
1218 : /** \brief Get the value as a long.
1219 : *
1220 : * This function returns the value converted to a `long`.
1221 : *
1222 : * If the value does not represent a valid long value, an error is
1223 : * emitted through the logger.
1224 : *
1225 : * \note
1226 : * The function will transform all the values in case this is a
1227 : * GETOPT_FLAG_CONFIGURATION_MULTIPLE option and cache the results.
1228 : * Calling the function many times with the same index is very fast
1229 : * after the first time.
1230 : *
1231 : * \exception getopt_exception_undefined
1232 : * If the value was not defined, the function raises this exception.
1233 : *
1234 : * \param[in] idx The index of the value to retrieve as a long.
1235 : *
1236 : * \return The value at \p idx converted to a long or -1 on error.
1237 : */
1238 153 : long option_info::get_long(int idx) const
1239 : {
1240 153 : if(static_cast<size_t>(idx) >= f_value.size())
1241 : {
1242 : throw getopt_exception_undefined(
1243 : "option_info::get_long(): no value at index "
1244 2 : + std::to_string(idx)
1245 2 : + " (idx >= "
1246 4 : + std::to_string(f_value.size())
1247 2 : + ") for --"
1248 3 : + f_name
1249 3 : + " so you can't get this value.");
1250 : }
1251 :
1252 152 : if(f_integer.size() != f_value.size())
1253 : {
1254 : // we did not yet convert to integers do that now
1255 : //
1256 86 : size_t const max(f_value.size());
1257 176 : for(size_t i(f_integer.size()); i < max; ++i)
1258 : {
1259 : std::int64_t v;
1260 100 : if(!validator_integer::convert_string(f_value[i], v))
1261 : {
1262 10 : f_integer.clear();
1263 :
1264 20 : log << log_level_t::error
1265 10 : << "invalid number ("
1266 20 : << f_value[i]
1267 10 : << ") in parameter --"
1268 20 : << f_name
1269 10 : << " at offset "
1270 10 : << i
1271 10 : << "."
1272 10 : << end;
1273 10 : return -1;
1274 : }
1275 90 : f_integer.push_back(v);
1276 : }
1277 : }
1278 :
1279 142 : return f_integer[idx];
1280 : }
1281 :
1282 :
1283 : /** \brief Lock this value.
1284 : *
1285 : * This function allows for locking a value so further reading of data
1286 : * will not overwrite it.
1287 : *
1288 : * When parsing the data we have multiple levels. Here are these levels
1289 : * in priority order (first option found is the one we keep):
1290 : *
1291 : * \li Command line options
1292 : * \li Environment Variables
1293 : * \li Configuration File: Local (`./\<name>.conf`)
1294 : * \li Configuration File: User's (`~/.config/\<proc>/\<name>.conf`)
1295 : * \li Configuration File: Project sub-folder (`/etc/\<proc>/\<proc>.d/\<ohter-name>.conf`)
1296 : * \li Configuration File: Project folder (`/etc/\<proc>/\<other-name>.conf`)
1297 : * \li Configuration File: System sub-folder (`/etc/\<proc>/\<name>.conf`)
1298 : * \li Configuration File: System folder (`/etc/\<proc>/\<name>.conf`)
1299 : *
1300 : * \note
1301 : * Most of our packages do not have a Project and a System set of
1302 : * configuration files. Often they will have just the System files.
1303 : *
1304 : * We use this lock because we want to support multiple values so just
1305 : * detecting that a value is set to not add more options is not a good
1306 : * test. Instead we lock the values that are set before moving to the
1307 : * next level.
1308 : *
1309 : * \param[in] always Always lock that option, whether it is defined or not.
1310 : */
1311 6 : void option_info::lock(bool always)
1312 : {
1313 6 : if(!always)
1314 : {
1315 4 : if(!is_defined())
1316 : {
1317 2 : return;
1318 : }
1319 : }
1320 :
1321 4 : add_flag(GETOPT_FLAG_LOCK);
1322 : }
1323 :
1324 :
1325 : /** \brief Unlock this value.
1326 : *
1327 : * This function does the opposite of the lock() function. It allows for
1328 : * the value to be updated again.
1329 : *
1330 : * Once the getpot object is done parsing all the input, it unlocks all
1331 : * the values using this function. The unlock is always unconditional.
1332 : */
1333 4 : void option_info::unlock()
1334 : {
1335 4 : remove_flag(GETOPT_FLAG_LOCK);
1336 4 : }
1337 :
1338 :
1339 : /** \brief Reset this value.
1340 : *
1341 : * This function clears the value so it is marked as undefined again.
1342 : *
1343 : * To reuse the same getopt object multiple times, you can use the
1344 : * reset() function which clears the values. Then you can parse a
1345 : * new set of argc/argv parameters.
1346 : */
1347 24 : void option_info::reset()
1348 : {
1349 24 : f_value.clear();
1350 24 : f_integer.clear();
1351 24 : }
1352 :
1353 :
1354 :
1355 6 : } // namespace advgetopt
1356 : // vim: ts=4 sw=4 et
|