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;
00288 virtual void configureDirectAccess();
00290
00304
00305 iterator begin() { return m_sequential.begin(); }
00307 const_iterator begin() const { return m_sequential.begin(); }
00309 iterator end() { return m_sequential.end(); }
00311 const_iterator end() const { return m_sequential.end(); }
00313 reverse_iterator rbegin() { return m_sequential.rbegin(); }
00315 const_reverse_iterator rbegin() const { return m_sequential.rbegin(); }
00317 reverse_iterator rend() { return m_sequential.rend(); }
00319 const_reverse_iterator rend() const { return m_sequential.rend(); }
00321
00339 value_type object(const key_type& kval) const { return i_object(kval); }
00340
00350 value_type operator()(const key_type& kval) const { return i_object(kval); }
00352
00375 long erase(const key_type& kval) { return i_erase(0, kval); }
00376
00397 long erase(const value_type val) {
00398 return (val) ? i_erase(val, val->key()) : (long) Containers::OBJ_NOT_FOUND;
00399 }
00400
00421 long erase(iterator pos) { return erase(*pos); }
00422
00431 void erase(iterator pos_start, iterator pos_stop, bool use_temp=false);
00432
00451 const key_type& insert(const value_type val, const key_type& kval);
00452
00474 const key_type& insert(const value_type val);
00476 };
00477
00478
00486
00487 template <class DATATYPE, class MAPPING> inline
00488 KeyedContainer<DATATYPE, MAPPING>::~KeyedContainer()
00489 {
00490 erase(begin(), end());
00491 m_cont.clear();
00492 }
00493
00494
00495 template <class DATATYPE, class MAPPING> inline
00496 void KeyedContainer<DATATYPE, MAPPING>::configureDirectAccess()
00497 {
00498 int count = 0;
00499 m_cont.clearDirect();
00500 typename seq_type::iterator i = m_sequential.begin();
00501 typename seq_type::iterator s = m_sequential.end();
00502 for ( ; i != s; i++ ) {
00503 typename seq_type::value_type v = *i;
00504 if ( v ) {
00505 if ( !v->hasKey() ) {
00506 traits::setKey(v, v->key());
00507 traits::addRef(v);
00508 }
00509 long k0 = traits::hash(v->key());
00510 if(m_cont.insertDirect(this, v, v, k0) == Containers::OBJ_INSERTED) {
00511 }
00512 }
00513 else {
00514 ++count;
00515 }
00516 }
00517 if ( count > 0 ) {
00518 Containers::cannotInsertToContainer();
00519 }
00520 }
00521
00522
00523
00524 template <class DATATYPE, class MAPPING> inline
00525 const std::vector<const ContainedObject*>*
00526 KeyedContainer<DATATYPE, MAPPING>::containedObjects() const {
00527 return (const std::vector<const ContainedObject*>*)
00528 ((0==m_cont.isDirect()) ? m_random : &m_sequential);
00529 }
00530
00531 template <class DATATYPE, class MAPPING> inline
00532 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00533 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val,
00534 const key_type& kval)
00535 {
00536 if ( val ) {
00537 long k0 = traits::hash(kval);
00538 if ( !val->hasKey() || (traits::hash(val->key()) == k0) ) {
00539 if(m_cont.insert(this,val,val,k0) == Containers::OBJ_INSERTED) {
00540 if ( !val->hasKey() ) traits::setKey(val, kval);
00541 traits::addRef(val);
00542 return val->key();
00543 }
00544 }
00545 }
00546
00547 Containers::cannotInsertToContainer();
00548 return val->key();
00549 }
00550
00551
00552 template <class DATATYPE, class MAPPING>
00553 const typename KeyedContainer<DATATYPE, MAPPING>::key_type&
00554 KeyedContainer<DATATYPE, MAPPING>::insert(const value_type val)
00555 {
00556 if ( 0 != val ) {
00557 if ( val->hasKey() ) {
00558 if (m_cont.insert(this,val,val,traits::hash(val->key()))
00559 == Containers::OBJ_INSERTED) {
00560 traits::addRef(val);
00561 return val->key();
00562 }
00563 }
00564 long k0;
00565 if ( m_cont.insert(this, val, val, &k0) == Containers::OBJ_INSERTED ) {
00566 traits::setKey(val, traits::makeKey(k0));
00567 traits::addRef(val);
00568 return val->key();
00569 }
00570 }
00571
00572 Containers::cannotInsertToContainer();
00573 return val->key();
00574 }
00575
00576 template <class DATATYPE, class MAPPING> inline
00577 long KeyedContainer<DATATYPE, MAPPING>::index(const ContainedObject* p) const
00578 {
00579 const contained_type* ptr = dynamic_cast<const contained_type*>(p);
00580 if ( ptr ) return traits::identifier(ptr->key());
00581 return -1;
00582 }
00583
00584
00585 template <class DATATYPE, class MAPPING> inline
00586 typename KeyedContainer<DATATYPE, MAPPING>::size_type KeyedContainer<DATATYPE, MAPPING>::containedObjects
00587 (std::vector<ContainedObject*>& vec) const
00588 {
00589 typename seq_type::const_iterator i = m_sequential.begin();
00590 typename seq_type::const_iterator s = m_sequential.end();
00591 vec.clear();
00592 vec.reserve(size());
00593 for ( ; i != s; i++ ) {
00594 ContainedObject* p = const_cast<typename seq_type::value_type>(*i);
00595 vec.push_back(p);
00596 }
00597 return vec.size();
00598 }
00599
00600
00601 template <class DATATYPE, class MAPPING> inline
00602 long KeyedContainer<DATATYPE, MAPPING>::add(ContainedObject* pObject)
00603 {
00604 return traits::identifier(insert(dynamic_cast<typename seq_type::value_type>(pObject)));
00605 }
00606
00607
00608 template <class DATATYPE, class MAPPING> inline
00609 long KeyedContainer<DATATYPE, MAPPING>::remove(ContainedObject* p)
00610 {
00611 contained_type* p1 = dynamic_cast<contained_type*>(p);
00612 if ( p1 ) {
00613 return this->erase(p1);
00614 }
00615 else if ( p ) {
00616 const ObjectContainerBase* par = p->parent();
00617
00618
00619
00620
00621
00622
00623 if ( par ) {
00624 Containers::invalidContainerOperation();
00625 }
00626 return m_cont.erase(0, p)==0 ? (long) Containers::OBJ_ERASED
00627 : (long) Containers::OBJ_NOT_FOUND;
00628 }
00629 return (long) Containers::OBJ_NOT_FOUND;
00630 }
00631
00632 template <class DATATYPE, class MAPPING> inline
00633 void
00634 KeyedContainer<DATATYPE, MAPPING>::erase(iterator start_pos,
00635 iterator stop_pos,
00636 bool use_tmp)
00637 {
00638 bool is_start = start_pos == m_sequential.begin();
00639 bool is_stop = stop_pos == m_sequential.end();
00640 if ( is_start && is_stop ) {
00641
00642 }
00643 else if ( is_start || is_stop || use_tmp ) {
00644 std::vector<DATATYPE*> tmp(m_sequential.begin(), start_pos);
00645 tmp.insert(tmp.end(), stop_pos, m_sequential.end());
00646 std::for_each(tmp.begin(), tmp.end(), traits::addRef);
00647 this->erase(m_sequential.begin(), m_sequential.end());
00648 std::for_each(tmp.begin(), tmp.end(), _InsertRelease(this));
00649 return;
00650 }
00651 std::for_each(start_pos, stop_pos, _RemoveRelease(this));
00652 seq_type *sptr = &m_sequential;
00653 std::vector<void*>* v = (std::vector<void*>*)sptr;
00654 std::vector<void*>::iterator i1 =
00655 v->begin() + std::distance(m_sequential.begin(), start_pos);
00656 std::vector<void*>::iterator i2 =
00657 v->begin() + std::distance(m_sequential.begin(), stop_pos);
00658 m_cont.erase(i1, i2);
00659 }
00660
00661 #undef FORCE_INLINE
00662 #endif // GAUDIKERNEL_KEYEDCONTAINER_H