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>
23 #include <ecl/utilities/blueprints.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>
62 class ECL_PUBLIC BluePrintFactory< Array<Type,DynamicStorage> > {
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;
142  typedef formatters::ArrayFormatter<Type,DynamicStorage> Formatter;
145  typedef BluePrintFactory< Array<Type,DynamicStorage> > Factory;
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) ecl_assert_throw_decl(StandardException) :
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() ecl_assert_throw_decl(StandardException) {
229 
230  if ( underrun != NULL ) {
231  free(underrun);
232  }
233  underrun = NULL;
234  buffer = NULL;
235  overrun = NULL;
236  }
237  /*********************
238  ** Assignment
239  **********************/
253  containers::BoundedListInitialiser<value_type,iterator,DynamicStorage> operator<<(const Type &value) {
254  return containers::BoundedListInitialiser<value_type,iterator,DynamicStorage>(value,buffer,buffer_size);
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() ecl_assert_throw_decl(StandardException) {
276  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
277  return buffer;
278  }
285  const_iterator begin() const ecl_assert_throw_decl(StandardException) {
286  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
287  return buffer;
288  }
295  iterator end() ecl_assert_throw_decl(StandardException) {
296  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
297  return buffer+buffer_size;
298  }
305  const_iterator end() const ecl_assert_throw_decl(StandardException) {
306  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
307  return buffer+buffer_size;
308  }
315  reverse_iterator rbegin() ecl_assert_throw_decl(StandardException) {
316  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
317  return reverse_iterator(end());
318  }
325  const_reverse_iterator rbegin() const ecl_assert_throw_decl(StandardException) {
326  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
327  return const_reverse_iterator(end());
328  }
335  reverse_iterator rend() ecl_assert_throw_decl(StandardException) {
336  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
337  return reverse_iterator(begin());
338  }
345  const_reverse_iterator rend() const ecl_assert_throw_decl(StandardException) {
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() ecl_assert_throw_decl(StandardException) {
360  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
361  return buffer[0];
362  }
369  const_reference front() const ecl_assert_throw_decl(StandardException) {
370  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
371  return buffer[0];
372  }
379  reference back() ecl_assert_throw_decl(StandardException) {
380  ecl_assert_throw( buffer != NULL, StandardException(LOC,OutOfRangeError) );
381  return buffer[buffer_size-1];
382  }
389  const_reference back() const ecl_assert_throw_decl(StandardException) {
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) ecl_assert_throw_decl(StandardException) {
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) ecl_assert_throw_decl(StandardException) {
423  ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError));
424  return buffer[i];
425  }
437  const_reference operator[](size_type i) const ecl_assert_throw_decl(StandardException) {
438  ecl_assert_throw( i<buffer_size, StandardException(LOC,OutOfRangeError));
439  return buffer[i];
440  }
451  reference at(size_type i) throw(StandardException) {
452  if ( i>=buffer_size ) {
453  throw StandardException(LOC,OutOfRangeError);
454  }
455  return buffer[i];
456  }
469  const_reference at(size_type i) const throw(StandardException) {
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 ) ecl_assert_throw_decl(StandardException) {
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:
684  typedef ecl::Array<Type,ecl::DynamicStorage> base_type;
690  ConstantDynamicArray() {};
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.
bool bufferOverRun()
Manual handle to check for buffer overruns.
ecl_geometry_PUBLIC void resize(Trajectory2D &trajectory, const int &size)
#define LOC
Stringify the line of code you are at.
OutputStream & operator<<(OutputStream &ostream, const Void void_object)
Output stream operator for Void objects.
Definition: void.hpp:76
bool bufferOverFlow()
Manual handle to check for buffer under/over runs simultaneously.
void initialiseMagicSections()
Prepares the array for overrun and underrun detection.
#define ecl_assert_throw(expression, exception)
Debug mode throw with a logical condition check.
OutOfRangeError
ecl_geometry_PUBLIC int size(const Trajectory2D &trajectory)
#define ECL_PUBLIC
#define ecl_assert_throw_decl(exception)
Assure throw exception declaration.
const GenericPointer< typename T::ValueType > T2 value
DynamicStorage
#define ecl_compile_time_concept_check(Model)
Compile time concept checking assertion.
bool bufferUnderRun()
Manual handle to check for buffer underruns.
MatrixFormatter< Derived, Scalar > Formatter
Definition: plugin.hpp:28
MemoryError
Type
iterator begin()


xbot_node
Author(s): Roc, wangpeng@droid.ac.cn
autogenerated on Sat Oct 10 2020 03:28:13