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