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 GAUDI_API KeyedContainer: public ObjectContainerBase
00065 {
00066 friend struct GaudiDict::KeyedContainerDict<DATATYPE>;
00067
00068 public:
00070 typedef DATATYPE contained_type;
00072 typedef MAPPING container_type;
00073
00080
00081 typedef typename std::vector<contained_type*> seq_type;
00083 typedef typename contained_type::key_type key_type;
00085 typedef typename seq_type::value_type value_type;
00087 typedef typename seq_type::reference reference;
00089 typedef typename seq_type::const_reference const_reference;
00091 typedef typename seq_type::iterator iterator;
00093 typedef typename seq_type::const_iterator const_iterator;
00095 typedef typename seq_type::reverse_iterator reverse_iterator;
00099 typedef typename seq_type::const_reverse_iterator const_reverse_iterator;
00101 private:
00105 typedef typename Containers::traits<container_type, contained_type> traits;
00106
00110
00111 container_type m_cont;
00113 seq_type m_sequential;
00115 seq_type* m_random;
00116
00118 #ifdef CHECK_KEYED_CONTAINER
00119 value_type i_object(const key_type& k) const {
00120 if ( 0 == m_cont.isDirect() ) {
00121 if ( traits::checkBounds(m_random, k) ) {
00122 value_type p = *(m_random->begin()+traits::hash(k));
00123 if ( traits::checkKey(p, k) ) {
00124 return p;
00125 }
00126 }
00127 return 0;
00128 }
00129 value_type p = value_type(m_cont.object(traits::hash(k)));
00130 return traits::checkKey(p, k) ? p : 0;
00131 }
00132 #else
00133 FORCE_INLINE value_type i_object(const key_type& k) const {
00134 return 0==m_cont.isDirect()
00135 ? value_type(*(m_random->begin()+traits::hash(k)))
00136 : value_type(m_cont.object(traits::hash(k)));
00137 }
00138 #endif
00140 long i_erase(const_reference v, const key_type& k) {
00141 value_type p = value_type(m_cont.erase(traits::hash(k), v));
00142 if ( p ) {
00143 if ( p->parent() == this ) {
00144 p->setParent(0);
00145 }
00146 }
00147 return traits::release(p) <= 0 ? (long) Containers::OBJ_ERASED
00148 : (long) Containers::OBJ_DELETED;
00149 }
00150
00152 struct _InsertRelease {
00153 KeyedContainer<DATATYPE,MAPPING>* m_obj;
00154 _InsertRelease(KeyedContainer<DATATYPE,MAPPING>* p) : m_obj(p) {}
00155 void operator()(value_type p) {
00156 m_obj->insert(p);
00157 traits::release(p);
00158 }
00159 };
00160
00162 struct _RemoveRelease {
00163 ObjectContainerBase* m_obj;
00164 _RemoveRelease(ObjectContainerBase* p) : m_obj(p) {}
00165 void operator()(value_type p) {
00166 const ObjectContainerBase* par = p->parent();
00167 if ( par == m_obj ) {
00168 p->setParent(0);
00169 }
00170 traits::release(p);
00171 }
00172 };
00174
00175 public:
00179
00180 KeyedContainer(void)
00181 {
00182
00183 seq_type** rptr = &m_random;
00184 seq_type* sptr = &m_sequential;
00185 m_cont.setup((void*)sptr,(void**)rptr);
00186 }
00188 virtual ~KeyedContainer();
00190
00196
00197 virtual const CLID& clID() const { return this->classID(); }
00199 static const CLID& classID() {
00200 static CLID clid = contained_type::classID() + container_type::classID();
00201 return clid;
00202 }
00204
00221
00222 virtual size_type numberOfObjects() const { return m_sequential.size(); }
00234 virtual long add(ContainedObject* pObject);
00235
00248 virtual long remove(ContainedObject* pObject);
00249
00253 virtual ContainedObject* containedObject(long key_value) const {
00254 return i_object( traits::makeKey( key_value ) );
00255 }
00259 virtual long index(const ContainedObject* p) const;
00265 virtual size_type containedObjects(std::vector<ContainedObject*>& v) const;
00267
00273
00274 size_type size() const { return m_sequential.size(); }
00276 bool empty() const { return m_sequential.empty(); }
00278 void reserve(size_type value) { m_cont.reserve(value); }
00280 void clear() { erase(begin(), end()); }
00286 virtual const std::vector<const ContainedObject*>* containedObjects() const;
00291 virtual StatusCode update();
00293
00307
00308 iterator begin() { return m_sequential.begin(); }
00310 const_iterator begin() const { return m_sequential.begin(); }
00312 iterator end() { return m_sequential.end(); }
00314 const_iterator end() const { return m_sequential.end(); }
00316 reverse_iterator rbegin() { return m_sequential.rbegin(); }
00318 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
00320 reverse_iterator rend() { return m_sequential.rend(); }
00322 const_reverse_iterator rend() const { return m_sequential.rend(); }
00324
00342 value_type object(const key_type& kval) const { return i_object(kval); }
00343
00353 value_type operator()(const key_type& kval) const { return i_object(kval); }
00355
00378 long erase(const key_type& kval) { return i_erase(0, kval); }
00379
00400 long erase(const value_type val) {
00401 return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
00402 }
00403
00424 long erase(iterator pos) { return erase(*pos); }
00425
00434 void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
00435
00454 const key_type& insert(const value_type val, const key_type& kval);
00455
00477 const key_type& insert(const value_type val);
00479 };
00480
00481
00489
00490 template <class DATATYPE, class MAPPING> inline
00491 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
00492 {
00493 erase(begin(), end());
00494 m_cont.clear();
00495 }
00496
00497
00498 template <class DATATYPE, class MAPPING> inline
00499 StatusCode KeyedContainer<DATATYPE, MAPPING>::update()
00500 {
00501 int count = 0;
00502 m_cont.clearDirect();
00503 typename seq_type::iterator i = m_sequential.begin();
00504 typename seq_type::iterator s = m_sequential.end();
00505 for ( ; i != s; i++ ) {
00506 typename seq_type::value_type v = *i;
00507 if ( v ) {
00508 if ( !v->hasKey() ) {
00509 traits::setKey(v, v->key());
00510 traits::addRef(v);
00511 }
00512 long k0 = traits::hash(v->key());
00513 if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
00514 }
00515 }
00516 else {
00517 ++count;
00518 }
00519 }
00520 if ( count > 0 ) {
00521 Containers::cannotInsertToContainer();
00522 }
00523 return StatusCode::SUCCESS;
00524 }
00525
00526
00527
00528 template <class DATATYPE, class MAPPING> inline
00529 const std::vector<const ContainedObject*>*
00530 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const {
00531 return (const std::vector<const ContainedObject*>*)
00532 ((0==m_cont.isDirect()) ? m_random : &m_sequential);
00533 }
00534
00535 template <class DATATYPE, class MAPPING> inline
00536 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00537 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
00538 const key_type& kval)
00539 {
00540 if ( val ) {
00541 long k0 = traits::hash(kval);
00542 if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
00543 if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
00544 if ( !val->hasKey() ) traits::setKey(val, kval);
00545 traits::addRef(val);
00546 return val->key();
00547 }
00548 }
00549 }
00550
00551 Containers::cannotInsertToContainer();
00552 return val->key();
00553 }
00554
00555
00556 template <class DATATYPE, class MAPPING>
00557 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00558 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
00559 {
00560 if ( 0 != val ) {
00561 if ( val->hasKey() ) {
00562 if (m_cont.insert(this,val,val,traits::hash(val->key()))
00563 == Containers::OBJ_INSERTED) {
00564 traits::addRef(val);
00565 return val->key();
00566 }
00567 }
00568 long k0;
00569 if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
00570 traits::setKey(val, traits::makeKey(k0));
00571 traits::addRef(val);
00572 return val->key();
00573 }
00574 }
00575
00576 Containers::cannotInsertToContainer();
00577 return val->key();
00578 }
00579
00580 template <class DATATYPE, class MAPPING> inline
00581 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
00582 {
00583 const contained_type* ptr = dynamic_cast<const contained_type*>(p);
00584 if ( ptr ) return traits::identifier(ptr->key());
00585 return -1;
00586 }
00587
00588
00589 template <class DATATYPE, class MAPPING> inline
00590 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
00591 (std::vector<ContainedObject*>& vec) const
00592 {
00593 typename seq_type::const_iterator i = m_sequential.begin();
00594 typename seq_type::const_iterator s = m_sequential.end();
00595 vec.clear();
00596 vec.reserve(size());
00597 for ( ; i != s; i++ ) {
00598 ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
00599 vec.push_back(p);
00600 }
00601 return vec.size();
00602 }
00603
00604
00605 template <class DATATYPE, class MAPPING> inline
00606 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
00607 {
00608 return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
00609 }
00610
00611
00612 template <class DATATYPE, class MAPPING> inline
00613 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
00614 {
00615 contained_type* p1 = dynamic_cast<contained_type*>(p);
00616 if ( p1 ) {
00617 return this->erase(p1);
00618 }
00619 else if ( p ) {
00620 const ObjectContainerBase* par = p->parent();
00621
00622
00623
00624
00625
00626
00627 if ( par ) {
00628 Containers::invalidContainerOperation();
00629 }
00630 return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
00631 : (long) Containers::OBJ_NOT_FOUND;
00632 }
00633 return (long) Containers::OBJ_NOT_FOUND;
00634 }
00635
00636 template <class DATATYPE, class MAPPING> inline
00637 void
00638 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
00639 iterator stop_pos,
00640 bool use_tmp)
00641 {
00642 bool is_start = start_pos == m_sequential.begin();
00643 bool is_stop = stop_pos == m_sequential.end();
00644 if ( is_start && is_stop ) {
00645
00646 }
00647 else if ( is_start || is_stop || use_tmp ) {
00648 std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
00649 tmp.insert(tmp.end(), stop_pos, m_sequential.end());
00650 std::for_each(tmp.begin(), tmp.end(), traits::addRef);
00651 this->erase(m_sequential.begin(), m_sequential.end());
00652 std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
00653 return;
00654 }
00655 std::for_each(start_pos, stop_pos, _RemoveRelease(this));
00656 seq_type *sptr = &m_sequential;
00657 std::vector<void*>* v = (std::vector<void*>*)sptr;
00658 std::vector<void*>::iterator i1 =
00659 v->begin() + std::distance(m_sequential.begin(), start_pos);
00660 std::vector<void*>::iterator i2 =
00661 v->begin() + std::distance(m_sequential.begin(), stop_pos);
00662 m_cont.erase(i1, i2);
00663 }
00664
00665 #undef FORCE_INLINE
00666 #endif // GAUDIKERNEL_KEYEDCONTAINER_H