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