libshevek
src/args.hh
00001 /* args.hh - argument parsing made easy
00002  * Copyright 2003-2010 Bas Wijnen <wijnen@debian.org>
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation, either version 3 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 
00018 #ifndef SHEVEK_ARGS_HH
00019 #define SHEVEK_ARGS_HH
00020 
00021 #include <getopt.h>
00022 #include <string>
00023 #include <vector>
00024 #include <list>
00025 #include <sigc++/sigc++.h>
00026 #include <glibmm/ustring.h>
00027 #include "debug.hh"
00028 
00029 // Allow using this class without using automake.
00030 #ifndef PACKAGE_NAME
00031 #define PACKAGE_NAME "[name not defined]"
00032 #endif
00033 #ifndef PACKAGE_TARNAME
00034 #define PACKAGE_TARNAME PACKAGE_NAME
00035 #endif
00036 #ifndef PACKAGE_BUGREPORT
00037 #define PACKAGE_BUGREPORT "[bug report e-mail not defined]"
00038 #endif
00039 #ifndef PACKAGE_VERSION
00040 #define PACKAGE_VERSION "[version not defined]"
00041 #endif
00042 #ifndef COPYRIGHT_YEARS
00043 #define COPYRIGHT_YEARS "[no time of copyright defined]"
00044 #endif
00045 #ifndef COPYRIGHT_EMAIL
00046 #define COPYRIGHT_EMAIL ""
00047 #endif
00048 #ifndef COPYRIGHT_AUTHOR
00049 #define COPYRIGHT_AUTHOR "[no author defined]"
00050 #endif
00051 
00052 namespace shevek
00053 {
00055 
00065   class args
00066   {
00067   public:
00068     class option;
00071     args (int &argc, char **&argv, int min_args, int max_args, Glib::ustring const &description,
00072           /* The parameters below should always have their default values,
00073            * they are just here to get the #define'd values into the library.
00074            * The COPYRIGHT_* values should be defined in configure.ac
00075            */
00076           Glib::ustring const &copyright_years = COPYRIGHT_YEARS,
00077           Glib::ustring const &copyright_email = (COPYRIGHT_EMAIL[0] == '\0' ? PACKAGE_BUGREPORT : COPYRIGHT_EMAIL),
00078           Glib::ustring const &programmer = COPYRIGHT_AUTHOR,
00079           Glib::ustring const &email = PACKAGE_BUGREPORT,
00080           char const *programname = PACKAGE_NAME,
00081           char const *packagename = PACKAGE_TARNAME,
00082           char const *version = PACKAGE_VERSION);
00084     template <unsigned size_>
00085     args (int &argc, char **&argv, option (&o)[size_], int min_args,
00086           int max_args, Glib::ustring const &description);
00088     unsigned size () const;
00090     std::string const &operator[] (unsigned idx) const;
00092     std::vector <std::string>::const_iterator begin () const;
00094     std::vector <std::string>::const_iterator end () const;
00095   private:
00096     std::vector <std::string> m_args;
00097     void l_setup (int &argc, char **&argv, option *o, unsigned num_options,
00098                   int min_args, int max_args,
00099                   Glib::ustring const &description,
00100                   struct ::option *longopts,
00101                   Glib::ustring const &copyright_years = COPYRIGHT_YEARS,
00102                   Glib::ustring const &copyright_email = (COPYRIGHT_EMAIL[0] == '\0' ? PACKAGE_BUGREPORT : COPYRIGHT_EMAIL),
00103                   Glib::ustring const &programmer = COPYRIGHT_AUTHOR,
00104                   Glib::ustring const &email = PACKAGE_BUGREPORT,
00105                   char const *programname = PACKAGE_NAME,
00106                   char const *packagename = PACKAGE_TARNAME,
00107                   char const *version = PACKAGE_VERSION);
00108   };
00109 
00111   class args::option
00112   {
00113   public:
00115     typedef sigc::slot1 <void, bool> callback0;
00117     typedef sigc::slot2 <void, bool, Glib::ustring const &> callback1;
00119     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, callback0 handle, bool *used = NULL);
00121     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, callback1 handle, Glib::ustring default_val = Glib::ustring (), bool *used = NULL);
00123     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, callback0 handle0, callback1 handle1, bool *used = NULL);
00125     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool &var, bool value, bool *used = NULL);
00127     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, Glib::ustring &var, bool *used = NULL);
00129     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, std::string &var, bool *used = NULL);
00131     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, unsigned long &var, bool *used = NULL);
00133     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, long &var, bool *used = NULL);
00135     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, unsigned &var, bool *used = NULL);
00137     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, int &var, bool *used = NULL);
00139     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, unsigned short &var, bool *used = NULL);
00141     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, short &var, bool *used = NULL);
00143     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, float &var, bool *used = NULL);
00145     option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, double &var, bool *used = NULL);
00148     template <typename _T> option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, std::list <_T> &list);
00149   private:
00150     friend class args;
00151     enum opt_t {NEED_ARG, NO_ARG, OPT_ARG};
00152     void setup (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, bool have_default, opt_t have_arg, callback0 handle0, callback1 handle1, bool *used);
00153     void call (bool is_double, char const *optarg);
00154     char m_shortopt;
00155     Glib::ustring m_longopt;
00156     Glib::ustring m_help;
00157     bool m_have_default;
00158     Glib::ustring m_default;
00159     opt_t m_have_arg;
00160     callback0 m_handle0;
00161     callback1 m_handle1;
00162     bool *m_used;
00163     bool m_is_used;
00164     static void l_set (bool is_double, Glib::ustring const &arg, Glib::ustring *var);
00165     static void l_setstd (bool is_double, Glib::ustring const &arg, std::string *var);
00166     static void l_setint (bool is_double, Glib::ustring const &arg, int *var);
00167     static void l_setuint (bool is_double, Glib::ustring const &arg, unsigned *var);
00168     static void l_setlint (bool is_double, Glib::ustring const &arg, long *var);
00169     static void l_setulint (bool is_double, Glib::ustring const &arg, unsigned long *var);
00170     static void l_setsint (bool is_double, Glib::ustring const &arg, short *var);
00171     static void l_setusint (bool is_double, Glib::ustring const &arg, unsigned short *var);
00172     static void l_setbool (bool is_double, bool val, bool *var);
00173     static void l_setfloat (bool is_double, Glib::ustring const &arg, float *var);
00174     static void l_setdfloat (bool is_double, Glib::ustring const &arg, double *var);
00175     template <typename _T>
00176     static void l_setlist (bool is_double, Glib::ustring const &arg, std::list <_T> *list);
00177   };
00178 
00179   template <unsigned size_> args::args (int &argc, char **&argv,
00180                                         option (&o)[size_],
00181                                         int min_args, int max_args,
00182                                         Glib::ustring const &description)
00183   {
00184     startfunc;
00185     struct ::option longopts[size_ + 4];
00186     l_setup (argc, argv, o, size_, min_args, max_args, description, longopts);
00187   }
00188 
00189 
00190   template <typename _T>
00191   args::option::option (char shortopt, Glib::ustring const &longopt, Glib::ustring const &help_line, std::list <_T> &list)
00192   {
00193     startfunc;
00194     setup (shortopt, longopt, help_line, false, NEED_ARG, callback0 (),
00195            sigc::bind (sigc::ptr_fun (&l_setlist <_T>), &list), NULL);
00196   }
00197 
00198   template <typename _T>
00199   void args::option::l_setlist (bool is_double, Glib::ustring const &arg, std::list <_T> *list)
00200   {
00201     startfunc;
00202     list->push_back (_T () );
00203     option tmp ('x', "x", "x", false, list->back () );
00204     tmp.m_handle1 (false, arg);
00205   }
00206 }
00207 
00208 #endif