Itasca C++ Interface
Loading...
Searching...
No Matches
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 T *emplace_back(const T &t) { checkAllocated(size()+1); new(end_) T(t); ++size_; return end_++; }
53 void pop_back() { assert(size()); --end_; end_->~T(); --size_; }
54 void resize(size_type i,const T &t=T()) {
55 if (size()==i) return;
56 if (size()>i) {
57 T *e = end_;
58 end_ = begin_ + i;
59 for (T *p=e-1;p>=end_;--p)
60 p->~T();
61 size_ = i;
62 return;
63 }
64 auto s = size();
65 checkAllocated(i);
66 end_ = begin_ + i;
67 size_ = i;
68 for (T *p=begin_+s;p<end_;++p)
69 new(p) T(t);
70 }
71 size_type removeReplaceLast(size_type i) {
72 if (i>=size()) return -1;
73 auto last = end_-1;
74 iterator it = &begin_[i];
75 (*it) = *last;
76 pop_back();
77 return size();
78 }
79 size_type removeReplaceLastClip(size_type i) {
80 if (i>=size()) return -1;
81 auto last = end_-1;
82 iterator it = &begin_[i];
83 (*it) = *last;
84 pop_back();
85 clip();
86 return size();
87 }
88
89 bool remove(size_type i) {
90 if (i>=size()) return false;
91 for (iterator it=begin_+i;it<end_;++it)
92 *it = *(it+1);
93 pop_back();
94 return true;
95 }
96
97 size_type removeAll(const T &t) {
98 size_type ret = 0;
99 for (size_type i=0;i<size();) {
100 if (t==at(i)) {
101 remove(i);
102 ++ret;
103 } else
104 ++i;
105 }
106 return ret;
107 }
108
109 void clear() {
110 if (!std::is_trivial<T>::value)
111 for (T *b=begin_;b<end_;++b)
112 b->~T();
113 end_ = begin_;
114 size_ = 0;
115 }
116
117 void reset() {
118 clear();
119 if (defaultStorage_ != allocated_) {
120 if (begin_)
121 std::free(begin_);
122 end_ = begin_ = 0;
123 allocated_ = 0;
124 if (defaultStorage_)
125 changeAllocated(defaultStorage_);
126 }
127 }
128
129 void clip() { if (size()*multFac_<allocated_) changeAllocated(size()*multFac_); }
130 iterator begin() { return begin_; }
131 const_iterator begin() const { return begin_; }
132 const_iterator constBegin() const { return begin_; }
133 iterator end() { return end_; }
134 const_iterator end() const { return end_; }
135 const_iterator constEnd() const { return end_; }
136 T & at(size_type i) { return begin_[i]; }
137 const T & at(size_type i) const { return begin_[i]; }
138 T & operator[](size_type i) { return at(i); }
139 const T & operator[](size_type i) const { return at(i); }
140private:
141 void checkAllocated(size_type target) {
142 if (target<=allocated_) return;
143 // How many should be allocated?
144 size_type oldSize = std::max<size_type>(allocated_,defaultStorage_);
145 size_type newsize = multFac_*std::max<size_type>(target,oldSize);
146 changeAllocated(newsize);
147 }
148 void changeAllocated(size_type newSize) {
149 size_type old_size = size();
150 assert(old_size<=newSize);
151 T *newBegin = 0;
152 if (newSize)
153#ifdef _DEBUG
154 newBegin = reinterpret_cast<T *>(itasca::memory::imalloc(newSize*sizeof(T),__FILE__,__LINE__));
155#else
156 newBegin = reinterpret_cast<T *>(std::malloc(newSize*sizeof(T)));
157#endif
158 T *tl = newBegin;
159 for (T *tr=begin_;tr<end_;++tl,++tr) {
160 new(tl) T(*tr);
161 tr->~T();
162 }
163 std::free(begin_);
164 begin_ = newBegin;
165 end_ = begin_ + old_size;
166 allocated_ = newSize;
167 }
168 T * begin_ = 0;
169 T * end_= 0;
170 size_type allocated_ = 0;
171 size_type size_ = 0;
172 size_type defaultStorage_ = 1000;
173 double multFac_ = 1.3;
174};
175
176template <class T> class FlatArrayVec : public std::vector<T> {
177public:
178 typedef uint64 size_type;
179 FlatArrayVec() { }
180 FlatArrayVec(size_type s,double =1.3) : defaultStorage_(s) { this->reserve(defaultStorage_); }
181 FlatArrayVec(const FlatArrayVec<T> &f) { operator=(f); }
182 FlatArrayVec(std::initializer_list<T> l) {
183 for (auto it=l.begin();it!=l.end();++it)
184 push_back(*it);
185 }
186 ~FlatArrayVec() { defaultStorage_=0; reset(); }
187 using std::vector<T>::reserve;
188 using std::vector<T>::assign;
189 const FlatArrayVec<T> &operator=(const FlatArrayVec<T> &f) {
190 defaultStorage_ = f.defaultStorage_;
191 this->clear();
192 reserve(f.capacity());
193 assign(f.begin(),f.end());
194 return *this;
195 }
196 const size_type &allocated() const { return this->capacity(); }
197 size_type removeReplaceLast(size_type i) {
198 if (i>=this->size())
199 throw Exception("RemoveReplaceLast failed");
200 std::swap(this->at(i),this->back());
201 this->pop_back();
202 return this->size();
203 }
204 size_type removeReplaceLastClip(size_type i) {
205 size_type ret = removeReplaceLast(i);
206 this->shrink_to_fit();
207 return ret;
208 }
209
210 bool remove(size_type i) {
211 if (i>=this->size())
212 throw Exception("Remove failed");
213 this->erase(i);
214 return true;
215 }
216 size_type removeAll(const T &t) {
217 size_type ret = 0;
218 for (size_type i=0;i<this->size();) {
219 if (t==this->at(i)) {
220 remove(i);
221 ++ret;
222 } else
223 ++i;
224 }
225 return ret;
226 }
227 void reset() {
228 this->clear();
229 if (defaultStorage_ != this->capacity()) {
230 this->resize(defaultStorage_);
231 this->shrink_to_fit();
232 this->clear();
233 }
234 }
235 void clip() { this->shrink_to_fit(); }
236 const T & operator[] (const int nIndex) const {
237 try {
238#ifdef _DEBUG
239 if (nIndex >= (int)this->size() or nIndex < 0)
240 throw Exception("Size check failed in FlatArray");
241#endif
242 return std::vector<T>::operator[](nIndex);
243 } catch (...) {
244 throw;
245 }
246 }
247
248 T & operator[] (const int nIndex) {
249 try {
250#ifdef _DEBUG
251 if (nIndex >= (int)this->size() or nIndex < 0)
252 throw Exception("Size check failed in FlatArray");
253#endif
254 return std::vector<T>::operator[](nIndex);
255 } catch (...) {
256 throw;
257 }
258 }
259private:
260 size_type defaultStorage_ = 1000;
261};
262// 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:176