|
activemq-cpp-3.4.0
|
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_*/