AFEPack
|
00001 00011 #ifndef __PropertyTable_h__ 00012 #define __PropertyTable_h__ 00013 00014 #include <iostream> 00015 #include <vector> 00016 #include <list> 00017 #include <map> 00018 00019 #include "Miscellaneous.h" 00020 00021 template <class T> class property_id_t; 00022 class PropertyTable; 00023 00024 namespace details { 00029 class property_id_allocator_t 00030 { 00031 public: 00032 virtual ~property_id_allocator_t() {} 00033 00034 virtual void * allocate() const {return NULL;} 00035 virtual void deallocate(void *) const {} 00036 }; 00037 00038 struct null_type {}; 00039 00040 class PropertyTableBase; 00041 00050 template <class T> 00051 void _new_property_id(property_id_t<T>& id); 00052 00059 template <class T> 00060 void _free_property_id(property_id_t<T>& id); 00061 00062 }; 00063 00064 00069 template <class T = details::null_type> 00070 class property_id_t : public details::property_id_allocator_t { 00071 public: 00072 typedef T value_type; 00073 private: 00074 typedef property_id_t<value_type> _Self; 00075 public: 00076 property_id_t() : _id(0xffff) {} 00077 property_id_t(const _Self& id) : _id(id.id()) {} 00078 virtual ~property_id_t() { 00079 if (_id != 0xffff) { 00080 details::_free_property_id<value_type>(*this); 00081 } 00082 } 00083 00084 u_int id() const {return _id;} 00085 00086 public: 00087 virtual void * allocate() const { 00088 return (void *)(new value_type()); 00089 } 00090 virtual void deallocate(void * p_t) const { 00091 delete (value_type *)(p_t); 00092 } 00093 00094 private: 00095 friend void details::_new_property_id<>(_Self&); 00096 friend void details::_free_property_id<>(_Self&); 00097 00098 private: 00099 u_int& id() {return _id;} 00100 u_int _id; 00101 }; 00102 00103 namespace details { 00104 00105 class PropertyTableBase { 00106 public: 00108 class property_entry_t { 00109 public: 00110 property_entry_t() : p_obj(NULL), p_data(NULL) {} 00111 property_entry_t(PropertyTableBase * po, void * pd) : 00112 p_obj(po), p_data(pd) {} 00113 property_entry_t(const property_entry_t& pe) : 00114 p_obj(pe.p_obj), p_data(pe.p_data) {} 00115 00116 public: 00117 property_entry_t& operator=(const property_entry_t& pe) { 00118 p_obj = pe.p_obj; 00119 p_data = pe.p_data; 00120 00121 return *this; 00122 } 00123 00124 PropertyTableBase * object_ptr() const {return p_obj;} 00125 PropertyTableBase *& object_ptr() {return p_obj;} 00126 00127 void * data_ptr() const {return p_data;} 00128 void *& data_ptr() {return p_data;} 00129 00130 private: 00131 PropertyTableBase * p_obj; 00132 void * p_data; 00133 }; 00134 00136 typedef std::list<property_entry_t> prop_tbl_list_t; 00137 typedef prop_tbl_list_t::iterator prop_tbl_list_iterator_t; 00138 00141 struct prop_tbl_entry_t { 00142 property_id_allocator_t * _alloc; 00143 prop_tbl_list_t _list; 00144 }; 00145 typedef std::map<u_int, prop_tbl_entry_t> prop_tbl_t; 00146 00148 struct prop_iter_entry_t { 00149 prop_tbl_entry_t * _global_entry; 00150 prop_tbl_list_iterator_t _iter; 00151 }; 00152 typedef std::map<u_int, prop_iter_entry_t> prop_iter_t; 00153 typedef prop_iter_t::iterator prop_iter_iter_t; 00154 typedef prop_iter_t::const_iterator prop_iter_const_iter_t; 00155 00156 private: 00158 00159 PropertyTableBase() {} 00160 PropertyTableBase(const PropertyTableBase& pt) {} 00161 virtual ~PropertyTableBase(); 00163 00165 PropertyTableBase& operator=(const PropertyTableBase& pt) { return *this; } 00166 00167 template <class T> 00168 bool has_property(const property_id_t<T>& i, 00169 prop_iter_const_iter_t& iter) const 00170 { 00171 iter = _prop_iter.find(i.id()); 00172 return (iter != _prop_iter.end()); 00173 } 00174 template <class T> 00175 bool has_property(const property_id_t<T>& i, 00176 prop_iter_iter_t& iter) 00177 { 00178 iter = _prop_iter.find(i.id()); 00179 return (iter != _prop_iter.end()); 00180 } 00181 00182 public: 00190 template <class T> 00191 bool has_property(const property_id_t<T>& i) const 00192 { 00193 return (_prop_iter.find(i.id()) != _prop_iter.end()); 00194 } 00195 00203 template <class T> 00204 T * new_property(const property_id_t<T>& i) 00205 { 00206 assert(! has_property(i)); 00207 return (T *)new_property(i.id()); 00208 } 00209 00217 template <class T> 00218 T * get_property(const property_id_t<T>& i) const 00219 { 00220 prop_iter_const_iter_t iter; 00221 if (! has_property(i, iter)) { 00222 return (T *)NULL; 00223 } 00224 else { 00225 return (T *)(iter->second._iter->data_ptr()); 00226 } 00227 } 00228 00235 template <class T> 00236 void free_property(const property_id_t<T>& i) 00237 { 00238 prop_iter_iter_t iter; 00239 if (has_property(i, iter)) { 00240 free_property(iter); 00241 } 00242 } 00243 00248 void clear_property(); 00249 00250 public: 00251 template <class T> friend void _new_property_id(property_id_t<T>& i); 00252 template <class T> friend void _free_property_id(property_id_t<T>& i); 00253 friend class ::PropertyTable; 00254 00255 private: 00257 00258 void * new_property(u_int i); 00259 void free_property(prop_iter_iter_t& it); 00260 00261 00262 prop_iter_t _prop_iter; 00264 static prop_tbl_t _prop_tbl; 00265 }; 00266 }; 00267 00276 class PropertyTable { 00277 private: 00278 typedef details::PropertyTableBase Base; 00279 void * p_tbl; 00280 public: 00282 00283 PropertyTable() { 00284 p_tbl = new Base(); 00285 } 00287 PropertyTable(const PropertyTable& ptp) { 00288 p_tbl = new Base(); 00289 } 00290 ~PropertyTable() { 00291 Base * p = (Base *)p_tbl; 00292 delete p; 00293 } 00295 00297 PropertyTable& operator=(const PropertyTable& ptp) { 00298 return *this; 00299 } 00300 00301 public: 00309 template <class T> 00310 bool has_property(const property_id_t<T>& id) const { 00311 Base * p = (Base *)p_tbl; 00312 return p->has_property(id); 00313 } 00314 00322 template <class T> 00323 T * new_property(const property_id_t<T>& id) const { 00324 Base * p = (Base *)p_tbl; 00325 return p->new_property(id); 00326 } 00327 00335 template <class T> 00336 T * get_property(const property_id_t<T>& id) const { 00337 Base * p = (Base *)p_tbl; 00338 return p->get_property(id); 00339 } 00340 00347 template <class T> 00348 void free_property(const property_id_t<T>& id) const { 00349 Base * p = (Base *)p_tbl; 00350 p->free_property(id); 00351 } 00352 00353 void clear_property() { 00354 Base * p = (Base *)p_tbl; 00355 p->clear_property(); 00356 } 00357 }; 00358 00359 namespace details { 00360 template <class T> 00361 void _new_property_id(property_id_t<T>& i) { 00362 typedef details::PropertyTableBase PTB; 00364 i.id() = 0; 00365 while (PTB::_prop_tbl.find(i.id()) != PTB::_prop_tbl.end()) { 00366 ++ i.id(); 00367 } 00368 00369 std::pair<u_int, typename PTB::prop_tbl_entry_t> entry; 00370 entry.first = i.id(); 00371 entry.second._alloc = &i; 00372 PTB::_prop_tbl.insert(entry); 00373 } 00374 00375 template <class T> 00376 void _free_property_id(property_id_t<T>& i) 00377 { 00378 typedef details::PropertyTableBase PTB; 00379 typename PTB::prop_tbl_t::iterator entry = PTB::_prop_tbl.find(i.id()); 00380 if (entry == PTB::_prop_tbl.end()) return; 00381 00382 typename PTB::prop_tbl_list_t& lst = entry->second._list; 00383 typename PTB::prop_tbl_list_t::iterator the_ptr = lst.begin(); 00384 typename PTB::prop_tbl_list_t::iterator end_ptr = lst.end(); 00385 for (;the_ptr != end_ptr;) { 00386 typename PTB::prop_tbl_list_iterator_t this_ptr = the_ptr; 00387 ++ the_ptr; 00388 this_ptr->object_ptr()->free_property(i); 00389 } 00390 PTB::_prop_tbl.erase(entry); 00391 i.id() = 0xffff; 00392 } 00393 } 00394 00395 template <class T> void 00396 new_property_id(property_id_t<T>& pid) { 00397 details::_new_property_id(pid); 00398 } 00399 00400 template <class T> void 00401 free_property_id(property_id_t<T>& pid) { 00402 details::_free_property_id(pid); 00403 } 00404 00405 00406 #endif // __PropertyTable_h__ 00407