comparison deps/Platinum/ThirdParty/Neptune/Source/Core/NptArray.h @ 0:3425707ddbf6

Initial import (hopefully this mercurial stuff works...)
author fraserofthenight
date Mon, 06 Jul 2009 08:06:28 -0700
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:3425707ddbf6
1 /*****************************************************************
2 |
3 | Neptune - Arrays
4 |
5 | Copyright (c) 2002-2008, Axiomatic Systems, LLC.
6 | All rights reserved.
7 |
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | * Neither the name of Axiomatic Systems nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 |
30 ****************************************************************/
31
32 #ifndef _NPT_ARRAY_H_
33 #define _NPT_ARRAY_H_
34
35 /*----------------------------------------------------------------------
36 | includes
37 +---------------------------------------------------------------------*/
38 #include "NptConfig.h"
39 #if defined(NPT_CONFIG_HAVE_NEW_H)
40 #include <new>
41 #endif
42 #include "NptTypes.h"
43 #include "NptResults.h"
44
45 /*----------------------------------------------------------------------
46 | constants
47 +---------------------------------------------------------------------*/
48 const int NPT_ARRAY_INITIAL_MAX_SIZE = 128; // bytes
49
50 /*----------------------------------------------------------------------
51 | NPT_Array
52 +---------------------------------------------------------------------*/
53 template <typename T>
54 class NPT_Array
55 {
56 public:
57 // types
58 typedef T Element;
59 typedef T* Iterator;
60
61 // methods
62 NPT_Array<T>(): m_Capacity(0), m_ItemCount(0), m_Items(0) {}
63 explicit NPT_Array<T>(NPT_Cardinal count);
64 NPT_Array<T>(NPT_Cardinal count, const T& item);
65 NPT_Array<T>(const T* items, NPT_Cardinal item_count);
66 ~NPT_Array<T>();
67 NPT_Array<T>(const NPT_Array<T>& copy);
68 NPT_Array<T>& operator=(const NPT_Array<T>& copy);
69 bool operator==(const NPT_Array<T>& other) const;
70 bool operator!=(const NPT_Array<T>& other) const;
71 NPT_Cardinal GetItemCount() const { return m_ItemCount; }
72 NPT_Result Add(const T& item);
73 T& operator[](NPT_Ordinal pos) { return m_Items[pos]; }
74 const T& operator[](NPT_Ordinal pos) const { return m_Items[pos]; }
75 NPT_Result Erase(Iterator which);
76 NPT_Result Erase(NPT_Ordinal which) { return Erase(&m_Items[which]); }
77 NPT_Result Erase(Iterator first, Iterator last);
78 NPT_Result Erase(NPT_Ordinal first, NPT_Ordinal last) { return Erase(&m_Items[first], &m_Items[last]); }
79 NPT_Result Insert(Iterator where, const T& item, NPT_Cardinal count = 1);
80 NPT_Result Reserve(NPT_Cardinal count);
81 NPT_Cardinal GetCapacity() const { return m_Capacity; }
82 NPT_Result Resize(NPT_Cardinal count);
83 NPT_Result Resize(NPT_Cardinal count, const T& fill);
84 NPT_Result Clear();
85 bool Contains(const T& data) const;
86 Iterator GetFirstItem() const { return m_ItemCount?&m_Items[0]:NULL; }
87 Iterator GetLastItem() const { return m_ItemCount?&m_Items[m_ItemCount-1]:NULL; }
88 Iterator GetItem(NPT_Ordinal n) { return n<m_ItemCount?&m_Items[n]:NULL; }
89
90 // template list operations
91 // keep these template members defined here because MSV6 does not let
92 // us define them later
93 template <typename X>
94 NPT_Result Apply(const X& function) const
95 {
96 for (unsigned int i=0; i<m_ItemCount; i++) function(m_Items[i]);
97 return NPT_SUCCESS;
98 }
99
100 template <typename X, typename P>
101 NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
102 {
103 for (unsigned int i=0; i<m_ItemCount; i++) {
104 NPT_Result return_value;
105 if (predicate(function(m_Items[i]), return_value)) {
106 if (match) *match = true;
107 return return_value;
108 }
109 }
110 if (match) *match = false;
111 return NPT_SUCCESS;
112 }
113
114 template <typename X>
115 T* Find(const X& predicate, NPT_Ordinal n=0, NPT_Ordinal* pos = NULL) const
116 {
117 if (pos) *pos = -1;
118
119 for (unsigned int i=0; i<m_ItemCount; i++) {
120 if (predicate(m_Items[i])) {
121 if (pos) *pos = i;
122 if (n == 0) return &m_Items[i];
123 --n;
124 }
125 }
126 return NULL;
127 }
128
129 protected:
130 // methods
131 T* Allocate(NPT_Cardinal count, NPT_Cardinal& allocated);
132
133 // members
134 NPT_Cardinal m_Capacity;
135 NPT_Cardinal m_ItemCount;
136 T* m_Items;
137 };
138
139 /*----------------------------------------------------------------------
140 | NPT_Array<T>::NPT_Array<T>
141 +---------------------------------------------------------------------*/
142 template <typename T>
143 inline
144 NPT_Array<T>::NPT_Array(NPT_Cardinal count) :
145 m_Capacity(0),
146 m_ItemCount(0),
147 m_Items(0)
148 {
149 Reserve(count);
150 }
151
152 /*----------------------------------------------------------------------
153 | NPT_Array<T>::NPT_Array<T>
154 +---------------------------------------------------------------------*/
155 template <typename T>
156 inline
157 NPT_Array<T>::NPT_Array(const NPT_Array<T>& copy) :
158 m_Capacity(0),
159 m_ItemCount(0),
160 m_Items(0)
161 {
162 Reserve(copy.GetItemCount());
163 for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
164 new ((void*)&m_Items[i]) T(copy.m_Items[i]);
165 }
166 m_ItemCount = copy.m_ItemCount;
167 }
168
169 /*----------------------------------------------------------------------
170 | NPT_Array<T>::NPT_Array<T>
171 +---------------------------------------------------------------------*/
172 template <typename T>
173 inline
174 NPT_Array<T>::NPT_Array(NPT_Cardinal count, const T& item) :
175 m_Capacity(0),
176 m_ItemCount(count),
177 m_Items(0)
178 {
179 Reserve(count);
180 for (NPT_Ordinal i=0; i<count; i++) {
181 new ((void*)&m_Items[i]) T(item);
182 }
183 }
184
185 /*----------------------------------------------------------------------
186 | NPT_Array<T>::NPT_Array<T>
187 +---------------------------------------------------------------------*/
188 template <typename T>
189 inline
190 NPT_Array<T>::NPT_Array(const T* items, NPT_Cardinal item_count) :
191 m_Capacity(0),
192 m_ItemCount(item_count),
193 m_Items(0)
194 {
195 Reserve(item_count);
196 for (NPT_Ordinal i=0; i<item_count; i++) {
197 new ((void*)&m_Items[i]) T(items[i]);
198 }
199 }
200
201 /*----------------------------------------------------------------------
202 | NPT_Array<T>::~NPT_Array<T>
203 +---------------------------------------------------------------------*/
204 template <typename T>
205 inline
206 NPT_Array<T>::~NPT_Array()
207 {
208 // remove all items
209 Clear();
210
211 // free the memory
212 ::operator delete((void*)m_Items);
213 }
214
215 /*----------------------------------------------------------------------
216 | NPT_Array<T>::operator=
217 +---------------------------------------------------------------------*/
218 template <typename T>
219 NPT_Array<T>&
220 NPT_Array<T>::operator=(const NPT_Array<T>& copy)
221 {
222 // do nothing if we're assigning to ourselves
223 if (this == &copy) return *this;
224
225 // destroy all elements
226 Clear();
227
228 // copy all elements from the other object
229 Reserve(copy.GetItemCount());
230 m_ItemCount = copy.m_ItemCount;
231 for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
232 new ((void*)&m_Items[i]) T(copy.m_Items[i]);
233 }
234
235 return *this;
236 }
237
238 /*----------------------------------------------------------------------
239 | NPT_Array<T>::Clear
240 +---------------------------------------------------------------------*/
241 template <typename T>
242 NPT_Result
243 NPT_Array<T>::Clear()
244 {
245 // destroy all items
246 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
247 m_Items[i].~T();
248 }
249
250 m_ItemCount = 0;
251
252 return NPT_SUCCESS;
253 }
254
255 /*----------------------------------------------------------------------
256 | NPT_Array<T>::Allocate
257 +---------------------------------------------------------------------*/
258 template <typename T>
259 T*
260 NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated)
261 {
262 if (m_Capacity) {
263 allocated = 2*m_Capacity;
264 } else {
265 // start with just enough elements to fill
266 // NPT_ARRAY_INITIAL_MAX_SIZE worth of memory
267 allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
268 if (allocated == 0) allocated = 1;
269 }
270 if (allocated < count) allocated = count;
271
272 // allocate the items
273 return (T*)::operator new(allocated*sizeof(T));
274 }
275
276 /*----------------------------------------------------------------------
277 | NPT_Array<T>::Reserve
278 +---------------------------------------------------------------------*/
279 template <typename T>
280 NPT_Result
281 NPT_Array<T>::Reserve(NPT_Cardinal count)
282 {
283 if (count <= m_Capacity) return NPT_SUCCESS;
284
285 // (re)allocate the items
286 NPT_Cardinal new_capacity;
287 T* new_items = Allocate(count, new_capacity);
288 if (new_items == NULL) {
289 return NPT_ERROR_OUT_OF_MEMORY;
290 }
291 if (m_ItemCount && m_Items) {
292 for (unsigned int i=0; i<m_ItemCount; i++) {
293 // construct the copy
294 new ((void*)&new_items[i])T(m_Items[i]);
295
296 // destroy the item
297 m_Items[i].~T();
298 }
299 }
300 ::operator delete((void*)m_Items);
301 m_Items = new_items;
302 m_Capacity = new_capacity;
303
304 return NPT_SUCCESS;
305 }
306
307 /*----------------------------------------------------------------------
308 | NPT_Array<T>::Add
309 +---------------------------------------------------------------------*/
310 template <typename T>
311 inline
312 NPT_Result
313 NPT_Array<T>::Add(const T& item)
314 {
315 // ensure capacity
316 NPT_Result result = Reserve(m_ItemCount+1);
317 if (result != NPT_SUCCESS) return result;
318
319 // store the item
320 new ((void*)&m_Items[m_ItemCount++]) T(item);
321
322 return NPT_SUCCESS;
323 }
324
325 /*----------------------------------------------------------------------
326 | NPT_Array<T>::Erase
327 +---------------------------------------------------------------------*/
328 template <typename T>
329 inline
330 NPT_Result
331 NPT_Array<T>::Erase(Iterator which)
332 {
333 return Erase(which, which);
334 }
335
336 /*----------------------------------------------------------------------
337 | NPT_Array<T>::Erase
338 +---------------------------------------------------------------------*/
339 template <typename T>
340 NPT_Result
341 NPT_Array<T>::Erase(Iterator first, Iterator last)
342 {
343 // check parameters
344 if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
345
346 // check the bounds
347 NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
348 NPT_Ordinal last_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
349 if (first_index >= m_ItemCount ||
350 last_index >= m_ItemCount ||
351 first_index > last_index) {
352 return NPT_ERROR_INVALID_PARAMETERS;
353 }
354
355 // shift items to the left
356 NPT_Cardinal interval = last_index-first_index+1;
357 NPT_Cardinal shifted = m_ItemCount-last_index-1;
358 for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
359 m_Items[i] = m_Items[i+interval];
360 }
361
362 // destruct the remaining items
363 for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
364 m_Items[i].~T();
365 }
366
367 // update the item count
368 m_ItemCount -= interval;
369
370 return NPT_SUCCESS;
371 }
372
373 /*----------------------------------------------------------------------
374 | NPT_Array<T>::Insert
375 +---------------------------------------------------------------------*/
376 template <typename T>
377 NPT_Result
378 NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
379 {
380 // check bounds
381 NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
382 if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
383
384 NPT_Cardinal needed = m_ItemCount+repeat;
385 if (needed > m_Capacity) {
386 // allocate more memory
387 NPT_Cardinal new_capacity;
388 T* new_items = Allocate(needed, new_capacity);
389 if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
390 m_Capacity = new_capacity;
391
392 // move the items before the insertion point
393 for (NPT_Ordinal i=0; i<where_index; i++) {
394 new((void*)&new_items[i])T(m_Items[i]);
395 m_Items[i].~T();
396 }
397
398 // move the items after the insertion point
399 for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
400 new((void*)&new_items[i+repeat])T(m_Items[i]);
401 m_Items[i].~T();
402 }
403
404 // use the new items instead of the current ones
405 ::operator delete((void*)m_Items);
406 m_Items = new_items;
407 } else {
408 // shift items after the insertion point to the right
409 for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
410 new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
411 m_Items[i-1].~T();
412 }
413 }
414
415 // insert the new items
416 for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
417 new((void*)&m_Items[i])T(item);
418 }
419
420 // update the item count
421 m_ItemCount += repeat;
422
423 return NPT_SUCCESS;
424 }
425
426 /*----------------------------------------------------------------------
427 | NPT_Array<T>::Resize
428 +---------------------------------------------------------------------*/
429 template <typename T>
430 NPT_Result
431 NPT_Array<T>::Resize(NPT_Cardinal size)
432 {
433 if (size < m_ItemCount) {
434 // shrink
435 for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
436 m_Items[i].~T();
437 }
438 m_ItemCount = size;
439 } else if (size > m_ItemCount) {
440 return Resize(size, T());
441 }
442
443 return NPT_SUCCESS;
444 }
445
446 /*----------------------------------------------------------------------
447 | NPT_Array<T>::Resize
448 +---------------------------------------------------------------------*/
449 template <typename T>
450 NPT_Result
451 NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
452 {
453 if (size < m_ItemCount) {
454 return Resize(size);
455 } else if (size > m_ItemCount) {
456 Reserve(size);
457 for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
458 new ((void*)&m_Items[i]) T(fill);
459 }
460 m_ItemCount = size;
461 }
462
463 return NPT_SUCCESS;
464 }
465
466 /*----------------------------------------------------------------------
467 | NPT_Array<T>::Contains
468 +---------------------------------------------------------------------*/
469 template <typename T>
470 bool
471 NPT_Array<T>::Contains(const T& data) const
472 {
473 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
474 if (m_Items[i] == data) return true;
475 }
476
477 return false;
478 }
479
480 /*----------------------------------------------------------------------
481 | NPT_Array<T>::operator==
482 +---------------------------------------------------------------------*/
483 template <typename T>
484 bool
485 NPT_Array<T>::operator==(const NPT_Array<T>& other) const
486 {
487 // we need the same number of items
488 if (other.m_ItemCount != m_ItemCount) return false;
489
490 // compare all items
491 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
492 if (!(m_Items[i] == other.m_Items[i])) return false;
493 }
494
495 return true;
496 }
497
498 /*----------------------------------------------------------------------
499 | NPT_Array<T>::operator!=
500 +---------------------------------------------------------------------*/
501 template <typename T>
502 inline
503 bool
504 NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
505 {
506 return !(*this == other);
507 }
508
509 #endif // _NPT_ARRAY_H_
510
511
512
513
514
515
516
517
518
519
520
521
522