00001
00002
00003
00004
00005
00006
00007 #ifndef QuickVec_hh
00008 #define QuickVec_hh
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <cassert>
00018
00019
00020
00021 #include <vector>
00022
00023
00024 #ifndef TRACE
00025 # define TRACE( lvl, ... )
00026 # define UNDEF_TRACE_AT_END
00027 #endif
00028
00029 #define USE_UNIQUE_PTR 0
00030 #define QV_ALIGN 512
00031 static inline void *QV_MEMALIGN(size_t boundary, size_t size) { void *retadr; posix_memalign(&retadr, boundary, size); return retadr; }
00032
00033 #ifndef QUICKVEC_DO_TEMPLATE
00034 # define QUICKVEC_DO_TEMPLATE 1
00035 #endif
00036
00037 #undef NOT_OLD_CXXSTD
00038 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
00039 # define NOT_OLD_CXXSTD 1
00040 #endif
00041
00042 #if QUICKVEC_DO_TEMPLATE == 0
00043 # ifndef QUICKVEC_TT
00044 # define QUICKVEC_TT unsigned long long
00045 # endif
00046 # define TT_ QUICKVEC_TT
00047 # define QUICKVEC_TEMPLATE
00048 # define QUICKVEC QuickVec
00049 # define QUICKVEC_TN QuickVec
00050 # define QUICKVEC_VERSION
00051 #else
00052 # define QUICKVEC_TEMPLATE template <typename TT_>
00053 # define QUICKVEC QuickVec<TT_>
00054 # define QUICKVEC_TN typename QuickVec<TT_>
00055
00056 # define QUICKVEC_VERSION static short Class_Version() { return 5; } // proper version for templates
00057 #endif
00058
00059 QUICKVEC_TEMPLATE
00060 struct QuickVec
00061 {
00062 typedef TT_* iterator;
00063 typedef const TT_* const_iterator;
00064 typedef TT_& reference;
00065 typedef const TT_& const_reference;
00066 typedef TT_ value_type;
00067 typedef ptrdiff_t difference_type;
00068 typedef size_t size_type;
00069
00070 QuickVec(size_t sz);
00071 QuickVec(size_t sz, TT_ val);
00072 # if USE_UNIQUE_PTR == 0
00073 virtual ~QuickVec() noexcept;
00074 # define PTR_(xx) xx
00075 # else
00076 # define PTR_(xx) xx.get()
00077 # endif
00078 QuickVec(std::vector<TT_> & other)
00079
00080 : size_(other.size()), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity())
00081 {
00082 memcpy(PTR_(data_), (void*)&other[0], size_ * sizeof(TT_));
00083 }
00084 void clear() { size_ = 0; }
00085
00086 QuickVec(const QuickVec & other)
00087
00088 : size_(other.size_), data_((TT_*)QV_MEMALIGN(QV_ALIGN, other.capacity() * sizeof(TT_))), capacity_(other.capacity_)
00089 {
00090 TRACE(10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00091 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00092 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00093 }
00094 QUICKVEC & operator=(const QuickVec & other)
00095 {
00096 TRACE(10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00097 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_);
00098 resize(other.size_);
00099 memcpy(PTR_(data_), PTR_(other.data_), size_ * sizeof(TT_));
00100 return *this;
00101 }
00102 # if NOT_OLD_CXXSTD
00103 QuickVec(QuickVec && other) noexcept
00104 : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
00105 {
00106 TRACE(10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00107 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00108 # if USE_UNIQUE_PTR == 0
00109 other.data_ = nullptr;
00110 # endif
00111 }
00112 QUICKVEC & operator=(QuickVec && other) noexcept
00113 {
00114 TRACE(10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00115 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_));
00116 size_ = other.size_;
00117
00118 free(data_);
00119 data_ = std::move(other.data_);
00120 capacity_ = other.capacity_;
00121 # if USE_UNIQUE_PTR == 0
00122 other.data_ = nullptr;
00123 # endif
00124 return *this;
00125 }
00126 # endif
00127
00128 TT_& operator[](int idx);
00129 const TT_& operator[](int idx) const;
00130 size_t size() const;
00131 size_t capacity() const;
00132 iterator begin();
00133 const_iterator begin() const;
00134 iterator end();
00135 const_iterator end() const;
00136 void reserve(size_t size);
00137 void resize(size_t size);
00138 void resize(size_t size, TT_ val);
00139 iterator insert(const_iterator position, size_t nn, const TT_& val);
00140 iterator insert(const_iterator position, const_iterator first
00141 , const_iterator last);
00142 iterator erase(const_iterator first, const_iterator last);
00143 void swap(QuickVec& x) noexcept;
00144 void push_back(const value_type& val);
00145
00146 QUICKVEC_VERSION
00147
00148 private:
00149
00150
00151
00152 unsigned size_;
00153 # if USE_UNIQUE_PTR == 0
00154 TT_ * data_;
00155 # else
00156 std::unique_ptr<TT_[]> data_;
00157 # endif
00158 unsigned capacity_;
00159 };
00160
00161 QUICKVEC_TEMPLATE
00162 inline QUICKVEC::QuickVec(size_t sz)
00163
00164 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
00165 {
00166 TRACE(15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_));
00167 }
00168 QUICKVEC_TEMPLATE
00169 inline QUICKVEC::QuickVec(size_t sz, TT_ val)
00170
00171 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN, sz * sizeof(TT_))), capacity_(sz)
00172 {
00173 TRACE(15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_));
00174 for (iterator ii = begin(); ii != end(); ++ii) *ii = val;
00175
00176 }
00177
00178 #if USE_UNIQUE_PTR == 0
00179 QUICKVEC_TEMPLATE
00180 inline QUICKVEC::~QuickVec() noexcept
00181 {
00182 TRACE(15, "QuickVec %p dtor start data_=%p size_=%d"
00183 , (void*)this, (void*)PTR_(data_), size_);
00184
00185 free(data_);
00186 TRACE(15, "QuickVec %p dtor return", (void*)this);
00187 }
00188 #endif
00189
00190 QUICKVEC_TEMPLATE
00191 inline TT_& QUICKVEC::operator[](int idx)
00192 {
00193 assert(idx < (int)size_); return data_[idx];
00194 }
00195
00196 QUICKVEC_TEMPLATE
00197 inline const TT_& QUICKVEC::operator[](int idx) const
00198 {
00199 assert(idx < (int)size_);
00200 return data_[idx];
00201 }
00202
00203 QUICKVEC_TEMPLATE
00204 inline size_t QUICKVEC::size() const { return size_; }
00205 QUICKVEC_TEMPLATE
00206 inline size_t QUICKVEC::capacity() const { return capacity_; }
00207
00208 QUICKVEC_TEMPLATE
00209 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
00210 QUICKVEC_TEMPLATE
00211 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
00212 QUICKVEC_TEMPLATE
00213 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_) + size_); }
00214 QUICKVEC_TEMPLATE
00215 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_) + size_); }
00216
00217 QUICKVEC_TEMPLATE
00218 inline void QUICKVEC::reserve(size_t size)
00219 {
00220 if (size > capacity_)
00221 {
00222 # if USE_UNIQUE_PTR == 0
00223 TT_ * old = data_;
00224
00225 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00226 memcpy(data_, old, size_ * sizeof(TT_));
00227 TRACE(13, "QUICKVEC::reserve this=%p old=%p data_=%p"
00228 , (void*)this, (void*)old, (void*)data_);
00229
00230 free(old);
00231 # else
00232 std::unique_ptr<TT_[]> old = std::move(data_);
00233
00234 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00235 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00236 # endif
00237 capacity_ = size;
00238
00239 }
00240 }
00241
00242 QUICKVEC_TEMPLATE
00243 inline void QUICKVEC::resize(size_t size)
00244 {
00245 if (size < size_) size_ = size;
00246 else if (size <= capacity_) size_ = size;
00247 else
00248 {
00249 # if USE_UNIQUE_PTR == 0
00250 TT_ * old = data_;
00251
00252 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_));
00253 memcpy(data_, old, size_ * sizeof(TT_));
00254 TRACE(13, "QUICKVEC::resize this=%p old=%p data_=%p"
00255 , (void*)this, (void*)old, (void*)data_);
00256
00257 free(old);
00258 # else
00259 std::unique_ptr<TT_[]> old = std::move(data_);
00260
00261 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN, size * sizeof(TT_)));
00262 memcpy(data_.get(), old.get(), size_ * sizeof(TT_));
00263 # endif
00264 size_ = capacity_ = size;
00265
00266 }
00267 }
00268 QUICKVEC_TEMPLATE
00269 inline void QUICKVEC::resize(size_type size, TT_ val)
00270 {
00271 size_type old_size = size;
00272 resize(size);
00273 if (size > old_size)
00274 for (iterator ii = begin() + old_size; ii != end(); ++ii) *ii = val;
00275 }
00276
00277 QUICKVEC_TEMPLATE
00278 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00279 , size_t nn
00280 , const TT_& val)
00281 {
00282 assert(position <= end());
00283 size_t offset = position - begin();
00284 reserve(size_ + nn);
00285
00286 iterator dst = end() + nn;
00287 iterator src = end();
00288 size_t cnt = end() - (begin() + offset);
00289 while (cnt--) *--dst = *--src;
00290
00291 dst = begin() + offset;
00292 size_ += nn;
00293 while (nn--) *dst++ = val;
00294 return begin() + offset;
00295 }
00296 QUICKVEC_TEMPLATE
00297 inline QUICKVEC_TN::iterator QUICKVEC::insert(const_iterator position
00298 , const_iterator first
00299 , const_iterator last)
00300 {
00301 assert(position <= end());
00302 size_t nn = (last - first);
00303 size_t offset = position - begin();
00304 reserve(size_ + nn);
00305
00306 iterator dst = end() + nn;
00307 iterator src = end();
00308 size_t cnt = end() - (begin() + offset);
00309 while (cnt--) *--dst = *--src;
00310
00311 dst = begin() + offset;
00312 size_ += nn;
00313 while (nn--) *dst++ = *first++;
00314 return begin() + offset;
00315 }
00316
00317 QUICKVEC_TEMPLATE
00318 inline QUICKVEC_TN::iterator QUICKVEC::erase(const_iterator first
00319 , const_iterator last)
00320 {
00321 assert(last <= end());
00322 size_t nn = (last - first);
00323 size_t offset = first - begin();
00324
00325 iterator dst = begin() + offset;
00326 iterator src = dst + nn;
00327 size_t cnt = end() - src;
00328 while (cnt--) *dst++ = *src++;
00329
00330 size_ -= nn;
00331 return begin() + offset;
00332 }
00333
00334 QUICKVEC_TEMPLATE
00335 inline void QUICKVEC::swap(QuickVec& x) noexcept
00336 {
00337 TRACE(12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00338 , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_));
00339 std::swap(data_, x.data_);
00340 std::swap(size_, x.size_);
00341 std::swap(capacity_, x.capacity_);
00342 TRACE(12, "QUICKVEC::swap return data_=%p x.data_=%p"
00343 , (void*)PTR_(data_), (void*)PTR_(x.data_));
00344 }
00345
00346 QUICKVEC_TEMPLATE
00347 inline void QUICKVEC::push_back(const value_type& val)
00348 {
00349 if (size_ == capacity_)
00350 {
00351 reserve(size_ + size_ / 10 + 1);
00352 }
00353 *end() = val;
00354 ++size_;
00355 }
00356
00357 #ifdef UNDEF_TRACE_AT_END
00358 # undef TRACE
00359 #endif
00360 #endif