00001
00002
00003
00004
00005
00006
00007 #ifndef QuickVec_hh
00008 #define QuickVec_hh
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00021 #include <cassert>
00022 #include <vector>
00025
00026 #ifndef TRACE
00027 # define TRACE( lvl, ... )
00028 # define UNDEF_TRACE_AT_END
00029 #endif
00030
00031 #define USE_UNIQUE_PTR 0
00032 #define QV_ALIGN 512
00033
00040 static inline void* QV_MEMALIGN(size_t boundary, size_t size)
00041 {
00042 void* retadr;
00043 posix_memalign(&retadr, boundary, size);
00044 return retadr;
00045 }
00046
00047 #ifndef QUICKVEC_DO_TEMPLATE
00048 # define QUICKVEC_DO_TEMPLATE 1
00049 #endif
00050
00051 #undef NOT_OLD_CXXSTD
00052 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
00053 # define NOT_OLD_CXXSTD 1
00054 #endif
00055
00056 #if QUICKVEC_DO_TEMPLATE == 0
00057 # ifndef QUICKVEC_TT
00058 # define QUICKVEC_TT unsigned long long
00059 # endif
00060 # define TT_ QUICKVEC_TT
00061 # define QUICKVEC_TEMPLATE
00062 # define QUICKVEC QuickVec
00063 # define QUICKVEC_TN QuickVec
00064 # define QUICKVEC_VERSION
00065 #else
00066 # define QUICKVEC_TEMPLATE template <typename TT_>
00067 # define QUICKVEC QuickVec<TT_>
00068 # define QUICKVEC_TN typename QuickVec<TT_>
00069 # define QUICKVEC_VERSION \
00070 \
00076 static short Class_Version() { return 5; } // proper version for templates
00077 #endif
00078
00079 namespace artdaq {
00080
00086 QUICKVEC_TEMPLATE
00087 struct QuickVec
00088 {
00089 typedef TT_* iterator;
00090 typedef const TT_* const_iterator;
00091 typedef TT_& reference;
00092 typedef const TT_& const_reference;
00093 typedef TT_ value_type;
00094 typedef ptrdiff_t difference_type;
00095 typedef size_t size_type;
00096
00101 QuickVec(size_t sz);
00102
00108 QuickVec(size_t sz, TT_ val);
00109 # if USE_UNIQUE_PTR == 0
00110
00113 virtual ~QuickVec() noexcept;
00114
00115 # define PTR_(xx) xx
00116 # else
00117 # define PTR_(xx) xx.get()
00118 # endif
00119
00124 QuickVec(std::vector<TT_>& other)
00125 : size_(other.size())
00126 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00127 , capacity_(other.capacity())
00128 {
00129 memcpy(PTR_(data_), (void*)&other[0], size_ * sizeof(TT_));
00130 }
00131
00135 void clear() { size_ = 0; }
00136
00137
00142 QuickVec(const QuickVec& other)
00143 : size_(other.size_)
00144 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00145 , capacity_(other.capacity_)
00146 {
00147 TRACE(10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00148 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00149 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00150 }
00151
00157 QUICKVEC& operator=(const QuickVec& other)
00158 {
00159 TRACE(10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00160 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00161 resize(other.size_);
00162 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00163 return *this;
00164 }
00165 # if NOT_OLD_CXXSTD
00166
00170 QuickVec(QuickVec&& other) noexcept
00171 : size_(other.size_)
00172 , data_(std::move(other.data_))
00173 , capacity_(other.capacity_)
00174 {
00175 TRACE(10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00176 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00177 # if USE_UNIQUE_PTR == 0
00178 other.data_ = nullptr;
00179 # endif
00180 }
00181
00187 QUICKVEC& operator=(QuickVec&& other) noexcept
00188 {
00189 TRACE(10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00190 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00191 size_ = other.size_;
00192
00193 free(data_);
00194 data_ = std::move(other.data_);
00195 capacity_ = other.capacity_;
00196 # if USE_UNIQUE_PTR == 0
00197 other.data_ = nullptr;
00198 # endif
00199 return *this;
00200 }
00201 # endif
00202
00208 TT_& operator[](int idx);
00209
00215 const TT_& operator[](int idx) const;
00216
00221 size_t size() const;
00222
00231 size_t capacity() const;
00232
00237 iterator begin();
00238
00243 const_iterator begin() const;
00244
00249 iterator end();
00250
00255 const_iterator end() const;
00256
00264 void reserve(size_t size);
00265
00274 void resize(size_t size);
00275
00281 void resize(size_t size, TT_ val);
00282
00294 iterator insert(const_iterator position, size_t nn, const TT_& val);
00295
00307 iterator insert(const_iterator position, const_iterator first
00308 , const_iterator last);
00309
00320 iterator erase(const_iterator first, const_iterator last);
00321
00326 void swap(QuickVec& other) noexcept;
00327
00332 void push_back(const value_type& val);
00333
00334 QUICKVEC_VERSION
00335
00336 private:
00337
00338
00339
00340 unsigned size_;
00341 # if USE_UNIQUE_PTR == 0
00342 TT_* data_;
00343 # else
00344 std::unique_ptr<TT_[]> data_;
00345 # endif
00346 unsigned capacity_;
00347 };
00348
00349 QUICKVEC_TEMPLATE
00350 inline QUICKVEC::QuickVec(size_t sz)
00351
00352 : size_(sz)
00353 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00354 , capacity_(sz)
00355 {
00356 TRACE(15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_));
00357 }
00358
00359 QUICKVEC_TEMPLATE
00360 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00361
00362 : size_(sz)
00363 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00364 , capacity_(sz)
00365 {
00366 TRACE(15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_));
00367 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00368
00369 }
00370
00371 #if USE_UNIQUE_PTR == 0
00372 QUICKVEC_TEMPLATE
00373 inline QUICKVEC::~QuickVec() noexcept
00374 {
00375 TRACE(15, "QuickVec %p dtor start data_=%p size_=%d"
00376 , (void*)this, (void*)PTR_(data_), size_);
00377
00378 free(data_);
00379 TRACE(15, "QuickVec %p dtor return", (void*)this);
00380 }
00381 #endif
00382
00383 QUICKVEC_TEMPLATE
00384 inline TT_& QUICKVEC::operator[](int idx)
00385 {
00386 assert(idx < (int)size_);
00387 return data_[idx];
00388 }
00389
00390 QUICKVEC_TEMPLATE
00391 inline const TT_& QUICKVEC::operator[](int idx) const
00392 {
00393 assert(idx < (int)size_);
00394 return data_[idx];
00395 }
00396
00397 QUICKVEC_TEMPLATE
00398 inline size_t QUICKVEC::size() const { return size_; }
00399
00400 QUICKVEC_TEMPLATE
00401 inline size_t QUICKVEC::capacity() const { return capacity_; }
00402
00403 QUICKVEC_TEMPLATE
00404 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
00405
00406 QUICKVEC_TEMPLATE
00407 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
00408
00409 QUICKVEC_TEMPLATE
00410 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_) + size_); }
00411
00412 QUICKVEC_TEMPLATE
00413 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_) + size_); }
00414
00415 QUICKVEC_TEMPLATE
00416 inline void QUICKVEC::reserve(size_t size)
00417 {
00418 if (size > capacity_)
00419 {
00420 # if USE_UNIQUE_PTR == 0
00421 TT_* old = data_;
00422
00423 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00424 memcpy(data_, old, size_ * sizeof(TT_));
00425 TRACE(13, "QUICKVEC::reserve this=%p old=%p data_=%p"
00426 , (void*)this, (void*)old, (void*)data_);
00427
00428 free(old);
00429 # else
00430 std::unique_ptr<TT_[]> old = std::move(data_);
00431
00432 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00433 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00434 # endif
00435 capacity_ = size;
00436
00437 }
00438 }
00439
00440 QUICKVEC_TEMPLATE
00441 inline void QUICKVEC::resize(size_t size)
00442 {
00443 if (size < size_) size_ = size;
00444 else if (size <= capacity_) size_ = size;
00445 else
00446 {
00447 # if USE_UNIQUE_PTR == 0
00448 TT_* old = data_;
00449
00450 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00451 memcpy(data_, old, size_ * sizeof(TT_));
00452 TRACE(13, "QUICKVEC::resize this=%p old=%p data_=%p"
00453 , (void*)this, (void*)old, (void*)data_);
00454
00455 free(old);
00456 # else
00457 std::unique_ptr<TT_[]> old = std::move(data_);
00458
00459 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00460 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00461 # endif
00462 size_ = capacity_ = size;
00463
00464 }
00465 }
00466
00467 QUICKVEC_TEMPLATE
00468 inline void QUICKVEC::resize(size_type size, TT_ val)
00469 {
00470 size_type old_size = size;
00471 resize(size);
00472 if (size > old_size)
00473 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00474 }
00475
00476 QUICKVEC_TEMPLATE
00477 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00478 , size_t nn
00479 , const TT_& val)
00480 {
00481 assert(position <= end());
00482 size_t offset = position - begin();
00483 reserve(size_ + nn);
00484
00485 iterator dst = end() + nn;
00486 iterator src = end();
00487 size_t cnt = end() - (begin() + offset);
00488 while (cnt--) *--dst = *--src;
00489
00490 dst = begin() + offset;
00491 size_ += nn;
00492 while (nn--) *dst++ = val;
00493 return begin() + offset;
00494 }
00495
00496 QUICKVEC_TEMPLATE
00497 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00498 , const_iterator first
00499 , const_iterator last)
00500 {
00501 assert(position <= end());
00502 size_t nn = (last - first);
00503 size_t offset = position - begin();
00504 reserve(size_ + nn);
00505
00506 iterator dst = end() + nn;
00507 iterator src = end();
00508 size_t cnt = end() - (begin() + offset);
00509 while (cnt--) *--dst = *--src;
00510
00511 dst = begin() + offset;
00512 size_ += nn;
00513 while (nn--) *dst++ = *first++;
00514 return begin() + offset;
00515 }
00516
00517 QUICKVEC_TEMPLATE
00518 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00519 , const_iterator last)
00520 {
00521 assert(last <= end());
00522 size_t nn = (last - first);
00523 size_t offset = first - begin();
00524
00525 iterator dst = begin() + offset;
00526 iterator src = dst + nn;
00527 size_t cnt = end() - src;
00528 while (cnt--) *dst++ = *src++;
00529
00530 size_ -= nn;
00531 return begin() + offset;
00532 }
00533
00534 QUICKVEC_TEMPLATE
00535 inline void QUICKVEC::swap(QuickVec& x) noexcept
00536 {
00537 TRACE(12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00538 , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_));
00539 std::swap(data_, x.data_);
00540 std::swap(size_, x.size_);
00541 std::swap(capacity_, x.capacity_);
00542 TRACE(12, "QUICKVEC::swap return data_=%p x.data_=%p"
00543 , (void*)PTR_(data_), (void*)PTR_(x.data_));
00544 }
00545
00546 QUICKVEC_TEMPLATE
00547 inline void QUICKVEC::push_back(const value_type& val)
00548 {
00549 if (size_ == capacity_)
00550 {
00551 reserve(size_ + size_ / 10 + 1);
00552 }
00553 *end() = val;
00554 ++size_;
00555 }
00556
00557 }
00558
00559 #ifdef UNDEF_TRACE_AT_END
00560 # undef TRACE
00561 #endif
00562 #endif