Drizzled Public API Documentation

constrained_value.h

00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2010 Monty Taylor
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
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> /* for in_port_t */
00027 
00028 namespace drizzled
00029 {
00030 
00031 /* We have to make this mixin exception class because boost program_option
00032   exceptions don't derive from f-ing boost::exception. FAIL
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 } /* namespace drizzled */
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