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)
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 
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 {
287  return buffer;
288  }
295  iterator end() {
297  return buffer+buffer_size;
298  }
305  const_iterator end() const {
307  return buffer+buffer_size;
308  }
315  reverse_iterator rbegin() {
317  return reverse_iterator(end());
318  }
325  const_reverse_iterator rbegin() const {
327  return const_reverse_iterator(end());
328  }
335  reverse_iterator rend() {
337  return reverse_iterator(begin());
338  }
345  const_reverse_iterator rend() const {
347  return const_reverse_iterator(begin());
348  }
349 
350  /*********************
351  ** Front/Back
352  **********************/
359  reference front() {
361  return buffer[0];
362  }
369  const_reference front() const {
371  return buffer[0];
372  }
379  reference back() {
381  return buffer[buffer_size-1];
382  }
389  const_reference back() const {
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) {
424  return buffer[i];
425  }
437  const_reference operator[](size_type i) const {
439  return buffer[i];
440  }
451  reference at(size_type i) throw(StandardException) {
452  if ( i>=buffer_size ) {
454  }
455  return buffer[i];
456  }
469  const_reference at(size_type i) const throw(StandardException) {
470  if ( i>=buffer_size ) {
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 ) :
702  reserve_size(size),
703  val(value)
704  {}
705 
706  virtual ~ConstantDynamicArray() {};
707 
718  base_type instantiate() {
719  ecl::Array<Type> array(reserve_size);
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_ */
Fixed size container with a few bells and whistles.
static const unsigned int & bufferOverrunLength()
Embedded control libraries.
Parent class for array blueprints.
Array(const blueprints::ArrayBluePrint< T > &blueprint)
Blueprint constructor.
const_reference at(size_type i) const
OutputStream & operator<<(OutputStream &ostream, Format< std::string > &formatter)
ConstantDynamicArray(size_t size, const Type &value)
Constructor that properly configures/initialises the blueprint.
void apply(base_type &array) const
Apply the blueprint to configure an existing object.
formatters::ArrayFormatter< Type, DynamicStorage > Formatter
Formatter for this class.
#define LOC
Array(const unsigned int reserve_size)
Reserves storage for the array.
void operator=(const Array< Type, DynamicStorage > &array)
const_reverse_iterator rbegin() const
#define ecl_assert_throw(expression, exception)
void clear()
Clear the array, deleting all storage space previously allocated.
OutOfRangeError
const_reference operator[](size_type i) const
void resize(size_t n)
Resize the array, clearing whatever was in there before.
Pseudo formatter for integral type arrays.
base_type instantiate()
Instantiate a copy of the object that is blueprinted.
size_type size() const
The size of the array.
std::reverse_iterator< iterator > reverse_iterator
Convenience initialiser with bounds checking for fixed size containers.
Definition: initialiser.hpp:49
A safe windowing class that opens onto array-like containers.
#define ecl_compile_time_concept_check(Model)
Blueprint for generating a cubic spline satisfying C2 constraints.
std::reverse_iterator< const_iterator > const_reverse_iterator
static const unsigned int & bufferUnderrunLength()
static blueprints::ConstantDynamicArray< Type > Constant(size_t size, const Type &value)
Generates a constant array of the specified size.
Stencil< Array< Type, DynamicStorage > > stencil(const unsigned int &start_index, const unsigned int &n)
Open a window (stencil) onto the array.
Fixed size containers with a few bells and whistles.
Array(const Array< Type, DynamicStorage > &array)
Copy constructor.
MemoryError
Dynamic size container with a few bells and whistles.
void implementApply(BaseType &array) const
#define ECL_PUBLIC
BluePrintFactory< Array< Type, DynamicStorage > > Factory
Generates blueprints for this class.
ecl::Array< Type, ecl::DynamicStorage > base_type
Abstract representation of the class to be instantiated/configured.


ecl_containers
Author(s): Daniel Stonier
autogenerated on Mon Feb 28 2022 22:18:43