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