lean cpp library
A lean C++ library providing efficient utility classes for high-performance C++ applications.
|
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