lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
property.h
00001 /*****************************************************/
00002 /* lean Properties              (c) Tobias Zirr 2011 */
00003 /*****************************************************/
00004 
00005 #ifndef LEAN_PROPERTIES_PROPERTY
00006 #define LEAN_PROPERTIES_PROPERTY
00007 
00008 #include "../lean.h"
00009 #include "../smart/cloneable.h"
00010 #include "../smart/cloneable_obj.h"
00011 #include "../tags/noncopyable.h"
00012 #include "../meta/conditional.h"
00013 #include "../strings/types.h"
00014 #include "../type_info.h"
00015 
00016 namespace lean
00017 {
00018 namespace properties
00019 {
00020 
00022 template <class Class>
00023 class property_setter : public cloneable
00024 {
00025 public:
00027     virtual bool operator ()(Class &object, const std::type_info &type, const void *values, size_t count) = 0;
00028 
00030     template <class Value>
00031     LEAN_INLINE bool operator ()(Class &object, const Value *values, size_t count)
00032     {
00033         return (*this)(object, typeid(Value), values, count);
00034     }
00035 };
00036 
00038 template <class Class>
00039 class property_getter : public cloneable
00040 {
00041 public:
00043     virtual bool operator ()(const Class &object, const std::type_info &type, void *values, size_t count) const = 0;
00044 
00046     template <class Value>
00047     LEAN_INLINE bool operator ()(const Class &object, Value *values, size_t count) const
00048     {
00049         return (*this)(object, typeid(Value), values, count);
00050     }
00051 };
00052 
00053 class property_type
00054 {
00055 protected:
00056     ~property_type() throw() { }
00057 
00058 public:
00060     virtual size_t size(size_t count) const = 0;
00062     virtual const type_info& type_info() const = 0;
00063 
00065     virtual void* allocate(size_t count) const = 0;
00067     virtual void construct(void *elements, size_t count) const = 0;
00069     virtual void destruct(void *elements, size_t count) const = 0;
00071     virtual void deallocate(void *elements, size_t count) const = 0;
00072 };
00073 
00074 struct destruct_property_data_policy
00075 {
00076     static void release(const property_type &type, void *data, size_t count)
00077     {
00078         type.destruct(data, count);
00079     }
00080 };
00081 struct deallocate_property_data_policy
00082 {
00083     static void release(const property_type &type, void *data, size_t count)
00084     {
00085         type.deallocate(data, count);
00086     }
00087 };
00088 struct delete_property_data_policy
00089 {
00090     static void release(const property_type &type, void *data, size_t count)
00091     {
00092         try
00093         {
00094             type.destruct(data, count);
00095         }
00096         catch (...)
00097         {
00098             type.deallocate(data, count);
00099             throw;
00100         }
00101 
00102         type.deallocate(data, count);
00103     }
00104 };
00105 
00106 template <class Polocy = delete_property_data_policy>
00107 class scoped_property_data : public noncopyable
00108 {
00109     const property_type *m_type;
00110     void *m_data;
00111     size_t m_count;
00112 
00113 public:
00114     LEAN_INLINE scoped_property_data(const property_type *type, void *data, size_t count)
00115         : m_type(type),
00116         m_data(data),
00117         m_count(count) { }
00118     LEAN_INLINE ~scoped_property_data()
00119     {
00120         m_type->destruct(m_data, m_count);
00121     }
00122 
00123     LEAN_INLINE void* data() { return m_data; }
00124     LEAN_INLINE const void* data() const { return m_data; }
00125 
00126     LEAN_INLINE size_t count() const { return m_count; }
00127 };
00128 
00130 template <class Class, class Derived = void>
00131 struct property_desc
00132 {
00134     typedef typename first_non_void<Derived, property_desc>::type actual_type;
00135 
00137     const property_type *type;  
00138     size_t count;               
00139 
00141     typedef property_setter<Class> setter_type;
00142     typedef cloneable_obj<setter_type, true> setter_storage_type;
00144     typedef property_getter<Class> getter_type;
00145     typedef cloneable_obj<getter_type, true> getter_storage_type;
00146 
00147     setter_storage_type setter; 
00148     getter_storage_type getter; 
00149 
00151     property_desc()
00152         : type(nullptr),
00153         count(0),
00154         setter(setter_storage_type::null()),
00155         getter(getter_storage_type::null()) { }
00157     property_desc(const property_type &type, size_t count)
00158         : type(&type),
00159         count(count),
00160         setter(setter_storage_type::null()),
00161         getter(getter_storage_type::null()) { }
00162 
00164     actual_type& set_setter(const setter_type &setter) { this->setter = setter; return static_cast<actual_type&>(*this); }
00166     actual_type& set_getter(const getter_type &getter) { this->getter = getter; return static_cast<actual_type&>(*this); }
00167 };
00168 
00170 template <class Class, class Derived = void>
00171 struct named_property_desc : public property_desc<Class, typename first_non_void< Derived, named_property_desc<Class, Derived> >::type>
00172 {
00174     typedef typename first_non_void<Derived, named_property_desc>::type actual_type;
00175 
00176     utf8_string name;   
00177 
00179     named_property_desc() { }
00181     named_property_desc(const utf8_ntri &name, const property_type &type, size_t count)
00182         : property_desc<Class, actual_type>(type, count),
00183         name(name.to<utf8_string>()) { }
00184 };
00185 
00187 template <class Class, class Widget, class Derived = void>
00188 struct ui_property_desc : public named_property_desc<Class, typename first_non_void< Derived, ui_property_desc<Class, Widget, Derived> >::type>
00189 {
00191     typedef typename first_non_void<Derived, ui_property_desc>::type actual_type;
00192 
00193     Widget widget;  
00194 
00196     typedef property_getter<Class> value_type;
00197     typedef cloneable_obj<value_type, true> value_storage_type;
00198 
00199     value_storage_type default_value;   
00200 
00201     value_storage_type min_value;       
00202     value_storage_type value_step;      
00203     value_storage_type max_value;       
00204 
00206     ui_property_desc()
00207         : default_value(value_storage_type::null()),
00208         min_value(value_storage_type::null()),
00209         value_step(value_storage_type::null()),
00210         max_value(value_storage_type::null()) { }
00212     ui_property_desc(const utf8_ntri &name, const property_type &type, size_t count, const Widget &widget)
00213         : named_property_desc<Class, actual_type>(name, type, count),
00214         widget(widget),
00215         default_value(value_storage_type::null()),
00216         min_value(value_storage_type::null()),
00217         value_step(value_storage_type::null()),
00218         max_value(value_storage_type::null()) { }
00219 
00221     actual_type& set_default_value(const value_type &getter) { this->default_value = getter; return static_cast<actual_type&>(*this); }
00223     actual_type& set_min_value(const value_type &getter) { this->min_value = getter; return static_cast<actual_type&>(*this); }
00225     actual_type& set_value_step(const value_type &getter) { this->value_step = getter; return static_cast<actual_type&>(*this); }
00227     actual_type& set_max_value(const value_type &getter) { this->max_value = getter; return static_cast<actual_type&>(*this); }
00228 };
00229 
00231 template <class Class, class Value>
00232 LEAN_INLINE bool set_property(Class &object, property_setter<Class> *setter, const Value *values, size_t count)
00233 {
00234     return (setter) ? (*setter)(object, values, count) : false;
00235 }
00237 template <class Class, class Value>
00238 LEAN_INLINE bool set_property(Class &object, cloneable_obj<property_setter<Class>, false> &setter, const Value *values, size_t count)
00239 {
00240     return (*setter)(object, values, count);
00241 }
00243 template <class Class, class Value>
00244 LEAN_INLINE bool set_property(Class &object, const cloneable_obj<property_setter<Class>, true> &setter, const Value *values, size_t count)
00245 {
00246     return set_property(object, setter.getptr(), values, count);
00247 }
00248 
00250 template <class Class, class Value>
00251 LEAN_INLINE bool get_property(const Class &object, const property_getter<Class> *getter, Value *values, size_t count)
00252 {
00253     return (getter) ? (*getter)(object, values, count) : false;
00254 }
00256 template <class Class, class Value, bool PointerSem>
00257 LEAN_INLINE bool get_property(const Class &object, const cloneable_obj<property_getter<Class>, PointerSem> &getter, Value *values, size_t count)
00258 {
00259     return (PointerSem)
00260         ? get_property(object, getter.getptr(), values, count)
00261         : (*getter)(object, values, count);
00262 }
00263 
00265 static const size_t invalid_property_id = static_cast<size_t>(-1);
00266 
00268 template <class String, class Collection, class ID>
00269 inline size_t find_property(const Collection &collection, const String &name, ID invalidID = invalid_property_id)
00270 {
00271     for (typename Collection::const_iterator itProperty = collection.begin();
00272         itProperty != collection.end(); ++itProperty)
00273         if (itProperty->name == name)
00274             return itProperty - collection.begin();
00275 
00276     return invalidID;
00277 }
00278 
00279 } // namespace
00280 
00281 using properties::property_setter;
00282 using properties::property_getter;
00283 using properties::property_type;
00284 
00285 using properties::property_desc;
00286 using properties::named_property_desc;
00287 using properties::ui_property_desc;
00288 
00289 using properties::get_property;
00290 using properties::set_property;
00291 
00292 using properties::invalid_property_id;
00293 using properties::find_property;
00294 
00295 using properties::scoped_property_data;
00296 using properties::delete_property_data_policy;
00297 using properties::destruct_property_data_policy;
00298 using properties::deallocate_property_data_policy;
00299 
00300 } // namespace
00301 
00302 #endif