00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef _DECAF_UTIL_ARRAYLIST_H_
00019 #define _DECAF_UTIL_ARRAYLIST_H_
00020
00021 #include <memory>
00022 #include <decaf/util/NoSuchElementException.h>
00023 #include <decaf/lang/exceptions/UnsupportedOperationException.h>
00024 #include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
00025 #include <decaf/lang/System.h>
00026 #include <decaf/lang/Integer.h>
00027 #include <decaf/util/Config.h>
00028 #include <decaf/util/Iterator.h>
00029 #include <decaf/util/ListIterator.h>
00030 #include <decaf/util/List.h>
00031 #include <decaf/util/AbstractList.h>
00032
00033 namespace decaf {
00034 namespace util {
00035
00036 using decaf::lang::System;
00037
00038 template< typename E >
00039 class ArrayList : public decaf::util::AbstractList<E> {
00040 private:
00041
00042 E* elements;
00043 int capacity;
00044 int head;
00045 int curSize;
00046
00047 public:
00048
00049 ArrayList() : AbstractList<E>(), elements(NULL), capacity(0), head(0), curSize(0) {
00050 this->ensureCapacity(10);
00051 }
00052
00053 ArrayList(const Collection<E>& collection) :
00054 AbstractList<E>(), elements(NULL), capacity(0), head(0), curSize(0) {
00055
00056 this->capacity = collection.size() + (collection.size() / 10);
00057 this->elements = new E[this->capacity];
00058
00059 std::auto_ptr<Iterator<E> > iter(collection.iterator());
00060 while (iter->hasNext()) {
00061 this->elements[this->head++] = iter->next();
00062 this->curSize++;
00063 }
00064 }
00065
00066 ArrayList(const ArrayList<E>& arrayList) :
00067 AbstractList<E>(), elements(NULL), capacity(0), head(0), curSize(0) {
00068
00069 this->capacity = arrayList.size() + (arrayList.size() / 10);
00070 this->elements = new E[this->capacity];
00071
00072 std::auto_ptr<Iterator<E> > iter(arrayList.iterator());
00073 while (iter->hasNext()) {
00074 this->elements[this->head++] = iter->next();
00075 this->curSize++;
00076 }
00077 }
00078
00079 ArrayList(int initialCapacity) :
00080 AbstractList<E>(), elements(NULL), capacity(initialCapacity), head(0), curSize(0) {
00081
00082 if (initialCapacity < 0) {
00083 throw decaf::lang::exceptions::IllegalArgumentException(__FILE__, __LINE__, "Initial Capacity argument cannot be negative.");
00084 }
00085
00086 this->elements = new E[this->capacity];
00087 }
00088
00089 virtual ~ArrayList() {
00090 try {
00091 delete[] elements;
00092 }
00093 DECAF_CATCHALL_NOTHROW()
00094 }
00095
00096 public:
00097
00098 ArrayList<E>& operator= ( const ArrayList<E>& list ) {
00099 this->clear();
00100 this->addAll( list );
00101 return *this;
00102 }
00103
00104 ArrayList<E>& operator= ( const Collection<E>& collection ) {
00105 this->clear();
00106 this->addAll( 0, collection );
00107 return *this;
00108 }
00109
00110 bool operator==(const ArrayList<E>& other) const {
00111 return this->equals(other);
00112 }
00113
00114 bool operator!=(const ArrayList<E>& other) const {
00115 return !this->equals(other);
00116 }
00117
00118 public:
00119
00129 void ensureCapacity( int minimumCapacity ) {
00130
00131 if( minimumCapacity < 0 || this->capacity >= minimumCapacity ) {
00132 return;
00133 }
00134
00135 int newCapacity = minimumCapacity == 0 ? 10 : minimumCapacity;
00136
00137 E* newElements = new E[newCapacity];
00138 if( this->curSize > 0 ) {
00139 decaf::lang::System::arraycopy( this->elements, this->head, newElements, 0, this->curSize );
00140 }
00141 delete [] this->elements;
00142 this->elements = newElements;
00143 this->capacity = newCapacity;
00144 AbstractList<E>::modCount++;
00145 }
00146
00151 void trimToSize() {
00152
00153 if( this->curSize < this->capacity ) {
00154
00155 int newCapacity = this->curSize == 0 ? 10 : this->curSize;
00156
00157 E* newElements = new E[newCapacity];
00158 if( this->curSize > 0 ) {
00159 System::arraycopy( this->elements, 0, newElements, 0, this->curSize );
00160 }
00161
00162 delete [] this->elements;
00163 this->elements = newElements;
00164 this->capacity = newCapacity;
00165 }
00166
00167 AbstractList<E>::modCount++;
00168 }
00169
00170 public:
00171
00172 virtual void clear() {
00173 delete [] this->elements;
00174 this->curSize = 0;
00175 this->capacity = 10;
00176 this->elements = new E[this->capacity];
00177 AbstractList<E>::modCount++;
00178 }
00179
00180 virtual bool isEmpty() const {
00181 return this->curSize == 0;
00182 }
00183
00184 virtual int size() const {
00185 return this->curSize;
00186 }
00187
00188 virtual E set( int index, const E& element ) {
00189
00190 if( index < 0 || index >= this->curSize ) {
00191 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00192 __FILE__, __LINE__,
00193 "List::get - Index greater than size() or negative" );
00194 }
00195
00196 E oldValue = this->elements[index];
00197 this->elements[index] = element;
00198
00199 return oldValue;
00200 }
00201
00202 virtual E get( int index ) const {
00203
00204 if( index < 0 || index >= this->curSize ) {
00205 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00206 __FILE__, __LINE__,
00207 "List::get - Index greater than size() or negative" );
00208 }
00209
00210 return this->elements[index];
00211 }
00212
00213 virtual bool add( const E& value ) {
00214
00215 this->expandEnd( 1 );
00216 this->elements[this->curSize++] = value;
00217 AbstractList<E>::modCount++;
00218
00219 return true;
00220 }
00221
00222 virtual void add( int index, const E& element ) {
00223
00224 if( index < 0 || index > this->curSize ) {
00225 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00226 __FILE__, __LINE__,
00227 "Index was negative or greater than size()" );
00228 }
00229
00230 if( index == 0 ) {
00231 this->expandFront( 1 );
00232 } else if( index == this->curSize ) {
00233 this->expandEnd( 1 );
00234 } else {
00235 this->expandMiddle( index, 1 );
00236 }
00237
00238 this->elements[index] = element;
00239 this->curSize++;
00240 AbstractList<E>::modCount++;
00241 }
00242
00243 virtual bool addAll( const Collection<E>& collection ) {
00244
00245 int csize = collection.size();
00246 if( csize == 0 ) {
00247 return false;
00248 }
00249
00250 std::vector<E> array = collection.toArray();
00251
00252 this->expandEnd( csize );
00253
00254 for( int i = 0; i < csize; ++i ) {
00255 this->elements[this->curSize++] = array[i];
00256 }
00257
00258 AbstractList<E>::modCount++;
00259
00260 return true;
00261 }
00262
00263 virtual bool addAll( int index, const Collection<E>& collection ) {
00264
00265 if( index < 0 || index > this->curSize ) {
00266 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00267 __FILE__, __LINE__,
00268 "List::addAll - Index greater than size()" );
00269 }
00270
00271 int csize = collection.size();
00272 if( csize == 0 ) {
00273 return false;
00274 }
00275
00276 std::vector<E> array = collection.toArray();
00277
00278 if( index == 0 ) {
00279 this->expandFront( csize );
00280 } else if( index == this->curSize ) {
00281 this->expandEnd( csize );
00282 } else {
00283 this->expandMiddle( index, csize );
00284 }
00285
00286 for( int i = 0; i < csize; ++i, ++this->curSize ) {
00287 this->elements[index++] = array[i];
00288 }
00289
00290 AbstractList<E>::modCount++;
00291
00292 return true;
00293 }
00294
00295 virtual bool remove( const E& value ) {
00296
00297 int result = indexOf( value );
00298 if( result != -1 ) {
00299 this->removeAt( result );
00300 return true;
00301 }
00302
00303 return false;
00304 }
00305
00306 virtual E removeAt( int index ) {
00307
00308 if( index < 0 || index >= this->curSize ) {
00309 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00310 __FILE__, __LINE__,
00311 "List::removeAt - Index greater than size() or negative" );
00312 }
00313
00314 E old = this->elements[index];
00315
00316 System::arraycopy( this->elements, 0, this->elements, 0, index );
00317
00318 if( this->curSize > index ) {
00319 System::arraycopy( this->elements, index + 1, this->elements, index, this->curSize - index - 1 );
00320 }
00321
00322 this->elements[--this->curSize] = E();
00323 AbstractList<E>::modCount++;
00324
00325 return old;
00326 }
00327
00328 virtual bool contains( const E& value ) const {
00329 return this->indexOf( value ) != -1;
00330 }
00331
00332 virtual int indexOf( const E& value ) const {
00333
00334 for( int i = 0; i < this->curSize; ++i ) {
00335 if( this->elements[i] == value ) {
00336 return i;
00337 }
00338 }
00339
00340 return -1;
00341 }
00342
00343 virtual int lastIndexOf( const E& value ) const {
00344
00345 for( int i = this->curSize - 1; i >= 0; --i ) {
00346 if( this->elements[i] == value ) {
00347 return i;
00348 }
00349 }
00350
00351 return -1;
00352 }
00353
00354 virtual std::vector<E> toArray() const {
00355
00356 std::vector<E> result;
00357
00358 for( int i = 0; i < this->curSize; ++i ) {
00359 result.push_back( this->elements[i] );
00360 }
00361
00362 return result;
00363 }
00364
00365 virtual std::string toString() const {
00366
00367 std::string result;
00368
00369 result.append( "decaf::util::ArrayList [ size = " );
00370 result.append( decaf::lang::Integer::toString( this->curSize ) );
00371 result.append( " ]");
00372
00373 return result;
00374 }
00375
00376 private:
00377
00378 void expandFront( int amount ) {
00379
00380 if( amount == 0 ) {
00381 return;
00382 }
00383
00384 E* previous = this->elements;
00385
00386 if( amount > this->capacity - this->curSize ) {
00387 this->capacity = this->capacity + amount + 11;
00388 this->elements = new E[this->capacity];
00389 }
00390
00391 if( this->curSize > 0 ) {
00392 System::arraycopy( previous, 0, this->elements, amount, this->curSize );
00393 }
00394
00395 if( previous != this->elements ) {
00396 delete [] previous;
00397 }
00398 }
00399
00400 void expandEnd( int amount ) {
00401
00402 if( amount == 0 ) {
00403 return;
00404 }
00405
00406 E* previous = this->elements;
00407
00408 if( amount > this->capacity - this->curSize ) {
00409 this->capacity = this->capacity + amount + 11;
00410 this->elements = new E[this->capacity];
00411 System::arraycopy( previous, 0, this->elements, 0, this->curSize );
00412 }
00413
00414 if( previous != this->elements ) {
00415 delete [] previous;
00416 }
00417 }
00418
00419 void expandMiddle( int index, int amount ) {
00420
00421 if( amount == 0 ) {
00422 return;
00423 }
00424
00425 E* previous = this->elements;
00426
00427 if( amount > this->capacity - this->curSize ) {
00428 this->capacity = this->capacity + amount + 11;
00429 this->elements = new E[this->capacity];
00430 }
00431
00432 if( this->curSize > 0 ) {
00433 System::arraycopy( previous, 0, this->elements, 0, index );
00434 }
00435
00436 if( this->curSize > index ) {
00437 System::arraycopy( previous, index, this->elements, index + amount, this->curSize - index );
00438 }
00439
00440 if( previous != this->elements ) {
00441 delete [] previous;
00442 }
00443 }
00444
00445 };
00446
00447 }}
00448
00449 #endif