artdaq_core  v1_05_07
 All Classes Namespaces Functions
QuickVec.hh
1  // This file (QuickVec.hh) was created by Ron Rechenmacher <ron@fnal.gov> on
2  // Sep 3, 2014. "TERMS AND CONDITIONS" governing this file are in the README
3  // or COPYING file. If you do not have such a file, one can be obtained by
4  // contacting Ron or Fermi Lab in Batavia IL, 60510, phone: 630-840-3000.
5  // $RCSfile: QuickVec.hh,v $
6  // rev="$Revision: 1.8 $$Date: 2014/09/05 19:21:11 $";
7 #ifndef QuickVec_hh
8 #define QuickVec_hh
9 
10 extern "C" {
11 #include <stdint.h>
12 }
13 
14 #include <cassert>
15 #include <cstddef> // ptrdiff_t
16 #include <string.h> // memcpy
17 #include <strings.h> // bzero
18 #include <utility> // std::swap
19 #include <memory> // unique_ptr
20 #include <vector>
21 
22 //#include "trace.h" // TRACE
23 #ifndef TRACE
24 # define TRACE( lvl, ... )
25 # define UNDEF_TRACE_AT_END
26 #endif
27 
28 #define USE_UNIQUE_PTR 0
29 
30 #ifndef QUICKVEC_DO_TEMPLATE
31 # define QUICKVEC_DO_TEMPLATE 1
32 #endif
33 
34 #undef NOT_OLD_CXXSTD
35 #if !defined(__GCCXML__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
36 # define NOT_OLD_CXXSTD 1
37 #endif
38 
39 #if QUICKVEC_DO_TEMPLATE == 0
40 # ifndef QUICKVEC_TT
41 # define QUICKVEC_TT unsigned long long
42 # endif
43 # define TT_ QUICKVEC_TT
44 # define QUICKVEC_TEMPLATE
45 # define QUICKVEC QuickVec
46 # define QUICKVEC_TN QuickVec
47 # define QUICKVEC_VERSION
48 #else
49 # define QUICKVEC_TEMPLATE template <typename TT_>
50 # define QUICKVEC QuickVec<TT_>
51 # define QUICKVEC_TN typename QuickVec<TT_>
52 // Class_Version() MUST be updated every time private member data change.
53 # define QUICKVEC_VERSION static short Class_Version() { return 5; } // proper version for templates
54 #endif
55 
56 QUICKVEC_TEMPLATE
57 struct QuickVec
58 {
59  typedef TT_* iterator;
60  typedef const TT_* const_iterator;
61  typedef TT_& reference;
62  typedef const TT_& const_reference;
63  typedef TT_ value_type;
64  typedef ptrdiff_t difference_type;
65  typedef size_t size_type;
66 
67  QuickVec( size_t sz );
68  QuickVec( size_t sz, TT_ val );
69 # if USE_UNIQUE_PTR == 0
70  ~QuickVec();
71 # define PTR_(xx) xx
72 # else
73 # define PTR_(xx) xx.get()
74 # endif
75  QuickVec( std::vector<TT_> & other )
76  : size_(other.size()), data_(new TT_[other.capacity()]), capacity_(other.capacity())
77  { memcpy( PTR_(data_), (void*)&other[0], size_*sizeof(TT_) );
78  }
79  void clear() { size_=0; }
80 
81  QuickVec( const QuickVec & other ) //= delete; // non construction-copyable
82  : size_(other.size_), data_(new TT_[other.capacity_]), capacity_(other.capacity_)
83  { TRACE( 10, "QuickVec copy ctor this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
84  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
85  memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
86  }
87  QUICKVEC & operator=( const QuickVec & other ) //= delete; // non copyable
88  { TRACE( 10, "QuickVec copy assign this=%p data_=%p other.data_=%p size_=%d other.size_=%d"
89  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_), size_, other.size_ );
90  resize( other.size_ );
91  memcpy( PTR_(data_), PTR_(other.data_), size_*sizeof(TT_) );
92  return *this;
93  }
94 # if NOT_OLD_CXXSTD
95  QuickVec( QuickVec && other ) // construction-movable
96  : size_(other.size_), data_(std::move(other.data_)), capacity_(other.capacity_)
97  { TRACE( 10, "QuickVec move ctor this=%p data_=%p other.data_=%p"
98  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
99 # if USE_UNIQUE_PTR == 0
100  other.data_ = nullptr;
101 # endif
102  }
103  QUICKVEC & operator=( QuickVec && other ) // assign movable
104  { TRACE( 10, "QuickVec move assign this=%p data_=%p other.data_=%p"
105  , (void*)this, (void*)PTR_(data_), (void*)PTR_(other.data_) );
106  size_ = other.size_;
107  delete [] data_;
108  data_ = std::move(other.data_);
109  capacity_ = other.capacity_;
110 # if USE_UNIQUE_PTR == 0
111  other.data_ = nullptr;
112 # endif
113  return *this;
114  }
115 # endif
116 
117  TT_& operator[](int idx);
118  const TT_& operator[](int idx) const;
119  size_t size() const;
120  size_t capacity() const;
121  iterator begin();
122  const_iterator begin() const;
123  iterator end();
124  const_iterator end() const;
125  void reserve( size_t size );
126  void resize( size_t size );
127  void resize( size_t size, TT_ val );
128  iterator insert( const_iterator position, size_t nn, const TT_& val );
129  iterator insert( const_iterator position, const_iterator first
130  , const_iterator last);
131  iterator erase( const_iterator first, const_iterator last );
132  void swap( QuickVec& x );
133  void push_back( const value_type& val );
134 
135  QUICKVEC_VERSION
136 
137 private:
138  // Root needs the size_ member first. It must be of type int.
139  // Root then needs the [size_] comment after data_.
140  // Note: NO SPACE between "//" and "[size_]"
141  unsigned size_;
142 # if USE_UNIQUE_PTR == 0
143  TT_ * data_; //[size_]
144 # else
145  std::unique_ptr<TT_[]> data_;
146 # endif
147  unsigned capacity_;
148 };
149 
150 QUICKVEC_TEMPLATE
151 inline QUICKVEC::QuickVec( size_t sz )
152  : size_(sz), data_(new TT_[sz]), capacity_(sz)
153 { TRACE( 15, "QuickVec %p ctor sz=%d data_=%p", (void*)this, size_, (void*)PTR_(data_) );
154 }
155 QUICKVEC_TEMPLATE
156 inline QUICKVEC::QuickVec( size_t sz, TT_ val )
157  : size_(sz), data_(new TT_[sz]), capacity_(sz)
158 { TRACE( 15, "QuickVec %p ctor sz=%d/v data_=%p", (void*)this, size_, (void*)PTR_(data_) );
159  for (iterator ii=begin(); ii!=end(); ++ii) *ii=val;
160  //bzero( &data_[0], (sz<4)?(sz*sizeof(TT_)):(4*sizeof(TT_)) );
161 }
162 
163 #if USE_UNIQUE_PTR == 0
164 QUICKVEC_TEMPLATE
165 inline QUICKVEC::~QuickVec()
166 { TRACE( 15, "QuickVec %p dtor start data_=%p size_=%d"
167  , (void*)this, (void*)PTR_(data_), size_ );
168  delete [] data_;
169  TRACE( 15, "QuickVec %p dtor return", (void*)this );
170 }
171 #endif
172 
173 QUICKVEC_TEMPLATE
174 inline TT_& QUICKVEC::operator[](int idx)
175 { assert(idx<(int)size_); return data_[idx];
176 }
177 
178 QUICKVEC_TEMPLATE
179 inline const TT_& QUICKVEC::operator[](int idx) const
180 { assert(idx < (int)size_);
181  return data_[idx];
182 }
183 
184 QUICKVEC_TEMPLATE
185 inline size_t QUICKVEC::size() const { return size_; }
186 QUICKVEC_TEMPLATE
187 inline size_t QUICKVEC::capacity() const { return capacity_; }
188 
189 QUICKVEC_TEMPLATE
190 inline QUICKVEC_TN::iterator QUICKVEC::begin() { return iterator(PTR_(data_)); }
191 QUICKVEC_TEMPLATE
192 inline QUICKVEC_TN::const_iterator QUICKVEC::begin() const { return iterator(PTR_(data_)); }
193 QUICKVEC_TEMPLATE
194 inline QUICKVEC_TN::iterator QUICKVEC::end() { return iterator(PTR_(data_)+size_); }
195 QUICKVEC_TEMPLATE
196 inline QUICKVEC_TN::const_iterator QUICKVEC::end() const { return const_iterator(PTR_(data_)+size_); }
197 
198 QUICKVEC_TEMPLATE
199 inline void QUICKVEC::reserve( size_t size )
200 { if (size > capacity_) // reallocation if true
201  {
202 # if USE_UNIQUE_PTR == 0
203  TT_ * old=data_;
204  data_ = new TT_[size];
205  memcpy( data_, old, size_*sizeof(TT_) );
206  TRACE( 13, "QUICKVEC::reserve this=%p old=%p data_=%p"
207  , (void*)this, (void*)old, (void*)data_ );
208  delete [] old;
209 # else
210  std::unique_ptr<TT_[]> old=std::move(data_);
211  data_ = std::unique_ptr<TT_[]>(new TT_[size]);
212  memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
213 # endif
214  capacity_ = size;
215  // bye to old(unique_ptr)
216  }
217 }
218 
219 QUICKVEC_TEMPLATE
220 inline void QUICKVEC::resize( size_t size )
221 { if (size < size_) size_ = size; // decrease
222  else if (size <= capacity_) size_ = size;
223  else // increase/reallocate
224  {
225 # if USE_UNIQUE_PTR == 0
226  TT_ * old=data_;
227  data_ = new TT_[size];
228  memcpy( data_, old, size_*sizeof(TT_) );
229  TRACE( 13, "QUICKVEC::resize this=%p old=%p data_=%p"
230  , (void*)this, (void*)old, (void*)data_ );
231  delete [] old;
232 # else
233  std::unique_ptr<TT_[]> old=std::move(data_);
234  data_ = std::unique_ptr<TT_[]>(new TT_[size]);
235  memcpy( data_.get(), old.get(), size_*sizeof(TT_) );
236 # endif
237  size_ = capacity_ = size;
238  // bye to old(unique_ptr)
239  }
240 }
241 QUICKVEC_TEMPLATE
242 inline void QUICKVEC::resize( size_type size, TT_ val )
243 { size_type old_size=size;
244  resize( size );
245  if (size > old_size)
246  for (iterator ii=begin()+old_size; ii!=end(); ++ii) *ii=val;
247 }
248 
249 QUICKVEC_TEMPLATE
250 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
251  , size_t nn
252  , const TT_& val)
253 { assert(position<=end()); // the current end
254  size_t offset=position-begin();
255  reserve( size_+nn ); // may reallocate and invalidate "position"
256 
257  iterator dst=end()+nn; // for shifting existing data after
258  iterator src=end(); // insertion point
259  size_t cnt=end()-(begin()+offset);
260  while (cnt--) *--dst = *--src;
261 
262  dst=begin()+offset;
263  size_+=nn;
264  while (nn--) *dst++ = val;
265  return begin()+offset;
266 }
267 QUICKVEC_TEMPLATE
268 inline QUICKVEC_TN::iterator QUICKVEC::insert( const_iterator position
269  , const_iterator first
270  , const_iterator last)
271 { assert(position<=end()); // the current end
272  size_t nn=(last-first);
273  size_t offset=position-begin();
274  reserve( size_+nn ); // may reallocate and invalidate "position"
275 
276  iterator dst=end()+nn; // for shifting existing data after
277  iterator src=end(); // insertion point
278  size_t cnt=end()-(begin()+offset);
279  while (cnt--) *--dst = *--src;
280 
281  dst=begin()+offset;
282  size_+=nn;
283  while (nn--) *dst++ = *first++;
284  return begin()+offset;
285 }
286 
287 QUICKVEC_TEMPLATE
288 inline QUICKVEC_TN::iterator QUICKVEC::erase( const_iterator first
289  ,const_iterator last )
290 { assert(last<=end()); // the current end
291  size_t nn=(last-first);
292  size_t offset=first-begin();
293 
294  iterator dst=begin()+offset; // for shifting existing data from last
295  iterator src=dst+nn; // to first
296  size_t cnt=end()-src;
297  while (cnt--) *dst++ = *src++;
298 
299  size_-=nn;
300  return begin()+offset;
301 }
302 
303 QUICKVEC_TEMPLATE
304 inline void QUICKVEC::swap( QuickVec& x )
305 { TRACE( 12, "QUICKVEC::swap this=%p enter data_=%p x.data_=%p"
306  , (void*)this, (void*)PTR_(data_), (void*)PTR_(x.data_) );
307  std::swap( data_, x.data_ );
308  std::swap( size_, x.size_ );
309  std::swap( capacity_, x.capacity_ );
310  TRACE( 12, "QUICKVEC::swap return data_=%p x.data_=%p"
311  , (void*)PTR_(data_), (void*)PTR_(x.data_) );
312 }
313 
314 QUICKVEC_TEMPLATE
315 inline void QUICKVEC::push_back( const value_type& val )
316 { if (size_ == capacity_)
317  { reserve( size_ + size_/10 + 1 );
318  }
319  *end() = val;
320  ++size_;
321 }
322 
323 #ifdef UNDEF_TRACE_AT_END
324 # undef TRACE
325 #endif
326 #endif /* QuickVec_hh */