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 #include <stdlib.h>
00017 #include <cassert>
00018 #include <cstddef>
00019 #include <utility>
00020 #include <memory>
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 ~QuickVec();
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 { memcpy( PTR_(data_), (void*)&other[0], size_*sizeof(TT_) );
00082 }
00083 void clear() { size_=0; }
00084
00085 QuickVec( const QuickVec & other )
00086
00087 : size_(other.size_), data_((TT_*)QV_MEMALIGN(QV_ALIGN,other.capacity()*sizeof(TT_))), capacity_(other.capacity_)
00088 { TRACE( 10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00089 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
00090 memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
00091 }
00092 QUICKVEC & operator=( const QuickVec & other )
00093 { TRACE( 10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
00094 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
00095 resize( other.size_ );
00096 memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
00097 return *this;
00098 }
00099 # if NOT_OLD_CXXSTD
00100 QuickVec( QuickVec && other )
00101 : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
00102 { TRACE( 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
00103 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
00104 # if USE_UNIQUE_PTR == 0
00105 other.data_ = nullptr;
00106 # endif
00107 }
00108 QUICKVEC & operator=( QuickVec && other )
00109 { TRACE( 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
00110 , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
00111 size_ = other.size_;
00112
00113 free( data_ );
00114 data_ = std::move(other.data_);
00115 capacity_ = other.capacity_;
00116 # if USE_UNIQUE_PTR == 0
00117 other.data_ = nullptr;
00118 # endif
00119 return *this;
00120 }
00121 # endif
00122
00123 TT_& operator[](int idx);
00124 const TT_& operator[](int idx) const;
00125 size_t size() const;
00126 size_t capacity() const;
00127 iterator begin();
00128 const_iterator begin() const;
00129 iterator end();
00130 const_iterator end() const;
00131 void reserve( size_t size );
00132 void resize( size_t size );
00133 void resize( size_t size, TT_ val );
00134 iterator insert( const_iterator position, size_t nn, const TT_& val );
00135 iterator insert( const_iterator position, const_iterator first
00136 , const_iterator last);
00137 iterator erase( const_iterator first, const_iterator last );
00138 void swap( QuickVec& x );
00139 void push_back( const value_type& val );
00140
00141 QUICKVEC_VERSION
00142
00143 private:
00144
00145
00146
00147 unsigned size_;
00148 # if USE_UNIQUE_PTR == 0
00149 TT_ * data_;
00150 # else
00151 std::unique_ptr<TT_[]> data_;
00152 # endif
00153 unsigned capacity_;
00154 };
00155
00156 QUICKVEC_TEMPLATE
00157 inline QUICKVEC::QuickVec( size_t sz )
00158
00159 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN,sz*sizeof(TT_))), capacity_(sz)
00160 { TRACE( 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_) );
00161 }
00162 QUICKVEC_TEMPLATE
00163 inline QUICKVEC::QuickVec( size_t sz, TT_ val )
00164
00165 : size_(sz), data_((TT_*)QV_MEMALIGN(QV_ALIGN,sz*sizeof(TT_))), capacity_(sz)
00166 { TRACE( 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_) );
00167 for (iterator ii=begin(); ii!=end(); ++ii) *ii=val;
00168
00169 }
00170
00171 #if USE_UNIQUE_PTR == 0
00172 QUICKVEC_TEMPLATE
00173 inline QUICKVEC::~QuickVec()
00174 { TRACE( 15, "QuickVec %p dtor start data_=%p size_=%d"
00175 , (void*)this, (void*)PTR_(data_), size_ );
00176
00177 free( data_ );
00178 TRACE( 15, "QuickVec %p dtor return", (void*)this );
00179 }
00180 #endif
00181
00182 QUICKVEC_TEMPLATE
00183 inline TT_& QUICKVEC::operator[](int idx)
00184 { assert(idx<(int)size_); return data_[idx];
00185 }
00186
00187 QUICKVEC_TEMPLATE
00188 inline const TT_& QUICKVEC::operator[](int idx) const
00189 { assert(idx < (int)size_);
00190 return data_[idx];
00191 }
00192
00193 QUICKVEC_TEMPLATE
00194 inline size_t QUICKVEC::size() const { return size_; }
00195 QUICKVEC_TEMPLATE
00196 inline size_t QUICKVEC::capacity() const { return capacity_; }
00197
00198 QUICKVEC_TEMPLATE
00199 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
00200 QUICKVEC_TEMPLATE
00201 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
00202 QUICKVEC_TEMPLATE
00203 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_)+size_); }
00204 QUICKVEC_TEMPLATE
00205 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_)+size_); }
00206
00207 QUICKVEC_TEMPLATE
00208 inline void QUICKVEC::reserve( size_t size )
00209 { if (size > capacity_)
00210 {
00211 # if USE_UNIQUE_PTR == 0
00212 TT_ * old=data_;
00213
00214 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_));
00215 memcpy( data_, old, size_*sizeof(TT_) );
00216 TRACE( 13, "QUICKVEC::reserve this=%p old=%p data_=%p"
00217 , (void*)this, (void*)old, (void*)data_ );
00218
00219 free( old );
00220 # else
00221 std::unique_ptr<TT_[]> old=std::move(data_);
00222
00223 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_)));
00224 memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
00225 # endif
00226 capacity_ = size;
00227
00228 }
00229 }
00230
00231 QUICKVEC_TEMPLATE
00232 inline void QUICKVEC::resize( size_t size )
00233 { if (size < size_) size_ = size;
00234 else if (size <= capacity_) size_ = size;
00235 else
00236 {
00237 # if USE_UNIQUE_PTR == 0
00238 TT_ * old=data_;
00239
00240 data_ = (TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_));
00241 memcpy( data_, old, size_*sizeof(TT_) );
00242 TRACE( 13, "QUICKVEC::resize this=%p old=%p data_=%p"
00243 , (void*)this, (void*)old, (void*)data_ );
00244
00245 free( old );
00246 # else
00247 std::unique_ptr<TT_[]> old=std::move(data_);
00248
00249 data_ = std::unique_ptr<TT_[]>((TT_*)QV_MEMALIGN(QV_ALIGN,size*sizeof(TT_)));
00250 memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
00251 # endif
00252 size_ = capacity_ = size;
00253
00254 }
00255 }
00256 QUICKVEC_TEMPLATE
00257 inline void QUICKVEC::resize( size_type size, TT_ val )
00258 { size_type old_size=size;
00259 resize( size );
00260 if (size > old_size)
00261 for (iterator ii=begin()+old_size; ii!=end(); ++ii) *ii=val;
00262 }
00263
00264 QUICKVEC_TEMPLATE
00265 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
00266 , size_t nn
00267 , const TT_& val)
00268 { assert(position<=end());
00269 size_t offset=position-begin();
00270 reserve( size_+nn );
00271
00272 iterator dst=end()+nn;
00273 iterator src=end();
00274 size_t cnt=end()-(begin()+offset);
00275 while (cnt--) *--dst = *--src;
00276
00277 dst=begin()+offset;
00278 size_+=nn;
00279 while (nn--) *dst++ = val;
00280 return begin()+offset;
00281 }
00282 QUICKVEC_TEMPLATE
00283 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
00284 , const_iterator first
00285 , const_iterator last)
00286 { assert(position<=end());
00287 size_t nn=(last-first);
00288 size_t offset=position-begin();
00289 reserve( size_+nn );
00290
00291 iterator dst=end()+nn;
00292 iterator src=end();
00293 size_t cnt=end()-(begin()+offset);
00294 while (cnt--) *--dst = *--src;
00295
00296 dst=begin()+offset;
00297 size_+=nn;
00298 while (nn--) *dst++ = *first++;
00299 return begin()+offset;
00300 }
00301
00302 QUICKVEC_TEMPLATE
00303 inline QUICKVEC_TN::iterator QUICKVEC::erase( const_iterator first
00304 ,const_iterator last )
00305 { assert(last<=end());
00306 size_t nn=(last-first);
00307 size_t offset=first-begin();
00308
00309 iterator dst=begin()+offset;
00310 iterator src=dst+nn;
00311 size_t cnt=end()-src;
00312 while (cnt--) *dst++ = *src++;
00313
00314 size_-=nn;
00315 return begin()+offset;
00316 }
00317
00318 QUICKVEC_TEMPLATE
00319 inline void QUICKVEC::swap( QuickVec& x )
00320 { TRACE( 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
00321 , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_) );
00322 std::swap( data_, x.data_ );
00323 std::swap( size_, x.size_ );
00324 std::swap( capacity_, x.capacity_ );
00325 TRACE( 12, "QUICKVEC::swap return data_=%p x.data_=%p"
00326 , (void*)PTR_(data_), (void*)PTR_(x.data_) );
00327 }
00328
00329 QUICKVEC_TEMPLATE
00330 inline void QUICKVEC::push_back( const value_type& val )
00331 { if (size_ == capacity_)
00332 { reserve( size_ + size_/10 + 1 );
00333 }
00334 *end() = val;
00335 ++size_;
00336 }
00337
00338 #ifdef UNDEF_TRACE_AT_END
00339 # undef TRACE
00340 #endif
00341 #endif