Itasca C++ Interface
flatarray.h
1 #pragma once
2 #include <tuple>
3 
4 template <typename TupleT, typename Fn>
5 void for_each_tuple(TupleT&& tp, Fn&& fn) {
6  std::apply(
7  [&fn](auto&& ...args)
8  {
9  (fn(std::forward<decltype(args)>(args)), ...);
10  }, std::forward<TupleT>(tp)
11  );
12 }
13 
14 template <class T> class FlatArray {
15 public:
16  typedef uint64 size_type;
17  typedef T * iterator;
18  typedef const T *const_iterator;
19 
21  FlatArray() { }
22  FlatArray(size_type s,double fac=1.3) : defaultStorage_(s), multFac_(fac) { checkAllocated(s); }
23  FlatArray(const FlatArray<T> &f) { operator=(f); }
24  FlatArray(std::initializer_list<T> l) {
25  for (auto it=l.begin();it!=l.end();++it)
26  push_back(*it);
27  }
28  ~FlatArray() { defaultStorage_=0; reset(); }
29  const FlatArray<T> &operator=(const FlatArray<T> &f) {
30  clear();
31  defaultStorage_ = f.defaultStorage_;
32  checkAllocated(f.size());
33  end_ = begin_ + f.size();
34  size_ = f.size();
35  T *bl=begin_;
36  for (T *br=f.begin();bl<end();++bl,++br)
37  new(bl) T(*br);
38  return *this;
39  }
40  const size_type &size() const { return size_; }
41  const size_type &allocated() const { return allocated_; }
42  bool empty() const { return end_ == begin_; }
43  T * data() { return begin_; }
44  const T * data() const { return begin_; }
45  T & front() { return *begin_; }
46  const T & front() const { return *begin_; }
47  T & back() { return *(end_-1); }
48  const T & back() const { return *(end_-1); }
49 
50  void push_back(const T &t) { checkAllocated(size()+1); new(end_) T(t); ++end_; ++size_; }
51  T *emplace_back() { checkAllocated(size()+1); ++size_; return end_++; }
52  void pop_back() { assert(size()); --end_; end_->~T(); --size_; }
53  void resize(size_type i,const T &t=T()) {
54  if (size()==i) return;
55  if (size()>i) {
56  T *e = end_;
57  end_ = begin_ + i;
58  for (T *p=e-1;p>=end_;--p)
59  p->~T();
60  size_ = i;
61  return;
62  }
63  auto s = size();
64  checkAllocated(i);
65  end_ = begin_ + i;
66  size_ = i;
67  for (T *p=begin_+s;p<end_;++p)
68  new(p) T(t);
69  }
70  size_type removeReplaceLast(size_type i) {
71  if (i>=size()) return -1;
72  auto last = end_-1;
73  iterator it = &begin_[i];
74  (*it) = *last;
75  pop_back();
76  return size();
77  }
78  size_type removeReplaceLastClip(size_type i) {
79  if (i>=size()) return -1;
80  auto last = end_-1;
81  iterator it = &begin_[i];
82  (*it) = *last;
83  pop_back();
84  clip();
85  return size();
86  }
87 
88  bool remove(size_type i) {
89  if (i>=size()) return false;
90  for (iterator it=begin_+i;it<end_;++it)
91  *it = *(it+1);
92  pop_back();
93  return true;
94  }
95 
96  size_type removeAll(const T &t) {
97  size_type ret = 0;
98  for (size_type i=0;i<size();) {
99  if (t==at(i)) {
100  remove(i);
101  ++ret;
102  } else
103  ++i;
104  }
105  return ret;
106  }
107 
108  void clear() {
109  if (!std::is_trivial<T>::value)
110  for (T *b=begin_;b<end_;++b)
111  b->~T();
112  end_ = begin_;
113  size_ = 0;
114  }
115 
116  void reset() {
117  clear();
118  if (defaultStorage_ != allocated_) {
119  if (begin_)
120  std::free(begin_);
121  end_ = begin_ = 0;
122  allocated_ = 0;
123  if (defaultStorage_)
124  changeAllocated(defaultStorage_);
125  }
126  }
127 
128  void clip() { if (size()*multFac_<allocated_) changeAllocated(size()*multFac_); }
129  iterator begin() { return begin_; }
130  const_iterator begin() const { return begin_; }
131  const_iterator constBegin() const { return begin_; }
132  iterator end() { return end_; }
133  const_iterator end() const { return end_; }
134  const_iterator constEnd() const { return end_; }
135  T & at(size_type i) { return begin_[i]; }
136  const T & at(size_type i) const { return begin_[i]; }
137  T & operator[](size_type i) { return at(i); }
138  const T & operator[](size_type i) const { return at(i); }
139 private:
140  void checkAllocated(size_type target) {
141  if (target<=allocated_) return;
142  // How many should be allocated?
143  size_type oldSize = std::max<size_type>(allocated_,defaultStorage_);
144  size_type newsize = multFac_*std::max<size_type>(target,oldSize);
145  changeAllocated(newsize);
146  }
147  void changeAllocated(size_type newSize) {
148  size_type old_size = size();
149  assert(old_size<=newSize);
150  T *newBegin = 0;
151  if (newSize)
152 #ifdef _DEBUG
153  newBegin = reinterpret_cast<T *>(itasca::memory::imalloc(newSize*sizeof(T),__FILE__,__LINE__));
154 #else
155  newBegin = reinterpret_cast<T *>(std::malloc(newSize*sizeof(T)));
156 #endif
157  T *tl = newBegin;
158  for (T *tr=begin_;tr<end_;++tl,++tr) {
159  new(tl) T(*tr);
160  tr->~T();
161  }
162  std::free(begin_);
163  begin_ = newBegin;
164  end_ = begin_ + old_size;
165  allocated_ = newSize;
166  }
167  T * begin_ = 0;
168  T * end_= 0;
169  size_type allocated_ = 0;
170  size_type size_ = 0;
171  size_type defaultStorage_ = 1000;
172  double multFac_ = 1.3;
173 };
174 
175 template <class T> class FlatArrayVec : public std::vector<T> {
176 public:
177  typedef uint64 size_type;
178  FlatArrayVec() { }
179  FlatArrayVec(size_type s,double =1.3) : defaultStorage_(s) { this->reserve(defaultStorage_); }
180  FlatArrayVec(const FlatArrayVec<T> &f) { operator=(f); }
181  FlatArrayVec(std::initializer_list<T> l) {
182  for (auto it=l.begin();it!=l.end();++it)
183  push_back(*it);
184  }
185  ~FlatArrayVec() { defaultStorage_=0; reset(); }
186  using std::vector<T>::reserve;
187  using std::vector<T>::assign;
188  const FlatArrayVec<T> &operator=(const FlatArrayVec<T> &f) {
189  defaultStorage_ = f.defaultStorage_;
190  this->clear();
191  reserve(f.capacity());
192  assign(f.begin(),f.end());
193  return *this;
194  }
195  const size_type &allocated() const { return this->capacity(); }
196  size_type removeReplaceLast(size_type i) {
197  if (i>=this->size())
198  throw Exception("RemoveReplaceLast failed");
199  std::swap(this->at(i),this->back());
200  this->pop_back();
201  return this->size();
202  }
203  size_type removeReplaceLastClip(size_type i) {
204  size_type ret = removeReplaceLast(i);
205  this->shrink_to_fit();
206  return ret;
207  }
208 
209  bool remove(size_type i) {
210  if (i>=this->size())
211  throw Exception("Remove failed");
212  this->erase(i);
213  return true;
214  }
215  size_type removeAll(const T &t) {
216  size_type ret = 0;
217  for (size_type i=0;i<this->size();) {
218  if (t==this->at(i)) {
219  remove(i);
220  ++ret;
221  } else
222  ++i;
223  }
224  return ret;
225  }
226  void reset() {
227  this->clear();
228  if (defaultStorage_ != this->capacity()) {
229  this->resize(defaultStorage_);
230  this->shrink_to_fit();
231  this->clear();
232  }
233  }
234  void clip() { this->shrink_to_fit(); }
235  const T & operator[] (const int nIndex) const {
236  try {
237 #ifdef _DEBUG
238  if (nIndex >= (int)this->size() or nIndex < 0)
239  throw Exception("Size check failed in FlatArray");
240 #endif
241  return std::vector<T>::operator[](nIndex);
242  } catch (...) {
243  throw;
244  }
245  }
246 
247  T & operator[] (const int nIndex) {
248  try {
249 #ifdef _DEBUG
250  if (nIndex >= (int)this->size() or nIndex < 0)
251  throw Exception("Size check failed in FlatArray");
252 #endif
253  return std::vector<T>::operator[](nIndex);
254  } catch (...) {
255  throw;
256  }
257  }
258 private:
259  size_type defaultStorage_ = 1000;
260 };
261 // EoF
Base exception class for all Itasca code.
Definition: baseexception.h:10
Definition: flatarray.h:14
T * iterator
Typedef to assist in STL compatibility.
Definition: flatarray.h:17
FlatArray()
Default constructor - the array size is zero.
Definition: flatarray.h:21
const T * const_iterator
Typedef to assist in STL compatibility.
Definition: flatarray.h:18
uint64 size_type
Typedef to assist in STL compatibility.
Definition: flatarray.h:16
Definition: flatarray.h:175