Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. #include <string>
  2. #include <map>
  3. #include <typeinfo>
  4. #include "boost/lexical_cast.hpp"
  5.  
  6.     struct prop_holder {
  7.         prop_holder() : read_only(false) {}
  8.         virtual ~prop_holder() {}
  9.         virtual void from_string(void* owner, const std::string&) const = 0;
  10.         virtual std::string to_string(const void* owner) const = 0;
  11.         bool read_only;
  12.     };
  13.  
  14.     template<class OwnerType, typename ValueType>
  15.     struct prop_holder_t : prop_holder{
  16.         virtual ValueType get(const OwnerType*) const = 0;
  17.         virtual void set(OwnerType*, const ValueType&) const = 0;
  18.     };
  19.  
  20.     template<class T, typename V>
  21.     struct prop_holder_m_const : prop_holder_t<T, V>{
  22.         typedef typename V const T::* const mptr_t;
  23.         mptr_t ptr;
  24.  
  25.         prop_holder_m_const (mptr_t p): ptr(p) {read_only = true;} 
  26.  
  27.         virtual void set(T* po, const V& v) const {return;}
  28.         virtual void from_string(void* owner, const std::string& str) const {return;}
  29.        
  30.         virtual V get(const T* po) const { return po ? po->*(ptr) : V(0);}
  31.         virtual std::string to_string(const void* owner) const {
  32.             T* ot = (T*)owner;
  33.             return boost::lexical_cast<std::string>((*ot).*ptr);
  34.         }
  35.     };
  36.  
  37.     template<class T, typename V>
  38.     struct prop_holder_m : prop_holder_t<T, V>{
  39.         typedef typename V T::*mptr_t;
  40.         mptr_t ptr;
  41.  
  42.         prop_holder_m (mptr_t p): ptr(p) {read_only = false;}  
  43.  
  44.         virtual V get(const T* po) const { return po ? po->*(ptr) : V(0);}
  45.  
  46.         virtual void set(T* po, const V& v) const {
  47.             if (read_only || !po) return;
  48.             po->*(ptr) = v;
  49.         }
  50.  
  51.         virtual void from_string(void* owner, const std::string& str) const {
  52.             T* ot = (T*)owner;
  53.             if (read_only || !owner) return;
  54.             (*ot).*ptr = boost::lexical_cast<V>(str);
  55.         }
  56.  
  57.         virtual std::string to_string(const void* owner) const {
  58.             T* ot = (T*)owner;
  59.             return boost::lexical_cast<std::string>((*ot).*ptr);
  60.         }
  61.     };
  62.  
  63.     template<class OwnerType, typename ValueType>
  64.     struct prop_holder_f : prop_holder_t<OwnerType, ValueType>{
  65.         //typedef typename ValueType OwnerType::*mptr_t;
  66.         typedef void (OwnerType::* setter_t) (ValueType);
  67.         typedef ValueType (OwnerType::* getter_t) () const;
  68.  
  69.         getter_t getter;
  70.         setter_t setter;
  71.  
  72.         prop_holder_f(getter_t g, setter_t s): getter(g), setter(s)
  73.             {read_only = s ? false : true;}
  74.  
  75.         virtual ValueType get(const OwnerType* po) const {
  76.             return po ? (po->*getter)() : ValueType(0);
  77.         }
  78.  
  79.         virtual void set(OwnerType* po, const ValueType& v) const {
  80.             if (read_only || !po) return;
  81.             (po->*setter)(v);
  82.         }
  83.  
  84.         virtual void from_string(void* owner, const std::string& str) const {
  85.             if (read_only || !owner) return;
  86.             OwnerType* ot = (OwnerType*)owner;         
  87.             ValueType v = boost::lexical_cast<ValueType>(str);
  88.             (ot->*setter)(v);
  89.         }
  90.  
  91.         virtual std::string to_string(const void* owner) const {
  92.             if (!owner) return std::string();
  93.             OwnerType* ot = (OwnerType*)owner;         
  94.             ValueType v = (ot->*getter)();
  95.             return boost::lexical_cast<std::string>(v);
  96.         }
  97.     };
  98.  
  99.  
  100. class property {
  101.  
  102. public:
  103.     property() : value_type(typeid(void)), owner_type(typeid(void)), holder(0){}
  104.     property(const std::type_info& owner_type, const std::type_info& value_type, prop_holder* holder)
  105.         : value_type(value_type), owner_type(owner_type), holder(holder)
  106.     {}
  107.  
  108.     ~property() {
  109.         delete holder; holder = 0;
  110.     }
  111.    
  112.     //data member property
  113.     template<class T, typename V>
  114.     static property* create(V T::* p, bool read_only) {
  115.         const std::type_info& ot = typeid(T);
  116.         const std::type_info& vt = typeid(V);
  117.         prop_holder* holder = 0;
  118.         if (read_only)
  119.             holder = new prop_holder_m_const <T,V>(p);
  120.         else
  121.             holder = new prop_holder_m <T,V>(p);
  122.  
  123.         property* out = new property(ot, vt, holder);
  124.         return out;
  125.     }
  126.  
  127.     //handle case of const data member
  128.     template<class T, typename V>
  129.     static property* create(V const T::* const p) {
  130.         const std::type_info& ot = typeid(T);
  131.         const std::type_info& vt = typeid(V);
  132.         prop_holder* holder = new prop_holder_m_const <T,V>(p);
  133.         property* out = new property(ot, vt, holder);
  134.         return out;
  135.     }
  136.  
  137.     template<class T, typename V>
  138.     static property* create(V (T::* getter) () const, void (T::* setter) (V)) {
  139.         const std::type_info& ot = typeid(T);
  140.         const std::type_info& vt = typeid(V);      
  141.         prop_holder* holder = new prop_holder_f<T,V>(getter, setter);
  142.         property* out = new property(ot, vt, holder);
  143.         return out;
  144.         //return 0;
  145.     }
  146.  
  147.     template<class T>
  148.     void set(T* owner, const char* s) const{
  149.         if (typeid(const char*)!=value_type)
  150.             set(owner, std::string(s));
  151.         else
  152.             set<T, const char*>(owner, s);
  153.     }
  154.  
  155.     template<class T, typename V>
  156.     void set(T* owner, V v) const{
  157.         if (typeid(T)!=owner_type) return;
  158.         if (typeid(V)==value_type){
  159.             prop_holder_t<T, V>* h = static_cast<prop_holder_t<T, V>*>(holder);
  160.             h->set(owner, v);
  161.         }
  162.         else{
  163.             holder->from_string(owner, boost::lexical_cast<std::string>(v));
  164.         }
  165.     }
  166.  
  167.     template<class T, typename V>
  168.     V get(const T* owner) const{
  169.         if (typeid(T)!=owner_type) return V(0);
  170.         if (typeid(V)!=value_type)
  171.             return boost::lexical_cast<V>(holder->to_string(owner));
  172.  
  173.         prop_holder_t<T, V>* h = (prop_holder_t<T, V>*)holder;
  174.         return h->get(owner);
  175.     }
  176.  
  177.     const std::type_info& owner_type;
  178.     const std::type_info& value_type;
  179.  
  180.     operator bool() const { return owner_type != typeid(void); }
  181.  
  182. private:
  183.     prop_holder* holder;
  184. };
  185.  
  186. struct registry{
  187.     typedef std::map<std::string, property*> properties_t;
  188.     typedef std::map<std::string, properties_t> types_t;
  189.  
  190.     template<class T, typename V>
  191.     static const property& reg(const char* name, V T::*ptr, bool read_only = false){
  192.         const type_info& ti = typeid(T);
  193.         property* p = property::create<T, V>(ptr, read_only);
  194.         types[ti.name()][name] = p;
  195.         return *p;
  196.     }
  197.  
  198.     template<class T, typename V>
  199.     static const property& reg(const char* name, V const T::* const ptr){
  200.         const type_info& ti = typeid(T);
  201.         property* p = property::create<T, V>(ptr);
  202.         types[ti.name()][name] = p;
  203.         return *p;
  204.     }
  205.  
  206.     template<class T, typename V>
  207.     static const property& reg(const char* name, V (T::* getter) () const, void (T::* setter) (V)=0){
  208.         const type_info& ti = typeid(T);
  209.         property* p = property::create<T, V>(getter, setter);
  210.         types[ti.name()][name] = p;
  211.         return *p;
  212.     }
  213.  
  214.     template<class T>
  215.     static const property& get(const char* name){
  216.         const type_info& ti = typeid(T);       
  217.         return *(types[ti.name()][name]);
  218.     }
  219. private:
  220.     static types_t types;
  221. };
  222.  
  223. registry::types_t registry::types;
  224.  
  225. class A {
  226. public:
  227.     static void reg(){
  228.         registry::reg("value", &A::value);
  229.         registry::reg("bvalue", &A::get, &A::set);
  230.         registry::reg("cvalue", &A::cget);
  231.         registry::reg("cvalue", &A::dvalue, true);
  232.         registry::reg("const_value", &A::const_value);
  233.     }
  234.     A():value(-1), const_value(10.0f){
  235.     }
  236. private:
  237.     void set(int i ) {
  238.         bvalue = i;
  239.     }
  240.     int get() const {
  241.         return bvalue;
  242.     }
  243.     int cget() const {return cvalue;}
  244.  
  245.     int value, bvalue, cvalue, dvalue;
  246.     const float const_value;
  247. };
  248.  
  249. //TODO:
  250. // - add read/write from xml/stream
  251. //      -- look as simple add overloaded funcs
  252. //      -- need to handle case when property hold registered in props. registry type (with nested properties)
  253.  
  254. int main()
  255. {
  256.     A::reg();
  257.  
  258.     const property& p = registry::get<A>("value");
  259.  
  260.     if (!p) return 1;
  261.  
  262.     A a;
  263.     p.set(&a, 2);
  264.     p.set(&a, "5");
  265.  
  266.     std::string svalue = p.get<A, std::string>(&a);
  267.     int ivalue = p.get<A, int>(&a);
  268.  
  269.     const property& pc = registry::get<A>("const_value");
  270.     if (!pc) return 1;
  271.     float const_value = pc.get<A, float>(&a);
  272.  
  273.     const property& pb = registry::get<A>("bvalue");
  274.     pb.set(&a, 5);
  275.     int bv = pb.get<A, int>(&a);
  276.  
  277.     return 0;
  278. }
  279.