Itasca C++ Interface
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Modules Pages
flatarray.h
1#pragma once
2#include <tuple>
3
4template <typename TupleT, typename Fn>
5void 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
14template <class T> class FlatArray {
15public:
16 typedef uint64 size_type;
17 typedef T * iterator;
18 typedef const T *const_iterator;
19
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); }
139private:
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
175template <class T> class FlatArrayVec : public std::vector<T> {
176public:
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 }
258private:
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