Tapkee
parameters.hpp
Go to the documentation of this file.
00001 /* This software is distributed under BSD 3-clause license (see LICENSE file).
00002  *
00003  * Copyright (c) 2012-2013 Sergey Lisitsyn
00004  */
00005 
00006 #ifndef TAPKEE_PARAMETERS_H_
00007 #define TAPKEE_PARAMETERS_H_
00008 
00009 /* Tapkee includes */
00010 #include <tapkee/parameters/value_keeper.hpp>
00011 /* End of Tapkee includes */
00012 
00013 #include <sstream>
00014 #include <vector>
00015 #include <map>
00016 
00017 namespace tapkee
00018 {
00019 
00020 struct Message
00021 {
00022     Message() : ss()
00023     {
00024     }
00025     template <typename T>
00026     Message& operator<<(const T& data)
00027     {
00028         ss << data;
00029         return *this;
00030     }
00031     operator std::string() 
00032     {
00033         return ss.str();
00034     }
00035 
00036     std::stringstream ss;
00037 };
00038 
00039 class ParametersSet;
00040 class CheckedParameter;
00041 
00042 class Parameter
00043 {
00044     friend class CheckedParameter;
00045 
00046     typedef std::string ParameterName;
00047 
00048 private:
00049 
00050     template <typename T>
00051     Parameter(const ParameterName& pname, const T& value) : 
00052         valid(true), invalidity_reason(),
00053         parameter_name(pname), keeper(tapkee_internal::ValueKeeper(value))
00054     {
00055     }
00056 
00057 public:
00058 
00059     template <typename T>
00060     static Parameter create(const std::string& name, const T& value) 
00061     {
00062         return Parameter(name, value);
00063     }
00064 
00065     Parameter() : 
00066         valid(false), invalidity_reason(),
00067         parameter_name("unknown"), keeper(tapkee_internal::ValueKeeper())
00068     {
00069     }
00070 
00071     Parameter(const Parameter& p) : 
00072         valid(p.valid), invalidity_reason(p.invalidity_reason),
00073         parameter_name(p.name()), keeper(p.keeper)
00074     {
00075     }
00076 
00077     ~Parameter()
00078     {
00079     }
00080 
00081     template <typename T>
00082     inline Parameter withDefault(T value)
00083     {
00084         if (!isInitialized())
00085         {
00086             keeper = tapkee_internal::ValueKeeper(value);
00087         }
00088         return *this;
00089     }
00090 
00091     template <typename T>
00092     inline operator T()
00093     {
00094         if (!valid)
00095         {
00096             throw wrong_parameter_error(invalidity_reason);
00097         }
00098         try 
00099         {
00100             return getValue<T>();
00101         }
00102         catch (const missed_parameter_error&)
00103         {
00104             throw missed_parameter_error(parameter_name + " is missed");
00105         }
00106     }
00107 
00108     operator ParametersSet();
00109 
00110     template <typename T>
00111     bool is(T v)
00112     {
00113         if (!isTypeCorrect<T>())
00114             return false;
00115         T kv = keeper.getValue<T>();
00116         if (v == kv)
00117             return true;
00118         return false;
00119     }
00120 
00121     template <typename T>
00122     bool operator==(T v) const
00123     {
00124         return is<T>(v);
00125     }
00126 
00127     CheckedParameter checked();
00128 
00129     template <typename T>
00130     bool isInRange(T lower, T upper) const
00131     {
00132         return keeper.inRange<T>(lower, upper);
00133     }
00134 
00135     template <typename T>
00136     bool isEqual(T value) const
00137     {
00138         return keeper.equal<T>(value);
00139     }
00140 
00141     template <typename T>
00142     bool isNotEqual(T value) const
00143     {
00144         return keeper.notEqual<T>(value);
00145     }
00146 
00147     bool isPositive() const 
00148     {
00149         return keeper.positive();
00150     }
00151     
00152     bool isNonNegative() const 
00153     {
00154         return keeper.nonNegative();
00155     }
00156 
00157     bool isNegative() const
00158     {
00159         return keeper.negative();
00160     }
00161 
00162     template <typename T>
00163     bool isGreater(T lower) const
00164     {
00165         return keeper.greater<T>(lower);
00166     }
00167 
00168     template <typename T>
00169     bool isLesser(T upper) const
00170     {
00171         return keeper.lesser<T>(upper);
00172     }
00173 
00174     bool isInitialized() const
00175     {
00176         return keeper.isInitialized();
00177     }
00178 
00179     ParameterName name() const 
00180     {
00181         return parameter_name;
00182     }
00183 
00184     ParametersSet operator,(const Parameter& p);
00185 
00186 private:
00187 
00188     template <typename T>
00189     inline T getValue() const
00190     {
00191         return keeper.getValue<T>();
00192     }
00193     
00194     template <typename T>
00195     inline bool isTypeCorrect() const
00196     {
00197         return keeper.isTypeCorrect<T>();
00198     }
00199 
00200     inline void invalidate(const std::string& reason)
00201     {
00202         valid = false;
00203         invalidity_reason = reason;
00204     }
00205 
00206 private:
00207 
00208     bool valid;
00209     std::string invalidity_reason;
00210 
00211     ParameterName parameter_name;
00212 
00213     tapkee_internal::ValueKeeper keeper; 
00214 
00215 };
00216 
00217 class CheckedParameter
00218 {
00219 
00220 public:
00221 
00222     explicit CheckedParameter(Parameter& p) : parameter(p)
00223     {
00224     }
00225 
00226     inline operator const Parameter&()
00227     {
00228         return parameter;
00229     }
00230 
00231     template <typename T>
00232     bool is(T v)
00233     {
00234         return parameter.is<T>(v);
00235     }
00236 
00237     template <typename T>
00238     bool operator==(T v)
00239     {
00240         return is<T>(v);
00241     }
00242 
00243     template <typename T>
00244     CheckedParameter& inRange(T lower, T upper)
00245     {
00246         if (!parameter.isInRange(lower, upper))
00247         {
00248             std::string reason = 
00249                 (Message() << "Value of " << parameter.name() << " " 
00250                  << parameter.getValue<T>() << " doesn't fit the range [" << 
00251                     lower << ", " << upper << ")");
00252             parameter.invalidate(reason);
00253         }
00254         return *this;
00255     }
00256 
00257     template <typename T>
00258     CheckedParameter& inClosedRange(T lower, T upper)
00259     {
00260         if (!parameter.isInRange(lower, upper) && !parameter.is(upper))
00261         {
00262             std::string reason = 
00263                 (Message() << "Value of " << parameter.name() << " " 
00264                  << parameter.getValue<T>() << " doesn't fit the range [" << 
00265                     lower << ", " << upper << "]");
00266             parameter.invalidate(reason);
00267         }
00268         return *this;
00269     }
00270 
00271     CheckedParameter& positive()
00272     {
00273         if (!parameter.isPositive())
00274         {
00275             std::string reason = 
00276                 (Message() << "Value of " << parameter.name() << " is not positive");
00277             parameter.invalidate(reason);
00278         }
00279         return *this;
00280     }
00281 
00282     CheckedParameter& nonNegative()
00283     {
00284         if (!parameter.isNonNegative())
00285         {
00286             std::string reason = 
00287                 (Message() << "Value of " << parameter.name() << " is negative");
00288             parameter.invalidate(reason);
00289         }
00290         return *this;
00291     }
00292 
00293 
00294 private:
00295 
00296     Parameter& parameter;
00297 
00298 };
00299 
00300 CheckedParameter Parameter::checked() 
00301 {
00302     return CheckedParameter(*this);
00303 }
00304 
00305 class ParametersSet
00306 {
00307 public:
00308 
00309     typedef std::map<std::string, Parameter> ParametersMap;
00310 
00311     ParametersSet() : pmap() 
00312     {
00313     }
00314     void add(const Parameter& p) 
00315     {
00316         if (pmap.count(p.name()))
00317             throw multiple_parameter_error(Message() << "Parameter " << p.name() << " is set more than once");
00318 
00319         pmap[p.name()] = p;
00320     }
00321     bool contains(const std::string& name) const
00322     {
00323         return pmap.count(name) > 0;
00324     }
00325     void merge(const ParametersSet& pg) 
00326     {
00327         typedef ParametersMap::const_iterator MapIter;
00328         for (MapIter iter = pg.pmap.begin(); iter!=pg.pmap.end(); ++iter)
00329         {
00330             if (!pmap.count(iter->first))
00331             {
00332                 pmap[iter->first] = iter->second;
00333             }
00334         }
00335     }
00336     Parameter operator()(const std::string& name) const
00337     {
00338         ParametersMap::const_iterator it = pmap.find(name);
00339         if (it != pmap.end())
00340         {
00341             return it->second;
00342         }
00343         else
00344         {
00345             throw missed_parameter_error(Message() << "Parameter " << name << " is missed");
00346         }
00347     }
00348     ParametersSet& operator,(const Parameter& p)
00349     {
00350         add(p);
00351         return *this;
00352     }
00353 
00354 private:
00355 
00356     ParametersMap pmap;
00357 };
00358 
00359 ParametersSet Parameter::operator,(const Parameter& p)
00360 {
00361     ParametersSet pg;
00362     pg.add(*this);
00363     pg.add(p);
00364     return pg;
00365 }
00366 
00367 Parameter::operator ParametersSet()
00368 {
00369     ParametersSet pg;
00370     pg.add(*this);
00371     return pg;
00372 }
00373 
00374 
00375 }
00376 
00377 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines