00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #pragma once
00021
00022 #include <boost/exception/info.hpp>
00023 #include <boost/program_options.hpp>
00024 #include <boost/program_options/errors.hpp>
00025 #include <iostream>
00026 #include <netinet/in.h>
00027
00028 namespace drizzled
00029 {
00030
00031
00032
00033
00034 class invalid_option_value :
00035 public boost::exception,
00036 public boost::program_options::invalid_option_value
00037 {
00038 public:
00039 invalid_option_value(const std::string &option_value) :
00040 boost::exception(),
00041 boost::program_options::invalid_option_value(option_value)
00042 {}
00043 };
00044
00045 template<class T> class constrained_value;
00046 template<class T>
00047 std::istream& operator>>(std::istream& is, constrained_value<T>& bound_val);
00048 template<class T>
00049 std::ostream& operator<<(std::ostream& os, const constrained_value<T>& v);
00050
00051 template<class T>
00052 class constrained_value
00053 {
00054 T m_val;
00055 protected:
00056
00057 virtual constrained_value<T>& set_value(const constrained_value<T>& rhs)= 0;
00058 virtual constrained_value<T>& set_value(T rhs)= 0;
00059
00060 public:
00061 explicit constrained_value<T>(T in_value= 0) :
00062 m_val(in_value)
00063 { }
00064
00065 virtual ~constrained_value<T>()
00066 {}
00067
00068 operator T() const
00069 {
00070 return m_val;
00071 }
00072
00073 constrained_value<T>& operator=(const constrained_value<T>& rhs)
00074 {
00075 return set_value(rhs);
00076 }
00077
00078 constrained_value<T>& operator=(T rhs)
00079 {
00080 return set_value(rhs);
00081 }
00082
00083 T get() const
00084 {
00085 return m_val;
00086 }
00087
00088 void setVal(T in_val)
00089 {
00090 m_val= in_val;
00091 }
00092
00093 friend std::istream&
00094 operator>>(std::istream& is,
00095 constrained_value<T>& bound_val)
00096 {
00097 T inner_val;
00098 is >> inner_val;
00099 bound_val= inner_val;
00100 return is;
00101 }
00102
00103 friend
00104 std::ostream& operator<<(std::ostream& os, const constrained_value<T>& v)
00105 {
00106 os << v.get();
00107 return os;
00108 }
00109 };
00110
00111 namespace
00112 {
00113 template<class T, T min_val>
00114 bool less_than_min(T val_to_check)
00115 {
00116 return val_to_check < min_val;
00117 }
00118
00119 template<>
00120 inline bool less_than_min<uint16_t, 0>(uint16_t)
00121 {
00122 return false;
00123 }
00124
00125 template<>
00126 inline bool less_than_min<uint32_t, 0>(uint32_t)
00127 {
00128 return false;
00129 }
00130
00131 template<>
00132 inline bool less_than_min<uint64_t, 0>(uint64_t)
00133 {
00134 return false;
00135 }
00136
00137 template<class T, T min_val>
00138 bool greater_than_max(T val_to_check)
00139 {
00140 return val_to_check > min_val;
00141 }
00142
00143 template<>
00144 inline bool greater_than_max<uint16_t, UINT16_MAX>(uint16_t)
00145 {
00146 return false;
00147 }
00148
00149 template<>
00150 inline bool greater_than_max<uint32_t, UINT32_MAX>(uint32_t)
00151 {
00152 return false;
00153 }
00154
00155 template<>
00156 inline bool greater_than_max<uint64_t, UINT64_MAX>(uint64_t)
00157 {
00158 return false;
00159 }
00160 }
00161
00162 typedef boost::error_info<struct tag_invalid_max,uint64_t> invalid_max_info;
00163 typedef boost::error_info<struct tag_invalid_min,int64_t> invalid_min_info;
00164 typedef boost::error_info<struct tag_invalid_min,std::string> invalid_value;
00165
00166 template<class T,
00167 T MAXVAL,
00168 T MINVAL, unsigned int ALIGN= 1>
00169 class constrained_check :
00170 public constrained_value<T>
00171 {
00172 public:
00173 constrained_check<T,MAXVAL,MINVAL,ALIGN>(T in_value= 0) :
00174 constrained_value<T>(in_value)
00175 { }
00176
00177 protected:
00178 constrained_value<T>& set_value(const constrained_value<T>& rhs)
00179 {
00180 return set_value(rhs.get());
00181 }
00182
00183 constrained_value<T>& set_value(T rhs)
00184 {
00185 if (greater_than_max<T,MAXVAL>(rhs))
00186 {
00187 boost::throw_exception(invalid_option_value(boost::lexical_cast<std::string>(rhs)) << invalid_max_info(static_cast<uint64_t>(MAXVAL)));
00188 }
00189
00190 if (less_than_min<T,MINVAL>(rhs))
00191 {
00192 boost::throw_exception(invalid_option_value(boost::lexical_cast<std::string>(rhs)) << invalid_min_info(static_cast<int64_t>(MINVAL)));
00193 }
00194 rhs-= rhs % ALIGN;
00195 this->setVal(rhs);
00196 return *this;
00197 }
00198
00199
00200 };
00201
00202 typedef constrained_check<uint64_t, UINT64_MAX, 0> uint64_constraint;
00203 typedef constrained_check<uint32_t, UINT32_MAX, 0> uint32_constraint;
00204 typedef constrained_check<uint64_t, UINT64_MAX, 1> uint64_nonzero_constraint;
00205 typedef constrained_check<uint32_t, UINT32_MAX, 1> uint32_nonzero_constraint;
00206 typedef drizzled::constrained_check<in_port_t, 65535, 0> port_constraint;
00207
00208 typedef constrained_check<uint32_t,65535,1> back_log_constraints;
00209
00210 }
00211
00212 template<class T>
00213 void validate(boost::any& v,
00214 const std::vector<std::string>& values,
00215 drizzled::constrained_value<T> val, int)
00216 {
00217 boost::program_options::validators::check_first_occurrence(v);
00218 const std::string& s= boost::program_options::validators::get_single_string(values);
00219
00220 val= boost::lexical_cast<T>(s);
00221 v= boost::any(val);
00222 }
00223
00224