00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #ifndef _BASE_ARRAY_
00026 #define _BASE_ARRAY_
00027
00028 #include <iterator>
00029 #include <stdexcept>
00030
00031
00032 namespace base {
00033
00034 template<typename T>
00035 class array
00036 {
00037 public:
00038 typedef T value_type;
00039 typedef value_type* pointer;
00040 typedef const value_type* const_pointer;
00041 typedef value_type* iterator;
00042 typedef const value_type* const_iterator;
00043 typedef value_type& reference;
00044 typedef const value_type& const_reference;
00045 typedef Int size_type;
00046 typedef SInt difference_type;
00047
00048 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00049 typedef std::reverse_iterator<iterator> reverse_iterator;
00050
00051 array() { init(0,1); }
00052 array(size_type n) { init(n,n); }
00053 array(size_type n, size_type initial_capacity) { init(n,initial_capacity); }
00054
00055 array(size_type n, T a[], bool by_reference=true) {
00056 if (!by_reference) {
00057 init(n,n);
00058 for(size_type e=0; e<n; ++e) _a[e] = a[e];
00059 }
00060 else {
00061 _size = _capacity = n;
00062 _a = a;
00063 _owner = false;
00064 }
00065 }
00066
00067 array(const array& a) {
00068 init(a._size,a._size);
00069 copy(a);
00070 }
00071
00072 ~array() {
00073 if (_owner) delete[] _a;
00074 }
00075
00076
00077 array& operator=(const array& a)
00078 {
00079 copy(a);
00080 return *this;
00081 }
00082
00083 bool operator==(const array& a) const
00084 {
00085 if (_size != a._size) return false;
00086 for(size_type e=0; e<_size; ++e)
00087 if (!(_a[e] == a._a[e])) return false;
00088 return true;
00089 }
00090
00091 bool operator!=(const array& a) const
00092 {
00093 if (_size != a._size) return true;
00094 for(size_type e=0; e<_size; ++e)
00095 if (_a[e] != a._a[e]) return true;
00096 return false;
00097 }
00098
00099
00100
00101 reference operator[](difference_type i) {
00102 #ifdef DEBUG
00103 if ((size_type(i) >= _size) || (i<0)) {
00104 Assertm( false, "array index within bounds (debug only check)");
00105 }
00106 #endif
00107 return _a[i];
00108 }
00109
00110 const_reference operator[](difference_type i) const {
00111 #ifdef DEBUG
00112 if ((size_type(i) >= _size) || (i<0)) {
00113 Assertm( false, "array index within bounds (debug only check)");
00114 }
00115 #endif
00116 return _a[i];
00117 }
00118
00119
00120 reference operator()(difference_type i) {
00121 #ifdef DEBUG
00122 if ((size_type(i) > _size) || (i<1)) {
00123 Assertm( false, "array index within bounds (debug only check)");
00124 }
00125 #endif
00126 return _a[i-1];
00127 }
00128 const_reference operator()(difference_type i) const {
00129 #ifdef DEBUG
00130 if ((size_type(i) > _size) || (i<1)) {
00131 Assertm( false, "array index within bounds (debug only check)");
00132 }
00133 #endif
00134 return _a[i-1];
00135 }
00136
00137
00138 reference at(difference_type i) throw(std::out_of_range) {
00139 if (size_type(i) >= _size) {
00140 if (_owner)
00141 resize(i+1);
00142 else
00143 throw std::out_of_range(Exception("array index out of bounds"));
00144 }
00145 return _a[i];
00146 }
00147
00148 size_type size() const { return _size; }
00149 size_type capacity() const { return _capacity; }
00150
00151 array& clear()
00152 {
00153 if (_owner) delete[] _a;
00154 init(0,1);
00155 return *this;
00156 }
00157
00158 bool empty() { return _size == size_type(0); }
00159
00160
00161
00162 void swap(array& a) {
00163 T* tmp_a = _a;
00164 size_type tmp_size = _size;
00165 size_type tmp_capacity = _capacity;
00166 bool tmp_owner = _owner;
00167
00168 _a = a._a;
00169 _size = a._size;
00170 _capacity = a._capacity;
00171 _owner = a._owner;
00172
00173 a._a = tmp_a;
00174 a._size = tmp_size;
00175 a._capacity = tmp_capacity;
00176 a._owner = tmp_owner;
00177 }
00178
00179
00180
00181 reference front() throw(std::out_of_range) {
00182 if (_size>0)
00183 return _a[0];
00184 else
00185 throw std::out_of_range((Exception("array has no elements (no front)")));
00186 }
00187
00188 const_reference front() const throw(std::out_of_range) {
00189 if (_size>0)
00190 return _a[0];
00191 else
00192 throw std::out_of_range((Exception("array has no elements (no front)")));
00193 }
00194
00195 reference back() throw(std::out_of_range) {
00196 if (_size>0)
00197 return _a[_size-1];
00198 else
00199 throw std::out_of_range((Exception("array has no elements (no back)")));
00200 }
00201
00202 const_reference back() const throw(std::out_of_range) {
00203 if (_size>0)
00204 return _a[_size-1];
00205 else
00206 throw std::out_of_range((Exception("array has no elements (no back)")));
00207 }
00208
00209 void push_back(const T& e) {
00210 resize(_size+1);
00211 _a[_size-1] = e;
00212 }
00213
00214 void pop_back() throw(std::out_of_range) {
00215 if (_size>0)
00216 resize(_size-1);
00217 else
00218 throw std::out_of_range((Exception("array has no elements (nothing to pop)")));
00219 }
00220
00221
00222 iterator begin() { return _a; }
00223 const_iterator begin() const { return _a; }
00224
00225 iterator end() { return _a + _size; }
00226 const_iterator end() const { return _a + _size; }
00227
00228 pointer c_array() { return _a; }
00229 const_pointer c_array() const { return _a; }
00230
00231
00232
00233
00234 void extend(size_type new_min_capacity)
00235 {
00236 size_type newcapacity = _capacity;
00237 while (newcapacity < new_min_capacity)
00238 newcapacity = size_type((Real(newcapacity) * 1.5) +1);
00239
00240 if (newcapacity > _capacity) {
00241 T *_olda = _a;
00242 _a = new T[newcapacity];
00243 for(size_type e=0; e<_size; ++e)
00244 _a[e] = _olda[e];
00245
00246 if (_owner) delete[] _olda;
00247 _capacity = newcapacity;
00248 _owner=true;
00249 }
00250 }
00251
00252
00253 array& trim()
00254 {
00255 if (!_owner) return *this;
00256 size_type newcapacity = _size;
00257 if (newcapacity==0) newcapacity=1;
00258 T *_olda = _a;
00259 _a = new T[newcapacity];
00260 for(size_type e=0; e<_size; ++e)
00261 _a[e] = _olda[e];
00262 delete[] _olda;
00263 _capacity = newcapacity;
00264 return *this;
00265 }
00266
00267
00268 array& resize(size_type newsize)
00269 {
00270 if (newsize > _capacity) extend(newsize);
00271 _size = newsize;
00272 return *this;
00273 }
00274
00275
00276 array& destructive_resize(size_type newsize)
00277 {
00278 if (_owner) delete[] _a;
00279 _size = _capacity = newsize;
00280 _a = new T[_capacity];
00281 _owner = true;
00282 return *this;
00283 }
00284
00285
00286 private:
00287 T *_a;
00288 size_type _size;
00289 size_type _capacity;
00290 bool _owner;
00291
00292 void init(size_type size, size_type cap) {
00293 if (cap<size) cap = size;
00294 if (cap<=0) cap=1;
00295 _size=size; _capacity=cap;
00296 _a = new T[_capacity];
00297 _owner = true;
00298 }
00299
00300 void copy(const array& a)
00301 {
00302 if (_owner)
00303 resize(a._size);
00304 size_type minsize = (_size<a._size)?_size:a._size;
00305 for(size_type e=0; e<minsize; ++e)
00306 _a[e] = a._a[e];
00307 }
00308
00309 };
00310
00311 }
00312
00313 #endif