00001 #ifndef DataFormats_Common_RefVectorHolderBase_h 00002 #define DataFormats_Common_RefVectorHolderBase_h 00003 #include "DataFormats/Common/interface/RefHolderBase.h" 00004 #include "FWCore/Utilities/interface/EDMException.h" 00005 #include "Reflex/Type.h" 00006 #include "boost/shared_ptr.hpp" 00007 00008 namespace edm { 00009 template <typename T> class RefToBase; 00010 namespace reftobase { 00011 class RefVectorHolderBase { 00012 public: 00013 virtual ~RefVectorHolderBase() {} 00014 typedef size_t size_type; 00015 typedef RefHolderBase value_type; 00016 void swap(RefVectorHolderBase& other) {} // nothing to swap 00017 virtual bool empty() const = 0; 00018 virtual size_type size() const = 0; 00019 virtual void clear() = 0; 00020 virtual void reserve( size_type n ) = 0; 00021 virtual ProductID id() const = 0; 00022 virtual EDProductGetter const* productGetter() const = 0; 00023 virtual RefVectorHolderBase * clone() const = 0; 00024 virtual RefVectorHolderBase * cloneEmpty() const = 0; 00025 virtual void push_back( const RefHolderBase * r ) = 0; 00026 // the following structure is public 00027 // to allow reflex dictionary to compile 00028 // protected: 00029 struct const_iterator_imp { 00030 typedef ptrdiff_t difference_type; 00031 const_iterator_imp() { } 00032 virtual ~const_iterator_imp() { } 00033 virtual const_iterator_imp * clone() const = 0; 00034 virtual void increase() = 0; 00035 virtual void decrease() = 0; 00036 virtual void increase( difference_type d ) = 0; 00037 virtual void decrease( difference_type d ) = 0; 00038 virtual bool equal_to( const const_iterator_imp * ) const = 0; 00039 virtual bool less_than( const const_iterator_imp * ) const = 0; 00040 virtual void assign( const const_iterator_imp * ) = 0; 00041 virtual boost::shared_ptr<RefHolderBase> deref() const = 0; 00042 virtual difference_type difference( const const_iterator_imp * ) const = 0; 00043 }; 00044 00045 struct const_iterator : public std::iterator <std::random_access_iterator_tag, void *>{ 00046 typedef boost::shared_ptr<RefHolderBase> value_type; 00047 typedef std::ptrdiff_t difference_type; 00048 const_iterator() : i( 0 ) { } 00049 const_iterator( const_iterator_imp * it ) : i( it ) { } 00050 const_iterator( const const_iterator & it ) : i( it.isValid() ? it.i->clone() : 0 ) { } 00051 ~const_iterator() { delete i; } 00052 const_iterator & operator=( const const_iterator & it ) { 00053 if ( isInvalid() ) i = it.i; 00054 else i->assign( it.i ); 00055 return *this; 00056 } 00057 const_iterator& operator++() { 00058 if ( isInvalid() ) 00059 throw edm::Exception( edm::errors::InvalidReference ) 00060 << "Trying to increment an inavlid RefToBaseVector<T>::const_iterator\n"; 00061 i->increase(); 00062 return *this; 00063 } 00064 const_iterator operator++( int ) { 00065 if ( isInvalid() ) 00066 throw edm::Exception( edm::errors::InvalidReference ) 00067 << "Trying to postincrement an inavlid RefToBaseVector<T>::const_iterator\n"; 00068 const_iterator ci = *this; 00069 i->increase(); 00070 return ci; 00071 } 00072 const_iterator& operator--() { 00073 if ( isInvalid() ) 00074 throw edm::Exception( edm::errors::InvalidReference ) 00075 << "Trying to decrement an inavlid RefToBaseVector<T>::const_iterator\n"; 00076 i->decrease(); 00077 return *this; 00078 } 00079 const_iterator operator--( int ) { 00080 if ( isInvalid() ) 00081 throw edm::Exception( edm::errors::InvalidReference ) 00082 << "Trying to postdecrement an inavlid RefToBaseVector<T>::const_iterator\n"; 00083 const_iterator ci = *this; 00084 i->decrease(); 00085 return ci; 00086 } 00087 difference_type operator-( const const_iterator & o ) const { 00088 if ( isInvalid() && o.isInvalid() ) return 0; 00089 if ( isInvalid() || o.isInvalid() ) 00090 throw edm::Exception( edm::errors::InvalidReference ) 00091 << "Trying to compute difference with an inavlid RefToBaseVector<T>::const_iterator\n"; 00092 return i->difference( o.i ); 00093 } 00094 const_iterator operator+( difference_type n ) const { 00095 if ( isInvalid() ) 00096 throw edm::Exception( edm::errors::InvalidReference ) 00097 << "Trying to compute sum with an inavlid RefToBaseVector<T>::const_iterator\n"; 00098 const_iterator_imp * ii = i->clone(); 00099 ii->increase( n ); 00100 return const_iterator( ii ); 00101 } 00102 const_iterator operator-( difference_type n ) const { 00103 if ( isInvalid() ) 00104 throw edm::Exception( edm::errors::InvalidReference ) 00105 << "Trying to compute difference with an inavlid RefToBaseVector<T>::const_iterator\n"; 00106 const_iterator_imp * ii = i->clone(); 00107 ii->decrease( n ); 00108 return const_iterator( ii ); 00109 } 00110 bool operator<( const const_iterator & o ) const { 00111 if ( isInvalid() && o.isInvalid() ) return false; 00112 if ( isInvalid() || o.isInvalid() ) 00113 throw edm::Exception( edm::errors::InvalidReference ) 00114 << "Trying to compute < operator with an inavlid RefToBaseVector<T>::const_iterator\n"; 00115 return i->less_than( o.i ); 00116 } 00117 bool operator==( const const_iterator& ci ) const { 00118 if ( isInvalid() && ci.isInvalid() ) return true; 00119 if ( isInvalid() || ci.isInvalid() ) return false; 00120 return i->equal_to( ci.i ); 00121 } 00122 bool operator!=( const const_iterator& ci ) const { 00123 if ( isInvalid() && ci.isInvalid() ) return false; 00124 if ( isInvalid() || ci.isInvalid() ) return true; 00125 return ! i->equal_to( ci.i ); 00126 } 00127 value_type operator * () const { 00128 if ( isInvalid() ) 00129 throw edm::Exception( edm::errors::InvalidReference ) 00130 << "Trying to dereference an inavlid RefToBaseVector<T>::const_iterator\n"; 00131 return i->deref(); 00132 } 00133 const_iterator & operator -=( difference_type d ) { 00134 if ( isInvalid() ) 00135 throw edm::Exception( edm::errors::InvalidReference ) 00136 << "Trying to decrement an inavlid RefToBaseVector<T>::const_iterator\n"; 00137 i->decrease( d ); 00138 return *this; 00139 } 00140 const_iterator & operator +=( difference_type d ) { 00141 if ( isInvalid() ) 00142 throw edm::Exception( edm::errors::InvalidReference ) 00143 << "Trying to increment an inavlid RefToBaseVector<T>::const_iterator\n"; 00144 i->increase( d ); 00145 return *this; 00146 } 00147 bool isValid() const { return i != 0; } 00148 bool isInvalid() const { return i == 0; } 00149 00150 private: 00151 const_iterator_imp * i; 00152 }; 00153 00154 virtual const_iterator begin() const = 0; 00155 virtual const_iterator end() const = 0; 00156 template <class T> RefToBase<T> getRef( size_t idx ) const; 00157 virtual const void * product() const = 0; 00158 virtual void reallyFillView( const void *, const ProductID &, std::vector<void const*> & ) = 0; 00159 00162 virtual bool isAvailable() const = 0; 00163 00164 private: 00165 virtual boost::shared_ptr<reftobase::RefHolderBase> refBase(size_t idx) const = 0; 00166 }; 00167 00168 template <class T> 00169 RefToBase<T> RefVectorHolderBase::getRef( size_t idx ) const { 00170 boost::shared_ptr<reftobase::RefHolderBase> rb = refBase(idx); 00171 return RefToBase<T>( rb ); 00172 } 00173 00174 // Free swap function 00175 inline 00176 void swap(RefVectorHolderBase& lhs, RefVectorHolderBase& rhs) { 00177 lhs.swap(rhs); 00178 } 00179 00180 } 00181 } 00182 00183 #endif