$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_CONTAINERS_ARRAY_MEM_CHECK_HPP_ 00013 #define ECL_CONTAINERS_ARRAY_MEM_CHECK_HPP_ 00014 #ifdef ECL_MEM_CHECK_ARRAYS 00015 00016 /***************************************************************************** 00017 ** Includes 00018 *****************************************************************************/ 00019 00020 #include <algorithm> // std::copy 00021 #include <cstddef> // size_t 00022 #include <iterator> 00023 #include "../definitions.hpp" 00024 #include "../initialiser.hpp" 00025 #include "../stencil.hpp" 00026 #include <ecl/config/macros.hpp> 00027 #include <ecl/concepts/macros.hpp> 00028 #include <ecl/concepts/blueprints.hpp> 00029 #include <ecl/concepts/streams.hpp> 00030 #include <ecl/errors/compile_time_assert.hpp> 00031 #include <ecl/exceptions/standard_exception.hpp> 00032 00033 /***************************************************************************** 00034 ** Namespaces 00035 *****************************************************************************/ 00036 00037 namespace ecl { 00038 00039 /***************************************************************************** 00040 ** Forward Declarations 00041 *****************************************************************************/ 00042 00043 namespace blueprints { 00044 00045 template <typename Type, size_t N> class ArrayFactory; 00046 template <typename Derived> class ArrayBluePrint; 00047 template <typename Type, size_t Size> class ConstantArray; 00048 00049 } // namespace blueprints 00050 00051 namespace formatters { 00052 00053 template <typename Type, size_t N> class ArrayFormatter; 00054 00055 } // namespace formatters 00056 00057 /***************************************************************************** 00058 ** Interface [Array][Fixed] 00059 *****************************************************************************/ 00105 template<typename Type, std::size_t Size = DynamicStorage> 00106 class ECL_PUBLIC Array : public blueprints::ArrayFactory<Type,Size> { 00107 public: 00108 /********************* 00109 ** Typedefs 00110 **********************/ 00111 typedef Type value_type; 00112 typedef Type* iterator; 00113 typedef const Type* const_iterator; 00114 typedef Type& reference; 00115 typedef const Type& const_reference; 00116 typedef std::size_t size_type; 00117 typedef std::ptrdiff_t difference_type; 00118 typedef std::reverse_iterator<iterator> reverse_iterator; 00119 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00120 typedef blueprints::ArrayFactory<value_type,Size> Factory; 00121 typedef formatters::ArrayFormatter<Type,Size> Formatter; 00123 /********************* 00124 ** Constructors 00125 **********************/ 00130 Array() { initialiseMagicSections(); }; 00153 template<typename T> 00154 Array(const blueprints::ArrayBluePrint< T > &blueprint) { 00155 ecl_compile_time_concept_check(BluePrintConcept<T>); 00156 blueprint.implementApply(*this); 00157 initialiseMagicSections(); 00158 } 00159 00160 virtual ~Array() {}; // The user should manually check these in the classes that hold them. 00161 00162 /********************* 00163 ** Assignment 00164 **********************/ 00178 containers::BoundedListInitialiser<Type,Type*,Size> operator<<(const Type &value) { 00179 return containers::BoundedListInitialiser<value_type,iterator,Size>(value,elements); 00180 } 00181 00182 /********************* 00183 ** Iterators 00184 **********************/ 00189 iterator begin() { return elements; } 00194 const_iterator begin() const { return elements; } 00199 iterator end() { return elements+Size; } 00204 const_iterator end() const { return elements+Size; } 00209 reverse_iterator rbegin() { return reverse_iterator(end()); } 00214 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } 00219 reverse_iterator rend() { return reverse_iterator(begin()); } 00224 const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } 00225 00226 /********************* 00227 ** Front/Back 00228 **********************/ 00233 reference front() { return elements[0]; } 00238 const_reference front() const { return elements[0]; } 00243 reference back() { return elements[Size-1]; } 00248 const_reference back() const { return elements[Size-1]; } 00249 00250 /********************* 00251 ** Accessors 00252 **********************/ 00264 Stencil< Array<Type,Size> > stencil(const unsigned int& start_index, const unsigned int& n) ecl_assert_throw_decl(StandardException) { 00265 ecl_assert_throw(start_index < Size, StandardException(LOC, OutOfRangeError, "Start index provided is larger than the underlying array size.")); 00266 ecl_assert_throw(start_index+n <= Size, StandardException(LOC, OutOfRangeError, "Finish index provided is larger than the underlying array size.")); 00267 return Stencil< Array<Type,Size> >(*this, begin()+start_index, begin()+start_index+n); 00268 } 00278 reference operator[](size_type i) ecl_assert_throw_decl(StandardException) { 00279 ecl_assert_throw( i<Size, StandardException(LOC,OutOfRangeError)); 00280 return elements[i]; 00281 } 00293 const_reference operator[](size_type i) const ecl_assert_throw_decl(StandardException) { 00294 ecl_assert_throw( i<Size, StandardException(LOC,OutOfRangeError)); 00295 return elements[i]; 00296 } 00307 reference at(size_type i) throw(StandardException) { 00308 if ( i>=Size ) { 00309 throw StandardException(LOC,OutOfRangeError); 00310 } 00311 return elements[i]; 00312 } 00325 const_reference at(size_type i) const throw(StandardException) { 00326 if ( i>=Size ) { 00327 throw StandardException(LOC,OutOfRangeError); 00328 } 00329 return elements[i]; 00330 } 00331 00332 /********************* 00333 ** Utilities 00334 **********************/ 00340 static size_type size() { return Size; } 00341 00342 /********************* 00343 ** Streaming 00344 **********************/ 00352 template <typename OutputStream, typename ElementType, size_t ArraySize> 00353 friend OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,ArraySize> &array); 00354 00355 /****************************************** 00356 ** Buffer under/overrun checks 00357 *******************************************/ 00358 bool bufferUnderRun(); 00359 bool bufferOverRun(); 00360 bool bufferOverFlow(); 00361 00362 private: 00363 void initialiseMagicSections(); 00364 00365 static const unsigned int& bufferOverrunLength() { 00366 static const unsigned int buffer_overrun_length = 4; 00367 return buffer_overrun_length; 00368 } 00369 static const unsigned int& bufferUnderrunLength() { 00370 static const unsigned int buffer_underrun_length = 4; 00371 return buffer_underrun_length; 00372 } 00373 static const char& magicChar() { 00374 static const char magic_char = 0xCC; 00375 return magic_char; 00376 } 00377 char underrun[4]; 00378 value_type elements[Size]; 00379 char overrun[4]; 00380 }; 00381 00382 /***************************************************************************** 00383 ** Implementation [Array] 00384 *****************************************************************************/ 00391 template<typename Type, size_t Size> 00392 void Array<Type,Size>::initialiseMagicSections() { 00393 00394 for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) { 00395 underrun[i] = magicChar(); 00396 } 00397 for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) { 00398 overrun[i] = magicChar(); 00399 } 00400 00401 } 00411 template<typename Type, size_t Size> 00412 bool Array<Type,Size>::bufferOverRun() { 00413 00414 for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) { 00415 if ( overrun[i] != magicChar() ) { 00416 return true; 00417 } 00418 } 00419 return false; 00420 } 00421 00430 template<typename Type, size_t Size> 00431 bool Array<Type,Size>::bufferUnderRun() { 00432 for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) { 00433 if ( underrun[i] != magicChar() ) { 00434 return true; 00435 } 00436 } 00437 return false; 00438 } 00448 template<typename Type, size_t Size> 00449 bool Array<Type,Size>::bufferOverFlow() { 00450 return ( bufferOverRun() || bufferUnderRun() ); 00451 } 00452 00453 00454 /***************************************************************************** 00455 ** Implementation [Array][Streaming] 00456 *****************************************************************************/ 00457 00458 template <typename OutputStream, typename ElementType, size_t ArraySize> 00459 OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,ArraySize> &array) { 00460 00461 ecl_compile_time_concept_check(StreamConcept<OutputStream>); 00462 00463 ostream << "[ "; 00464 for(size_t i = 0; i < ArraySize; ++i ) 00465 { 00466 ostream << array[i] << " "; 00467 } 00468 ostream << "]"; 00469 ostream.flush(); 00470 00471 return ostream; 00472 } 00473 00474 /***************************************************************************** 00475 ** BluePrints 00476 *****************************************************************************/ 00477 00478 namespace blueprints { 00479 00504 template <typename Derived> 00505 class ArrayBluePrint { 00506 public: 00519 template <typename BaseType> 00520 BaseType implementInstantiate() { 00521 return static_cast<Derived*>(this)->instantiate(); 00522 } 00536 template <typename BaseType> 00537 void implementApply(BaseType& array) const { 00538 static_cast<const Derived*>(this)->apply(array); 00539 } 00540 00541 virtual ~ArrayBluePrint() {} 00542 }; 00551 template <typename Type, size_t Size> 00552 class ConstantArray : public ArrayBluePrint< ConstantArray<Type, Size> > { 00553 public: 00557 typedef ecl::Array<Type,Size> base_type; 00566 ConstantArray(const Type& value = 0) : val(value) {} 00567 00568 virtual ~ConstantArray() {}; 00569 00580 base_type instantiate() { 00581 ecl::Array<Type,Size> array; 00582 std::fill_n(array.begin(),Size,val); 00583 return array; 00584 } 00585 00590 void apply(base_type& array) const { 00591 std::fill_n(array.begin(),Size,val); 00592 } 00593 00594 private: 00595 const Type& val; 00596 }; 00597 00606 template<typename Type, size_t Size> 00607 class ArrayFactory { 00608 public: 00615 static ConstantArray<Type,Size> Constant(const Type& value) { 00616 return ConstantArray<Type,Size>(value); 00617 } 00618 00619 virtual ~ArrayFactory() {}; 00620 }; 00621 00622 } // namespace blueprints 00623 } // namespace ecl 00624 00625 #endif /* ECL_MEM_CHECK_ARRAYS */ 00626 #endif /* ECL_CONTAINERS_ARRAY_MEM_CHECK_HPP_ */