CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/DataFormats/Common/interface/OwnArray.h

Go to the documentation of this file.
00001 #ifndef DataFormats_Common_OwnArray_h
00002 #define DataFormats_Common_OwnArray_h
00003 
00004 #include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
00005 #include "DataFormats/Common/interface/ClonePolicy.h"
00006 #include "DataFormats/Common/interface/fillPtrVector.h"
00007 #include "DataFormats/Common/interface/Ref.h"
00008 #include "DataFormats/Common/interface/setPtr.h"
00009 #include "DataFormats/Common/interface/traits.h"
00010 
00011 #if defined CMS_USE_DEBUGGING_ALLOCATOR
00012 #include "DataFormats/Common/interface/debugging_allocator.h"
00013 #endif
00014 #include "FWCore/Utilities/interface/EDMException.h"
00015 
00016 #include <algorithm>
00017 #include <functional>
00018 #include <typeinfo>
00019 #include <vector>
00020 
00021 namespace edm {
00022   class ProductID;
00023   template <typename T, unsigned int MAX_SIZE, typename P = ClonePolicy<T> >
00024   class OwnArray {
00025   private:
00026     typedef OwnArray<T,MAX_SIZE,P> self;
00027     typedef std::vector<T*> base;
00028   public:
00029     typedef unsigned int size_type;
00030     typedef T value_type;
00031     typedef T* pointer;
00032     typedef T& reference;
00033     typedef T const& const_reference;
00034     typedef P policy_type;
00035     
00036     class iterator;
00037     class const_iterator {
00038     public:
00039       typedef T value_type;
00040       typedef T* pointer;
00041       typedef T const& reference;
00042       typedef ptrdiff_t difference_type;
00043       typedef typename base::const_iterator::iterator_category iterator_category;
00044       const_iterator(pointer const *  it) : i(it) { }
00045       const_iterator(iterator const& it) : i(it.i) { }
00046       const_iterator() {}
00047       const_iterator& operator++() { ++i; return *this; }
00048       const_iterator operator++(int) { const_iterator ci = *this; ++i; return ci; }
00049       const_iterator& operator--() { --i; return *this; }
00050       const_iterator operator--(int) { const_iterator ci = *this; --i; return ci; }
00051       difference_type operator-(const_iterator const& o) const { return i - o.i; }
00052       const_iterator operator+(difference_type n) const { return const_iterator(i + n); }
00053       const_iterator operator-(difference_type n) const { return const_iterator(i - n); }
00054       bool operator<(const_iterator const& o) const { return i < o.i; }
00055       bool operator==(const_iterator const& ci) const { return i == ci.i; }
00056       bool operator!=(const_iterator const& ci) const { return i != ci.i; }
00057       T const& operator *() const { return **i; }
00058       //    operator T const*() const { return & **i; }
00059       T const* operator->() const { return & (operator*()); }
00060       const_iterator & operator +=(difference_type d) { i += d; return *this; }
00061       const_iterator & operator -=(difference_type d) { i -= d; return *this; }
00062       reference operator[](difference_type d) const { return *const_iterator(i+d); } // for boost::iterator_range []
00063     private:
00064       pointer const * i;
00065     };
00066     class iterator {
00067     public:
00068       typedef T value_type;
00069       typedef T * pointer;
00070       typedef T & reference;
00071       typedef ptrdiff_t difference_type;
00072       typedef typename base::iterator::iterator_category iterator_category;
00073       iterator(pointer * it) : i(it) { }
00074       iterator() {}
00075       iterator& operator++() { ++i; return *this; }
00076       iterator operator++(int) { iterator ci = *this; ++i; return ci; }
00077       iterator& operator--() { --i; return *this; }
00078       iterator operator--(int) { iterator ci = *this; --i; return ci; }
00079       difference_type operator-(iterator const& o) const { return i - o.i; }
00080       iterator operator+(difference_type n) const { return iterator(i + n); }
00081       iterator operator-(difference_type n) const { return iterator(i - n); }
00082       bool operator<(iterator const& o) const { return i < o.i; }
00083       bool operator==(iterator const& ci) const { return i == ci.i; }
00084       bool operator!=(iterator const& ci) const { return i != ci.i; }
00085       T & operator *() const { return **i; }
00086       //    operator T *() const { return & **i; }
00087       //T *& get() { return *i; }
00088       T * operator->() const { return & (operator*()); }
00089       iterator & operator +=(difference_type d) { i += d; return *this; }
00090       iterator & operator -=(difference_type d) { i -= d; return *this; }
00091       reference operator[](difference_type d) const { return *iterator(i+d); } // for boost::iterator_range []
00092     private:
00093       pointer * i;
00094       friend class const_iterator;
00095       friend class OwnArray<T, MAX_SIZE, P>;
00096     };
00097     
00098     
00099     OwnArray();
00100     OwnArray(size_type);
00101     OwnArray(OwnArray const&);
00102 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00103     OwnArray(OwnArray&&);
00104 #endif
00105     
00106     ~OwnArray();
00107     
00108     iterator begin();
00109     iterator end();
00110     const_iterator begin() const;
00111     const_iterator end() const;
00112     size_type size() const;
00113     bool empty() const;
00114     reference operator[](size_type);
00115     const_reference operator[](size_type) const;
00116     
00117     self& operator=(self const&);
00118 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00119     self& operator=(self&&);
00120 #endif
00121     
00122     
00123     void reserve(size_t){}
00124     size_type capacity() const { return MAX_SIZE;}
00125     template <typename D> void push_back(D*& d);
00126     template <typename D> void push_back(D* const& d);
00127     template <typename D> void push_back(std::auto_ptr<D> d);
00128     void push_back(T const& valueToCopy);
00129     bool is_back_safe() const;
00130     void pop_back();
00131     reference back();
00132     const_reference back() const;
00133     reference front();
00134     const_reference front() const;
00135     pointer const * data() const;
00136     void clear();
00137     iterator erase(iterator pos);
00138     iterator erase(iterator first, iterator last);
00139     template<typename S>
00140     void sort(S s);
00141     void sort();
00142     
00143     void swap(self& other);
00144     
00145     void fillView(ProductID const& id,
00146                   std::vector<void const*>& pointers,
00147                   helper_vector& helpers) const;
00148     
00149     void setPtr(std::type_info const& toType,
00150                 unsigned long index,
00151                 void const*& ptr) const;
00152     
00153     void fillPtrVector(std::type_info const& toType,
00154                        std::vector<unsigned long> const& indices,
00155                        std::vector<void const*>& ptrs) const;
00156     
00157     
00158     //Used by ROOT storage
00159     CMS_CLASS_VERSION(11)
00160     
00161     private:
00162     void destroy();
00163     template<typename O>
00164     struct Ordering {
00165       Ordering(O const& c) : comp(c) { }
00166       bool operator()(T const* t1, T const* t2) const {
00167         return comp(*t1, *t2);
00168       }
00169     private:
00170       O comp;
00171     };
00172     template<typename O>
00173     static Ordering<O> ordering(O const& comp) {
00174       return Ordering<O>(comp);
00175     }
00176     pointer data_[MAX_SIZE];
00177     size_type size_;
00178   };
00179   
00180   template<typename T, unsigned int M, typename P>
00181   inline OwnArray<T, M, P>::OwnArray() : data_{{0}}, size_(0) {
00182   }
00183   
00184   template<typename T, unsigned int M, typename P>
00185   inline OwnArray<T, M, P>::OwnArray(size_type n) : data_{{0}}, size_(n) {
00186   }
00187   
00188   template<typename T, unsigned int M, typename P>
00189   inline OwnArray<T, M, P>::OwnArray(OwnArray<T, M, P> const& o) : size_(o.size()) {
00190     size_type current = 0;
00191     for (const_iterator i = o.begin(), e = o.end(); i != e; ++i,++current)
00192       data_[current] = policy_type::clone(*i);
00193   }
00194   
00195 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00196   template<typename T, unsigned int M, typename P>
00197   inline OwnArray<T, M, P>::OwnArray(OwnArray<T, M, P>&& o)  {
00198     std::swap_ranges(data_,data_+M, o.data_);
00199   }
00200 #endif
00201   
00202   template<typename T, unsigned int M, typename P>
00203   inline OwnArray<T, M, P>::~OwnArray() {
00204     destroy();
00205   }
00206   
00207   template<typename T, unsigned int M, typename P>
00208   inline OwnArray<T, M, P>& OwnArray<T, M, P>::operator=(OwnArray<T, M, P> const& o) {
00209     OwnArray<T,M,P> temp(o);
00210     swap(temp);
00211     return *this;
00212   }
00213   
00214 #if defined(__GXX_EXPERIMENTAL_CXX0X__)
00215   template<typename T, unsigned int M, typename P>
00216   inline OwnArray<T, M, P>& OwnArray<T, M, P>::operator=(OwnArray<T, M, P>&& o) {
00217     std::swap_ranges(data_,data_+M, o.data_);
00218     return *this;
00219   }
00220 #endif
00221   
00222   
00223   template<typename T, unsigned int M, typename P>
00224   inline typename OwnArray<T, M, P>::iterator OwnArray<T, M, P>::begin() {
00225     return iterator(data_);
00226   }
00227   
00228    template<typename T, unsigned int M, typename P>
00229    inline typename OwnArray<T, M, P>::iterator OwnArray<T, M, P>::end() {
00230      return iterator(data_+size());
00231    }
00232   
00233   template<typename T, unsigned int M, typename P>
00234   inline typename OwnArray<T, M, P>::const_iterator OwnArray<T, M, P>::begin() const {
00235     return const_iterator(data_);
00236   }
00237   
00238   template<typename T, unsigned int M, typename P>
00239   inline typename OwnArray<T, M, P>::const_iterator OwnArray<T, M, P>::end() const {
00240     return const_iterator(data_+size());
00241   }
00242   
00243   template<typename T, unsigned int M, typename P>
00244   inline typename OwnArray<T, M, P>::size_type OwnArray<T, M, P>::size() const {
00245     return size_;
00246   }
00247   
00248   template<typename T, unsigned int M, typename P>
00249   inline bool OwnArray<T, M, P>::empty() const {
00250     return 0==size_;
00251   }
00252 
00253   template<typename T, unsigned int M, typename P>
00254   inline typename OwnArray<T, M, P>::reference OwnArray<T, M, P>::operator[](size_type n) {
00255     return *data_[n];
00256   }
00257   
00258   template<typename T, unsigned int M, typename P>
00259   inline typename OwnArray<T, M, P>::const_reference OwnArray<T, M, P>::operator[](size_type n) const {
00260     return *data_[n];
00261   }
00262   
00263   template<typename T, unsigned int M, typename P>
00264   template<typename D>
00265   inline void OwnArray<T, M, P>::push_back(D*& d) {
00266     // C++ does not yet support rvalue references, so d should only be
00267     // able to bind to an lvalue.
00268     // This should be called only for lvalues.
00269     data_[size_++]=d; 
00270     d = 0;
00271   }
00272   
00273   template<typename T, unsigned int M, typename P>
00274   template<typename D>
00275   inline void OwnArray<T, M, P>::push_back(D* const& d) {
00276     
00277     // C++ allows d to be bound to an lvalue or rvalue. But the other
00278     // signature should be a better match for an lvalue (because it
00279     // does not require an lvalue->rvalue conversion). Thus this
00280     // signature should only be chosen for rvalues.
00281     data_[size_++]=d; 
00282   }
00283   
00284   
00285   template<typename T, unsigned int M, typename P>
00286   template<typename D>
00287   inline void OwnArray<T, M, P>::push_back(std::auto_ptr<D> d) {
00288     data_[size_++]=d.release();
00289   }
00290   
00291   
00292   template<typename T, unsigned int M, typename P>
00293   inline void OwnArray<T, M, P>::push_back(T const& d) {
00294     data_[size_++]=policy_type::clone(d);
00295   }
00296   
00297   
00298   template<typename T, unsigned int M, typename P>
00299   inline void OwnArray<T, M, P>::pop_back() {
00300     // We have to delete the pointed-to thing, before we squeeze it
00301     // out of the vector...
00302     delete data_[--size_];
00303   }
00304   
00305   template <typename T, unsigned int M, typename P>
00306   inline bool OwnArray<T, M, P>::is_back_safe() const {
00307     return data_[size_-1] != 0;
00308   }
00309   
00310   template<typename T, unsigned int M, typename P>
00311   inline typename OwnArray<T, M, P>::reference OwnArray<T, M, P>::back() {
00312     pointer result = data_[size_-1];
00313     if (result == 0) {
00314       Exception::throwThis(errors::NullPointerError,
00315                            "In OwnArray::back() we have intercepted an attempt to dereference a null pointer\n"
00316                            "Since OwnArray is allowed to contain null pointers, you much assure that the\n"
00317                            "pointer at the end of the collection is not null before calling back()\n"
00318                            "if you wish to avoid this exception.\n"
00319                            "Consider using OwnArray::is_back_safe()\n");
00320     }
00321     return *result;
00322   }
00323   
00324   template<typename T, unsigned int M, typename P>
00325   inline typename OwnArray<T, M, P>::const_reference OwnArray<T, M, P>::back() const {
00326     pointer const * result = data_[size_-1];
00327     if (result == 0) {
00328       Exception::throwThis(errors::NullPointerError,
00329                            "In OwnArray::back() we have intercepted an attempt to dereference a null pointer\n"
00330                            "Since OwnArray is allowed to contain null pointers, you much assure that the\n"
00331                            "pointer at the end of the collection is not null before calling back()\n"
00332                            "if you wish to avoid this exception.\n"
00333                            "Consider using OwnArray::is_back_safe()\n");
00334     }
00335     return *result;
00336   }
00337   
00338   template<typename T, unsigned int M, typename P>
00339   inline typename OwnArray<T, M, P>::reference OwnArray<T, M, P>::front() {
00340     return *data_[0];
00341   }
00342   
00343   template<typename T, unsigned int M, typename P>
00344   inline typename OwnArray<T, M, P>::const_reference OwnArray<T, M, P>::front() const {
00345     return *data_[0];
00346   }
00347   
00348   template<typename T, unsigned int M, typename P>
00349   inline void OwnArray<T, M, P>::destroy() {
00350     pointer * b = data_, * e = data_+size();
00351     for(pointer * i = b; i != e; ++ i)
00352       delete * i;
00353   }
00354   
00355   template<typename T, unsigned int M, typename P>
00356   inline typename OwnArray<T, M, P>::pointer const * OwnArray<T, M, P>::data() const {
00357     return data_;
00358   }
00359 
00360    template<typename T, unsigned int M, typename P>
00361   inline void OwnArray<T, M, P>::clear() {
00362     destroy();
00363     size_=0;
00364   }
00365 
00366    template<typename T, unsigned int M, typename P>
00367   typename OwnArray<T, M, P>::iterator OwnArray<T, M, P>::erase(iterator pos) {
00368     pointer * b = pos.i;
00369     delete *b;
00370     pointer * e = data_+size();
00371     for(pointer * i = b; i != e-1; ++ i) *i = *(i+1);
00372     size_--;
00373     return iterator(b);
00374   }
00375 
00376    template<typename T, unsigned int M, typename P>
00377   typename OwnArray<T, M, P>::iterator OwnArray<T, M, P>::erase(iterator first, iterator last) {
00378      pointer * b = first.i, * e = last.i;
00379     for(pointer * i = b; i != e; ++ i) delete * i;
00380     pointer * l = data_+size();
00381     auto ib=b;
00382     for(pointer * i = e; i != l; ++i)  *(ib++) = *i;
00383     size_ -= (e-b);
00384     return iterator(b);
00385   }
00386 
00387    template<typename T, unsigned int M, typename P> template<typename S>
00388   void OwnArray<T, M, P>::sort(S comp) {
00389      std::sort(data_, data_+size(), ordering(comp));
00390   }
00391 
00392    template<typename T, unsigned int M, typename P>
00393   void OwnArray<T, M, P>::sort() {
00394     std::sort(data_, data_+size(), ordering(std::less<value_type>()));
00395   }
00396 
00397    template<typename T, unsigned int M, typename P>
00398   inline void OwnArray<T, M, P>::swap(OwnArray<T, M, P>& other) {
00399      std::swap_ranges(data_,data_+M, other.data_);
00400   }
00401 
00402    template<typename T, unsigned int M, typename P>
00403   void OwnArray<T, M, P>::fillView(ProductID const& id,
00404                                  std::vector<void const*>& pointers,
00405                                  helper_vector& helpers) const {
00406     typedef Ref<OwnArray>      ref_type ;
00407     typedef reftobase::RefHolder<ref_type> holder_type;
00408 
00409     size_type numElements = this->size();
00410     pointers.reserve(numElements);
00411     helpers.reserve(numElements);
00412     size_type key = 0;
00413     for(typename base::const_iterator i=data_.begin(), e=data_.end(); i!=e; ++i, ++key) {
00414 
00415       if (*i == 0) {
00416         Exception::throwThis(errors::NullPointerError,
00417           "In OwnArray::fillView() we have intercepted an attempt to put a null pointer\n"
00418           "into a View and that is not allowed.  It is probably an error that the null\n"
00419           "pointer was in the OwnArray in the first place.\n");
00420       }
00421       else {
00422         pointers.push_back(*i);
00423         holder_type h(ref_type(id, *i, key,this));
00424         helpers.push_back(&h);
00425       }
00426     }
00427   }
00428 
00429    template<typename T, unsigned int M, typename P>
00430   inline void swap(OwnArray<T, M, P>& a, OwnArray<T, M, P>& b) {
00431     a.swap(b);
00432   }
00433 
00434   //----------------------------------------------------------------------
00435   //
00436   // Free function template to support creation of Views.
00437 
00438   template <typename T, unsigned int M, typename P>
00439   inline
00440   void
00441   fillView(OwnArray<T,M,P> const& obj,
00442            ProductID const& id,
00443            std::vector<void const*>& pointers,
00444            helper_vector& helpers) {
00445     obj.fillView(id, pointers, helpers);
00446   }
00447 
00448 
00449   template <typename T, unsigned int M, typename P>
00450   struct has_fillView<edm::OwnArray<T, M, P> > {
00451     static bool const value = true;
00452   };
00453 
00454 
00455   // Free function templates to support the use of edm::Ptr.
00456 
00457   template <typename T, unsigned int M, typename P>
00458   inline
00459   void
00460   OwnArray<T,M,P>::setPtr(std::type_info const& toType,
00461                                    unsigned long index,
00462                                    void const*& ptr) const {
00463     detail::reallySetPtr<OwnArray<T,M,P> >(*this, toType, index, ptr);
00464   }
00465 
00466   template <typename T, unsigned int M, typename P>
00467   inline
00468   void
00469   setPtr(OwnArray<T,M,P> const& obj,
00470          std::type_info const& toType,
00471          unsigned long index,
00472          void const*& ptr) {
00473     obj.setPtr(toType, index, ptr);
00474   }
00475 
00476   template <typename T, unsigned int M, typename P>
00477   inline
00478   void
00479     OwnArray<T,M,P>::fillPtrVector(std::type_info const& toType,
00480                                   std::vector<unsigned long> const& indices,
00481                                   std::vector<void const*>& ptrs) const {
00482     detail::reallyfillPtrVector(*this, toType, indices, ptrs);
00483   }
00484 
00485 
00486   template <typename T, unsigned int M, typename P>
00487   inline
00488   void
00489   fillPtrVector(OwnArray<T,M,P> const& obj,
00490                 std::type_info const& toType,
00491                 std::vector<unsigned long> const& indices,
00492                 std::vector<void const*>& ptrs) {
00493     obj.fillPtrVector(toType, indices, ptrs);
00494   }
00495 
00496 
00497   template <typename T, unsigned int M, typename P>
00498   struct has_setPtr<edm::OwnArray<T,M,P> > {
00499      static bool const value = true;
00500    };
00501 
00502 
00503 }
00504 
00505 
00506 #endif