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 TRACE
00027 # define TRACE( lvl, ... )
00028 # define TRACEN( nam, lvl, ... )
00029 # define UNDEF_TRACE_AT_END
00030 #endif
00031
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
00113 virtual ~QuickVec() noexcept;
00114
00119 QuickVec(std::vector<TT_>& other)
00120 : size_(other.size())
00121 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00122 , capacity_(other.capacity())
00123 {
00124 TRACEN("QuickVec", 10, "QuickVec std::vector ctor b4 memcpy this=%p data_=%p &other[0]=%p size_=%d other.size()=%d"
00125 , (void*)this, (void*)data_, (void*)&other[0], size_, other.size());
00126 memcpy( data_, (void*)&other[0], size_ * sizeof(TT_));
00127 }
00128
00132 void clear() { size_ = 0; }
00133
00134
00139 QuickVec(const QuickVec& other)
00140 : size_(other.size_)
00141 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_)))
00142 , capacity_(other.capacity_)
00143 {
00144 TRACEN("QuickVec",10, "QuickVec copy ctor b4 memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00145 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00146 memcpy( data_, other.data_, size_ * sizeof(TT_));
00147 }
00148
00154 QUICKVEC& operator=(const QuickVec& other)
00155 {
00156 TRACEN("QuickVec", 10, "QuickVec copy assign b4 resize/memcpy this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00157 , (void*)this, (void*)data_, (void*)other.data_, size_, other.size_);
00158 resize(other.size_);
00159 memcpy( data_, other.data_, size_ * sizeof(TT_));
00160 return *this;
00161 }
00162 # if NOT_OLD_CXXSTD
00163
00167 QuickVec(QuickVec&& other) noexcept
00168 : size_(other.size_)
00169 , data_(std::move(other.data_))
00170 , capacity_(other.capacity_)
00171 {
00172 TRACEN("QuickVec", 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00173 , (void*)this, (void*)data_, (void*)other.data_ );
00174 other.data_ = nullptr;
00175 }
00176
00182 QUICKVEC& operator=(QuickVec&& other) noexcept
00183 {
00184 TRACEN("QuickVec", 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00185 , (void*)this, (void*)data_, (void*)other.data_ );
00186 size_ = other.size_;
00187
00188 free(data_);
00189 data_ = std::move(other.data_);
00190 capacity_ = other.capacity_;
00191 other.data_ = nullptr;
00192 return *this;
00193 }
00194 # endif
00195
00201 TT_& operator[](int idx);
00202
00208 const TT_& operator[](int idx) const;
00209
00214 size_t size() const;
00215
00224 size_t capacity() const;
00225
00230 iterator begin();
00231
00236 const_iterator begin() const;
00237
00242 iterator end();
00243
00248 const_iterator end() const;
00249
00257 void reserve(size_t size);
00258
00267 void resize(size_t size);
00268
00274 void resize(size_t size, TT_ val);
00275
00287 iterator insert(const_iterator position, size_t nn, const TT_& val);
00288
00300 iterator insert(const_iterator position, const_iterator first
00301 , const_iterator last);
00302
00313 iterator erase(const_iterator first, const_iterator last);
00314
00319 void swap(QuickVec& other) noexcept;
00320
00325 void push_back(const value_type& val);
00326
00327 QUICKVEC_VERSION
00328
00329 private:
00330
00331
00332
00333 unsigned size_;
00334 TT_* data_;
00335 unsigned capacity_;
00336 };
00337
00338 QUICKVEC_TEMPLATE
00339 inline QUICKVEC::QuickVec(size_t sz)
00340 : size_(sz)
00341 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00342 , capacity_(sz)
00343 {
00344 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)data_ );
00345 }
00346
00347 QUICKVEC_TEMPLATE
00348 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00349 : size_(sz)
00350 , data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_)))
00351 , capacity_(sz)
00352 {
00353 TRACEN("QuickVec", 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)data_ );
00354 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00355
00356 }
00357
00358 QUICKVEC_TEMPLATE
00359 inline QUICKVEC::~QuickVec() noexcept
00360 {
00361 TRACEN("QuickVec", 15, "QuickVec %p dtor start data_=%p size_=%d"
00362 , (void*)this, (void*)data_, size_);
00363 free(data_);
00364 TRACEN("QuickVec", 15, "QuickVec %p dtor return", (void*)this);
00365 }
00366
00367 QUICKVEC_TEMPLATE
00368 inline TT_& QUICKVEC::operator[](int idx)
00369 {
00370 assert(idx < (int)size_);
00371 return data_[idx];
00372 }
00373
00374 QUICKVEC_TEMPLATE
00375 inline const TT_& QUICKVEC::operator[](int idx) const
00376 {
00377 assert(idx < (int)size_);
00378 return data_[idx];
00379 }
00380
00381 QUICKVEC_TEMPLATE
00382 inline size_t QUICKVEC::size() const { return size_; }
00383
00384 QUICKVEC_TEMPLATE
00385 inline size_t QUICKVEC::capacity() const { return capacity_; }
00386
00387 QUICKVEC_TEMPLATE
00388 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(data_); }
00389
00390 QUICKVEC_TEMPLATE
00391 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(data_); }
00392
00393 QUICKVEC_TEMPLATE
00394 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(data_+size_); }
00395
00396 QUICKVEC_TEMPLATE
00397 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(data_+size_); }
00398
00399 QUICKVEC_TEMPLATE
00400 inline void QUICKVEC::reserve(size_t size)
00401 {
00402 if (size > capacity_)
00403 {
00404 TT_* old = data_;
00405
00406 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00407 memcpy(data_, old, size_ * sizeof(TT_));
00408 TRACEN("QuickVec", 13, "QUICKVEC::reserve after memcpy this=%p old=%p data_=%p"
00409 , (void*)this, (void*)old, (void*)data_);
00410 free(old);
00411 capacity_ = size;
00412 }
00413 }
00414
00415 QUICKVEC_TEMPLATE
00416 inline void QUICKVEC::resize(size_t size)
00417 {
00418 if (size < size_) size_ = size;
00419 else if (size <= capacity_) size_ = size;
00420 else
00421 {
00422 TT_* old = data_;
00423 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00424 memcpy(data_, old, size_ * sizeof(TT_));
00425 TRACEN("QuickVec", 13, "QUICKVEC::resize after memcpy this=%p old=%p data_=%p"
00426 , (void*)this, (void*)old, (void*)data_);
00427 free(old);
00428 size_ = capacity_ = size;
00429 }
00430 }
00431
00432 QUICKVEC_TEMPLATE
00433 inline void QUICKVEC::resize(size_type size, TT_ val)
00434 {
00435 size_type old_size = size;
00436 resize(size);
00437 if (size > old_size) {
00438 TRACEN("QuickVec", 13, "QUICKVEC::resize initializing %zu elements", size-old_size );
00439 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00440 }
00441 }
00442
00443 QUICKVEC_TEMPLATE
00444 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00445 , size_t nn
00446 , const TT_& val)
00447 {
00448 assert(position <= end());
00449 size_t offset = position - begin();
00450 reserve(size_ + nn);
00451
00452 iterator dst = end() + nn;
00453 iterator src = end();
00454 size_t cnt = end() - (begin() + offset);
00455 while (cnt--) *--dst = *--src;
00456
00457 dst = begin() + offset;
00458 size_ += nn;
00459 while (nn--) *dst++ = val;
00460 return begin() + offset;
00461 }
00462
00463 QUICKVEC_TEMPLATE
00464 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00465 , const_iterator first
00466 , const_iterator last)
00467 {
00468 assert(position <= end());
00469 size_t nn = (last - first);
00470 size_t offset = position - begin();
00471 reserve(size_ + nn);
00472
00473 iterator dst = end() + nn;
00474 iterator src = end();
00475 size_t cnt = end() - (begin() + offset);
00476 while (cnt--) *--dst = *--src;
00477
00478 dst = begin() + offset;
00479 size_ += nn;
00480 while (nn--) *dst++ = *first++;
00481 return begin() + offset;
00482 }
00483
00484 QUICKVEC_TEMPLATE
00485 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00486 , const_iterator last)
00487 {
00488 assert(last <= end());
00489 size_t nn = (last - first);
00490 size_t offset = first - begin();
00491
00492 iterator dst = begin() + offset;
00493 iterator src = dst + nn;
00494 size_t cnt = end() - src;
00495 while (cnt--) *dst++ = *src++;
00496
00497 size_ -= nn;
00498 return begin() + offset;
00499 }
00500
00501 QUICKVEC_TEMPLATE
00502 inline void QUICKVEC::swap(QuickVec& x) noexcept
00503 {
00504 TRACEN("QuickVec", 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00505 , (void*)this, (void*)data_, (void*)x.data_ );
00506 std::swap(data_, x.data_);
00507 std::swap(size_, x.size_);
00508 std::swap(capacity_, x.capacity_);
00509 TRACEN("QuickVec", 12, "QUICKVEC::swap return data_=%p x.data_=%p"
00510 , (void*)data_, (void*)x.data_ );
00511 }
00512
00513 QUICKVEC_TEMPLATE
00514 inline void QUICKVEC::push_back(const value_type& val)
00515 {
00516 if (size_ == capacity_)
00517 {
00518 reserve(size_ + size_ / 10 + 1);
00519 }
00520 *end() = val;
00521 ++size_;
00522 }
00523
00524 }
00525
00526 #ifdef UNDEF_TRACE_AT_END
00527 # undef TRACE
00528 # undef TRACEN
00529 #endif
00530 #endif