vector.h
1 /*************************************************************************/
2 /* vector.h */
3 /*************************************************************************/
4 /* This file is part of: */
5 /* GODOT ENGINE */
6 /* http://www.godotengine.org */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
9 /* */
10 /* Permission is hereby granted, free of charge, to any person obtaining */
11 /* a copy of this software and associated documentation files (the */
12 /* "Software"), to deal in the Software without restriction, including */
13 /* without limitation the rights to use, copy, modify, merge, publish, */
14 /* distribute, sublicense, and/or sell copies of the Software, and to */
15 /* permit persons to whom the Software is furnished to do so, subject to */
16 /* the following conditions: */
17 /* */
18 /* The above copyright notice and this permission notice shall be */
19 /* included in all copies or substantial portions of the Software. */
20 /* */
21 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
22 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
23 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
24 /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
25 /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
26 /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
27 /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
28 /*************************************************************************/
29 #ifndef VECTOR_H
30 #define VECTOR_H
31 
37 #include "os/memory.h"
38 #include "error_macros.h"
39 #include "safe_refcount.h"
40 #include "sort.h"
41 
42 template<class T>
43 class Vector {
44 
45  mutable T* _ptr;
46 
47  // internal helpers
48 
49  _FORCE_INLINE_ SafeRefCount* _get_refcount() const {
50 
51  if (!_ptr)
52  return NULL;
53 
54  return reinterpret_cast<SafeRefCount*>((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount));
55  }
56 
57  _FORCE_INLINE_ int* _get_size() const {
58 
59  if (!_ptr)
60  return NULL;
61  return reinterpret_cast<int*>((uint8_t*)_ptr-sizeof(int));
62 
63  }
64  _FORCE_INLINE_ T* _get_data() const {
65 
66  if (!_ptr)
67  return NULL;
68  return reinterpret_cast<T*>(_ptr);
69 
70  }
71 
72  _FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
73  //return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
74  return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
75  }
76 
77  _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
78 #if defined(_add_overflow) && defined(_mul_overflow)
79  size_t o;
80  size_t p;
81  if (_mul_overflow(p_elements, sizeof(T), &o)) return false;
82  if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false;
83  *out = nearest_power_of_2(p);
84  return true;
85 #else
86  // Speed is more important than correctness here, do the operations unchecked
87  // and hope the best
88  *out = _get_alloc_size(p_elements);
89  return true;
90 #endif
91  }
92 
93  void _unref(void *p_data);
94 
95  void _copy_from(const Vector& p_from);
96  void _copy_on_write();
97 public:
98 
99 
100  _FORCE_INLINE_ T *ptr() { if (!_ptr) return NULL; _copy_on_write(); return (T*)_get_data(); }
101  _FORCE_INLINE_ const T *ptr() const { if (!_ptr) return NULL; return _get_data(); }
102 
103 
104  _FORCE_INLINE_ void clear() { resize(0); }
105 
106  _FORCE_INLINE_ int size() const {
107  int* size = _get_size();
108  if (size)
109  return *size;
110  else
111  return 0;
112  }
113  _FORCE_INLINE_ bool empty() const { return _ptr == 0; }
114  Error resize(int p_size);
115  bool push_back(T p_elem);
116 
117  void remove(int p_index);
118  void erase(const T& p_val) { int idx = find(p_val); if (idx>=0) remove(idx); };
119  void invert();
120 
121 
122  template <class T_val>
123  int find(const T_val& p_val) const;
124 
125  void set(int p_index,T p_elem);
126  T get(int p_index) const;
127 
128  inline T& operator[](int p_index) {
129 
130  if (p_index<0 || p_index>=size()) {
131  T& aux=*((T*)0); //nullreturn
132  ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
133  }
134 
135  _copy_on_write(); // wants to write, so copy on write.
136 
137  return _get_data()[p_index];
138  }
139 
140  inline const T& operator[](int p_index) const {
141 
142  if (p_index<0 || p_index>=size()) {
143  const T& aux=*((T*)0); //nullreturn
144  ERR_FAIL_COND_V(p_index<0 || p_index>=size(),aux);
145  }
146  // no cow needed, since it's reading
147  return _get_data()[p_index];
148  }
149 
150  Error insert(int p_pos,const T& p_val);
151 
152  template<class C>
153  void sort_custom() {
154 
155  int len = size();
156  if (len==0)
157  return;
158  T *data = &operator[](0);
159  SortArray<T,C> sorter;
160  sorter.sort(data,len);
161  }
162 
163  void sort() {
164 
165  sort_custom<_DefaultComparator<T> >();
166  }
167 
168  void ordered_insert(const T& p_val) {
169  int i;
170  for (i=0; i<size(); i++) {
171 
172  if (p_val < operator[](i)) {
173  break;
174  };
175  };
176  insert(i, p_val);
177  }
178 
179  void operator=(const Vector& p_from);
180  Vector(const Vector& p_from);
181 
182  _FORCE_INLINE_ Vector();
183  _FORCE_INLINE_ ~Vector();
184 
185 };
186 
187 template<class T>
188 void Vector<T>::_unref(void *p_data) {
189 
190  if (!p_data)
191  return;
192 
193  SafeRefCount *src = reinterpret_cast<SafeRefCount*>((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
194 
195  if (!src->unref())
196  return; // still in use
197  // clean up
198 
199  int *count = (int*)(src+1);
200  T *data = (T*)(count+1);
201 
202  for (int i=0;i<*count;i++) {
203  // call destructors
204  data[i].~T();
205  }
206 
207  // free mem
208  memfree((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
209 
210 }
211 
212 template<class T>
214 
215  if (!_ptr)
216  return;
217 
218  if (_get_refcount()->get() > 1 ) {
219  /* in use by more than me */
220  void* mem_new = memalloc(_get_alloc_size(*_get_size()));
221  SafeRefCount *src_new=(SafeRefCount *)mem_new;
222  src_new->init();
223  int * _size = (int*)(src_new+1);
224  *_size=*_get_size();
225 
226  T*_data=(T*)(_size+1);
227 
228  // initialize new elements
229  for (int i=0;i<*_size;i++) {
230 
231  memnew_placement(&_data[i], T( _get_data()[i] ) );
232  }
233 
234  _unref(_ptr);
235  _ptr=_data;
236  }
237 
238 }
239 
240 template<class T> template<class T_val>
241 int Vector<T>::find(const T_val &p_val) const {
242 
243  int ret = -1;
244  if (size() == 0)
245  return ret;
246 
247  for (int i=0; i<size(); i++) {
248 
249  if (operator[](i) == p_val) {
250  ret = i;
251  break;
252  };
253  };
254 
255  return ret;
256 };
257 
258 template<class T>
259 Error Vector<T>::resize(int p_size) {
260 
261  ERR_FAIL_COND_V(p_size<0,ERR_INVALID_PARAMETER);
262 
263  if (p_size==size())
264  return OK;
265 
266  if (p_size==0) {
267  // wants to clean up
268  _unref(_ptr);
269  _ptr=NULL;
270  return OK;
271  }
272 
273  // possibly changing size, copy on write
274  _copy_on_write();
275 
276  size_t alloc_size;
277  ERR_FAIL_COND_V(!_get_alloc_size_checked(p_size, &alloc_size), ERR_OUT_OF_MEMORY);
278 
279  if (p_size>size()) {
280 
281  if (size()==0) {
282  // alloc from scratch
283  void* ptr=memalloc(alloc_size);
284  ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY);
285  _ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount));
286  _get_refcount()->init(); // init refcount
287  *_get_size()=0; // init size (currently, none)
288 
289  } else {
290  void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
291  ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
292  _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
293  }
294 
295  // construct the newly created elements
296  T*elems = _get_data();
297 
298  for (int i=*_get_size();i<p_size;i++) {
299 
300  memnew_placement(&elems[i], T) ;
301  }
302 
303  *_get_size()=p_size;
304 
305  } else if (p_size<size()) {
306 
307  // deinitialize no longer needed elements
308  for (int i=p_size;i<*_get_size();i++) {
309 
310  T* t = &_get_data()[i];
311  t->~T();
312  }
313 
314  void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
315  ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
316 
317  _ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
318 
319  *_get_size()=p_size;
320 
321  }
322 
323  return OK;
324 }
325 
326 
327 template<class T>
328 void Vector<T>::invert() {
329 
330  for(int i=0;i<size()/2;i++) {
331 
332  SWAP( operator[](i), operator[](size()-i-1) );
333  }
334 }
335 
336 template<class T>
337 void Vector<T>::set(int p_index,T p_elem) {
338 
339  operator[](p_index)=p_elem;
340 }
341 
342 template<class T>
343 T Vector<T>::get(int p_index) const {
344 
345  return operator[](p_index);
346 }
347 
348 template<class T>
349 bool Vector<T>::push_back(T p_elem) {
350 
351  Error err = resize(size()+1);
352  ERR_FAIL_COND_V( err, true )
353  set(size()-1,p_elem);
354 
355  return false;
356 }
357 
358 
359 template<class T>
360 void Vector<T>::remove(int p_index) {
361 
362  ERR_FAIL_INDEX(p_index, size());
363  T*p=ptr();
364  int len=size();
365  for (int i=p_index; i<len-1; i++) {
366 
367  p[i]=p[i+1];
368  };
369 
370  resize(len-1);
371 };
372 
373 template<class T>
374 void Vector<T>::_copy_from(const Vector& p_from) {
375 
376  if (_ptr == p_from._ptr)
377  return; // self assign, do nothing.
378 
379  _unref(_ptr);
380  _ptr=NULL;
381 
382  if (!p_from._ptr)
383  return; //nothing to do
384 
385  if (p_from._get_refcount()->ref()) // could reference
386  _ptr=p_from._ptr;
387 
388 }
389 
390 template<class T>
391 void Vector<T>::operator=(const Vector& p_from) {
392 
393  _copy_from(p_from);
394 }
395 
396 
397 template<class T>
398 Error Vector<T>::insert(int p_pos,const T& p_val) {
399 
400  ERR_FAIL_INDEX_V(p_pos,size()+1,ERR_INVALID_PARAMETER);
401  resize(size()+1);
402  for (int i=(size()-1);i>p_pos;i--)
403  set( i, get(i-1) );
404  set( p_pos, p_val );
405 
406  return OK;
407 }
408 
409 template<class T>
410 Vector<T>::Vector(const Vector& p_from) {
411 
412  _ptr=NULL;
413  _copy_from( p_from );
414 
415 }
416 
417 template<class T>
419 
420  _ptr=NULL;
421 }
422 
423 
424 template<class T>
426 
427  _unref(_ptr);
428 
429 }
430 
431 
432 #endif
Definition: safe_refcount.h:336
Definition: sort.h:44
Definition: vector.h:43