typed_value.h
Go to the documentation of this file.
00001 //
00002 //  Copyright (c) Benjamin Kaufmann 2004
00003 //
00004 //  This is free software; you can redistribute it and/or modify
00005 //  it under the terms of the GNU General Public License as published by
00006 //  the Free Software Foundation; either version 2 of the License, or
00007 //  (at your option) any later version. 
00008 // 
00009 //  This file is distributed in the hope that it will be useful,
00010 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 //  GNU General Public License for more details.
00013 //
00014 //  You should have received a copy of the GNU General Public License
00015 //  along with this file; if not, write to the Free Software
00016 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 //
00018 //
00019 // NOTE: ProgramOptions is inspired by Boost.Program_options
00020 //       see: www.boost.org/libs/program_options
00021 //
00022 #ifndef PROGRAM_OPTIONS_TYPED_VALUE_H_INCLUDED
00023 #define PROGRAM_OPTIONS_TYPED_VALUE_H_INCLUDED
00024 #ifdef _MSC_VER
00025 #pragma warning (disable : 4786)
00026 #pragma warning (disable : 4503)
00027 #pragma warning (disable : 4200)
00028 #endif
00029 #include "value.h"
00030 #include "string_convert.h"
00031 #include "detail/notifier.h"
00032 #include "errors.h"
00033 #include <memory>
00034 namespace ProgramOptions { namespace detail {
00035 template <class T>
00036 struct Parser { typedef bool (*type)(const std::string&, T&); };
00037 } // end namespace detail
00038 using bk_lib::string_cast;
00040 // Enumeration Parser: string->int mapping
00042 struct ValueMappingBase : private std::vector<std::pair<const char*, int> > {
00043         typedef std::vector<std::pair<const char*, int> > base_type;
00044         using base_type::size;
00045         using base_type::empty;
00046         void       add(const char* strVal, int eVal){ push_back(value_type(strVal, eVal)); }
00047         const int* get(const char* strVal) const    {
00048                 for (const_iterator it = begin(), end = this->end(); it != end; ++it) {
00049                         if (strcasecmp(strVal, it->first) == 0) { return &it->second; }
00050                 }
00051                 return 0;
00052         }
00053 };
00054 template <class T>
00055 struct ValueMapping : ValueMappingBase {
00056         typedef ValueMapping     this_type;
00057         typedef ValueMappingBase base_type;
00058         using base_type::get;
00059         this_type& operator()(const char* strVal, T eVal){ base_type::add(strVal, static_cast<int>(eVal)); return *this; }
00060         static ValueMapping& instance()                  { static ValueMapping m; return m; }
00061         operator typename detail::Parser<T>::type()      { return &parse<T>; }
00062         operator typename detail::Parser<int>::type()    { return &parse<int>; }
00063         template <class U>
00064         static bool parse(const std::string& value, U& out){ 
00065                 const ValueMappingBase& m = ValueMapping::instance();
00066                 if (const int* x = m.get(value.c_str())) { out = static_cast<U>(*x); return true; } 
00067                 return false; 
00068         }
00069 private:
00070         ValueMapping() {}
00071 };
00072 template <class T> ValueMapping<T>& values() { return ValueMapping<T>::instance(); }
00074 // StoredValue - a typed value that writes to an existing variable
00076 template <class T>
00077 class StoredValue : public Value {
00078 public:
00079         typedef typename detail::Parser<T>::type parser_type;
00080         StoredValue(T& var, parser_type p) 
00081                 : Value(0)
00082                 , address_(&var)
00083                 , parser_(p) {
00084                 this->setProperty(Value::property_location);
00085         }
00086         bool doParse(const std::string&, const std::string& value) {
00087                 return this->parser_(value, *address_);
00088         }
00089 protected:
00090         T*            address_; // storage location of this value
00091         parser_type   parser_;  // str -> T
00092 };
00094 // NotifiedValue - a typed value that is created on demand and passed to a callback
00096 template <class T>
00097 struct DefaultCreator {
00098         static T* create() { return new T(); }
00099 };
00100 template <class T>
00101 class NotifiedValue : public Value {
00102 public:
00103         typedef typename detail::Parser<T>::type parser_type;
00104         typedef detail::Notifier<const T*>       notifier_type;
00105         NotifiedValue(T* (*cf)(), const notifier_type& n, parser_type p) 
00106                 : Value(0)
00107                 , parser_(p)
00108                 , notify_(n) {
00109                 value_.create = cf;
00110         }
00111         NotifiedValue<T>* storeTo(T& obj) {
00112                 value_.address = &obj;
00113                 this->setProperty(Value::property_location);
00114                 return this;
00115         }
00116         bool doParse(const std::string& name, const std::string& value) {
00117                 bool ret;
00118                 T* pv = 0;
00119                 std::auto_ptr<T> holder;
00120                 if (this->hasProperty(Value::property_location)) {
00121                         pv  = value_.address;
00122                 }
00123                 else {
00124                         holder.reset(value_.create());
00125                         pv = holder.get();
00126                 }
00127                 ret = this->parser_(value, *pv);
00128                 if (ret && notify_.notify(name, pv)) {
00129                         this->storeTo(*pv);
00130                         holder.release();
00131                 }
00132                 return ret;
00133         }
00134 protected:
00135         union {
00136                 T* address;
00137                 T* (*create)();
00138         }             value_;
00139         parser_type   parser_;
00140         notifier_type notify_;
00141 };
00143 // CustomValue - a value that must be parsed/interpreted by a custom context
00145 class CustomValue : public Value {
00146 public:
00147         typedef detail::Notifier<const std::string&> notifier_type;
00148         CustomValue(const notifier_type& n) 
00149                 : Value(0)
00150                 , notify_(n) { }
00151         bool doParse(const std::string& name, const std::string& value) {
00152                 return notify_.notify(name, value);
00153         }
00154 protected:
00155         notifier_type notify_;
00156 };
00158 // value factories
00160 #define LIT_TO_STRING_X(lit) #lit
00161 
00162 #define LIT_TO_STRING(lit) LIT_TO_STRING_X(lit)
00163 struct FlagAction {
00164         typedef detail::Parser<bool>::type parser_t;
00165         static inline bool store_true(const std::string& v, bool& b) { 
00166                 if (v.empty()) { return (b = true); }
00167                 return string_cast<bool>(v, b);
00168         }
00169         static inline bool store_false(const std::string& v, bool& b) { 
00170                 bool temp;
00171                 return store_true(v, temp) && ((b = !temp), true);
00172         }
00173         enum Action { act_store_true, act_store_false } act;
00174         FlagAction(Action a) : act(a) {}
00175         parser_t parser() const { return act == act_store_true ? store_true : store_false; }
00176 };
00177 static const FlagAction store_true(  (FlagAction::act_store_true) );
00178 static const FlagAction store_false( (FlagAction::act_store_false));
00179 
00189 template <class T>
00190 inline StoredValue<T>* storeTo(T& v, typename detail::Parser<T>::type p = &string_cast<T>) {
00191         return new StoredValue<T>(v, p);
00192 }
00193 inline StoredValue<bool>* flag(bool& b, FlagAction x = store_true) { 
00194         return static_cast<StoredValue<bool>*>(storeTo(b, x.parser())->flag());
00195 }
00196 
00215 template <class T, class ParamT>
00216 inline NotifiedValue<T>* notify(ParamT* p0, typename detail::Notify<const T*, ParamT>::type nf, typename detail::Parser<T>::type parser = &string_cast<T>) {
00217         return new NotifiedValue<T>(&DefaultCreator<T>::create, detail::Notifier<const T*>(p0, nf), parser);
00218 }
00219 template <class T, class ParamT>
00220 inline NotifiedValue<T>* storeNotify(T& obj, ParamT* p0, typename detail::Notify<const T*, ParamT>::type nf, typename detail::Parser<T>::type parser = &string_cast<T>) {
00221         return notify<T>(p0, nf, parser)->storeTo(obj);
00222 }
00223 template <class ParamT>
00224 inline NotifiedValue<bool>* flag(ParamT* p0, typename detail::Notify<const bool*, ParamT>::type nf, FlagAction a = store_true) {
00225         return static_cast<NotifiedValue<bool>*>(notify<bool>(p0, nf, a.parser())->flag());
00226 }
00227 
00246 template <class ParamT>
00247 inline CustomValue* notify(ParamT* p0, typename detail::Notify<const std::string&, ParamT>::type nf) {
00248         return new CustomValue(detail::Notifier<const std::string&>(p0, nf));
00249 }
00250 }
00251 #endif


clasp
Author(s): Benjamin Kaufmann
autogenerated on Thu Aug 27 2015 12:41:40