array_dynamic_mem_check.hpp
Go to the documentation of this file.
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_ */


ecl_containers
Author(s): Daniel Stonier (d.stonier@gmail.com)
autogenerated on Thu Jan 2 2014 11:12:25