$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_ 00013 #define ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_ 00014 00015 /***************************************************************************** 00016 ** Includes 00017 *****************************************************************************/ 00018 00019 #include <algorithm> 00020 #include <cstdlib> 00021 #include <cstdio> 00022 #include <ecl/config/macros.hpp> 00023 #include <ecl/utilities/blueprints.hpp> 00024 #include "../definitions.hpp" 00025 #include "../initialiser.hpp" 00026 #include "../stencil.hpp" 00027 #include "array_mem_check.hpp" 00028 00029 /***************************************************************************** 00030 ** Namespaces 00031 *****************************************************************************/ 00032 00033 namespace ecl { 00034 00035 /***************************************************************************** 00036 ** Forward Declarations 00037 *****************************************************************************/ 00038 00039 template <typename Type> class Array<Type,DynamicStorage>; 00040 00041 namespace blueprints { 00042 00043 template <typename Type> class ConstantDynamicArray; 00044 00045 } // namespace blueprints 00046 00047 namespace formatters { 00048 00049 template <typename Type, size_t N> class ArrayFormatter; 00050 00051 } // namespace formatters 00052 00061 template<typename Type> 00062 class ECL_PUBLIC BluePrintFactory< Array<Type,DynamicStorage> > { 00063 public: 00072 static blueprints::ConstantDynamicArray<Type> Constant(size_t size, const Type &value) { 00073 return blueprints::ConstantDynamicArray<Type>(size,value); 00074 } 00075 virtual ~BluePrintFactory() {}; 00076 }; 00077 00078 /***************************************************************************** 00079 ** Interface [Array][Dynamic] 00080 *****************************************************************************/ 00127 template<typename Type> 00128 class ECL_PUBLIC Array<Type,DynamicStorage> : public BluePrintFactory< Array<Type,DynamicStorage> > { 00129 public: 00130 /********************* 00131 ** Typedefs 00132 **********************/ 00133 typedef Type value_type; 00134 typedef Type* iterator; 00135 typedef const Type* const_iterator; 00136 typedef Type& reference; 00137 typedef const Type& const_reference; 00138 typedef std::size_t size_type; 00139 typedef std::ptrdiff_t difference_type; 00140 typedef std::reverse_iterator<iterator> reverse_iterator; 00141 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00142 typedef formatters::ArrayFormatter<Type,DynamicStorage> Formatter; 00145 typedef BluePrintFactory< Array<Type,DynamicStorage> > Factory; 00146 00147 /********************* 00148 ** Constructors 00149 **********************/ 00155 explicit Array() : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) {} 00164 explicit Array(const unsigned int reserve_size) ecl_assert_throw_decl(StandardException) : 00165 buffer_size(reserve_size), 00166 underrun(NULL), 00167 buffer(NULL), 00168 overrun(NULL) 00169 { 00170 underrun = (char*) malloc(buffer_size*sizeof(Type)+bufferUnderrunLength()+bufferOverrunLength()); 00171 ecl_assert_throw(underrun != NULL, StandardException(LOC,MemoryError,"Failed to allocate memory to the dynamic array.")); 00172 buffer = (Type*) (underrun+bufferUnderrunLength()); 00173 overrun = (char*) underrun+bufferUnderrunLength()+buffer_size*sizeof(Type); 00174 // Leave it uninitialised, just like eigen containers...faster 00175 // for ( unsigned int i = 0; i < buffer_size; ++i ) { 00176 // buffer[i] = Type(); 00177 // } 00178 initialiseMagicSections(); 00179 }; 00187 Array(const Array<Type,DynamicStorage>& array) : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) { 00188 if ( array.size() != 0 ) { 00189 resize(array.size()); // not really optimal as we do a fill in resize and then copy here, but its debug version anyway. 00190 std::copy(array.begin(),array.end(),begin()); 00191 } 00192 } 00213 template<typename T> 00214 Array(const blueprints::ArrayBluePrint< T > &blueprint) : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) { 00215 // Note we're using a partially specialised parent interface here otherwise the 00216 // constructor that reserves sizes as well as the comma initialiser won't 00217 // conveniently convert types correctly 00218 // (e.g. Array<double> array(4); array = 1,2,3,4; will fail) 00219 ecl_compile_time_concept_check(BluePrintConcept<T>); 00220 blueprint.implementApply(*this); 00221 initialiseMagicSections(); 00222 } 00228 ~Array() ecl_assert_throw_decl(StandardException) { 00229 00230 if ( underrun != NULL ) { 00231 free(underrun); 00232 } 00233 underrun = NULL; 00234 buffer = NULL; 00235 overrun = NULL; 00236 } 00237 /********************* 00238 ** Assignment 00239 **********************/ 00253 containers::BoundedListInitialiser<value_type,iterator,DynamicStorage> operator<<(const Type &value) { 00254 return containers::BoundedListInitialiser<value_type,iterator,DynamicStorage>(value,buffer,buffer_size); 00255 } 00256 00257 void operator=(const Array<Type,DynamicStorage>& array) { 00258 if ( array.size() == 0 ) { 00259 clear(); 00260 } else { 00261 resize(array.size()); // not really optimal as we do a fill in resize and then copy here, but its debug version anyway. 00262 std::copy(array.begin(),array.end(),begin()); 00263 } 00264 } 00265 00266 /********************* 00267 ** Iterators 00268 **********************/ 00275 iterator begin() ecl_assert_throw_decl(StandardException) { 00276 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00277 return buffer; 00278 } 00285 const_iterator begin() const ecl_assert_throw_decl(StandardException) { 00286 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00287 return buffer; 00288 } 00295 iterator end() ecl_assert_throw_decl(StandardException) { 00296 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00297 return buffer+buffer_size; 00298 } 00305 const_iterator end() const ecl_assert_throw_decl(StandardException) { 00306 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00307 return buffer+buffer_size; 00308 } 00315 reverse_iterator rbegin() ecl_assert_throw_decl(StandardException) { 00316 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00317 return reverse_iterator(end()); 00318 } 00325 const_reverse_iterator rbegin() const ecl_assert_throw_decl(StandardException) { 00326 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00327 return const_reverse_iterator(end()); 00328 } 00335 reverse_iterator rend() ecl_assert_throw_decl(StandardException) { 00336 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00337 return reverse_iterator(begin()); 00338 } 00345 const_reverse_iterator rend() const ecl_assert_throw_decl(StandardException) { 00346 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00347 return const_reverse_iterator(begin()); 00348 } 00349 00350 /********************* 00351 ** Front/Back 00352 **********************/ 00359 reference front() ecl_assert_throw_decl(StandardException) { 00360 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00361 return buffer[0]; 00362 } 00369 const_reference front() const ecl_assert_throw_decl(StandardException) { 00370 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00371 return buffer[0]; 00372 } 00379 reference back() ecl_assert_throw_decl(StandardException) { 00380 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00381 return buffer[buffer_size-1]; 00382 } 00389 const_reference back() const ecl_assert_throw_decl(StandardException) { 00390 ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) ); 00391 return buffer[buffer_size-1]; 00392 } 00393 00394 /********************* 00395 ** Accessors 00396 **********************/ 00408 Stencil< Array<Type,DynamicStorage> > stencil(const unsigned int& start_index, const unsigned int& n) ecl_assert_throw_decl(StandardException) { 00409 ecl_assert_throw(start_index < size(), StandardException(LOC, OutOfRangeError, "Start index provided is larger than the underlying array size.")); 00410 ecl_assert_throw(start_index+n <= size(), StandardException(LOC, OutOfRangeError, "Finish index provided is larger than the underlying array size.")); 00411 return Stencil< Array<Type,DynamicStorage> >(*this, begin()+start_index, begin()+start_index+n); 00412 } 00422 reference operator[](size_type i) ecl_assert_throw_decl(StandardException) { 00423 ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError)); 00424 return buffer[i]; 00425 } 00437 const_reference operator[](size_type i) const ecl_assert_throw_decl(StandardException) { 00438 ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError)); 00439 return buffer[i]; 00440 } 00451 reference at(size_type i) throw(StandardException) { 00452 if ( i>=buffer_size ) { 00453 throw StandardException(LOC,OutOfRangeError); 00454 } 00455 return buffer[i]; 00456 } 00469 const_reference at(size_type i) const throw(StandardException) { 00470 if ( i>=buffer_size ) { 00471 throw StandardException(LOC,OutOfRangeError); 00472 } 00473 return buffer[i]; 00474 } 00475 00476 /********************* 00477 ** Utilities 00478 **********************/ 00486 size_type size() const { return buffer_size; } 00487 00496 void resize( size_t n ) ecl_assert_throw_decl(StandardException) { 00497 if ( underrun != NULL ) { 00498 free(underrun); 00499 } 00500 buffer_size = n; 00501 underrun = (char*) malloc(buffer_size*sizeof(Type)+bufferUnderrunLength()+bufferOverrunLength()); 00502 ecl_assert_throw(underrun != NULL, StandardException(LOC,MemoryError,"Failed to allocate memory to the dynamic array.")); 00503 buffer = (Type*) (underrun+bufferUnderrunLength()); 00504 overrun = (char*) underrun+bufferUnderrunLength()+buffer_size*sizeof(Type); 00505 // Leave it uninitialised, just like eigen containers...faster 00506 // for ( unsigned int i = 0; i < buffer_size; ++i ) { 00507 // buffer[i] = Type(); 00508 // } 00509 initialiseMagicSections(); 00510 } 00516 void clear() { 00517 if ( underrun != NULL ) { 00518 free(underrun); 00519 underrun = NULL; 00520 buffer = NULL; 00521 overrun = NULL; 00522 } 00523 buffer_size = 0; 00524 } 00525 00526 /********************* 00527 ** Streaming 00528 **********************/ 00536 template <typename OutputStream, typename ElementType> 00537 friend OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,DynamicStorage> &array); 00538 00539 /****************************************** 00540 ** Buffer under/overrun checks 00541 *******************************************/ 00542 bool bufferUnderRun(); 00543 bool bufferOverRun(); 00544 bool bufferOverFlow(); 00545 00546 private: 00547 void initialiseMagicSections(); 00548 00549 static const unsigned int& bufferOverrunLength() { 00550 static const unsigned int buffer_overrun_length = 4; 00551 return buffer_overrun_length; 00552 } 00553 static const unsigned int& bufferUnderrunLength() { 00554 static const unsigned int buffer_underrun_length = 4; 00555 return buffer_underrun_length; 00556 } 00557 static const char& magicChar() { 00558 static const char magic_char = 0xCC; 00559 return magic_char; 00560 } 00561 unsigned int buffer_size; 00562 char *underrun; 00563 Type *buffer; 00564 char *overrun; 00565 }; 00566 00567 /***************************************************************************** 00568 ** Implementation [Array][MemCheck] 00569 *****************************************************************************/ 00576 template<typename Type> 00577 void Array<Type,DynamicStorage>::initialiseMagicSections() { 00578 00579 // Should check that buffer != NULL here, but this isn't user API so just have to guarantee it internally. 00580 for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) { 00581 *(underrun+i) = magicChar(); 00582 } 00583 for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) { 00584 *(overrun+i) = magicChar(); 00585 } 00586 } 00595 template<typename Type> 00596 bool Array<Type,DynamicStorage>::bufferUnderRun() { 00597 if ( underrun != NULL ) { 00598 for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) { 00599 if ( *(underrun+i) != magicChar() ) { 00600 return true; 00601 } 00602 } 00603 } 00604 return false; 00605 } 00615 template<typename Type> 00616 bool Array<Type,DynamicStorage>::bufferOverRun() { 00617 00618 if ( overrun != NULL ) { 00619 for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) { 00620 if ( *(overrun+i) != magicChar() ) { 00621 return true; 00622 } 00623 } 00624 } 00625 return false; 00626 } 00627 00637 template<typename Type> 00638 bool Array<Type,DynamicStorage>::bufferOverFlow() { 00639 return ( bufferOverRun() || bufferUnderRun() ); 00640 } 00641 00642 00643 /***************************************************************************** 00644 ** Implementation [Array] 00645 *****************************************************************************/ 00646 00647 template <typename OutputStream, typename ElementType> 00648 OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,DynamicStorage> &array) { 00649 00650 ostream << "[ "; 00651 for(size_t i = 0; i < array.buffer_size; ++i ) 00652 { 00653 ostream << array[i] << " "; 00654 } 00655 ostream << "]"; 00656 ostream.flush(); 00657 00658 return ostream; 00659 } 00660 00661 /***************************************************************************** 00662 ** BluePrints 00663 *****************************************************************************/ 00664 00665 namespace blueprints { 00666 00667 /***************************************************************************** 00668 ** Interface [ConstantDynamicArray] 00669 *****************************************************************************/ 00670 00678 template <typename Type> 00679 class ConstantDynamicArray: public ArrayBluePrint< ConstantDynamicArray<Type> > { 00680 public: 00684 typedef ecl::Array<Type,ecl::DynamicStorage> base_type; 00690 ConstantDynamicArray() {}; 00691 00701 ConstantDynamicArray(size_t size, const Type &value ) : 00702 reserve_size(size), 00703 val(value) 00704 {} 00705 00706 virtual ~ConstantDynamicArray() {}; 00707 00718 base_type instantiate() { 00719 ecl::Array<Type> array(reserve_size); 00720 std::fill_n(array.begin(),reserve_size,val); 00721 return array; 00722 } 00723 00732 void apply(base_type& array) const { 00733 array.resize(reserve_size); 00734 std::fill_n(array.begin(),reserve_size,val); 00735 } 00736 00737 private: 00738 size_t reserve_size; 00739 Type val; 00740 }; 00741 00742 } // namespace blueprints 00743 } // namespace ecl 00744 00745 00746 #endif /* ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_ */