activemq-cpp-3.3.0

src/main/decaf/util/ArrayList.h

Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
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 ) : AbstractList<E>(), elements( NULL ),
00054                                                        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 ) : AbstractList<E>(), elements( NULL ),
00067                                                      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 ) : AbstractList<E>(), elements( NULL ),
00080                                            capacity( initialCapacity ), head( 0 ), curSize( 0 ) {
00081 
00082             if( initialCapacity < 0 ) {
00083                 throw decaf::lang::exceptions::IllegalArgumentException(
00084                     __FILE__, __LINE__, "Initial Capacity argument cannot be negative." );
00085             }
00086 
00087             this->elements = new E[this->capacity];
00088         }
00089 
00090         virtual ~ArrayList() {
00091             try{
00092                 delete [] elements;
00093             }
00094             DECAF_CATCHALL_NOTHROW()
00095         }
00096 
00097     public:
00098 
00099         ArrayList<E>& operator= ( const ArrayList<E>& list ) {
00100             this->clear();
00101             this->addAll( list );
00102             return *this;
00103         }
00104 
00105         ArrayList<E>& operator= ( const Collection<E>& collection ) {
00106             this->clear();
00107             this->addAll( 0, collection );
00108             return *this;
00109         }
00110 
00111     public:
00112 
00122         void ensureCapacity( int minimumCapacity ) {
00123 
00124             if( minimumCapacity < 0 || this->capacity >= minimumCapacity ) {
00125                 return;
00126             }
00127 
00128             int newCapacity = minimumCapacity == 0 ? 10 : minimumCapacity;
00129 
00130             E* newElements = new E[newCapacity];
00131             if( this->curSize > 0 ) {
00132                 decaf::lang::System::arraycopy( this->elements, this->head, newElements, 0, this->curSize );
00133             }
00134             delete [] this->elements;
00135             this->elements = newElements;
00136             this->capacity = newCapacity;
00137             AbstractList<E>::modCount++;
00138         }
00139 
00144         void trimToSize() {
00145 
00146             if( this->curSize < this->capacity ) {
00147 
00148                 int newCapacity = this->curSize == 0 ? 10 : this->curSize;
00149 
00150                 E* newElements = new E[newCapacity];
00151                 if( this->curSize > 0 ) {
00152                     System::arraycopy( this->elements, 0, newElements, 0, this->curSize );
00153                 }
00154 
00155                 delete [] this->elements;
00156                 this->elements = newElements;
00157                 this->capacity = newCapacity;
00158             }
00159 
00160             AbstractList<E>::modCount++;
00161         }
00162 
00163     public:
00164 
00165         virtual void clear() {
00166             delete [] this->elements;
00167             this->curSize = 0;
00168             this->capacity = 10;
00169             this->elements = new E[this->capacity];
00170             AbstractList<E>::modCount++;
00171         }
00172 
00173         virtual bool isEmpty() const {
00174             return this->curSize == 0;
00175         }
00176 
00177         virtual int size() const {
00178             return this->curSize;
00179         }
00180 
00181         virtual E set( int index, const E& element ) {
00182 
00183             if( index < 0 || index >= this->curSize ) {
00184                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00185                     __FILE__, __LINE__,
00186                     "List::get - Index greater than size() or negative" );
00187             }
00188 
00189             E oldValue = this->elements[index];
00190             this->elements[index] = element;
00191 
00192             return oldValue;
00193         }
00194 
00195         virtual E get( int index ) const {
00196 
00197             if( index < 0 || index >= this->curSize ) {
00198                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00199                     __FILE__, __LINE__,
00200                     "List::get - Index greater than size() or negative" );
00201             }
00202 
00203             return this->elements[index];
00204         }
00205 
00206         virtual bool add( const E& value ) {
00207 
00208             this->expandEnd( 1 );
00209             this->elements[this->curSize++] = value;
00210             AbstractList<E>::modCount++;
00211 
00212             return true;
00213         }
00214 
00215         virtual void add( int index, const E& element ) {
00216 
00217             if( index < 0 || index > this->curSize ) {
00218                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00219                     __FILE__, __LINE__,
00220                     "Index was negative or greater than size()" );
00221             }
00222 
00223             if( index == 0 ) {
00224                 this->expandFront( 1 );
00225             } else if( index == this->curSize ) {
00226                 this->expandEnd( 1 );
00227             } else {
00228                 this->expandMiddle( index, 1 );
00229             }
00230 
00231             this->elements[index] = element;
00232             this->curSize++;
00233             AbstractList<E>::modCount++;
00234         }
00235 
00236         virtual bool addAll( const Collection<E>& collection ) {
00237 
00238             int csize = collection.size();
00239             if( csize == 0 ) {
00240                 return false;
00241             }
00242 
00243             std::vector<E> array = collection.toArray();
00244 
00245             this->expandEnd( csize );
00246 
00247             for( int i = 0; i < csize; ++i ) {
00248                 this->elements[this->curSize++] = array[i];
00249             }
00250 
00251             AbstractList<E>::modCount++;
00252 
00253             return true;
00254         }
00255 
00256         virtual bool addAll( int index, const Collection<E>& collection ) {
00257 
00258             if( index < 0 || index > this->curSize ) {
00259                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00260                     __FILE__, __LINE__,
00261                     "List::addAll - Index greater than size()" );
00262             }
00263 
00264             int csize = collection.size();
00265             if( csize == 0 ) {
00266                 return false;
00267             }
00268 
00269             std::vector<E> array = collection.toArray();
00270 
00271             if( index == 0 ) {
00272                 this->expandFront( csize );
00273             } else if( index == this->curSize ) {
00274                 this->expandEnd( csize );
00275             } else {
00276                 this->expandMiddle( index, csize );
00277             }
00278 
00279             for( int i = 0; i < csize; ++i, ++this->curSize ) {
00280                 this->elements[index++] = array[i];
00281             }
00282 
00283             AbstractList<E>::modCount++;
00284 
00285             return true;
00286         }
00287 
00288         virtual bool remove( const E& value ) {
00289 
00290             int result = indexOf( value );
00291             if( result != -1 ) {
00292                 this->removeAt( result );
00293                 return true;
00294             }
00295 
00296             return false;
00297         }
00298 
00299         virtual E removeAt( int index ) {
00300 
00301             if( index < 0 || index >= this->curSize ) {
00302                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00303                     __FILE__, __LINE__,
00304                     "List::removeAt - Index greater than size() or negative" );
00305             }
00306 
00307             E old = this->elements[index];
00308 
00309             System::arraycopy( this->elements, 0, this->elements, 0, index );
00310 
00311             if( this->curSize > index ) {
00312                 System::arraycopy( this->elements, index + 1, this->elements, index, this->curSize - index - 1 );
00313             }
00314 
00315             this->elements[--this->curSize] = E();
00316             AbstractList<E>::modCount++;
00317 
00318             return old;
00319         }
00320 
00321         virtual bool contains( const E& value ) const {
00322             return this->indexOf( value ) != -1;
00323         }
00324 
00325         virtual int indexOf( const E& value ) const {
00326 
00327             for( int i = 0; i < this->curSize; ++i ) {
00328                 if( this->elements[i] == value ) {
00329                     return i;
00330                 }
00331             }
00332 
00333             return -1;
00334         }
00335 
00336         virtual int lastIndexOf( const E& value ) const {
00337 
00338             for( int i = this->curSize - 1; i >= 0 ; --i ) {
00339                 if( this->elements[i] == value ) {
00340                     return i;
00341                 }
00342             }
00343 
00344             return -1;
00345         }
00346 
00347         virtual std::vector<E> toArray() const {
00348 
00349             std::vector<E> result;
00350 
00351             for( int i = 0; i < this->curSize; ++i ) {
00352                 result.push_back( this->elements[i] );
00353             }
00354 
00355             return result;
00356         }
00357 
00358         virtual std::string toString() const {
00359 
00360             std::string result;
00361 
00362             result.append( "decaf::util::ArrayList [  size = " );
00363             result.append( decaf::lang::Integer::toString( this->curSize ) );
00364             result.append( " ]");
00365 
00366             return result;
00367         }
00368 
00369     private:
00370 
00371         void expandFront( int amount ) {
00372 
00373             if( amount == 0 ) {
00374                 return;
00375             }
00376 
00377             E* previous = this->elements;
00378 
00379             if( amount > this->capacity - this->curSize ) {
00380                 this->capacity = this->capacity + amount + 11;
00381                 this->elements = new E[this->capacity];
00382             }
00383 
00384             if( this->curSize > 0 ) {
00385                 System::arraycopy( previous, 0, this->elements, amount, this->curSize );
00386             }
00387 
00388             if( previous != this->elements ) {
00389                 delete [] previous;
00390             }
00391         }
00392 
00393         void expandEnd( int amount ) {
00394 
00395             if( amount == 0 ) {
00396                 return;
00397             }
00398 
00399             E* previous = this->elements;
00400 
00401             if( amount > this->capacity - this->curSize ) {
00402                 this->capacity = this->capacity + amount + 11;
00403                 this->elements = new E[this->capacity];
00404                 System::arraycopy( previous, 0, this->elements, 0, this->curSize );
00405             }
00406 
00407             if( previous != this->elements ) {
00408                 delete [] previous;
00409             }
00410         }
00411 
00412         void expandMiddle( int index, int amount ) {
00413 
00414             if( amount == 0 ) {
00415                 return;
00416             }
00417 
00418             E* previous = this->elements;
00419 
00420             if( amount > this->capacity - this->curSize ) {
00421                 this->capacity = this->capacity + amount + 11;
00422                 this->elements = new E[this->capacity];
00423             }
00424 
00425             if( this->curSize > 0 ) {
00426                 System::arraycopy( previous, 0, this->elements, 0, index );
00427             }
00428 
00429             if( this->curSize > index ) {
00430                 System::arraycopy( previous, index, this->elements, index + amount, this->curSize - index );
00431             }
00432 
00433             if( previous != this->elements ) {
00434                 delete [] previous;
00435             }
00436         }
00437 
00438     };
00439 
00440 }}
00441 
00442 #endif /* _DECAF_UTIL_ARRAYLIST_H_ */