00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef _NPT_ARRAY_H_
00011 #define _NPT_ARRAY_H_
00012
00013
00014
00015
00016 #include "NptConfig.h"
00017 #if defined(NPT_CONFIG_HAVE_NEW_H)
00018 #include <new>
00019 #endif
00020 #include "NptTypes.h"
00021 #include "NptResults.h"
00022
00023
00024
00025
00026 const int NPT_ARRAY_INITIAL_MAX_SIZE = 128;
00027
00028
00029
00030
00031 template <typename T>
00032 class NPT_Array
00033 {
00034 public:
00035
00036 typedef T Element;
00037 typedef T* Iterator;
00038
00039
00040 NPT_Array<T>(): m_Capacity(0), m_ItemCount(0), m_Items(0) {}
00041 explicit NPT_Array<T>(NPT_Cardinal count);
00042 NPT_Array<T>(NPT_Cardinal count, const T& item);
00043 NPT_Array<T>(const T* items, NPT_Cardinal item_count);
00044 ~NPT_Array<T>();
00045 NPT_Array<T>(const NPT_Array<T>& copy);
00046 NPT_Array<T>& operator=(const NPT_Array<T>& copy);
00047 bool operator==(const NPT_Array<T>& other) const;
00048 bool operator!=(const NPT_Array<T>& other) const;
00049 NPT_Cardinal GetItemCount() const { return m_ItemCount; }
00050 NPT_Result Add(const T& item);
00051 T& operator[](NPT_Ordinal pos) { return m_Items[pos]; }
00052 const T& operator[](NPT_Ordinal pos) const { return m_Items[pos]; }
00053 NPT_Result Erase(Iterator which);
00054 NPT_Result Erase(NPT_Ordinal which) { return Erase(&m_Items[which]); }
00055 NPT_Result Erase(Iterator first, Iterator last);
00056 NPT_Result Erase(NPT_Ordinal first, NPT_Ordinal last) { return Erase(&m_Items[first], &m_Items[last]); }
00057 NPT_Result Insert(Iterator where, const T& item, NPT_Cardinal count = 1);
00058 NPT_Result Reserve(NPT_Cardinal count);
00059 NPT_Cardinal GetCapacity(NPT_Cardinal count) const;
00060 NPT_Result Resize(NPT_Cardinal count);
00061 NPT_Result Resize(NPT_Cardinal count, const T& fill);
00062 NPT_Result Clear();
00063 bool Contains(const T& data) const;
00064 Iterator GetFirstItem() const { return m_ItemCount?&m_Items[0]:NULL; }
00065 Iterator GetLastItem() const { return m_ItemCount?m_Items[&m_ItemCount-1]:NULL; }
00066 Iterator GetItem(NPT_Ordinal n) { return n<m_ItemCount?&m_Items[n]:NULL; }
00067
00068
00069
00070
00071 template <typename X>
00072 NPT_Result Apply(const X& function) const
00073 {
00074 for (unsigned int i=0; i<m_ItemCount; i++) function(m_Items[i]);
00075 return NPT_SUCCESS;
00076 }
00077
00078 template <typename X, typename P>
00079 NPT_Result ApplyUntil(const X& function, const P& predicate, bool* match = NULL) const
00080 {
00081 for (unsigned int i=0; i<m_ItemCount; i++) {
00082 NPT_Result return_value;
00083 if (predicate(function(m_Items[i]), return_value)) {
00084 if (match) *match = true;
00085 return return_value;
00086 }
00087 }
00088 if (match) *match = false;
00089 return NPT_SUCCESS;
00090 }
00091
00092 template <typename X>
00093 T* Find(const X& predicate, NPT_Ordinal n=0) const
00094 {
00095 for (unsigned int i=0; i<m_ItemCount; i++) {
00096 if (predicate(m_Items[i])) {
00097 if (n == 0) return &m_Items[i];
00098 --n;
00099 }
00100 }
00101 return NULL;
00102 }
00103
00104 protected:
00105
00106 T* Allocate(NPT_Cardinal count, NPT_Cardinal& allocated);
00107
00108
00109 NPT_Cardinal m_Capacity;
00110 NPT_Cardinal m_ItemCount;
00111 T* m_Items;
00112 };
00113
00114
00115
00116
00117 template <typename T>
00118 inline
00119 NPT_Array<T>::NPT_Array(NPT_Cardinal count) :
00120 m_Capacity(0),
00121 m_ItemCount(0),
00122 m_Items(0)
00123 {
00124 Reserve(count);
00125 }
00126
00127
00128
00129
00130 template <typename T>
00131 inline
00132 NPT_Array<T>::NPT_Array(const NPT_Array<T>& copy) :
00133 m_Capacity(0),
00134 m_ItemCount(0),
00135 m_Items(0)
00136 {
00137 Reserve(copy.GetItemCount());
00138 for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
00139 new ((void*)&m_Items[i]) T(copy.m_Items[i]);
00140 }
00141 m_ItemCount = copy.m_ItemCount;
00142 }
00143
00144
00145
00146
00147 template <typename T>
00148 inline
00149 NPT_Array<T>::NPT_Array(NPT_Cardinal count, const T& item) :
00150 m_Capacity(0),
00151 m_ItemCount(count),
00152 m_Items(0)
00153 {
00154 Reserve(count);
00155 for (NPT_Ordinal i=0; i<count; i++) {
00156 new ((void*)&m_Items[i]) T(item);
00157 }
00158 }
00159
00160
00161
00162
00163 template <typename T>
00164 inline
00165 NPT_Array<T>::NPT_Array(const T* items, NPT_Cardinal item_count) :
00166 m_Capacity(0),
00167 m_ItemCount(item_count),
00168 m_Items(0)
00169 {
00170 Reserve(item_count);
00171 for (NPT_Ordinal i=0; i<item_count; i++) {
00172 new ((void*)&m_Items[i]) T(items[i]);
00173 }
00174 }
00175
00176
00177
00178
00179 template <typename T>
00180 inline
00181 NPT_Array<T>::~NPT_Array()
00182 {
00183
00184 Clear();
00185
00186
00187 ::operator delete((void*)m_Items);
00188 }
00189
00190
00191
00192
00193 template <typename T>
00194 NPT_Array<T>&
00195 NPT_Array<T>::operator=(const NPT_Array<T>& copy)
00196 {
00197
00198 if (this == ©) return *this;
00199
00200
00201 Clear();
00202
00203
00204 Reserve(copy.GetItemCount());
00205 for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
00206 new ((void*)&m_Items[i]) T(copy.m_Items[i]);
00207 }
00208
00209 return *this;
00210 }
00211
00212
00213
00214
00215 template <typename T>
00216 NPT_Result
00217 NPT_Array<T>::Clear()
00218 {
00219
00220 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00221 m_Items[i].~T();
00222 }
00223
00224 m_ItemCount = 0;
00225
00226 return NPT_SUCCESS;
00227 }
00228
00229
00230
00231
00232 template <typename T>
00233 T*
00234 NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated)
00235 {
00236 if (m_Capacity) {
00237 allocated = 2*m_Capacity;
00238 } else {
00239
00240
00241 allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
00242 if (allocated == 0) allocated = 1;
00243 }
00244 if (allocated < count) allocated = count;
00245
00246
00247 return (T*)::operator new(allocated*sizeof(T));
00248 }
00249
00250
00251
00252
00253 template <typename T>
00254 NPT_Result
00255 NPT_Array<T>::Reserve(NPT_Cardinal count)
00256 {
00257 if (count <= m_Capacity) return NPT_SUCCESS;
00258
00259
00260 NPT_Cardinal new_capacity;
00261 T* new_items = Allocate(count, new_capacity);
00262 if (new_items == NULL) {
00263 return NPT_ERROR_OUT_OF_MEMORY;
00264 }
00265 if (m_ItemCount && m_Items) {
00266 for (unsigned int i=0; i<m_ItemCount; i++) {
00267
00268 new ((void*)&new_items[i])T(m_Items[i]);
00269
00270
00271 m_Items[i].~T();
00272 }
00273 }
00274 ::operator delete((void*)m_Items);
00275 m_Items = new_items;
00276 m_Capacity = new_capacity;
00277
00278 return NPT_SUCCESS;
00279 }
00280
00281
00282
00283
00284 template <typename T>
00285 inline
00286 NPT_Result
00287 NPT_Array<T>::Add(const T& item)
00288 {
00289
00290 NPT_Result result = Reserve(m_ItemCount+1);
00291 if (result != NPT_SUCCESS) return result;
00292
00293
00294 new ((void*)&m_Items[m_ItemCount++]) T(item);
00295
00296 return NPT_SUCCESS;
00297 }
00298
00299
00300
00301
00302 template <typename T>
00303 inline
00304 NPT_Result
00305 NPT_Array<T>::Erase(Iterator which)
00306 {
00307 return Erase(which, which);
00308 }
00309
00310
00311
00312
00313 template <typename T>
00314 NPT_Result
00315 NPT_Array<T>::Erase(Iterator first, Iterator last)
00316 {
00317
00318 if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
00319
00320
00321 NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
00322 NPT_Ordinal last_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
00323 if (first_index >= m_ItemCount ||
00324 last_index >= m_ItemCount ||
00325 first_index > last_index) {
00326 return NPT_ERROR_INVALID_PARAMETERS;
00327 }
00328
00329
00330 NPT_Cardinal interval = last_index-first_index+1;
00331 NPT_Cardinal shifted = m_ItemCount-last_index-1;
00332 for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
00333 m_Items[i] = m_Items[i+interval];
00334 }
00335
00336
00337 for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
00338 m_Items[i].~T();
00339 }
00340
00341
00342 m_ItemCount -= interval;
00343
00344 return NPT_SUCCESS;
00345 }
00346
00347
00348
00349
00350 template <typename T>
00351 NPT_Result
00352 NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
00353 {
00354
00355 NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
00356 if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
00357
00358 NPT_Cardinal needed = m_ItemCount+repeat;
00359 if (needed < m_Capacity) {
00360
00361 NPT_Cardinal new_capacity;
00362 T* new_items = Allocate(needed, new_capacity);
00363 if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
00364 m_Capacity = new_capacity;
00365
00366
00367 for (NPT_Ordinal i=0; i<where_index; i++) {
00368 new((void*)&new_items[i])T(m_Items[i]);
00369 m_Items[i].~T();
00370 }
00371
00372
00373 for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
00374 new((void*)&new_items[i+repeat])T(m_Items[i]);
00375 m_Items[i].~T();
00376 }
00377
00378
00379 ::operator delete((void*)m_Items);
00380 m_Items = new_items;
00381 } else {
00382
00383 for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
00384 new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
00385 m_Items[i-1].~T();
00386 }
00387 }
00388
00389
00390 for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
00391 new((void*)&m_Items[i])T(item);
00392 }
00393
00394
00395 m_ItemCount += repeat;
00396
00397 return NPT_SUCCESS;
00398 }
00399
00400
00401
00402
00403 template <typename T>
00404 NPT_Result
00405 NPT_Array<T>::Resize(NPT_Cardinal size)
00406 {
00407 if (size < m_ItemCount) {
00408
00409 for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
00410 m_Items[i].~T();
00411 }
00412 m_ItemCount = size;
00413 } else if (size > m_ItemCount) {
00414 return Resize(size, T());
00415 }
00416
00417 return NPT_SUCCESS;
00418 }
00419
00420
00421
00422
00423 template <typename T>
00424 NPT_Result
00425 NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
00426 {
00427 if (size < m_ItemCount) {
00428 return Resize(size);
00429 } else if (size > m_ItemCount) {
00430 Reserve(size);
00431 for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
00432 new ((void*)&m_Items[i]) T(fill);
00433 }
00434 m_ItemCount = size;
00435 }
00436
00437 return NPT_SUCCESS;
00438 }
00439
00440
00441
00442
00443 template <typename T>
00444 bool
00445 NPT_Array<T>::Contains(const T& data) const
00446 {
00447 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00448 if (m_Items[i] == data) return true;
00449 }
00450
00451 return false;
00452 }
00453
00454
00455
00456
00457 template <typename T>
00458 bool
00459 NPT_Array<T>::operator==(const NPT_Array<T>& other) const
00460 {
00461
00462 if (other.m_ItemCount != m_ItemCount) return false;
00463
00464
00465 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00466 if (!(m_Items[i] == other.m_Items[i])) return false;
00467 }
00468
00469 return true;
00470 }
00471
00472
00473
00474
00475 template <typename T>
00476 inline
00477 bool
00478 NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
00479 {
00480 return !(*this == other);
00481 }
00482
00483 #endif // _NPT_ARRAY_H_
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496