Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #pragma once
00015
00019 #include "SharedPtr.h"
00020 #include "Allocator.h"
00021 #include "StdCMallocHeap.h"
00022
00023 namespace kNet
00024 {
00025
00026 template<typename T, typename AllocT = StdCAlloc>
00027 class Array;
00028
00030 template<typename T, typename AllocT>
00031 class ArrayIterator
00032 {
00033 public:
00034 ArrayIterator(const ArrayIterator &rhs):ptr(rhs.ptr), container(rhs.container) {}
00035 ~ArrayIterator() {}
00036
00037 inline void operator++()
00038 {
00039 assert(ptr <= container->endptr());
00040 assert(ptr >= container->beginptr());
00041 ++ptr;
00042 }
00043 inline void operator--()
00044 {
00045 assert(ptr <= container->endptr());
00046 assert(ptr >= container->beginptr());
00047 --ptr;
00048 }
00049
00050 inline operator T*()
00051 {
00052 assert(ptr >= container->beginptr());
00053 assert(ptr <= container->endptr());
00054 return ptr;
00055 }
00056
00057 inline operator const T*() const
00058 {
00059 assert(ptr >= container->beginptr());
00060 assert(ptr <= container->endptr());
00061 return ptr;
00062 }
00063
00064 inline const T &operator*() const
00065 {
00066 assert(ptr >= container->beginptr());
00067 assert(ptr <= container->endptr());
00068 return *ptr;
00069 }
00070
00071 inline T &operator*()
00072 {
00073 assert(ptr >= container->beginptr());
00074 assert(ptr <= container->endptr());
00075 return *ptr;
00076 }
00077
00078 inline bool operator<(const ArrayIterator &rhs) const { return ptr < rhs.ptr; }
00079 inline bool operator<=(const ArrayIterator &rhs) const { return ptr <= rhs.ptr; }
00080 inline bool operator==(const ArrayIterator &rhs) const { return ptr == rhs.ptr; }
00081 inline bool operator!=(const ArrayIterator &rhs) const { return ptr != rhs.ptr; }
00082 inline bool operator>(const ArrayIterator &rhs) const { return ptr > rhs.ptr; }
00083 inline bool operator>=(const ArrayIterator &rhs) const { return ptr >= rhs.ptr; }
00084
00085 private:
00086 T *ptr;
00087 Array<T, AllocT> *container;
00088
00089 ArrayIterator(Array<T, AllocT> &container_, T *ptr_)
00090 :container(&container_), ptr(ptr_)
00091 {
00092 assert(ptr >= container->beginptr());
00093 assert(ptr <= container->endptr());
00094 }
00095
00096 friend class Array<T, AllocT>;
00097 };
00098
00100 template<typename T, typename AllocT>
00101 class Array
00102 {
00103 public:
00104 typedef ArrayIterator<T, AllocT> iterator;
00105
00106 Array(AllocT *allocator_ = 0)
00107 :data(0), cap(0), used(0), allocator(allocator_)
00108 { }
00109
00110 Array(const Array &rhs)
00111 :allocator(rhs.allocator), data(0), cap(0), used(0)
00112 {
00113 reserve(rhs.cap);
00114 for(size_t i = 0; i < rhs.size(); ++i)
00115 data[i] = rhs.data[i];
00116 used = rhs.used;
00117 }
00118
00119 ~Array()
00120 {
00121 for(size_t i = 0; i < used; ++i)
00122 data[i] = T();
00123 DeleteArray(data, allocator);
00124 }
00125
00126 const T &front() const { assert(used > 0); return data[0]; }
00127 const T &back() const { assert(used > 0); return data[used-1]; }
00128 T &front() { assert(used > 0); return data[0]; }
00129 T &back() { assert(used > 0); return data[used-1]; }
00130
00132 size_t size() const { return used; }
00133
00135 size_t capacity() const { return cap; }
00136
00138 void set_allocator(AllocT *allocator_)
00139 {
00140 assert(cap == 0);
00141 assert(data == 0);
00142 allocator = allocator_;
00143 }
00144
00146 AllocT *get_allocator() const { return allocator; }
00147
00148 const T *beginptr() const { return data; }
00149 const T *endptr() const { return data + used; }
00150 const T *capptr() const { return data + cap; }
00151
00153 iterator begin() { return iterator(*this, data); }
00154
00156
00157
00159 iterator end() { return iterator(*this, data + used); }
00160
00162 const T *end() const { return data + used ; }
00163
00164 void insert(const T &val) { insert(used, val); }
00165
00167 void insert(int i, const T &val)
00168 {
00169 if (used >= cap)
00170 reserve(cap*2);
00171
00172
00173 for(int j = used+1; j > i; --j)
00174 data[j] = data[j-1];
00175
00176
00177 data[i] = val;
00178 ++used;
00179 }
00180
00181 void InsertMultiple(int i, const T &val, int numTimes)
00182 {
00183 if (used + numTimes > cap)
00184 reserve((cap+numTimes)*2);
00185
00186
00187 for(int j = used+numTimes; j > i+numTimes; --j)
00188 data[j] = data[j-numTimes];
00189
00190
00191 for(int j = i; j < i + numTimes; ++j)
00192 data[j] = val;
00193
00194 used += numTimes;
00195 }
00196
00198 bool MembersUnique() const
00199 {
00200 for(size_t i = 0; i < used; ++i)
00201 for(size_t j = i+1; j < used; ++j)
00202 if (data[i] == data[j])
00203 return false;
00204
00205 return true;
00206 }
00207
00209 void push_front(const T &val) { insert(0, val); }
00210
00212 void push_back(const T &val)
00213 {
00214 if (used >= cap)
00215 reserve(cap*2);
00216 data[used] = val;
00217 ++used;
00218 }
00219
00222 void push_back_unsafe(const T &val)
00223 {
00224 assert(used < cap);
00225 data[used++] = val;
00226 }
00227
00231 T &push_back_unsafe_pod()
00232 {
00233 assert(used < cap);
00234 return data[used++];
00235 }
00236
00238 T &push_back()
00239 {
00240 if (used >= cap)
00241 reserve(cap*2);
00242 data[used] = T();
00243 return data[used++];
00244 }
00245
00248 void erase(int start, int end)
00249 {
00250 assert(start >= 0);
00251 assert(end >= 0);
00252 assert(start <= end);
00253 assert(end <= used);
00254
00255 if (start == end)
00256 return;
00257
00258 const int items = end-start;
00259 for(int i = start; i < used-items; ++i)
00260 data[i] = data[i+items];
00261 for(int i = used-items; i < used; ++i)
00262 data[i] = T();
00263
00264 used -= items;
00265 }
00266
00268 void erase(int i)
00269 {
00270 assert(i >= 0);
00271 erase((size_t)i);
00272 }
00273
00275 void erase(size_t i)
00276 {
00277 assert(i < used);
00278
00279 for(size_t j = i; j+1 < used; ++j)
00280 data[j] = data[j+1];
00281
00282 data[used-1] = T();
00283 --used;
00284 }
00285
00287 void pop_back()
00288 {
00289 assert(used > 0);
00290
00291 data[used-1] = T();
00292 --used;
00293 }
00294
00297 void pop_back_pod()
00298 {
00299 assert(used > 0);
00300
00301 --used;
00302 }
00303
00305 void clear()
00306 {
00307 for(size_t i = 0; i < used; ++i)
00308 data[i] = T();
00309 used = 0;
00310 }
00311
00315 void clear_pod()
00316 {
00317 used = 0;
00318 }
00319
00321 void reserve(size_t newSize)
00322 {
00323 newSize = newSize < initialSize ? initialSize : newSize;
00324
00325
00326 if (newSize < cap)
00327 return;
00328
00329 const size_t alignment = 4;
00330 T *newData = NewArray<T, AllocT>(newSize, allocator, alignment);
00331
00332
00333
00334 for(size_t i = 0; i < used; ++i)
00335 newData[i] = data[i];
00336
00337 DeleteArray(data, allocator);
00338 data = newData;
00339 cap = newSize;
00340 }
00341
00342 const T &operator[](int index) const
00343 {
00344 assert(index >= 0);
00345 assert((size_t)index < used);
00346 return data[index];
00347 }
00348
00349 T &operator[](int index)
00350 {
00351 assert(index >= 0);
00352 assert((size_t)index < used);
00353 return data[index];
00354 }
00355
00356 Array<T, AllocT> &operator =(const Array<T, AllocT> &rhs)
00357 {
00358 if (this == &rhs)
00359 return *this;
00360
00361 reserve(rhs.size());
00362 for(size_t i = 0; i < rhs.size(); ++i)
00363 data[i] = rhs.data[i];
00364 used = rhs.size();
00365
00366 return *this;
00367 }
00368
00369 private:
00370 T *data;
00371 AllocT *allocator;
00372 size_t cap;
00373 size_t used;
00374
00375 static const size_t initialSize = 32;
00376 };
00377
00378 }