00001
00008
00009
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
00018
00019
00020 #include <algorithm>
00021 #include <cstddef>
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
00035
00036
00037 namespace ecl {
00038
00039
00040
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 }
00050
00051 namespace formatters {
00052
00053 template <typename Type, size_t N> class ArrayFormatter;
00054
00055 }
00056
00057
00058
00059
00105 template<typename Type, std::size_t Size = DynamicStorage>
00106 class ECL_PUBLIC Array : public blueprints::ArrayFactory<Type,Size> {
00107 public:
00108
00109
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
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() {};
00161
00162
00163
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
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
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
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
00334
00340 static size_type size() { return Size; }
00341
00342
00343
00344
00352 template <typename OutputStream, typename ElementType, size_t ArraySize>
00353 friend OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,ArraySize> &array);
00354
00355
00356
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
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
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
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 }
00623 }
00624
00625 #endif
00626 #endif