00001
00002 #ifndef GAUDIKERNEL_KEYEDCONTAINER_H
00003 #define GAUDIKERNEL_KEYEDCONTAINER_H
00004
00005
00006 #include <iterator>
00007 #include <algorithm>
00008
00009 namespace GaudiDict {
00010 template <class T> struct KeyedContainerDict;
00011 }
00012
00013
00014 #include "GaudiKernel/ObjectContainerBase.h"
00015 #include "GaudiKernel/KeyedObjectManager.h"
00016 #include "GaudiKernel/KeyedObject.h"
00017
00018
00019
00020
00021 #ifdef WIN32
00022 #define FORCE_INLINE __forceinline
00023 #else
00024 #define FORCE_INLINE inline
00025 #endif
00026
00063 template <class DATATYPE, class MAPPING=Containers::HashMap >
00064 class KeyedContainer
00065 : public ObjectContainerBase
00066 {
00067 friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
00068
00069 public:
00071 typedef DATATYPE contained_type;
00073 typedef MAPPING container_type;
00074
00081
00082 typedef typename std::vector<contained_type*> seq_type;
00084 typedef typename contained_type::key_type key_type;
00086 typedef typename seq_type::value_type value_type;
00088 typedef typename seq_type::reference reference;
00090 typedef typename seq_type::const_reference const_reference;
00092 typedef typename seq_type::iterator iterator;
00094 typedef typename seq_type::const_iterator const_iterator;
00096 typedef typename seq_type::reverse_iterator reverse_iterator;
00100 typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
00102 private:
00106 typedef typename Containers::traits<container_type, contained_type> traits;
00107
00111
00112 container_type m_cont;
00114 seq_type m_sequential;
00116 seq_type* m_random;
00117
00119 #ifdef CHECK_KEYED_CONTAINER
00120 value_type i_object(const key_type& k) const {
00121 if ( 0 == m_cont.isDirect() ) {
00122 if ( traits::checkBounds(m_random, k) ) {
00123 value_type p = *(m_random->begin()+traits::hash(k));
00124 if ( traits::checkKey(p, k) ) {
00125 return p;
00126 }
00127 }
00128 return 0;
00129 }
00130 value_type p = value_type(m_cont.object(traits::hash(k)));
00131 return traits::checkKey(p, k) ? p : 0;
00132 }
00133 #else
00134 FORCE_INLINE value_type i_object(const key_type& k) const {
00135 return 0==m_cont.isDirect()
00136 ? value_type(*(m_random->begin()+traits::hash(k)))
00137 : value_type(m_cont.object(traits::hash(k)));
00138 }
00139 #endif
00141 long i_erase(const_reference v, const key_type& k) {
00142 value_type p = value_type(m_cont.erase(traits::hash(k), v));
00143 if ( p ) {
00144 if ( p->parent() == this ) {
00145 p->setParent(0);
00146 }
00147 }
00148 return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
00149 : (long) Containers::OBJ_DELETED;
00150 }
00151
00153 struct _InsertRelease {
00154 KeyedContainer<DATATYPE,MAPPING>* m_obj;
00155 _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
00156 void operator()(value_type p) {
00157 m_obj->insert(p);
00158 traits::release(p);
00159 }
00160 };
00161
00163 struct _RemoveRelease {
00164 ObjectContainerBase* m_obj;
00165 _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
00166 void operator()(value_type p) {
00167 const ObjectContainerBase* par = p->parent();
00168 if ( par == m_obj ) {
00169 p->setParent(0);
00170 }
00171 traits::release(p);
00172 }
00173 };
00175
00176 public:
00180
00181 KeyedContainer(void)
00182 {
00183
00184 seq_type** rptr = &m_random;
00185 seq_type* sptr = &m_sequential;
00186 m_cont.setup((void*)sptr,(void**)rptr);
00187 }
00189 virtual ~KeyedContainer();
00191
00197
00198 virtual const CLID& clID() const { return this->classID(); }
00200 static const CLID& classID() {
00201 static CLID clid = contained_type::classID() + container_type::classID();
00202 return clid;
00203 }
00205
00222
00223 virtual size_type numberOfObjects() const { return m_sequential.size(); }
00235 virtual long add(ContainedObject* pObject);
00236
00249 virtual long remove(ContainedObject* pObject);
00250
00254 virtual ContainedObject* containedObject(long key_value) const {
00255 return i_object( traits::makeKey( key_value ) );
00256 }
00260 virtual long index(const ContainedObject* p) const;
00266 virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
00268
00274
00275 size_type size() const { return m_sequential.size(); }
00277 bool empty() const { return m_sequential.empty(); }
00279 void reserve(size_type value) { m_cont.reserve(value); }
00281 void clear() { erase(begin(), end()); }
00287 virtual const std::vector<const ContainedObject*>* containedObjects() const;
00289 virtual void configureDirectAccess();
00291
00305
00306 iterator begin() { return m_sequential.begin(); }
00308 const_iterator begin() const { return m_sequential.begin(); }
00310 iterator end() { return m_sequential.end(); }
00312 const_iterator end() const { return m_sequential.end(); }
00314 reverse_iterator rbegin() { return m_sequential.rbegin(); }
00316 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
00318 reverse_iterator rend() { return m_sequential.rend(); }
00320 const_reverse_iterator rend() const { return m_sequential.rend(); }
00322
00340 value_type object(const key_type& kval) const { return i_object(kval); }
00341
00351 value_type operator()(const key_type& kval) const { return i_object(kval); }
00353
00376 long erase(const key_type& kval) { return i_erase(0, kval); }
00377
00398 long erase(const value_type val) {
00399 return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
00400 }
00401
00422 long erase(iterator pos) { return erase(*pos); }
00423
00432 void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
00433
00452 const key_type& insert(const value_type val, const key_type& kval);
00453
00475 const key_type& insert(const value_type val);
00477 };
00478
00479
00487
00488 template <class DATATYPE, class MAPPING> inline
00489 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
00490 {
00491 erase(begin(), end());
00492 m_cont.clear();
00493 }
00494
00495
00496 template <class DATATYPE, class MAPPING> inline
00497 void KeyedContainer<DATATYPE, MAPPING>::configureDirectAccess()
00498 {
00499 int count = 0;
00500 m_cont.clearDirect();
00501 typename seq_type::iterator i = m_sequential.begin();
00502 typename seq_type::iterator s = m_sequential.end();
00503 for ( ; i != s; i++ ) {
00504 typename seq_type::value_type v = *i;
00505 if ( v ) {
00506 if ( !v->hasKey() ) {
00507 traits::setKey(v, v->key());
00508 traits::addRef(v);
00509 }
00510 long k0 = traits::hash(v->key());
00511 if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
00512 }
00513 }
00514 else {
00515 ++count;
00516 }
00517 }
00518 if ( count > 0 ) {
00519 Containers::cannotInsertToContainer();
00520 }
00521 }
00522
00523
00524
00525 template <class DATATYPE, class MAPPING> inline
00526 const std::vector<const ContainedObject*>*
00527 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const {
00528 return (const std::vector<const ContainedObject*>*)
00529 ((0==m_cont.isDirect()) ? m_random : &m_sequential);
00530 }
00531
00532 template <class DATATYPE, class MAPPING> inline
00533 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00534 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
00535 const key_type& kval)
00536 {
00537 if ( val ) {
00538 long k0 = traits::hash(kval);
00539 if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
00540 if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
00541 if ( !val->hasKey() ) traits::setKey(val, kval);
00542 traits::addRef(val);
00543 return val->key();
00544 }
00545 }
00546 }
00547
00548 Containers::cannotInsertToContainer();
00549 return val->key();
00550 }
00551
00552
00553 template <class DATATYPE, class MAPPING>
00554 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00555 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
00556 {
00557 if ( 0 != val ) {
00558 if ( val->hasKey() ) {
00559 if (m_cont.insert(this,val,val,traits::hash(val->key()))
00560 == Containers::OBJ_INSERTED) {
00561 traits::addRef(val);
00562 return val->key();
00563 }
00564 }
00565 long k0;
00566 if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
00567 traits::setKey(val, traits::makeKey(k0));
00568 traits::addRef(val);
00569 return val->key();
00570 }
00571 }
00572
00573 Containers::cannotInsertToContainer();
00574 return val->key();
00575 }
00576
00577 template <class DATATYPE, class MAPPING> inline
00578 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
00579 {
00580 const contained_type* ptr = dynamic_cast<const contained_type*>(p);
00581 if ( ptr ) return traits::identifier(ptr->key());
00582 return -1;
00583 }
00584
00585
00586 template <class DATATYPE, class MAPPING> inline
00587 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
00588 (std::vector<ContainedObject*>& vec) const
00589 {
00590 typename seq_type::const_iterator i = m_sequential.begin();
00591 typename seq_type::const_iterator s = m_sequential.end();
00592 vec.clear();
00593 vec.reserve(size());
00594 for ( ; i != s; i++ ) {
00595 ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
00596 vec.push_back(p);
00597 }
00598 return vec.size();
00599 }
00600
00601
00602 template <class DATATYPE, class MAPPING> inline
00603 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
00604 {
00605 return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
00606 }
00607
00608
00609 template <class DATATYPE, class MAPPING> inline
00610 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
00611 {
00612 contained_type* p1 = dynamic_cast<contained_type*>(p);
00613 if ( p1 ) {
00614 return this->erase(p1);
00615 }
00616 else if ( p ) {
00617 const ObjectContainerBase* par = p->parent();
00618
00619
00620
00621
00622
00623
00624 if ( par ) {
00625 Containers::invalidContainerOperation();
00626 }
00627 return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
00628 : (long) Containers::OBJ_NOT_FOUND;
00629 }
00630 return (long) Containers::OBJ_NOT_FOUND;
00631 }
00632
00633 template <class DATATYPE, class MAPPING> inline
00634 void
00635 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
00636 iterator stop_pos,
00637 bool use_tmp)
00638 {
00639 bool is_start = start_pos == m_sequential.begin();
00640 bool is_stop = stop_pos == m_sequential.end();
00641 if ( is_start && is_stop ) {
00642
00643 }
00644 else if ( is_start || is_stop || use_tmp ) {
00645 std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
00646 tmp.insert(tmp.end(), stop_pos, m_sequential.end());
00647 std::for_each(tmp.begin(), tmp.end(), traits::addRef);
00648 this->erase(m_sequential.begin(), m_sequential.end());
00649 std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
00650 return;
00651 }
00652 std::for_each(start_pos, stop_pos, _RemoveRelease(this));
00653 seq_type *sptr = &m_sequential;
00654 std::vector<void*>* v = (std::vector<void*>*)sptr;
00655 std::vector<void*>::iterator i1 =
00656 v->begin() + std::distance(m_sequential.begin(), start_pos);
00657 std::vector<void*>::iterator i2 =
00658 v->begin() + std::distance(m_sequential.begin(), stop_pos);
00659 m_cont.erase(i1, i2);
00660 }
00661
00662 #undef FORCE_INLINE
00663 #endif // GAUDIKERNEL_KEYEDCONTAINER_H