00001
00008
00009
00010
00011
00012 #ifndef ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_
00013 #define ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_
00014
00015
00016
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
00031
00032
00033 namespace ecl {
00034
00035
00036
00037
00038
00039 template <typename Type> class Array<Type,DynamicStorage>;
00040
00041 namespace blueprints {
00042
00043 template <typename Type> class ConstantDynamicArray;
00044
00045 }
00046
00047 namespace formatters {
00048
00049 template <typename Type, size_t N> class ArrayFormatter;
00050
00051 }
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
00080
00127 template<typename Type>
00128 class ECL_PUBLIC Array<Type,DynamicStorage> : public BluePrintFactory< Array<Type,DynamicStorage> > {
00129 public:
00130
00131
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
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
00175
00176
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());
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
00216
00217
00218
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
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());
00262 std::copy(array.begin(),array.end(),begin());
00263 }
00264 }
00265
00266
00267
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
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
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
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
00506
00507
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
00528
00536 template <typename OutputStream, typename ElementType>
00537 friend OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,DynamicStorage> &array);
00538
00539
00540
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
00569
00576 template<typename Type>
00577 void Array<Type,DynamicStorage>::initialiseMagicSections() {
00578
00579
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
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
00663
00664
00665 namespace blueprints {
00666
00667
00668
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 }
00743 }
00744
00745
00746 #endif