libmoost
/home/mhx/git/github/libmoost/include/moost/service/standard_options.hpp
Go to the documentation of this file.
00001 /* vim:set ts=3 sw=3 sts=3 et: */
00028 #ifndef FM_LAST_MOOST_SERVICE_STANDARD_OPTIONS_H_
00029 #define FM_LAST_MOOST_SERVICE_STANDARD_OPTIONS_H_
00030 
00035 #include <string>
00036 
00037 #include <boost/algorithm/string.hpp>
00038 #include <boost/program_options.hpp>
00039 #include <boost/noncopyable.hpp>
00040 
00041 #include "option_validator.hpp"
00042 
00043 namespace moost { namespace service {
00044 
00045 class standard_options : public boost::noncopyable
00046 {
00047 private:
00048    class option
00049    {
00050    private:
00051       const char *m_spec;
00052       const char *m_desc;
00053 
00054    public:
00055       option(const char *spec, const char *desc)
00056         : m_spec(spec)
00057         , m_desc(desc)
00058       {
00059       }
00060 
00061       const char *spec() const
00062       {
00063          return m_spec;
00064       }
00065 
00066       const char *desc() const
00067       {
00068          return m_desc;
00069       }
00070 
00071       static std::string longname(const char *spec)
00072       {
00073          std::vector<std::string> parts;
00074          boost::split(parts, spec, boost::is_any_of(","));
00075          return parts[0];
00076       }
00077 
00078       std::string longname() const
00079       {
00080          return longname(m_spec);
00081       }
00082    };
00083 
00084    option opt_config() const
00085    {
00086       return option("config,c", "config file name");
00087    }
00088 
00089    boost::program_options::options_description& m_od;
00090    option_validator& m_val;
00091 
00092    template <typename T>
00093    standard_options& add_option(const option& opt, boost::program_options::typed_value<T> *value)
00094    {
00095       m_od.add_options() (opt.spec(), value, opt.desc());
00096       return *this;
00097    }
00098 
00099    template <typename T>
00100    standard_options& add_option(const option& opt, boost::program_options::typed_value<T> *value, boost::shared_ptr<validator::base> validator, bool mandatory = false)
00101    {
00102       validator->set_option(opt.longname(), opt.desc());
00103       validator->mandatory(mandatory);
00104       m_val.add(validator);
00105       return add_option(opt, value);
00106    }
00107 
00108 public:
00109    struct options
00110    {
00111       std::string config_file;
00112       int port;
00113       int pool;
00114       bool verbose;
00115    };
00116 
00117    standard_options(boost::program_options::options_description& od, option_validator& val)
00118      : m_od(od)
00119      , m_val(val)
00120    {
00121    }
00122 
00123    standard_options(boost::program_options::options_description& od, option_validator& val,
00124                     options& target, int default_port, int default_pool = 8)
00125      : m_od(od)
00126      , m_val(val)
00127    {
00128       config(target.config_file);
00129       port(target.port, default_port);
00130       pool(target.pool, default_pool);
00131       verbose(target.verbose);
00132    }
00133 
00134    standard_options& config(std::string& storage, bool mandatory = true)
00135    {
00136       return add_option(opt_config(),
00137                         boost::program_options::value<std::string>(&storage),
00138                         validator::file(storage),
00139                         mandatory);
00140    }
00141 
00142    standard_options& config(std::string& storage, const std::string& defval)
00143    {
00144       return add_option(opt_config(),
00145                         boost::program_options::value<std::string>(&storage)->default_value(defval),
00146                         validator::file(storage));
00147    }
00148 
00149    template <typename T>
00150    standard_options& port(T& storage, const T& defval)
00151    {
00152       return add_option(option("port,p", "listening port of service"),
00153                         boost::program_options::value<T>(&storage)->default_value(defval),
00154                         validator::number<T>(storage, 1024, 65535));
00155    }
00156 
00157    template <typename T>
00158    standard_options& port(const char *spec, const char *desc, T& storage, bool mandatory = false)
00159    {
00160       return add_option(option(spec, desc),
00161                         boost::program_options::value<T>(&storage),
00162                         validator::number<T>(storage, 1024, 65535),
00163                         mandatory);
00164    }
00165 
00166    template <typename T>
00167    standard_options& port(const char *spec, const char *desc, T& storage, const T& defval)
00168    {
00169       return add_option(option(spec, desc),
00170                         boost::program_options::value<T>(&storage)->default_value(defval),
00171                         validator::number<T>(storage, 1024, 65535));
00172    }
00173 
00174    template <typename T>
00175    standard_options& pool(T& storage, const T& defval = 8)
00176    {
00177       return add_option(option("pool", "pool size"),
00178                         boost::program_options::value<T>(&storage)->default_value(defval),
00179                         validator::number<T>(storage, 1, std::numeric_limits<T>::max()));
00180    }
00181 
00182    standard_options& verbose(bool& storage)
00183    {
00184       return add_option(option("verbose,v", "start with verbose set to 'everything'"),
00185                         boost::program_options::value<bool>(&storage)->zero_tokens()->default_value(false));
00186    }
00187 
00188    standard_options& operator()(const char *spec, const char *desc)
00189    {
00190       m_od.add_options() (spec, desc);
00191       return *this;
00192    }
00193 
00194    template <class T>
00195    standard_options& operator()(const char *spec, boost::program_options::typed_value<T> *value, const char *desc)
00196    {
00197       return add_option(option(spec, desc), value);
00198    }
00199 
00200    template <class T>
00201    standard_options& operator()(const char *spec, boost::program_options::typed_value<T> *value, const char *desc,
00202                                 boost::shared_ptr<validator::base> validator)
00203    {
00204       return add_option(option(spec, desc), value, validator);
00205    }
00206 };
00207 
00208 } }
00209 
00210 #endif