array_dynamic_mem_check.hpp
Go to the documentation of this file.
1 
8 /*****************************************************************************
9 ** Ifdefs
10 *****************************************************************************/
11 
12 #ifndef ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_
13 #define ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_
14 
15 /*****************************************************************************
16 ** Includes
17 *****************************************************************************/
18 
19 #include <algorithm>
20 #include <cstdlib>
21 #include <cstdio>
22 #include <ecl/config/macros.hpp>
24 #include "../definitions.hpp"
25 #include "../initialiser.hpp"
26 #include "../stencil.hpp"
27 #include "array_mem_check.hpp"
28 
29 /*****************************************************************************
30 ** Namespaces
31 *****************************************************************************/
32 
33 namespace ecl {
34 
35 /*****************************************************************************
36 ** Forward Declarations
37 *****************************************************************************/
38 
39 template <typename Type> class Array<Type,DynamicStorage>;
40 
41 namespace blueprints {
42 
43 template <typename Type> class ConstantDynamicArray;
44 
45 } // namespace blueprints
46 
47 namespace formatters {
48 
49 template <typename Type, size_t N> class ArrayFormatter;
50 
51 } // namespace formatters
52 
61 template<typename Type>
63  public:
72  static blueprints::ConstantDynamicArray<Type> Constant(size_t size, const Type &value) {
73  return blueprints::ConstantDynamicArray<Type>(size,value);
74  }
75  virtual ~BluePrintFactory() {};
76 };
77 
78 /*****************************************************************************
79 ** Interface [Array][Dynamic]
80 *****************************************************************************/
127 template<typename Type>
128 class ECL_PUBLIC Array<Type,DynamicStorage> : public BluePrintFactory< Array<Type,DynamicStorage> > {
129  public:
130  /*********************
131  ** Typedefs
132  **********************/
133  typedef Type value_type;
134  typedef Type* iterator;
135  typedef const Type* const_iterator;
136  typedef Type& reference;
137  typedef const Type& const_reference;
138  typedef std::size_t size_type;
139  typedef std::ptrdiff_t difference_type;
140  typedef std::reverse_iterator<iterator> reverse_iterator;
141  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
146 
147  /*********************
148  ** Constructors
149  **********************/
155  explicit Array() : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) {}
164  explicit Array(const unsigned int reserve_size) :
165  buffer_size(reserve_size),
166  underrun(NULL),
167  buffer(NULL),
168  overrun(NULL)
169  {
170  underrun = (char*) malloc(buffer_size*sizeof(Type)+bufferUnderrunLength()+bufferOverrunLength());
171  ecl_assert_throw(underrun != NULL, StandardException(LOC,MemoryError,"Failed to allocate memory to the dynamic array."));
172  buffer = (Type*) (underrun+bufferUnderrunLength());
173  overrun = (char*) underrun+bufferUnderrunLength()+buffer_size*sizeof(Type);
174  // Leave it uninitialised, just like eigen containers...faster
175 // for ( unsigned int i = 0; i < buffer_size; ++i ) {
176 // buffer[i] = Type();
177 // }
178  initialiseMagicSections();
179  };
187  Array(const Array<Type,DynamicStorage>& array) : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) {
188  if ( array.size() != 0 ) {
189  resize(array.size()); // not really optimal as we do a fill in resize and then copy here, but its debug version anyway.
190  std::copy(array.begin(),array.end(),begin());
191  }
192  }
213  template<typename T>
214  Array(const blueprints::ArrayBluePrint< T > &blueprint) : buffer_size(0), underrun(NULL), buffer(NULL), overrun(NULL) {
215  // Note we're using a partially specialised parent interface here otherwise the
216  // constructor that reserves sizes as well as the comma initialiser won't
217  // conveniently convert types correctly
218  // (e.g. Array<double> array(4); array = 1,2,3,4; will fail)
219  ecl_compile_time_concept_check(BluePrintConcept<T>);
220  blueprint.implementApply(*this);
221  initialiseMagicSections();
222  }
228  ~Array() {
229 
230  if ( underrun != NULL ) {
231  free(underrun);
232  }
233  underrun = NULL;
234  buffer = NULL;
235  overrun = NULL;
236  }
237  /*********************
238  ** Assignment
239  **********************/
255  }
256 
257  void operator=(const Array<Type,DynamicStorage>& array) {
258  if ( array.size() == 0 ) {
259  clear();
260  } else {
261  resize(array.size()); // not really optimal as we do a fill in resize and then copy here, but its debug version anyway.
262  std::copy(array.begin(),array.end(),begin());
263  }
264  }
265 
266  /*********************
267  ** Iterators
268  **********************/
275  iterator begin() {
277  return buffer;
278  }
285  const_iterator begin() const {
286  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
287  return buffer;
288  }
295  iterator end() {
296  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
297  return buffer+buffer_size;
298  }
305  const_iterator end() const {
306  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
307  return buffer+buffer_size;
308  }
315  reverse_iterator rbegin() {
316  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
317  return reverse_iterator(end());
318  }
325  const_reverse_iterator rbegin() const {
326  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
327  return const_reverse_iterator(end());
328  }
335  reverse_iterator rend() {
336  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
337  return reverse_iterator(begin());
338  }
345  const_reverse_iterator rend() const {
346  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
347  return const_reverse_iterator(begin());
348  }
349 
350  /*********************
351  ** Front/Back
352  **********************/
359  reference front() {
360  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
361  return buffer[0];
362  }
369  const_reference front() const {
370  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
371  return buffer[0];
372  }
379  reference back() {
380  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
381  return buffer[buffer_size-1];
382  }
389  const_reference back() const {
390  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
391  return buffer[buffer_size-1];
392  }
393 
394  /*********************
395  ** Accessors
396  **********************/
408  Stencil< Array<Type,DynamicStorage> > stencil(const unsigned int& start_index, const unsigned int& n) {
409  ecl_assert_throw(start_index < size(), StandardException(LOC, OutOfRangeError, "Start index provided is larger than the underlying array size."));
410  ecl_assert_throw(start_index+n <= size(), StandardException(LOC, OutOfRangeError, "Finish index provided is larger than the underlying array size."));
411  return Stencil< Array<Type,DynamicStorage> >(*this, begin()+start_index, begin()+start_index+n);
412  }
422  reference operator[](size_type i) {
423  ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError));
424  return buffer[i];
425  }
437  const_reference operator[](size_type i) const {
438  ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError));
439  return buffer[i];
440  }
451  reference at(size_type i) {
452  if ( i>=buffer_size ) {
453  throw StandardException(LOC,OutOfRangeError);
454  }
455  return buffer[i];
456  }
469  const_reference at(size_type i) const {
470  if ( i>=buffer_size ) {
471  throw StandardException(LOC,OutOfRangeError);
472  }
473  return buffer[i];
474  }
475 
476  /*********************
477  ** Utilities
478  **********************/
486  size_type size() const { return buffer_size; }
487 
496  void resize( size_t n ) {
497  if ( underrun != NULL ) {
498  free(underrun);
499  }
500  buffer_size = n;
501  underrun = (char*) malloc(buffer_size*sizeof(Type)+bufferUnderrunLength()+bufferOverrunLength());
502  ecl_assert_throw(underrun != NULL, StandardException(LOC,MemoryError,"Failed to allocate memory to the dynamic array."));
503  buffer = (Type*) (underrun+bufferUnderrunLength());
504  overrun = (char*) underrun+bufferUnderrunLength()+buffer_size*sizeof(Type);
505  // Leave it uninitialised, just like eigen containers...faster
506 // for ( unsigned int i = 0; i < buffer_size; ++i ) {
507 // buffer[i] = Type();
508 // }
509  initialiseMagicSections();
510  }
516  void clear() {
517  if ( underrun != NULL ) {
518  free(underrun);
519  underrun = NULL;
520  buffer = NULL;
521  overrun = NULL;
522  }
523  buffer_size = 0;
524  }
525 
526  /*********************
527  ** Streaming
528  **********************/
536  template <typename OutputStream, typename ElementType>
537  friend OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,DynamicStorage> &array);
538 
539  /******************************************
540  ** Buffer under/overrun checks
541  *******************************************/
542  bool bufferUnderRun();
543  bool bufferOverRun();
544  bool bufferOverFlow();
545 
546  private:
547  void initialiseMagicSections();
548 
549  static const unsigned int& bufferOverrunLength() {
550  static const unsigned int buffer_overrun_length = 4;
551  return buffer_overrun_length;
552  }
553  static const unsigned int& bufferUnderrunLength() {
554  static const unsigned int buffer_underrun_length = 4;
555  return buffer_underrun_length;
556  }
557  static const char& magicChar() {
558  static const char magic_char = 0xCC;
559  return magic_char;
560  }
561  unsigned int buffer_size;
562  char *underrun;
563  Type *buffer;
564  char *overrun;
565 };
566 
567 /*****************************************************************************
568 ** Implementation [Array][MemCheck]
569 *****************************************************************************/
576 template<typename Type>
578 
579  // Should check that buffer != NULL here, but this isn't user API so just have to guarantee it internally.
580  for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) {
581  *(underrun+i) = magicChar();
582  }
583  for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) {
584  *(overrun+i) = magicChar();
585  }
586 }
595 template<typename Type>
597  if ( underrun != NULL ) {
598  for ( unsigned int i = 0; i < bufferUnderrunLength(); ++i ) {
599  if ( *(underrun+i) != magicChar() ) {
600  return true;
601  }
602  }
603  }
604  return false;
605 }
615 template<typename Type>
617 
618  if ( overrun != NULL ) {
619  for ( unsigned int i = 0; i < bufferOverrunLength(); ++i ) {
620  if ( *(overrun+i) != magicChar() ) {
621  return true;
622  }
623  }
624  }
625  return false;
626 }
627 
637 template<typename Type>
639  return ( bufferOverRun() || bufferUnderRun() );
640 }
641 
642 
643 /*****************************************************************************
644 ** Implementation [Array]
645 *****************************************************************************/
646 
647 template <typename OutputStream, typename ElementType>
648 OutputStream& operator<<(OutputStream &ostream , const Array<ElementType,DynamicStorage> &array) {
649 
650  ostream << "[ ";
651  for(size_t i = 0; i < array.buffer_size; ++i )
652  {
653  ostream << array[i] << " ";
654  }
655  ostream << "]";
656  ostream.flush();
657 
658  return ostream;
659 }
660 
661 /*****************************************************************************
662 ** BluePrints
663 *****************************************************************************/
664 
665 namespace blueprints {
666 
667 /*****************************************************************************
668 ** Interface [ConstantDynamicArray]
669 *****************************************************************************/
670 
678 template <typename Type>
679 class ConstantDynamicArray: public ArrayBluePrint< ConstantDynamicArray<Type> > {
680  public:
691 
701  ConstantDynamicArray(size_t size, const Type &value ) :
703  val(value)
704  {}
705 
706  virtual ~ConstantDynamicArray() {};
707 
720  std::fill_n(array.begin(),reserve_size,val);
721  return array;
722  }
723 
732  void apply(base_type& array) const {
733  array.resize(reserve_size);
734  std::fill_n(array.begin(),reserve_size,val);
735  }
736 
737  private:
738  size_t reserve_size;
739  Type val;
740 };
741 
742 } // namespace blueprints
743 } // namespace ecl
744 
745 
746 #endif /* ECL_CONTAINERS_ARRAY_DYNAMIC_MEM_CHECK_HPP_ */
ecl::blueprints::ConstantDynamicArray::~ConstantDynamicArray
virtual ~ConstantDynamicArray()
Definition: array_dynamic_mem_check.hpp:718
ecl::Array< Type, DynamicStorage >::size_type
std::size_t size_type
Definition: array_dynamic_mem_check.hpp:146
ecl::blueprints::ConstantDynamicArray::base_type
ecl::Array< Type, ecl::DynamicStorage > base_type
Abstract representation of the class to be instantiated/configured.
Definition: array_dynamic_mem_check.hpp:696
ecl_compile_time_concept_check
#define ecl_compile_time_concept_check(Model)
ecl::Array< Type, DynamicStorage >::difference_type
std::ptrdiff_t difference_type
Definition: array_dynamic_mem_check.hpp:147
ecl::Array< Type, DynamicStorage >::bufferOverFlow
bool bufferOverFlow()
Manual handle to check for buffer under/over runs simultaneously.
Definition: array_dynamic_mem_check.hpp:644
ecl::operator<<
OutputStream & operator<<(OutputStream &ostream, Format< std::string > &formatter)
ecl::DynamicStorage
@ DynamicStorage
Definition: definitions.hpp:42
ecl::Array< Type, DynamicStorage >::bufferUnderRun
bool bufferUnderRun()
Manual handle to check for buffer underruns.
Definition: array_dynamic_mem_check.hpp:602
ecl::blueprints::ConstantDynamicArray::apply
void apply(base_type &array) const
Apply the blueprint to configure an existing object.
Definition: array_dynamic_mem_check.hpp:744
ecl::blueprints::ConstantDynamicArray::val
Type val
Definition: array_dynamic_mem_check.hpp:751
ecl::MemoryError
MemoryError
ecl::BluePrintFactory< Array< Type, DynamicStorage > >
Blueprint factory for dynamic arrays.
Definition: array_dynamic_mem_check.hpp:68
ecl::blueprints::ConstantDynamicArray::ConstantDynamicArray
ConstantDynamicArray()
Default constructor.
Definition: array_dynamic_mem_check.hpp:702
array_mem_check.hpp
Fixed size containers with a few bells and whistles.
ecl::blueprints::ConstantDynamicArray::reserve_size
size_t reserve_size
Definition: array_dynamic_mem_check.hpp:750
LOC
#define LOC
ecl::Array< Type, DynamicStorage >::iterator
Type * iterator
Definition: array_dynamic_mem_check.hpp:142
blueprints.hpp
ecl::StandardException
ecl::blueprints::ConstantDynamicArray::instantiate
base_type instantiate()
Instantiate a copy of the object that is blueprinted.
Definition: array_dynamic_mem_check.hpp:730
ecl::blueprints::ConstantDynamicArray
Blueprint for generating a cubic spline satisfying C2 constraints.
Definition: array_dynamic_mem_check.hpp:49
ecl::Array< Type, DynamicStorage >::size
size_type size() const
The size of the array.
Definition: array_dynamic_mem_check.hpp:494
ecl::Array< Type, DynamicStorage >::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: array_dynamic_mem_check.hpp:149
ecl::Array::begin
iterator begin()
Definition: array_no_mem_check.hpp:196
ecl_assert_throw
#define ecl_assert_throw(expression, exception)
ecl::formatters::ArrayFormatter
Pseudo formatter for integral type arrays.
Definition: array_dynamic_mem_check.hpp:55
ecl::Array< Type, DynamicStorage >::end
iterator end()
Definition: array_dynamic_mem_check.hpp:303
ecl::BluePrintFactory
ecl::Array< Type, DynamicStorage >
Dynamic size container with a few bells and whistles.
Definition: array_dynamic_mem_check.hpp:134
ecl::Array< Type, DynamicStorage >::bufferOverRun
bool bufferOverRun()
Manual handle to check for buffer overruns.
Definition: array_dynamic_mem_check.hpp:622
ecl::Array< Type, DynamicStorage >::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition: array_dynamic_mem_check.hpp:148
ecl::Array< Type, DynamicStorage >::begin
iterator begin()
Definition: array_dynamic_mem_check.hpp:283
ecl::containers::BoundedListInitialiser
Convenience initialiser with bounds checking for fixed size containers.
Definition: initialiser.hpp:61
ecl::Array
Fixed size container with a few bells and whistles.
Definition: array_no_mem_check.hpp:112
macros.hpp
ecl::OutOfRangeError
OutOfRangeError
ecl
Embedded control libraries.
ECL_PUBLIC
#define ECL_PUBLIC
ecl::Array< Type, DynamicStorage >::reference
Type & reference
Definition: array_dynamic_mem_check.hpp:144


ecl_containers
Author(s): Daniel Stonier
autogenerated on Sun Aug 2 2020 03:12:14