00001
00002
00003
00004
00005
00006
00007 #ifndef QuickVec_hh
00008 #define QuickVec_hh
00009
00010
00011
00012
00013
00014 #include <string.h>
00015
00016
00017 #include <cstddef>
00018
00019
00021 #include <cassert>
00022 #include <vector>
00025
00026 #ifndef TRACEN
00027 # define TRACEN( nam, lvl, ... )
00028 # define UNDEF_TRACE_AT_END
00029 #endif
00030
00031 #define QV_ALIGN 512
00032
00039 static inline void* QV_MEMALIGN(size_t boundary, size_t size)
00040 {
00041 void* retadr;
00042 posix_memalign(&retadr, boundary, size);
00043 return retadr;
00044 }
00045
00046 #ifndef QUICKVEC_DO_TEMPLATE
00047 # define QUICKVEC_DO_TEMPLATE 1
00048 #endif
00049
00050 #undef NOT_OLD_CXXSTD
00051 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
00052 # define NOT_OLD_CXXSTD 1
00053 #endif
00054
00055 #if QUICKVEC_DO_TEMPLATE == 0
00056 # ifndef QUICKVEC_TT
00057 # define QUICKVEC_TT unsigned long long
00058 # endif
00059 # define TT_ QUICKVEC_TT
00060 # define QUICKVEC_TEMPLATE
00061 # define QUICKVEC QuickVec
00062 # define QUICKVEC_TN QuickVec
00063 # define QUICKVEC_VERSION
00064 #else
00065 # define QUICKVEC_TEMPLATE template <typename TT_>
00066 # define QUICKVEC QuickVec<TT_>
00067 # define QUICKVEC_TN typename QuickVec<TT_>
00068 # define QUICKVEC_VERSION \
00069 \
00075 static short Class_Version() { return 5; } // proper version for templates
00076 #endif
00077
00078 namespace artdaq {
00079
00085 QUICKVEC_TEMPLATE
00086 struct QuickVec
00087 {
00088 typedef TT_* iterator;
00089 typedef const TT_* const_iterator;
00090 typedef TT_& reference;
00091 typedef const TT_& const_reference;
00092 typedef TT_ value_type;
00093 typedef ptrdiff_t difference_type;
00094 typedef size_t size_type;
00095
00100 QuickVec(size_t sz);
00101
00107 QuickVec(size_t sz, TT_ val);
00108
00112 virtual ~QuickVec() noexcept;
00113
00118 QuickVec(std::vector<TT_>& other)
00119 : size_(other.size())
00120 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00121 , capacity_(other.capacity())
00122 {
00123 TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d"
00124 , (void*)this, (void*)data_, (void*)&other[0], size_, other.size());
00125 memcpy( data_, (void*)&other[0], size_ * sizeof(TT_));
00126 }
00127
00131 void clear() { size_ = 0; }
00132
00133
00138 QuickVec(const QuickVec& other)
00139 : size_(other.size_)
00140 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00141 , capacity_(other.capacity_)
00142 {
00143 TRACEN("QuickVec",10, "QuickVec copy ctor b4 memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00144 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00145 memcpy( data_, other.data_, size_ * sizeof(TT_));
00146 }
00147
00153 QUICKVEC& operator=(const QuickVec& other)
00154 {
00155 TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00156 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00157 resize(other.size_);
00158 memcpy( data_, other.data_, size_ * sizeof(TT_));
00159 return *this;
00160 }
00161 # if NOT_OLD_CXXSTD
00162
00166 QuickVec(QuickVec&& other) noexcept
00167 : size_(other.size_)
00168 , data_(std::move(other.data_))
00169 , capacity_(other.capacity_)
00170 {
00171 TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00172 , (void*)this, (void*)data_, (void*)other.data_ );
00173 other.data_ = nullptr;
00174 }
00175
00181 QUICKVEC& operator=(QuickVec&& other) noexcept
00182 {
00183 TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00184 , (void*)this, (void*)data_, (void*)other.data_ );
00185 size_ = other.size_;
00186
00187 free(data_);
00188 data_ = std::move(other.data_);
00189 capacity_ = other.capacity_;
00190 other.data_ = nullptr;
00191 return *this;
00192 }
00193 # endif
00194
00200 TT_& operator[](int idx);
00201
00207 const TT_& operator[](int idx) const;
00208
00213 size_t size() const;
00214
00223 size_t capacity() const;
00224
00229 iterator begin();
00230
00235 const_iterator begin() const;
00236
00241 iterator end();
00242
00247 const_iterator end() const;
00248
00256 void reserve(size_t size);
00257
00266 void resize(size_t size);
00267
00273 void resize(size_t size, TT_ val);
00274
00286 iterator insert(const_iterator position, size_t nn, const TT_& val);
00287
00299 iterator insert(const_iterator position, const_iterator first
00300 , const_iterator last);
00301
00312 iterator erase(const_iterator first, const_iterator last);
00313
00318 void swap(QuickVec& other) noexcept;
00319
00324 void push_back(const value_type& val);
00325
00326 QUICKVEC_VERSION
00327
00328 private:
00329
00330
00331
00332 unsigned size_;
00333 TT_* data_;
00334 unsigned capacity_;
00335 };
00336
00337 QUICKVEC_TEMPLATE
00338 inline QUICKVEC::QuickVec(size_t sz)
00339 : size_(sz)
00340 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00341 , capacity_(sz)
00342 {
00343 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
00344 }
00345
00346 QUICKVEC_TEMPLATE
00347 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00348 : size_(sz)
00349 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00350 , capacity_(sz)
00351 {
00352 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
00353 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00354
00355 }
00356
00357 QUICKVEC_TEMPLATE
00358 inline QUICKVEC::~QuickVec() noexcept
00359 {
00360 TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
00361 , (void*)this, (void*)data_, size_);
00362 free(data_);
00363 TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
00364 }
00365
00366 QUICKVEC_TEMPLATE
00367 inline TT_& QUICKVEC::operator[](int idx)
00368 {
00369 assert(idx < (int)size_);
00370 return data_[idx];
00371 }
00372
00373 QUICKVEC_TEMPLATE
00374 inline const TT_& QUICKVEC::operator[](int idx) const
00375 {
00376 assert(idx < (int)size_);
00377 return data_[idx];
00378 }
00379
00380 QUICKVEC_TEMPLATE
00381 inline size_t QUICKVEC::size() const { return size_; }
00382
00383 QUICKVEC_TEMPLATE
00384 inline size_t QUICKVEC::capacity() const { return capacity_; }
00385
00386 QUICKVEC_TEMPLATE
00387 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
00388
00389 QUICKVEC_TEMPLATE
00390 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
00391
00392 QUICKVEC_TEMPLATE
00393 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
00394
00395 QUICKVEC_TEMPLATE
00396 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
00397
00398 QUICKVEC_TEMPLATE
00399 inline void QUICKVEC::reserve(size_t size)
00400 {
00401 if (size > capacity_)
00402 {
00403 TT_* old = data_;
00404
00405 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00406 memcpy(data_, old, size_ * sizeof(TT_));
00407 TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p"
00408 , (void*)this, (void*)old, (void*)data_);
00409 free(old);
00410 capacity_ = size;
00411 }
00412 }
00413
00414 QUICKVEC_TEMPLATE
00415 inline void QUICKVEC::resize(size_t size)
00416 {
00417 if (size < size_) size_ = size;
00418 else if (size <= capacity_) size_ = size;
00419 else
00420 {
00421 TT_* old = data_;
00422 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00423 memcpy(data_, old, size_ * sizeof(TT_));
00424 TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p"
00425 , (void*)this, (void*)old, (void*)data_);
00426 free(old);
00427 size_ = capacity_ = size;
00428 }
00429 }
00430
00431 QUICKVEC_TEMPLATE
00432 inline void QUICKVEC::resize(size_type size, TT_ val)
00433 {
00434 size_type old_size = size;
00435 resize(size);
00436 if (size > old_size) {
00437 TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
00438 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00439 }
00440 }
00441
00442 QUICKVEC_TEMPLATE
00443 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00444 , size_t nn
00445 , const TT_& val)
00446 {
00447 assert(position <= end());
00448 size_t offset = position - begin();
00449 reserve(size_ + nn);
00450
00451 iterator dst = end() + nn;
00452 iterator src = end();
00453 size_t cnt = end() - (begin() + offset);
00454 while (cnt--) *--dst = *--src;
00455
00456 dst = begin() + offset;
00457 size_ += nn;
00458 while (nn--) *dst++ = val;
00459 return begin() + offset;
00460 }
00461
00462 QUICKVEC_TEMPLATE
00463 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00464 , const_iterator first
00465 , const_iterator last)
00466 {
00467 assert(position <= end());
00468 size_t nn = (last - first);
00469 size_t offset = position - begin();
00470 reserve(size_ + nn);
00471
00472 iterator dst = end() + nn;
00473 iterator src = end();
00474 size_t cnt = end() - (begin() + offset);
00475 while (cnt--) *--dst = *--src;
00476
00477 dst = begin() + offset;
00478 size_ += nn;
00479 while (nn--) *dst++ = *first++;
00480 return begin() + offset;
00481 }
00482
00483 QUICKVEC_TEMPLATE
00484 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00485 , const_iterator last)
00486 {
00487 assert(last <= end());
00488 size_t nn = (last - first);
00489 size_t offset = first - begin();
00490
00491 iterator dst = begin() + offset;
00492 iterator src = dst + nn;
00493 size_t cnt = end() - src;
00494 while (cnt--) *dst++ = *src++;
00495
00496 size_ -= nn;
00497 return begin() + offset;
00498 }
00499
00500 QUICKVEC_TEMPLATE
00501 inline void QUICKVEC::swap(QuickVec& x) noexcept
00502 {
00503 TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00504 , (void*)this, (void*)data_, (void*)x.data_ );
00505 std::swap(data_, x.data_);
00506 std::swap(size_, x.size_);
00507 std::swap(capacity_, x.capacity_);
00508 TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
00509 , (void*)data_, (void*)x.data_ );
00510 }
00511
00512 QUICKVEC_TEMPLATE
00513 inline void QUICKVEC::push_back(const value_type& val)
00514 {
00515 if (size_ == capacity_)
00516 {
00517 reserve(size_ + size_ / 10 + 1);
00518 }
00519 *end() = val;
00520 ++size_;
00521 }
00522
00523 }
00524
00525 #ifdef UNDEF_TRACE_AT_END
00526 # undef TRACEN
00527 # undef UNDEF_TRACE_AT_END
00528 #endif
00529 #endif