activemq-cpp-3.4.0

src/main/decaf/lang/ArrayPointer.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_LANG_ARRAYPOINTER_H_
00019 #define _DECAF_LANG_ARRAYPOINTER_H_
00020 
00021 #include <decaf/util/Config.h>
00022 #include <decaf/lang/System.h>
00023 #include <decaf/lang/exceptions/NullPointerException.h>
00024 #include <decaf/lang/exceptions/IndexOutOfBoundsException.h>
00025 #include <decaf/lang/exceptions/IllegalArgumentException.h>
00026 #include <decaf/util/concurrent/atomic/AtomicRefCounter.h>
00027 #include <decaf/util/Comparator.h>
00028 #include <decaf/util/Arrays.h>
00029 #include <memory>
00030 #include <typeinfo>
00031 #include <algorithm>
00032 
00033 namespace decaf {
00034 namespace lang {
00035 
00050     template< typename T, typename REFCOUNTER = decaf::util::concurrent::atomic::AtomicRefCounter >
00051     class ArrayPointer : public REFCOUNTER {
00052     private:
00053 
00054         struct ArrayData {
00055             T* value;
00056             int length;
00057 
00058             ArrayData() : value( NULL ), length( 0 ) {}
00059             ArrayData( T* value, int length ) : value( value ), length( length ) {
00060                 if( value != NULL && length <= 0 ) {
00061                     throw decaf::lang::exceptions::IllegalArgumentException(
00062                         __FILE__, __LINE__, "Non-NULL array pointer cannot have a size <= zero" );
00063                 }
00064 
00065                 if( value == NULL && length > 0 ) {
00066                     throw decaf::lang::exceptions::IllegalArgumentException(
00067                         __FILE__, __LINE__, "NULL array pointer cannot have a size > zero" );
00068                 }
00069             }
00070         };
00071 
00072         typedef void (*deletionFuncPtr)(ArrayData* p);
00073 
00074     private:
00075 
00076         ArrayData* array;
00077 
00078         // Pointer to our internal delete function, allows incompletes.
00079         deletionFuncPtr onDelete;
00080 
00081     public:
00082 
00083         typedef T* PointerType;              // type returned by operator->
00084         typedef T& ReferenceType;            // type returned by operator*
00085         typedef const T& ConstReferenceType; // type returned by const operator*
00086         typedef REFCOUNTER CounterType;      // Type of the Reference Counter
00087 
00088     public:
00089 
00096         ArrayPointer() : REFCOUNTER(), array( new ArrayData() ), onDelete( onDeleteFunc ) {}
00097 
00105         ArrayPointer( int size ) :
00106             REFCOUNTER(), array( NULL ), onDelete( onDeleteFunc ) {
00107 
00108             if( size == 0 ) {
00109                 return;
00110             }
00111 
00112             try{
00113                 T* value = new T[size];
00114                 this->array = new ArrayData( value, size );
00115             } catch( std::exception& ex ) {
00116                 REFCOUNTER::release();
00117                 throw ex;
00118             } catch(...) {
00119                 REFCOUNTER::release();
00120                 throw std::bad_alloc();
00121             }
00122         }
00123 
00134         ArrayPointer( int size, const T& fillWith ) :
00135             REFCOUNTER(), array( NULL ), onDelete( onDeleteFunc ) {
00136 
00137             if( size == 0 ) {
00138                 return;
00139             }
00140 
00141             try{
00142                 T* value = new T[size];
00143                 decaf::util::Arrays::fill( value, size, 0, size, fillWith );
00144                 this->array = new ArrayData( value, size );
00145             } catch( std::exception& ex ) {
00146                 REFCOUNTER::release();
00147                 throw ex;
00148             } catch(...) {
00149                 REFCOUNTER::release();
00150                 throw std::bad_alloc();
00151             }
00152         }
00153 
00163         explicit ArrayPointer( const PointerType value, int size ) :
00164             REFCOUNTER(), array( NULL ), onDelete( onDeleteFunc ) {
00165 
00166             try{
00167                 this->array = new ArrayData( value, size );
00168             } catch( std::exception& ex ) {
00169                 REFCOUNTER::release();
00170                 throw ex;
00171             } catch(...) {
00172                 REFCOUNTER::release();
00173                 throw std::bad_alloc();
00174             }
00175         }
00176 
00181         ArrayPointer( const ArrayPointer& value ) throw() :
00182             REFCOUNTER( value ), array( value.array ), onDelete( onDeleteFunc ) {}
00183 
00184         virtual ~ArrayPointer() throw() {
00185             if( REFCOUNTER::release() == true ) {
00186                 onDelete( this->array );
00187             }
00188         }
00189 
00201         void reset( T* value, int size = 0 ) {
00202             ArrayPointer( value, size ).swap( *this );
00203         }
00204 
00216         T* release() {
00217             T* temp = this->array->value;
00218             this->array->value = NULL;
00219             this->array->length = 0;
00220             return temp;
00221         }
00222 
00231         PointerType get() const {
00232             return this->array->value;
00233         }
00234 
00241         int length() const {
00242             return this->array->length;
00243         }
00244 
00249         void swap( ArrayPointer& value ) throw() {
00250             std::swap( this->array, value.array );
00251             REFCOUNTER::swap( value );
00252         }
00253 
00260         ArrayPointer clone() const {
00261 
00262             if( this->array->length == 0 ){
00263                 return ArrayPointer();
00264             }
00265 
00266             ArrayPointer copy( this->array->length );
00267             decaf::lang::System::arraycopy( this->array->value, 0, copy.get(), 0, this->array->length );
00268             return copy;
00269         }
00270 
00275         ArrayPointer& operator= ( const ArrayPointer& right ) throw() {
00276             if( this == (void*)&right ) {
00277                 return *this;
00278             }
00279 
00280             ArrayPointer temp( right );
00281             temp.swap( *this );
00282             return *this;
00283         }
00284         template< typename T1, typename R1>
00285         ArrayPointer& operator= ( const ArrayPointer<T1, R1>& right ) throw() {
00286             if( this == (void*)&right ) {
00287                 return *this;
00288             }
00289 
00290             ArrayPointer temp( right );
00291             temp.swap( *this );
00292             return *this;
00293         }
00294 
00303         ReferenceType operator[]( int index ) {
00304             if( this->array->value == NULL ) {
00305                 throw decaf::lang::exceptions::NullPointerException(
00306                     __FILE__, __LINE__, "ArrayPointer operator& - Pointee is NULL." );
00307             }
00308 
00309             if( index < 0 || this->array->length <= index ) {
00310                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00311                     __FILE__, __LINE__, "Array Index %d is out of bounds for this array.", this->array->length );
00312             }
00313 
00314             return this->array->value[index];
00315         }
00316         ConstReferenceType operator[]( int index ) const {
00317             if( this->array->value == NULL ) {
00318                 throw decaf::lang::exceptions::NullPointerException(
00319                     __FILE__, __LINE__, "ArrayPointer operator& - Pointee is NULL." );
00320             }
00321 
00322             if( index < 0 || this->array->length <= index ) {
00323                 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00324                     __FILE__, __LINE__, "Array Index %d is out of bounds for this array.", this->array->length );
00325             }
00326 
00327             return this->array->value[index];
00328         }
00329 
00330         bool operator!() const {
00331             return this->array->value == NULL;
00332         }
00333 
00334         inline friend bool operator==( const ArrayPointer& left, const T* right ) {
00335             return left.get() == right;
00336         }
00337 
00338         inline friend bool operator==( const T* left, const ArrayPointer& right ) {
00339             return left == right.get();
00340         }
00341 
00342         inline friend bool operator!=( const ArrayPointer& left, const T* right ) {
00343             return left.get() != right;
00344         }
00345 
00346         inline friend bool operator!=( const T* left, const ArrayPointer& right ) {
00347             return left != right.get();
00348         }
00349 
00350         template< typename T1, typename R1 >
00351         bool operator==( const ArrayPointer<T1, R1>& right ) const {
00352             return this->array->value == right.get();
00353         }
00354 
00355         template< typename T1, typename R1 >
00356         bool operator!=( const ArrayPointer<T1, R1>& right ) const {
00357             return this->array->value != right.get();
00358         }
00359 
00360     private:
00361 
00362         // Internal Static deletion function.
00363         static void onDeleteFunc( ArrayData* value ) {
00364             delete [] value->value;
00365             delete value;
00366         }
00367 
00368     };
00369 
00371     template< typename T, typename R, typename U >
00372     inline bool operator==( const ArrayPointer<T, R>& left, const U* right ) {
00373         return left.get() == right;
00374     }
00375 
00377     template< typename T, typename R, typename U >
00378     inline bool operator==( const U* left, const ArrayPointer<T, R>& right ) {
00379         return right.get() == left;
00380     }
00381 
00383     template< typename T, typename R, typename U >
00384     inline bool operator!=( const ArrayPointer<T, R>& left, const U* right ) {
00385         return !( left.get() == right );
00386     }
00387 
00389     template< typename T, typename R, typename U >
00390     inline bool operator!=( const U* left, const ArrayPointer<T, R>& right ) {
00391         return right.get() != left;
00392     }
00393 
00403     template< typename T, typename R = decaf::util::concurrent::atomic::AtomicRefCounter >
00404     class ArrayPointerComparator : public decaf::util::Comparator< ArrayPointer<T,R> > {
00405     public:
00406 
00407         virtual ~ArrayPointerComparator() {}
00408 
00409         // Allows for operator less on types that implement Comparable or provide
00410         // a workable operator <
00411         virtual bool operator() ( const ArrayPointer<T,R>& left, const ArrayPointer<T,R>& right ) const {
00412             return left.get() < right.get();
00413         }
00414 
00415         // Requires that the type in the pointer is an instance of a Comparable.
00416         virtual int compare( const ArrayPointer<T,R>& left, const ArrayPointer<T,R>& right ) const {
00417             return left.get() < right.get() ? -1 : right.get() < left.get() ? 1 : 0;
00418         }
00419 
00420     };
00421 
00422 }}
00423 
00425 namespace std{
00426 
00431     template< typename T >
00432     struct less< decaf::lang::ArrayPointer<T> > :
00433         public binary_function< decaf::lang::ArrayPointer<T>,
00434                                 decaf::lang::ArrayPointer<T>, bool>
00435     {
00436         bool operator()( const decaf::lang::ArrayPointer<T>& left,
00437                          const decaf::lang::ArrayPointer<T>& right ) const
00438         {
00439             return less<T*>()( left.get(), right.get() );
00440         }
00441     };
00442 }
00443 
00444 #endif /*_DECAF_LANG_ARRAYPOINTER_H_*/