AFEPack
PropertyTable.h
浏览该文件的文档。
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