Mercurial > projects > hoofbaby
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 == ©) 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 |