14 * |
14 * |
15 * You should have received a copy of the GNU General Public License |
15 * You should have received a copy of the GNU General Public License |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 */ |
17 */ |
18 |
18 |
|
19 #pragma once |
19 #include <QVector> |
20 #include <QVector> |
20 |
21 |
21 /* |
22 /* |
22 * A vector that allocates elements on the heap and manages their lifetime. |
23 * A vector that allocates elements on the heap and manages their lifetime. |
23 */ |
24 */ |
24 template<typename T> |
25 template<typename T> |
25 class ResourceVector |
26 class ResourceVector |
26 { |
27 { |
27 public: |
28 public: |
|
29 using Filter = std::function<bool(T*, int)>; |
|
30 using Callback = std::function<void(T*, int)>; |
|
31 |
28 ~ResourceVector(); |
32 ~ResourceVector(); |
29 void append(T) = delete; |
33 void append(T) = delete; |
30 template<typename TT = T, typename... Args> |
34 template<typename TT = T, typename... Args> |
31 T* append(Args&&... args); |
35 TT* append(Args&&... args); |
32 T** const begin() const; |
36 void assimilate(int position, T* resource); |
33 T** const end() const; |
37 T* const* begin() const; |
|
38 T* const* end() const; |
|
39 int indexOf(T* resource) const; |
34 template<typename TT = T, typename... Args> |
40 template<typename TT = T, typename... Args> |
35 T* insert(int position, Args&&... args); |
41 TT* insert(int position, Args&&... args); |
|
42 bool isEmpty() const; |
36 void clear(); |
43 void clear(); |
37 void removeAt(int position); |
44 void removeAt(int position); |
38 T* operator[](int position) const; |
45 T* operator[](int position) const; |
39 int size() const; |
46 int size() const; |
|
47 void swap(int position1, int position2); |
|
48 void merge(ResourceVector<T>& other, int position = -1, Filter filter = nullptr, Callback callback = nullptr); |
|
49 const QVector<T*>& toQVector() const; |
40 |
50 |
41 private: |
51 private: |
42 QVector<T*> _data; |
52 QVector<T*> _data; |
43 }; |
53 }; |
44 |
54 |
57 /* |
67 /* |
58 * Creates a new resource and adds it to the end of this vector. |
68 * Creates a new resource and adds it to the end of this vector. |
59 */ |
69 */ |
60 template<typename T> |
70 template<typename T> |
61 template<typename TT, typename... Args> |
71 template<typename TT, typename... Args> |
62 T* ResourceVector<T>::append(Args&&... args) |
72 TT* ResourceVector<T>::append(Args&&... args) |
63 { |
73 { |
64 _data.append(new TT {args...}); |
74 TT* resource = new TT {args...}; |
65 return _data[size() - 1]; |
75 _data.append(resource); |
|
76 return resource; |
66 } |
77 } |
67 |
78 |
68 /* |
79 /* |
69 * Returns an iterator to the beginning of this vector. |
80 * Returns an iterator to the beginning of this vector. |
70 */ |
81 */ |
71 template<typename T> |
82 template<typename T> |
72 T** const ResourceVector<T>::begin() const |
83 T* const* ResourceVector<T>::begin() const |
73 { |
84 { |
74 return _data.cbegin(); |
85 return _data.cbegin(); |
75 } |
86 } |
76 |
87 |
77 /* |
88 /* |
78 * Returns an iterator to the end of this vector. |
89 * Returns an iterator to the end of this vector. |
79 */ |
90 */ |
80 template<typename T> |
91 template<typename T> |
81 T** const ResourceVector<T>::end() const |
92 T* const* ResourceVector<T>::end() const |
82 { |
93 { |
83 return _data.cend(); |
94 return _data.cend(); |
84 } |
95 } |
85 |
96 |
86 /* |
97 /* |
87 * Creates a new resource and inserts it to the specified position in this vector. |
98 * Creates a new resource and inserts it to the specified position in this vector. |
88 */ |
99 */ |
89 template<typename T> |
100 template<typename T> |
90 template<typename TT, typename... Args> |
101 template<typename TT, typename... Args> |
91 T* ResourceVector<T>::insert(int position, Args&&... args) |
102 TT* ResourceVector<T>::insert(int position, Args&&... args) |
92 { |
103 { |
93 _data.insert(position, new TT {args...}); |
104 TT* resource = new TT {args...}; |
|
105 _data.insert(position, resource); |
|
106 return resource; |
94 } |
107 } |
95 |
108 |
96 /* |
109 /* |
97 * Deletes all resources in this vector. |
110 * Deletes all resources in this vector. |
98 */ |
111 */ |
109 * Removes the resource at the provided position. Throws an exception if the index is out of range. |
122 * Removes the resource at the provided position. Throws an exception if the index is out of range. |
110 */ |
123 */ |
111 template<typename T> |
124 template<typename T> |
112 void ResourceVector<T>::removeAt(int position) |
125 void ResourceVector<T>::removeAt(int position) |
113 { |
126 { |
114 if (position < _data.size()) |
127 if (position >= 0 and position < _data.size()) |
115 { |
128 { |
116 delete _data[position]; |
129 delete _data[position]; |
117 _data.removeAt(position); |
130 _data.removeAt(position); |
118 } |
131 } |
119 else |
132 else |
126 * Returns the resource at the provided position. Throws an exception if the index is out of range. |
139 * Returns the resource at the provided position. Throws an exception if the index is out of range. |
127 */ |
140 */ |
128 template<typename T> |
141 template<typename T> |
129 T* ResourceVector<T>::operator[](int position) const |
142 T* ResourceVector<T>::operator[](int position) const |
130 { |
143 { |
131 if (position < _data.size()) |
144 if (position >= 0 and position < _data.size()) |
132 return _data[position]; |
145 return _data[position]; |
133 else |
146 else |
134 throw std::domain_error {"index out of range"}; |
147 throw std::domain_error {"index out of range"}; |
135 } |
148 } |
136 |
149 |
142 { |
155 { |
143 return _data.size(); |
156 return _data.size(); |
144 } |
157 } |
145 |
158 |
146 /* |
159 /* |
|
160 * Inserts an already existing resource into the vector. The resource is assumed to not be managed by anything else! |
|
161 * Please think twice before using this method. |
|
162 */ |
|
163 template<typename T> |
|
164 void ResourceVector<T>::assimilate(int position, T* resource) |
|
165 { |
|
166 _data.insert(position, resource); |
|
167 } |
|
168 |
|
169 /* |
|
170 * Returns the index of the provided resource in the vector, or -1 if not found. |
|
171 * This operation is of linear complexity O(n). |
|
172 */ |
|
173 template<typename T> |
|
174 int ResourceVector<T>::indexOf(T* resource) const |
|
175 { |
|
176 return _data.indexOf(resource); |
|
177 } |
|
178 |
|
179 /* |
|
180 * Swaps the locations of two resource in this vector. |
|
181 */ |
|
182 template<typename T> |
|
183 void ResourceVector<T>::swap(int position1, int position2) |
|
184 { |
|
185 if (position1 >= 0 and position2 >= 0 and position1 < size() and position2 < size()) |
|
186 { |
|
187 qSwap(_data[position1], _data[position2]); |
|
188 } |
|
189 else |
|
190 { |
|
191 throw std::domain_error {"index out of range"}; |
|
192 } |
|
193 } |
|
194 |
|
195 /* |
|
196 * Returns whether or not the vector is empty. |
|
197 */ |
|
198 template<typename T> |
|
199 bool ResourceVector<T>::isEmpty() const |
|
200 { |
|
201 return size() == 0; |
|
202 } |
|
203 |
|
204 /* |
|
205 * Migrates resources from the provided resource vector to this one. |
|
206 * - `position` indicates where to insert the new resources. Default is to the end. |
|
207 * - `filter` specifies a filter function for the migration. Objects not passing the filter will not be migrated. |
|
208 * - `callback` specifies a function that is called for each successfully migrated object. |
|
209 */ |
|
210 template<typename T> |
|
211 void ResourceVector<T>::merge(ResourceVector<T>& other, int position, Filter filter, Callback callback) |
|
212 { |
|
213 if (position < 0) |
|
214 position = size(); |
|
215 |
|
216 if (filter == nullptr) |
|
217 filter = [](T*, int){return true;}; |
|
218 |
|
219 if (callback == nullptr) |
|
220 callback = [](T*, int){}; |
|
221 |
|
222 for (int i = 0; i < other.size();) |
|
223 { |
|
224 T* resource = other[i]; |
|
225 |
|
226 if (filter(resource, i)) |
|
227 { |
|
228 _data.insert(position, resource); |
|
229 other._data.removeAt(i); |
|
230 callback(resource, position); |
|
231 position += 1; |
|
232 } |
|
233 else |
|
234 { |
|
235 i += 1; |
|
236 } |
|
237 } |
|
238 } |
|
239 |
|
240 /* |
|
241 * Returns the underlying vector. |
|
242 */ |
|
243 template<typename T> |
|
244 const QVector<T*>& ResourceVector<T>::toQVector() const |
|
245 { |
|
246 return _data; |
|
247 } |
|
248 |
|
249 /* |
147 * countof() overload for resource vectors. Returns the amount of resources in the given vector. |
250 * countof() overload for resource vectors. Returns the amount of resources in the given vector. |
148 */ |
251 */ |
149 template<typename T> |
252 template<typename T> |
150 int countof(const ResourceVector<T>& vector) |
253 int countof(const ResourceVector<T>& vector) |
151 { |
254 { |