popt_options.cpp

Go to the documentation of this file.
00001 
00012 #include <iostream>
00013 
00014 #include "op_popt.h"
00015 #include "op_version.h"
00016 
00017 #include "popt_options.h"
00018 #include "string_manip.h"
00019 
00020 using namespace std;
00021 
00022 namespace popt {
00023  
00030 class option_base {
00031 public:
00041     option_base(char const * option_name, char short_name,
00042             char const * help_str, char const * arg_help_str,
00043             void * data, unsigned int popt_flags);
00044 
00045     virtual ~option_base() {}
00046 
00050     virtual void post_process() {}
00051 
00052 protected:
00053     char const * option_name;
00054 };
00055 
00056 
00058 static vector<poptOption> & popt_options(void)
00059 {
00060     static vector<poptOption> *x = new(vector<poptOption>);
00061     return *x;
00062 }
00063 
00064 static vector<option_base *> & options_list(void)
00065 {
00066     static vector<option_base *> *x = new(vector<option_base *>);
00067     return *x;
00068 }
00069 
00070 static int showvers;
00071 
00072 static struct poptOption appended_options[] = {
00073     { "version", 'v', POPT_ARG_NONE, &showvers, 0, "show version", NULL, },
00074     POPT_AUTOHELP
00075     POPT_TABLEEND
00076     };
00077 
00078 
00079 /* options parameter can't be a local variable because caller can use the
00080  * returned poptContext which contains  pointer inside the options array */
00081 static poptContext do_parse_options(int argc, char const ** argv,
00082                                     vector<poptOption> & options,
00083                                     vector<string> & additional_params)
00084 {
00085     options = popt_options();
00086 
00087     int const nr_appended_options =
00088         sizeof(appended_options) / sizeof(appended_options[0]);
00089 
00090     options.insert(options.end(), appended_options,
00091                appended_options + nr_appended_options);
00092 
00093     poptContext con = op_poptGetContext(NULL, argc, argv, &options[0], 0);
00094 
00095     if (showvers)
00096         show_version(argv[0]);
00097 
00098     char const * file;
00099     while ((file = poptGetArg(con)) != 0)
00100         additional_params.push_back(file);
00101 
00102     for (size_t i = 0 ; i < options_list().size() ; ++i)
00103         options_list()[i]->post_process();
00104 
00105     return con;
00106 }
00107 
00108 
00109 void parse_options(int argc, char const ** argv,
00110                    vector<string> & additional_params)
00111 {
00112     vector<poptOption> options;
00113 
00114     poptContext con =
00115         do_parse_options(argc, argv, options, additional_params);
00116 
00117     poptFreeContext(con);
00118 }
00119 
00120 
00121 template <typename T> class option_imp;
00122 
00123 
00130 template <> class option_imp<void> : public option_base {
00131 public:
00132     option_imp(bool & value, char const * option_name, char short_name,
00133                char const * help_str);
00134 
00135     ~option_imp() {}
00136 
00137     void post_process();
00138 
00139 private:
00140     bool & value;
00141     int popt_value;
00142 };
00143 
00144 
00150 template <> class option_imp<int> : public option_base {
00151 public:
00152     option_imp(int & value, char const * option_name, char short_name,
00153                char const * help_str, char const * arg_help_str);
00154 
00155     ~option_imp() {}
00156 };
00157 
00158 
00164 template <> class option_imp<string> : public option_base {
00165 public:
00166     option_imp(string & value, char const * option_name,
00167                char short_name, char const * help_str,
00168                char const * arg_help_str);
00169 
00170     void post_process();
00171 
00172     ~option_imp() {}
00173 
00174 private:
00175     // we need an intermediate char array to pass to popt libs
00176     char * popt_value;
00177     string & value;
00178 };
00179 
00180 
00187 template <> class option_imp< vector<string> > : public option_base {
00188 public:
00189     option_imp(vector<string> & value,
00190                char const * option_name, char short_name,
00191                char const * help_str, char const * arg_help_str,
00192                char separator = ',');
00193 
00194     void post_process();
00195 
00196     ~option_imp() {}
00197 
00198 private:
00199     vector<string> & value;
00200     // we need an intermediate char array to pass to popt libs
00201     char * popt_value;
00202     char const separator;
00203 };
00204 
00205 
00206 option::~option()
00207 {
00208     delete the_option;
00209 }
00210 
00211 
00213 option::option(bool & value, char const * name, char short_name, char const * help)
00214     : the_option(new option_imp<void>(value, name, short_name, help))
00215 {
00216 }
00217 
00218 
00220 template <>
00221 option::option(int & value, char const * name, char short_name,
00222                char const * help, char const * arg_help)
00223     : the_option(new option_imp<int>
00224             (value, name, short_name, help, arg_help))
00225 {
00226 }
00227 
00228 
00230 template <>
00231 option::option(string & value, char const * name, char short_name,
00232                char const * help, char const * arg_help)
00233     : the_option(new option_imp<string>
00234             (value, name, short_name, help, arg_help))
00235 {
00236 }
00237 
00238 
00240 template <>
00241 option::option(vector<string> & value, char const * name, char short_name,
00242                char const * help, char const * arg_help)
00243     : the_option(new option_imp< vector<string> >
00244             (value, name, short_name, help, arg_help))
00245 {
00246 }
00247 
00248 
00249 option_base::option_base(char const * name, char short_name,
00250                          char const * help, char const * arg_help,
00251                          void * data, unsigned int popt_flags)
00252     : option_name(name)
00253 {
00254     poptOption const opt = { name, short_name, popt_flags,
00255                              data, 0, help, arg_help };
00256 
00257     popt_options().push_back(opt);
00258 
00259     options_list().push_back(this);
00260 }
00261 
00262 
00263 option_imp<void>::option_imp(bool & val, char const * name, char short_name,
00264                              char const * help)
00265     : option_base(name, short_name, help, 0, &popt_value, POPT_ARG_NONE),
00266       value(val), popt_value(0)
00267 {
00268 }
00269 
00270 
00271 void option_imp<void>::post_process()
00272 {
00273     if (popt_value) {
00274         if (is_prefix(option_name, "no-"))
00275             value = !popt_value;
00276         else 
00277             value = popt_value;
00278     }
00279 }
00280 
00281 
00282 option_imp<int>::option_imp(int & value, char const * name, char short_name,
00283                             char const * help, char const * arg_help)
00284     : option_base(name, short_name, help, arg_help, &value, POPT_ARG_INT)
00285 {
00286 }
00287 
00288 
00289 option_imp<string>::option_imp(string & val, char const * name, char short_name,
00290                                char const * help, char const * arg_help)
00291     : option_base(name, short_name, help, arg_help,
00292                       &popt_value, POPT_ARG_STRING),
00293       popt_value(0), value(val)
00294 {
00295 }
00296 
00297 
00298 void option_imp<string>::post_process()
00299 {
00300     if (popt_value) {
00301         value = popt_value;
00302         popt_value = 0;
00303     }
00304 }
00305 
00306 
00307 option_imp< vector<string> >::option_imp(vector<string> & val,
00308                                          char const * name, char short_name,
00309                                          char const * help,
00310                                          char const * arg_help, char sepchar)
00311     : option_base(name, short_name, help, arg_help,
00312                   &popt_value, POPT_ARG_STRING),
00313       value(val), popt_value(0), separator(sepchar)
00314 {
00315 }
00316 
00317 
00318 void option_imp< vector<string> >::post_process()
00319 {
00320     if (popt_value) {
00321         value = separate_token(popt_value, separator);
00322 
00323         popt_value = 0;
00324     }
00325 }
00326 
00327 } // namespace popt

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1