LCOV - code coverage report
Current view: top level - advgetopt - options.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 70 70 100.0 %
Date: 2024-10-05 13:34:54 Functions: 132 132 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // Copyright (c) 2006-2024  Made to Order Software Corp.  All Rights Reserved
       2             : //
       3             : // https://snapwebsites.org/project/advgetopt
       4             : // contact@m2osw.com
       5             : //
       6             : // This program is free software; you can redistribute it and/or modify
       7             : // it under the terms of the GNU General Public License as published by
       8             : // the Free Software Foundation; either version 2 of the License, or
       9             : // (at your option) any later version.
      10             : //
      11             : // This program is distributed in the hope that it will be useful,
      12             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             : // GNU General Public License for more details.
      15             : //
      16             : // You should have received a copy of the GNU General Public License along
      17             : // with this program; if not, write to the Free Software Foundation, Inc.,
      18             : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      19             : #pragma once
      20             : 
      21             : /** \file
      22             :  * \brief Definitions of the options class a initialization functions.
      23             :  *
      24             :  * The advgetopt library offers an advanced way to manage your command
      25             :  * line tools options on the command line, in environment variables, and
      26             :  * in configuration files.
      27             :  */
      28             : 
      29             : 
      30             : // self
      31             : //
      32             : #include    <advgetopt/option_info.h>
      33             : 
      34             : #include    <advgetopt/conf_file.h>
      35             : 
      36             : 
      37             : // snapdev
      38             : //
      39             : #include    <snapdev/not_used.h>
      40             : 
      41             : 
      42             : 
      43             : namespace advgetopt
      44             : {
      45             : 
      46             : 
      47             : 
      48             : 
      49             : 
      50             : 
      51             : // this structure is used to declare your command line options in a
      52             : // constexpr array
      53             : //
      54             : // TODO: plan to transform all the strings in an array with a scheme such
      55             : //       as:
      56             : //
      57             : //          "a:<alias>",
      58             : //          "d:<default>",
      59             : //          "h:<help>",
      60             : //          "n:<name>",
      61             : //          "s:<separator>",
      62             : //          "v:<validator>(<param>, ...)"
      63             : //
      64             : //       our templates should be able to create that array automatically.
      65             : //       This way we avoid many nullptr in so many definitions (i.e. most of
      66             : //       our definitions do not have a default, separators, or a validator)
      67             : //       We would also avoid the alias/help overload.
      68             : //
      69             : struct option
      70             : {
      71             :     short_name_t        f_short_name = NO_SHORT_NAME;           // letter option (or NO_SHORT_NAME == U'\0')
      72             :     flag_t              f_flags = GETOPT_FLAG_NONE;             // set of flags
      73             :     char const *        f_name = nullptr;                       // name of the option (i.e. "test" for --test, or nullptr)
      74             :     char const *        f_environment_variable_name = nullptr;  // name of an environment variable to read for the value from
      75             :     char const *        f_default = nullptr;                    // a default value if not nullptr
      76             :     char const *        f_help = nullptr;                       // help for this option, if nullptr it's a hidden option; if ALIAS then this is the actual alias
      77             :     char const *        f_validator = nullptr;                  // the name of a validator and optional parameters between parenthesis
      78             :     char const * const *f_multiple_separators = nullptr;        // nullptr terminated list of strings used as separators when GETOPT_FLAG_MULTIPLE is set
      79             : };
      80             : 
      81             : 
      82             : 
      83             : template<typename T>
      84             : class OptionValue
      85             : {
      86             : public:
      87             :     typedef T   value_t;
      88             : 
      89         360 :     constexpr OptionValue<T>(T const v)
      90         360 :         : f_value(v)
      91             :     {
      92         360 :     }
      93             : 
      94         264 :     constexpr value_t get() const
      95             :     {
      96         264 :         return f_value;
      97             :     }
      98             : 
      99             : private:
     100             :     value_t     f_value;
     101             : };
     102             : 
     103             : 
     104             : class ShortName
     105             :     : public OptionValue<short_name_t>
     106             : {
     107             : public:
     108          24 :     constexpr ShortName()
     109          24 :         : OptionValue<short_name_t>(NO_SHORT_NAME)
     110             :     {
     111          24 :     }
     112             : 
     113          17 :     constexpr ShortName(short_name_t name)
     114          17 :         : OptionValue<short_name_t>(name)
     115             :     {
     116          17 :     }
     117             : };
     118             : 
     119             : class Flags
     120             :     : public OptionValue<flag_t>
     121             : {
     122             : public:
     123          24 :     constexpr Flags()
     124          24 :         : OptionValue<flag_t>(GETOPT_FLAG_NONE)
     125             :     {
     126          24 :     }
     127             : 
     128          24 :     constexpr Flags(flag_t flags)
     129          24 :         : OptionValue<flag_t>(flags)
     130             :     {
     131          24 :     }
     132             : };
     133             : 
     134             : class Name
     135             :     : public OptionValue<char const *>
     136             : {
     137             : public:
     138             :     constexpr Name()
     139             :         : OptionValue<char const *>(nullptr)
     140             :     {
     141             :     }
     142             : 
     143          24 :     constexpr Name(char const * name)
     144          24 :         : OptionValue<char const *>(name)
     145             :     {
     146          24 :     }
     147             : };
     148             : 
     149             : class EnvironmentVariableName
     150             :     : public OptionValue<char const *>
     151             : {
     152             : public:
     153          48 :     constexpr EnvironmentVariableName()
     154          48 :         : OptionValue<char const *>(nullptr)
     155             :     {
     156          48 :     }
     157             : 
     158             :     constexpr EnvironmentVariableName(char const * name)
     159             :         : OptionValue<char const *>(name)
     160             :     {
     161             :     }
     162             : };
     163             : 
     164             : class DefaultValue
     165             :     : public OptionValue<char const *>
     166             : {
     167             : public:
     168          24 :     constexpr DefaultValue()
     169          24 :         : OptionValue<char const *>(nullptr)
     170             :     {
     171          24 :     }
     172             : 
     173          15 :     constexpr DefaultValue(char const * default_value)
     174          15 :         : OptionValue<char const *>(default_value)
     175             :     {
     176          15 :     }
     177             : };
     178             : 
     179             : class Alias
     180             :     : public OptionValue<char const *>
     181             : {
     182             : public:
     183          48 :     constexpr Alias()
     184          48 :         : OptionValue<char const *>(nullptr)
     185             :     {
     186          48 :     }
     187             : 
     188             :     constexpr Alias(char const * alias)
     189             :         : OptionValue<char const *>(alias)
     190             :     {
     191             :     }
     192             : };
     193             : 
     194             : class Help
     195             :     : public OptionValue<char const *>
     196             : {
     197             : public:
     198          24 :     constexpr Help()
     199          24 :         : OptionValue<char const *>(nullptr)
     200             :     {
     201          24 :     }
     202             : 
     203          24 :     constexpr Help(char const * help)
     204          24 :         : OptionValue<char const *>(help)
     205             :     {
     206          24 :     }
     207             : };
     208             : 
     209             : class Validator
     210             :     : public OptionValue<char const *>
     211             : {
     212             : public:
     213          24 :     constexpr Validator()
     214          24 :         : OptionValue<char const *>(nullptr)
     215             :     {
     216          24 :     }
     217             : 
     218             :     constexpr Validator(char const * validator)
     219             :         : OptionValue<char const *>(validator)
     220             :     {
     221             :     }
     222             : };
     223             : 
     224             : class Separators
     225             :     : public OptionValue<char const * const *>
     226             : {
     227             : public:
     228          24 :     constexpr Separators()
     229          24 :         : OptionValue<char const * const *>(nullptr)
     230             :     {
     231          24 :     }
     232             : 
     233          16 :     constexpr Separators(char const * const * separators)
     234          16 :         : OptionValue<char const * const *>(separators)
     235             :     {
     236          16 :     }
     237             : };
     238             : 
     239             : 
     240             : 
     241             : template<typename T, typename F, class ...ARGS>
     242         264 : constexpr typename std::enable_if<std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
     243             : {
     244         264 :     snapdev::NOT_USED(args...);
     245         264 :     return first.get();
     246             : }
     247             : 
     248             : 
     249             : template<typename T, typename F, class ...ARGS>
     250         960 : constexpr typename std::enable_if<!std::is_same<T, F>::value, typename T::value_t>::type find_option(F first, ARGS ...args)
     251             : {
     252         960 :     snapdev::NOT_USED(first);
     253         960 :     return find_option<T>(args...);
     254             : }
     255             : 
     256             : 
     257             : 
     258             : template<class ...ARGS>
     259          24 : constexpr option define_option(ARGS ...args)
     260             : {
     261             : #pragma GCC diagnostic push
     262             : #pragma GCC diagnostic ignored "-Wpedantic"
     263         120 :     option opt =
     264             :     {
     265          24 :         .f_short_name =          find_option<ShortName   >(args..., ShortName()),
     266          48 :         .f_flags =               find_option<Flags       >(args..., Flags())
     267          48 :                                     | (find_option<Alias>(args..., Alias()) != nullptr
     268          48 :                                             ? GETOPT_FLAG_ALIAS
     269             :                                             : GETOPT_FLAG_NONE)
     270          48 :                                     | (find_option<EnvironmentVariableName>(args..., EnvironmentVariableName()) != nullptr
     271          48 :                                             ? GETOPT_FLAG_ENVIRONMENT_VARIABLE
     272             :                                             : GETOPT_FLAG_NONE),
     273          24 :         .f_name =                find_option<Name        >(args...),    // no default, must be defined
     274             :         .f_environment_variable_name =
     275          24 :                                  find_option<EnvironmentVariableName>(args..., EnvironmentVariableName()),
     276          24 :         .f_default =             find_option<DefaultValue>(args..., DefaultValue()),
     277          48 :         .f_help =                find_option<Alias       >(args..., Alias()) != nullptr
     278          72 :                                             ? find_option<Alias       >(args..., Alias())
     279          24 :                                             : find_option<Help        >(args..., Help()),
     280          24 :         .f_validator =           find_option<Validator   >(args..., Validator()),
     281          24 :         .f_multiple_separators = find_option<Separators  >(args..., Separators()),
     282             :     };
     283             : #pragma GCC diagnostic pop
     284             : 
     285             :     // TODO: once possible (C++17/20?) add verification tests here
     286             : 
     287          24 :     return opt;
     288             : }
     289             : 
     290             : 
     291             : 
     292             : 
     293             : 
     294             : constexpr option end_options()
     295             : {
     296             :     return define_option(
     297             :               advgetopt::Name(nullptr)
     298             :             , advgetopt::Flags(advgetopt::end_flags())
     299             :         );
     300             : }
     301             : 
     302             : 
     303             : 
     304             : 
     305             : 
     306             : 
     307             : 
     308             : 
     309             : struct group_description
     310             : {
     311             :     flag_t          f_group = GETOPT_FLAG_GROUP_NONE;   // the default is used to mark the end of the list
     312             :     char const *    f_name = nullptr;                   // for --<name>-help
     313             :     char const *    f_description = nullptr;            // for usage() output
     314             : };
     315             : 
     316             : 
     317             : 
     318             : 
     319             : template<typename T>
     320             : class GroupValue
     321             : {
     322             : public:
     323             :     typedef T   value_t;
     324             : 
     325             :     constexpr GroupValue<T>(T const v)
     326             :         : f_value(v)
     327             :     {
     328             :     }
     329             : 
     330             :     constexpr value_t get() const
     331             :     {
     332             :         return f_value;
     333             :     }
     334             : 
     335             : private:
     336             :     value_t     f_value;
     337             : };
     338             : 
     339             : class GroupNumber
     340             :     : public OptionValue<flag_t>
     341             : {
     342             : public:
     343             :     constexpr GroupNumber()
     344             :         : OptionValue<flag_t>(GETOPT_FLAG_GROUP_NONE)
     345             :     {
     346             :     }
     347             : 
     348             :     constexpr GroupNumber(flag_t group)
     349             :         : OptionValue<flag_t>(group)
     350             :     {
     351             :     }
     352             : };
     353             : 
     354             : class GroupName
     355             :     : public GroupValue<char const *>
     356             : {
     357             : public:
     358             :     constexpr GroupName()
     359             :         : GroupValue<char const *>(nullptr)
     360             :     {
     361             :     }
     362             : 
     363             :     constexpr GroupName(char const * name)
     364             :         : GroupValue<char const *>(name)
     365             :     {
     366             :     }
     367             : };
     368             : 
     369             : class GroupDescription
     370             :     : public GroupValue<char const *>
     371             : {
     372             : public:
     373             :     constexpr GroupDescription()
     374             :         : GroupValue<char const *>(nullptr)
     375             :     {
     376             :     }
     377             : 
     378             :     constexpr GroupDescription(char const * description)
     379             :         : GroupValue<char const *>(description)
     380             :     {
     381             :     }
     382             : };
     383             : 
     384             : 
     385             : template<typename T, typename F, class ...ARGS>
     386             : constexpr typename std::enable_if<std::is_same<T, F>::value, typename T::value_t>::type find_group(F first, ARGS ...args)
     387             : {
     388             :     snapdev::NOT_USED(args...);
     389             :     return first.get();
     390             : }
     391             : 
     392             : 
     393             : template<typename T, typename F, class ...ARGS>
     394             : constexpr typename std::enable_if<!std::is_same<T, F>::value, typename T::value_t>::type find_group(F first, ARGS ...args)
     395             : {
     396             :     snapdev::NOT_USED(first);
     397             :     return find_group<T>(args...);
     398             : }
     399             : 
     400             : 
     401             : 
     402             : template<class ...ARGS>
     403             : constexpr group_description define_group(ARGS ...args)
     404             : {
     405             : #pragma GCC diagnostic push
     406             : #pragma GCC diagnostic ignored "-Wpedantic"
     407             :     group_description grp =
     408             :     {
     409             :         .f_group =              find_group<GroupNumber     >(args..., GroupNumber()),
     410             :         .f_name =               find_group<GroupName       >(args..., GroupName()),
     411             :         .f_description =        find_group<GroupDescription>(args..., GroupDescription()),
     412             :     };
     413             : #pragma GCC diagnostic pop
     414             : 
     415             :     return grp;
     416             : }
     417             : 
     418             : 
     419             : constexpr group_description end_groups()
     420             : {
     421             :     // the defaults are what we expect to end the list of groups
     422             :     return define_group();
     423             : }
     424             : 
     425             : 
     426             : 
     427             : 
     428             : 
     429             : 
     430             : 
     431             : 
     432             : constexpr flag_t    GETOPT_ENVIRONMENT_FLAG_DYNAMIC_PARAMETERS          = 0x0001;   // accept parameters that are not declared
     433             : 
     434             : constexpr flag_t    GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS           = 0x0002;   // add system parameters (i.e. --help, --version, etc.)
     435             : constexpr flag_t    GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS   = 0x0004;   // add & process system parameters
     436             : constexpr flag_t    GETOPT_ENVIRONMENT_FLAG_DEBUG_SOURCE                = 0x0008;   // debug source for each option
     437             : constexpr flag_t    GETOPT_ENVIRONMENT_FLAG_AUTO_DONE                   = 0x0010;   // if you want a valid getopt structure without parsing arguments, set this flag
     438             : 
     439             : 
     440             : struct options_environment
     441             : {
     442             :     char const *                f_project_name = nullptr;               // project/application name--used as filename for the .conf files (%a)
     443             :     char const *                f_group_name = nullptr;                 // sub-folder name (i.e. "snapwebsites")--if nullptr, use f_project_name
     444             :     option const *              f_options = nullptr;                    // raw options
     445             :     char const *                f_options_files_directory = nullptr;    // directory to check for option files (default "/usr/shared/advgetopt")
     446             :     char const *                f_environment_variable_name = nullptr;  // environment variable with additional options (%e)
     447             :     char const *                f_environment_variable_intro = nullptr; // introducer for option specific environment variable names (%E)
     448             :     char const *                f_section_variables_name = nullptr;     // the name of a section representing variables (%m)
     449             :     char const * const *        f_configuration_files = nullptr;        // nullptr terminated array of full paths to configuration files (%f)
     450             :     char const *                f_configuration_filename = nullptr;     // the configuration filename to search in f_configuration_directories (%g)
     451             :     char const * const *        f_configuration_directories = nullptr;  // nullptr terminated array of paths only to configuration files (%d)
     452             :     flag_t                      f_environment_flags = 0;                // GETOPT_ENVIRONMENT_FLAG_...
     453             :     char const *                f_help_header = nullptr;                // show on --help
     454             :     char const *                f_help_footer = nullptr;                // show on --help
     455             :     char const *                f_version = nullptr;                    // show on --version and %v
     456             :     char const *                f_license = nullptr;                    // show on --license and %l
     457             :     char const *                f_copyright = nullptr;                  // show on --copyright and %c
     458             :     char const *                f_build_date = UTC_BUILD_DATE;          // available to parameter %b
     459             :     char const *                f_build_time = UTC_BUILD_TIME;          // available to parameter %t
     460             :     group_description const *   f_groups = nullptr;                     // nullptr terminated array of group names %s
     461             :     conf_file_setup const *     f_config_setup = nullptr;               // default configuration file setup (except the filename)
     462             : };
     463             : 
     464             : 
     465             : 
     466             : 
     467             : 
     468             : }   // namespace advgetopt
     469             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.14

Snap C++ | List of projects | List of versions