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 m_ItemCount = copy.m_ItemCount;
00206 for (NPT_Ordinal i=0; i<copy.m_ItemCount; i++) {
00207 new ((void*)&m_Items[i]) T(copy.m_Items[i]);
00208 }
00209
00210 return *this;
00211 }
00212
00213
00214
00215
00216 template <typename T>
00217 NPT_Result
00218 NPT_Array<T>::Clear()
00219 {
00220
00221 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00222 m_Items[i].~T();
00223 }
00224
00225 m_ItemCount = 0;
00226
00227 return NPT_SUCCESS;
00228 }
00229
00230
00231
00232
00233 template <typename T>
00234 T*
00235 NPT_Array<T>::Allocate(NPT_Cardinal count, NPT_Cardinal& allocated)
00236 {
00237 if (m_Capacity) {
00238 allocated = 2*m_Capacity;
00239 } else {
00240
00241
00242 allocated = NPT_ARRAY_INITIAL_MAX_SIZE/sizeof(T);
00243 if (allocated == 0) allocated = 1;
00244 }
00245 if (allocated < count) allocated = count;
00246
00247
00248 return (T*)::operator new(allocated*sizeof(T));
00249 }
00250
00251
00252
00253
00254 template <typename T>
00255 NPT_Result
00256 NPT_Array<T>::Reserve(NPT_Cardinal count)
00257 {
00258 if (count <= m_Capacity) return NPT_SUCCESS;
00259
00260
00261 NPT_Cardinal new_capacity;
00262 T* new_items = Allocate(count, new_capacity);
00263 if (new_items == NULL) {
00264 return NPT_ERROR_OUT_OF_MEMORY;
00265 }
00266 if (m_ItemCount && m_Items) {
00267 for (unsigned int i=0; i<m_ItemCount; i++) {
00268
00269 new ((void*)&new_items[i])T(m_Items[i]);
00270
00271
00272 m_Items[i].~T();
00273 }
00274 }
00275 ::operator delete((void*)m_Items);
00276 m_Items = new_items;
00277 m_Capacity = new_capacity;
00278
00279 return NPT_SUCCESS;
00280 }
00281
00282
00283
00284
00285 template <typename T>
00286 inline
00287 NPT_Result
00288 NPT_Array<T>::Add(const T& item)
00289 {
00290
00291 NPT_Result result = Reserve(m_ItemCount+1);
00292 if (result != NPT_SUCCESS) return result;
00293
00294
00295 new ((void*)&m_Items[m_ItemCount++]) T(item);
00296
00297 return NPT_SUCCESS;
00298 }
00299
00300
00301
00302
00303 template <typename T>
00304 inline
00305 NPT_Result
00306 NPT_Array<T>::Erase(Iterator which)
00307 {
00308 return Erase(which, which);
00309 }
00310
00311
00312
00313
00314 template <typename T>
00315 NPT_Result
00316 NPT_Array<T>::Erase(Iterator first, Iterator last)
00317 {
00318
00319 if (first == NULL || last == NULL) return NPT_ERROR_INVALID_PARAMETERS;
00320
00321
00322 NPT_Ordinal first_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(first-m_Items));
00323 NPT_Ordinal last_index = (NPT_Ordinal)(NPT_POINTER_TO_LONG(last-m_Items));
00324 if (first_index >= m_ItemCount ||
00325 last_index >= m_ItemCount ||
00326 first_index > last_index) {
00327 return NPT_ERROR_INVALID_PARAMETERS;
00328 }
00329
00330
00331 NPT_Cardinal interval = last_index-first_index+1;
00332 NPT_Cardinal shifted = m_ItemCount-last_index-1;
00333 for (NPT_Ordinal i=first_index; i<first_index+shifted; i++) {
00334 m_Items[i] = m_Items[i+interval];
00335 }
00336
00337
00338 for (NPT_Ordinal i=first_index+shifted; i<m_ItemCount; i++) {
00339 m_Items[i].~T();
00340 }
00341
00342
00343 m_ItemCount -= interval;
00344
00345 return NPT_SUCCESS;
00346 }
00347
00348
00349
00350
00351 template <typename T>
00352 NPT_Result
00353 NPT_Array<T>::Insert(Iterator where, const T& item, NPT_Cardinal repeat)
00354 {
00355
00356 NPT_Ordinal where_index = where?((NPT_Ordinal)NPT_POINTER_TO_LONG(where-m_Items)):m_ItemCount;
00357 if (where > &m_Items[m_ItemCount] || repeat == 0) return NPT_ERROR_INVALID_PARAMETERS;
00358
00359 NPT_Cardinal needed = m_ItemCount+repeat;
00360 if (needed > m_Capacity) {
00361
00362 NPT_Cardinal new_capacity;
00363 T* new_items = Allocate(needed, new_capacity);
00364 if (new_items == NULL) return NPT_ERROR_OUT_OF_MEMORY;
00365 m_Capacity = new_capacity;
00366
00367
00368 for (NPT_Ordinal i=0; i<where_index; i++) {
00369 new((void*)&new_items[i])T(m_Items[i]);
00370 m_Items[i].~T();
00371 }
00372
00373
00374 for (NPT_Ordinal i=where_index; i<m_ItemCount; i++) {
00375 new((void*)&new_items[i+repeat])T(m_Items[i]);
00376 m_Items[i].~T();
00377 }
00378
00379
00380 ::operator delete((void*)m_Items);
00381 m_Items = new_items;
00382 } else {
00383
00384 for (NPT_Ordinal i=m_ItemCount; i>where_index; i--) {
00385 new((void*)&m_Items[i+repeat-1])T(m_Items[i-1]);
00386 m_Items[i-1].~T();
00387 }
00388 }
00389
00390
00391 for (NPT_Cardinal i=where_index; i<where_index+repeat; i++) {
00392 new((void*)&m_Items[i])T(item);
00393 }
00394
00395
00396 m_ItemCount += repeat;
00397
00398 return NPT_SUCCESS;
00399 }
00400
00401
00402
00403
00404 template <typename T>
00405 NPT_Result
00406 NPT_Array<T>::Resize(NPT_Cardinal size)
00407 {
00408 if (size < m_ItemCount) {
00409
00410 for (NPT_Ordinal i=size; i<m_ItemCount; i++) {
00411 m_Items[i].~T();
00412 }
00413 m_ItemCount = size;
00414 } else if (size > m_ItemCount) {
00415 return Resize(size, T());
00416 }
00417
00418 return NPT_SUCCESS;
00419 }
00420
00421
00422
00423
00424 template <typename T>
00425 NPT_Result
00426 NPT_Array<T>::Resize(NPT_Cardinal size, const T& fill)
00427 {
00428 if (size < m_ItemCount) {
00429 return Resize(size);
00430 } else if (size > m_ItemCount) {
00431 Reserve(size);
00432 for (NPT_Ordinal i=m_ItemCount; i<size; i++) {
00433 new ((void*)&m_Items[i]) T(fill);
00434 }
00435 m_ItemCount = size;
00436 }
00437
00438 return NPT_SUCCESS;
00439 }
00440
00441
00442
00443
00444 template <typename T>
00445 bool
00446 NPT_Array<T>::Contains(const T& data) const
00447 {
00448 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00449 if (m_Items[i] == data) return true;
00450 }
00451
00452 return false;
00453 }
00454
00455
00456
00457
00458 template <typename T>
00459 bool
00460 NPT_Array<T>::operator==(const NPT_Array<T>& other) const
00461 {
00462
00463 if (other.m_ItemCount != m_ItemCount) return false;
00464
00465
00466 for (NPT_Ordinal i=0; i<m_ItemCount; i++) {
00467 if (!(m_Items[i] == other.m_Items[i])) return false;
00468 }
00469
00470 return true;
00471 }
00472
00473
00474
00475
00476 template <typename T>
00477 inline
00478 bool
00479 NPT_Array<T>::operator!=(const NPT_Array<T>& other) const
00480 {
00481 return !(*this == other);
00482 }
00483
00484 #endif // _NPT_ARRAY_H_
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497