src/types/resourcevector.h

changeset 1186
eae8b3bce545
parent 1185
c2e0db52ea07
child 1189
0509b2b5eaa6
equal deleted inserted replaced
1185:c2e0db52ea07 1186:eae8b3bce545
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 {

mercurial