00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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/AtomicInteger.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 >
00051 class ArrayPointer {
00052 private:
00053
00054 struct ArrayData {
00055 private:
00056
00057 ArrayData(const ArrayData&);
00058 ArrayData& operator= (const ArrayData&);
00059
00060 public:
00061
00062 T* value;
00063 int length;
00064 decaf::util::concurrent::atomic::AtomicInteger refs;
00065
00066 ArrayData() : value(NULL), length(0), refs(1) {}
00067 ArrayData(T* value, int length) : value(value), length(length), refs(1) {
00068 if( value != NULL && length <= 0 ) {
00069 throw decaf::lang::exceptions::IllegalArgumentException(
00070 __FILE__, __LINE__, "Non-NULL array pointer cannot have a size <= zero" );
00071 }
00072
00073 if( value == NULL && length > 0 ) {
00074 throw decaf::lang::exceptions::IllegalArgumentException(
00075 __FILE__, __LINE__, "NULL array pointer cannot have a size > zero" );
00076 }
00077 }
00078
00079 bool release() {
00080 if (this->refs.decrementAndGet() < 1) {
00081 return true;
00082 }
00083 return false;
00084 }
00085 };
00086
00087 typedef void (*deletionFuncPtr)(ArrayData* p);
00088
00089 private:
00090
00091 ArrayData* array;
00092
00093
00094 deletionFuncPtr onDelete;
00095
00096 public:
00097
00098 typedef T* PointerType;
00099 typedef T& ReferenceType;
00100 typedef const T& ConstReferenceType;
00101
00102 public:
00103
00110 ArrayPointer() : array(new ArrayData()), onDelete(onDeleteFunc) {}
00111
00119 ArrayPointer(int size) : array(NULL), onDelete(onDeleteFunc) {
00120
00121 if (size == 0) {
00122 return;
00123 }
00124
00125 try {
00126 T* value = new T[size];
00127 this->array = new ArrayData(value, size);
00128 decaf::util::Arrays::fill(value, size, 0, size, T());
00129 } catch (std::exception& ex) {
00130 throw ex;
00131 } catch (...) {
00132 throw std::bad_alloc();
00133 }
00134 }
00135
00146 ArrayPointer(int size, const T& fillWith) : array(NULL), onDelete(onDeleteFunc) {
00147
00148 if (size == 0) {
00149 return;
00150 }
00151
00152 try {
00153 T* value = new T[size];
00154 decaf::util::Arrays::fill(value, size, 0, size, fillWith);
00155 this->array = new ArrayData(value, size);
00156 } catch (std::exception& ex) {
00157 throw ex;
00158 } catch (...) {
00159 throw std::bad_alloc();
00160 }
00161 }
00162
00172 explicit ArrayPointer(const PointerType value, int size) : array(NULL), onDelete(onDeleteFunc) {
00173
00174 try {
00175 this->array = new ArrayData(value, size);
00176 } catch (std::exception& ex) {
00177 throw ex;
00178 } catch (...) {
00179 throw std::bad_alloc();
00180 }
00181 }
00182
00187 ArrayPointer(const ArrayPointer& value) : array(value.array), onDelete(onDeleteFunc) {
00188 this->array->refs.incrementAndGet();
00189 }
00190
00191 virtual ~ArrayPointer() {
00192 if (this->array->release() == true) {
00193 onDelete(this->array);
00194 }
00195 }
00196
00208 void reset(T* value, int size = 0) {
00209 ArrayPointer(value, size).swap(*this);
00210 }
00211
00223 T* release() {
00224 T* temp = this->array->value;
00225 this->array->value = NULL;
00226 this->array->length = 0;
00227 this->array->refs.set(1);
00228 return temp;
00229 }
00230
00239 PointerType get() const {
00240 return this->array->value;
00241 }
00242
00249 int length() const {
00250 return this->array->length;
00251 }
00252
00257 void swap(ArrayPointer& value) {
00258 std::swap(this->array, value.array);
00259 }
00260
00267 ArrayPointer clone() const {
00268
00269 if (this->array->length == 0) {
00270 return ArrayPointer();
00271 }
00272
00273 ArrayPointer copy(this->array->length);
00274 decaf::lang::System::arraycopy(this->array->value, 0, copy.get(), 0, this->array->length);
00275 return copy;
00276 }
00277
00282 ArrayPointer& operator=(const ArrayPointer& right) {
00283 if (this == (void*) &right) {
00284 return *this;
00285 }
00286
00287 ArrayPointer temp(right);
00288 temp.swap(*this);
00289 return *this;
00290 }
00291 template< typename T1>
00292 ArrayPointer& operator=(const ArrayPointer<T1>& right) {
00293 if (this == (void*) &right) {
00294 return *this;
00295 }
00296
00297 ArrayPointer temp(right);
00298 temp.swap(*this);
00299 return *this;
00300 }
00301
00310 ReferenceType operator[](int index) {
00311 if (this->array->value == NULL) {
00312 throw decaf::lang::exceptions::NullPointerException(
00313 __FILE__, __LINE__, "ArrayPointer operator& - Pointee is NULL." );
00314 }
00315
00316 if (index < 0 || this->array->length <= index) {
00317 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00318 __FILE__, __LINE__, "Array Index %d is out of bounds for this array.", this->array->length );
00319 }
00320
00321 return this->array->value[index];
00322 }
00323 ConstReferenceType operator[](int index) const {
00324 if( this->array->value == NULL ) {
00325 throw decaf::lang::exceptions::NullPointerException(
00326 __FILE__, __LINE__, "ArrayPointer operator& - Pointee is NULL." );
00327 }
00328
00329 if( index < 0 || this->array->length <= index ) {
00330 throw decaf::lang::exceptions::IndexOutOfBoundsException(
00331 __FILE__, __LINE__, "Array Index %d is out of bounds for this array.", this->array->length );
00332 }
00333
00334 return this->array->value[index];
00335 }
00336
00337 bool operator!() const {
00338 return this->array->value == NULL;
00339 }
00340
00341 inline friend bool operator==(const ArrayPointer& left, const T* right) {
00342 return left.get() == right;
00343 }
00344
00345 inline friend bool operator==(const T* left, const ArrayPointer& right) {
00346 return left == right.get();
00347 }
00348
00349 inline friend bool operator!=(const ArrayPointer& left, const T* right) {
00350 return left.get() != right;
00351 }
00352
00353 inline friend bool operator!=(const T* left, const ArrayPointer& right) {
00354 return left != right.get();
00355 }
00356
00357 template<typename T1>
00358 bool operator==(const ArrayPointer<T1>& right) const {
00359 return this->array->value == right.get();
00360 }
00361
00362 template<typename T1>
00363 bool operator!=(const ArrayPointer<T1>& right) const {
00364 return this->array->value != right.get();
00365 }
00366
00367 private:
00368
00369
00370 static void onDeleteFunc(ArrayData* value) {
00371 delete [] value->value;
00372 delete value;
00373 }
00374
00375 };
00376
00378 template<typename T, typename U>
00379 inline bool operator==(const ArrayPointer<T>& left, const U* right) {
00380 return left.get() == right;
00381 }
00382
00384 template<typename T, typename U>
00385 inline bool operator==(const U* left, const ArrayPointer<T>& right) {
00386 return right.get() == left;
00387 }
00388
00390 template<typename T, typename U>
00391 inline bool operator!=(const ArrayPointer<T>& left, const U* right) {
00392 return !(left.get() == right);
00393 }
00394
00396 template<typename T, typename U>
00397 inline bool operator!=(const U* left, const ArrayPointer<T>& right) {
00398 return right.get() != left;
00399 }
00400
00410 template< typename T >
00411 class ArrayPointerComparator : public decaf::util::Comparator< ArrayPointer<T> > {
00412 public:
00413
00414 virtual ~ArrayPointerComparator() {}
00415
00416
00417
00418 virtual bool operator() ( const ArrayPointer<T>& left, const ArrayPointer<T>& right ) const {
00419 return left.get() < right.get();
00420 }
00421
00422
00423 virtual int compare(const ArrayPointer<T>& left, const ArrayPointer<T>& right) const {
00424 return left.get() < right.get() ? -1 : right.get() < left.get() ? 1 : 0;
00425 }
00426
00427 };
00428
00429 }}
00430
00432 namespace std{
00433
00438 template< typename T >
00439 struct less< decaf::lang::ArrayPointer<T> > {
00440
00441 typedef decaf::lang::ArrayPointer<T> first_argument_type;
00442 typedef decaf::lang::ArrayPointer<T> second_argument_type;
00443 typedef bool result_type;
00444
00445 bool operator()(const decaf::lang::ArrayPointer<T>& left,
00446 const decaf::lang::ArrayPointer<T>& right) const {
00447 return less<T*>()(left.get(), right.get());
00448 }
00449 };
00450 }
00451
00452 #endif