[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

array_vector.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2002-2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 #ifndef VIGRA_ARRAY_VECTOR_HXX
37 #define VIGRA_ARRAY_VECTOR_HXX
38 
39 #include "error.hxx"
40 #include "memory.hxx"
41 #include "numerictraits.hxx"
42 #include <memory>
43 #include <algorithm>
44 #include <iosfwd>
45 
46 #ifdef VIGRA_CHECK_BOUNDS
47 #define VIGRA_ASSERT_INSIDE(diff) \
48  vigra_precondition(diff >= 0, "Index out of bounds");\
49  vigra_precondition(diff < (difference_type)size_, "Index out of bounds");
50 #else
51 #define VIGRA_ASSERT_INSIDE(diff)
52 #endif
53 
54 namespace vigra
55 {
56 
57 template <class T, class Alloc = std::allocator<T> >
59 
60 /** Provide STL conforming interface for C-arrays.
61 
62  This template implements much of the functionality of <a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a>
63  on top of a C-array. <tt>ArrayVectorView</tt> does not manage the memory
64  it refers to (i.e. it does not allocate or deallocate any memory).
65  Thus, if the underlying memory changes, all dependent <tt>ArrayVectorView</tt>
66  objects are invalidated. This is especially important when <tt>ArrayVectorView</tt>
67  is used as a base class for <tt>ArrayVector</tt>, where several functions
68  (e.g. resize(), insert()) can allocate new memory and thus invalidate the
69  dependent views. The rules what operations invalidate view objects are the
70  same as the rules concerning standard iterators.
71 
72  <b>\#include</b> <vigra/array_vector.hxx><br>
73  Namespace: vigra
74 */
75 template <class T>
77 {
79 
80 public:
81  /** default constructor
82  */
83  typedef T value_type;
84  typedef value_type & reference;
85  typedef value_type const & const_reference;
86  typedef value_type * pointer;
87  typedef value_type const * const_pointer;
88  typedef value_type * iterator;
89  typedef value_type const * const_iterator;
90  typedef std::size_t size_type;
91  typedef std::ptrdiff_t difference_type;
92  typedef std::reverse_iterator<iterator> reverse_iterator;
93  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
94 
95 public:
96  /** default constructor.
97  View contains NULL pointer.
98  */
100  : size_(0),
101  data_(0)
102  {}
103 
104  /** Construct for given array \a data of length \a size.
105  <tt>data, data+size</tt> must form a valid range.
106  */
107  ArrayVectorView( size_type size, pointer const & data)
108  : size_(size),
109  data_(data)
110  {}
111 
112  /** Copy constructor.
113  */
114  ArrayVectorView( this_type const & rhs )
115  : size_(rhs.size_),
116  data_(rhs.data_)
117  {}
118 
119  /** Copy assignment. There are 3 cases:
120 
121  <ul>
122  <li> When this <tt>ArrayVectorView</tt> does not point to valid data
123  (e.g. after default construction), it becomes a copy of \a rhs.
124  <li> When the shapes of the two arrays match, the array contents
125  (not the pointers) are copied.
126  <li> Otherwise, a <tt>PreconditionViolation</tt> exception is thrown.
127  </ul>
128  */
129  ArrayVectorView & operator=( ArrayVectorView const & rhs );
130 
131  /** Copy assignment.
132  When the shapes of the two arrays match, the array contents
133  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
134  exception is thrown.
135  */
136  template <class U>
138  {
139  copyImpl(rhs);
140  return *this;
141  }
142 
143  /** Overwrite all array elements with the value \a initial.
144  */
145  template <class U>
146  void init(U const & initial)
147  {
148  std::fill(begin(), end(), initial);
149  }
150 
151  /** Copy array elements.
152  When the shapes of the two arrays match, the array contents
153  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
154  exception is thrown.
155  */
156  void copy( this_type const & rhs )
157  {
158  if(data_ != rhs.data_)
159  copyImpl(rhs);
160  }
161 
162  /** Copy array elements.
163  When the shapes of the two arrays match, the array contents
164  (not the pointers) are copied. Otherwise, a <tt>PreconditionViolation</tt>
165  exception is thrown.
166  */
167  template <class U>
168  void copy( ArrayVectorView<U> const & rhs )
169  {
170  copyImpl(rhs);
171  }
172 
173  /** Swap array elements.
174  When the shapes of the two arrays match, the array contents
175  (not the pointers) are swapped. Otherwise, a <tt>PreconditionViolation</tt>
176  exception is thrown.
177  */
178  void swapData(this_type rhs)
179  {
180  if(data_ != rhs.data_)
181  swapDataImpl(rhs);
182  }
183 
184  /** Swap array elements.
185  When the shapes of the two arrays match, the array contents
186  (not the pointers) are swapped. Otherwise, a <tt>PreconditionViolation</tt>
187  exception is thrown.
188  */
189  template <class U>
191  {
192  swapDataImpl(rhs);
193  }
194 
195  /** Construct <tt>ArrayVectorView</tt> referring to a subarray.
196  \a begin and \a end must be a valid sub-range of the current array.
197  Otherwise, a <tt>PreconditionViolation</tt>
198  exception is thrown.
199  */
200  this_type subarray (size_type begin, size_type end) const
201  {
202  vigra_precondition(begin <= end && end <= size_,
203  "ArrayVectorView::subarray(): Limits out of range.");
204  return this_type(end-begin, data_ + begin);
205  }
206 
207  /** Get contained const pointer to the data.
208  */
209  inline const_pointer data() const
210  {
211  return data_;
212  }
213 
214  /** Get contained pointer to the data.
215  */
216  inline pointer data()
217  {
218  return data_;
219  }
220 
221  /** Get const iterator referring to the first array element.
222  */
223  inline const_iterator begin() const
224  {
225  return data();
226  }
227 
228  /** Get iterator referring to the first array element.
229  */
230  inline iterator begin()
231  {
232  return data();
233  }
234 
235  /** Get const iterator pointing beyond the last array element.
236  */
237  inline const_iterator end() const
238  {
239  return data() + size();
240  }
241 
242  /** Get iterator pointing beyond the last array element.
243  */
244  inline iterator end()
245  {
246  return data() + size();
247  }
248 
249  /** Get const iterator referring to the first array element.
250  */
251  inline const_iterator cbegin() const
252  {
253  return data();
254  }
255 
256  /** Get const iterator pointing beyond the last array element.
257  */
258  inline const_iterator cend() const
259  {
260  return data() + size();
261  }
262 
263  /** Get reverse iterator referring to the last array element.
264  */
265  inline reverse_iterator rbegin()
266  {
267  return (reverse_iterator(end()));
268  }
269 
270  /** Get const reverse iterator referring to the last array element.
271  */
272  inline const_reverse_iterator rbegin() const
273  {
274  return (const_reverse_iterator(end()));
275  }
276 
277  /** Get reverse iterator pointing before the first array element.
278  */
279  inline reverse_iterator rend()
280  {
281  return (reverse_iterator(begin()));
282  }
283 
284  /** Get const reverse iterator pointing before the first array element.
285  */
286  inline const_reverse_iterator rend() const
287  {
288  return (const_reverse_iterator(begin()));
289  }
290 
291  /** Get const reverse iterator referring to the last array element.
292  */
293  inline const_reverse_iterator crbegin() const
294  {
295  return (const_reverse_iterator(end()));
296  }
297 
298  /** Get const reverse iterator pointing before the first array element.
299  */
300  inline const_reverse_iterator crend() const
301  {
302  return (const_reverse_iterator(begin()));
303  }
304 
305  /** Access first array element.
306  */
307  reference front()
308  {
309  return *data_;
310  }
311 
312  /** Read first array element.
313  */
314  const_reference front() const
315  {
316  return *data_;
317  }
318 
319  /** Access last array element.
320  */
321  reference back()
322  {
323  return data_[size_-1];
324  }
325 
326  /** Read last array element.
327  */
328  const_reference back() const
329  {
330  return data_[size_-1];
331  }
332 
333  /** Access array element \a i.
334  */
335  reference operator[]( difference_type i )
336  {
337  VIGRA_ASSERT_INSIDE(i);
338  return data()[i];
339  }
340 
341  /** Read array element \a i.
342  */
343  const_reference operator[]( difference_type i ) const
344  {
345  VIGRA_ASSERT_INSIDE(i);
346  return data()[i];
347  }
348 
349  /** Equivalent to <tt>size() == 0</tt>.
350  */
351  bool empty() const
352  {
353  return size_ == 0;
354  }
355 
356  /** Number of elements in the array.
357  */
358  size_type size() const
359  {
360  return size_;
361  }
362 
363  /** Check for element-wise equality of two array.
364  Also returns <tt>false</tt> if the two arrays have different sizes.
365  */
366  template <class U>
367  bool operator==(ArrayVectorView<U> const & rhs) const;
368 
369  /** check whether two arrays are not elementwise equal.
370  Also returns <tt>true</tt> if the two arrays have different sizes.
371  */
372  template <class U>
373  bool operator!=(ArrayVectorView<U> const & rhs) const
374  {
375  return !operator==(rhs);
376  }
377 
378  /** check whether the given point is in the array range.
379  */
380  bool isInside (difference_type const & p) const
381  {
382  return p >= 0 && p < size_;
383  }
384 
385  protected:
386 
387  template <class U>
388  void copyImpl(const ArrayVectorView <U>& rhs);
389 
390  void copyImpl(const ArrayVectorView & rhs);
391 
392  template <class U>
393  void swapDataImpl(const ArrayVectorView <U>& rhs);
394 
395  size_type size_;
396  pointer data_;
397 };
398 
399 template <class T>
400 ArrayVectorView<T> & ArrayVectorView<T>::operator=( ArrayVectorView<T> const & rhs )
401 {
402  if(data_ == 0)
403  {
404  size_ = rhs.size_;
405  data_ = rhs.data_;
406  }
407  else if(data_ != rhs.data_)
408  copyImpl(rhs);
409  return *this;
410 }
411 
412 template <class T>
413 template <class U>
415 {
416  if(size() != rhs.size())
417  return false;
418  for(size_type k=0; k<size(); ++k)
419  if(data_[k] != rhs[k])
420  return false;
421  return true;
422 }
423 
424 template <class T>
425 void
427 {
428  vigra_precondition (size() == rhs.size(),
429  "ArrayVectorView::copy(): shape mismatch.");
430  if(size() == 0) // needed because MSVC debug assertions in std::copy() may fire
431  return; // "invalid address: data_ == NULL" even when nothing is to be copied
432  // use copy() or copy_backward() according to possible overlap of this and rhs
433  if(data_ <= rhs.data())
434  {
435  std::copy(rhs.begin(), rhs.end(), begin());
436  }
437  else
438  {
439  std::copy_backward(rhs.begin(), rhs.end(), end());
440  }
441 }
442 
443 template <class T>
444 template <class U>
445 void
446 ArrayVectorView <T>::copyImpl(const ArrayVectorView <U>& rhs)
447 {
448  vigra_precondition (size() == rhs.size(),
449  "ArrayVectorView::copy(): shape mismatch.");
450  std::copy(rhs.begin(), rhs.end(), begin());
451 }
452 
453 template <class T>
454 template <class U>
455 void
456 ArrayVectorView <T>::swapDataImpl(const ArrayVectorView <U>& rhs)
457 {
458  vigra_precondition (size () == rhs.size() (),
459  "ArrayVectorView::swapData(): size mismatch.");
460 
461  // check for overlap
462  if(data_ + size_ <= rhs.data_ || rhs.data_ + size_ <= data_)
463  {
464  for(size_type k=0; k<size_; ++k)
465  std::swap(data_[k], rhs.data_[k]);
466  }
467  else
468  {
469  ArrayVector<T> t(*this);
470  copyImpl(rhs);
471  rhs.copyImpl(t);
472  }
473 }
474 
475 
476 /** Replacement for <tt>std::vector</tt>.
477 
478  This template implements the same functionality as <tt><a href="http://www.sgi.com/tech/stl/Vector.html">std::vector</a></tt> (see there for detailed documentation).
479  However, it gives two useful guarantees, that <tt>std::vector</tt> fails
480  to provide:
481 
482  <ul>
483  <li>The memory is always allocated as one contiguous piece.</li>
484  <li>The iterator is always a <TT>T *</TT> </li>
485  </ul>
486 
487  This means that memory managed by <tt>ArrayVector</tt> can be passed
488  to algorithms that expect raw memory. This is especially important
489  when legacy or C code has to be called, but it is also useful for certain
490  optimizations.
491 
492  Moreover, <tt>ArrayVector</tt> is derived from <tt>ArrayVectorView</tt> so that one
493  can create views of the array (in particular, subarrays). This implies another
494  important difference to <tt>std::vector</tt>: the indexing operator
495  (<tt>ArrayVector::operator[]</tt>) takes <tt>signed</tt> indices. In this way,
496  an <tt>ArrayVectorView</tt> can be used with negative indices:
497 
498  \code
499  ArrayVector<int> data(100);
500  ArrayVectorView<int> view = data.subarray(50, 100);
501 
502  view[-50] = 1; // valid access
503  \endcode
504 
505  Refer to the documentation of <tt>std::vector</tt> for a detailed
506  description of <tt>ArrayVector</tt> functionality.
507 
508  <b>\#include</b> <vigra/array_vector.hxx><br>
509  Namespace: vigra
510 */
511 template <class T, class Alloc /* = std::allocator<T> */ >
512 class ArrayVector
513 : public ArrayVectorView<T>
514 {
515  typedef ArrayVector<T, Alloc> this_type;
516  enum { minimumCapacity = 2, resizeFactor = 2 };
517 
518 public:
519  typedef ArrayVectorView<T> view_type;
520  typedef typename view_type::value_type value_type;
521  typedef typename view_type::reference reference;
522  typedef typename view_type::const_reference const_reference;
523  typedef typename view_type::pointer pointer;
524  typedef typename view_type::const_pointer const_pointer;
525  typedef typename view_type::iterator iterator;
526  typedef typename view_type::const_iterator const_iterator;
527  typedef typename view_type::size_type size_type;
528  typedef typename view_type::difference_type difference_type;
529  typedef typename view_type::reverse_iterator reverse_iterator;
530  typedef typename view_type::const_reverse_iterator const_reverse_iterator;
531  typedef Alloc allocator_type;
532 
533 public:
534  ArrayVector()
535  : view_type(),
536  capacity_(minimumCapacity),
537  alloc_(Alloc())
538  {
539  this->data_ = reserve_raw(capacity_);
540  }
541 
542  explicit ArrayVector(Alloc const & alloc)
543  : view_type(),
544  capacity_(minimumCapacity),
545  alloc_(alloc)
546  {
547  this->data_ = reserve_raw(capacity_);
548  }
549 
550  explicit ArrayVector( size_type size, Alloc const & alloc = Alloc())
551  : view_type(),
552  alloc_(alloc)
553  {
554  initImpl(size, value_type(), VigraTrueType());
555  }
556 
557  ArrayVector( size_type size, value_type const & initial, Alloc const & alloc = Alloc())
558  : view_type(),
559  alloc_(alloc)
560  {
561  initImpl(size, initial, VigraTrueType());
562  }
563 
564 
565  ArrayVector( this_type const & rhs )
566  : view_type(),
567  alloc_(rhs.alloc_)
568  {
569  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
570  }
571 
572  template <class U>
573  explicit ArrayVector( ArrayVectorView<U> const & rhs, Alloc const & alloc = Alloc() )
574  : view_type(),
575  alloc_(alloc)
576  {
577  initImpl(rhs.begin(), rhs.end(), VigraFalseType());
578  }
579 
580  template <class InputIterator>
581  ArrayVector(InputIterator i, InputIterator end)
582  {
583  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
584  }
585 
586  template <class InputIterator>
587  ArrayVector(InputIterator i, InputIterator end, Alloc const & alloc)
588  : alloc_(alloc)
589  {
590  initImpl(i, end, typename NumericTraits<InputIterator>::isIntegral());
591  }
592 
593  this_type & operator=( this_type const & rhs )
594  {
595  if(this == &rhs)
596  return *this;
597  if(this->size_ == rhs.size_)
598  this->copyImpl(rhs);
599  else
600  {
601  ArrayVector t(rhs);
602  this->swap(t);
603  }
604  return *this;
605  }
606 
607  template <class U>
608  this_type & operator=( ArrayVectorView<U> const & rhs);
609 
610  ~ArrayVector()
611  {
612  deallocate(this->data_, this->size_, this->capacity_);
613  }
614 
615  void pop_back();
616 
617  void push_back( value_type const & t );
618 
619  iterator insert(iterator p, value_type const & v);
620 
621  iterator insert(iterator p, size_type n, value_type const & v);
622 
623  template <class InputIterator>
624  iterator insert(iterator p, InputIterator i, InputIterator iend);
625 
626  iterator erase(iterator p);
627 
628  iterator erase(iterator p, iterator q);
629 
630  void clear();
631 
632  pointer reserveImpl( bool dealloc, size_type new_capacity );
633 
634  pointer reserveImpl( bool dealloc);
635 
636  void reserve()
637  {
638  reserveImpl(true);
639  }
640 
641  void reserve( size_type new_capacity )
642  {
643  reserveImpl(true, new_capacity);
644  }
645 
646  void resize( size_type new_size, value_type const & initial );
647 
648  void resize( size_type new_size )
649  {
650  resize(new_size, value_type());
651  }
652 
653  size_type capacity() const
654  {
655  return capacity_;
656  }
657 
658  void swap(this_type & rhs);
659 
660  private:
661 
662  void deallocate(pointer data, size_type size, size_type capacity);
663 
664  pointer reserve_raw(size_type capacity);
665 
666  void initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/);
667 
668  template <class Iter>
669  void initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/);
670 
671  template <class Iter>
672  void initImpl( Iter i, Iter end, Error_NumericTraits_not_specialized_for_this_case)
673  {
674  initImpl(i, end, VigraFalseType());
675  }
676 
677  size_type capacity_;
678  Alloc alloc_;
679 };
680 
681 template <class T, class Alloc>
682 template <class U>
683 ArrayVector<T, Alloc> & ArrayVector<T, Alloc>::operator=( ArrayVectorView<U> const & rhs )
684 {
685  if(this->size_ == rhs.size())
686  this->copyImpl(rhs);
687  else
688  {
689  ArrayVector t(rhs);
690  this->swap(t);
691  }
692  return *this;
693 }
694 
695 template <class T, class Alloc>
696 inline void ArrayVector<T, Alloc>::pop_back()
697 {
698  --this->size_;
699  alloc_.destroy(this->data_ + this->size_);
700 }
701 
702 template <class T, class Alloc>
703 inline void ArrayVector<T, Alloc>::push_back( value_type const & t )
704 {
705  size_type old_capacity = this->capacity_;
706  pointer old_data = reserveImpl(false);
707  alloc_.construct(this->data_ + this->size_, t);
708  // deallocate old data _after_ construction of new element, so that
709  // 't' can refer to the old data as in 'push_back(front())'
710  deallocate(old_data, this->size_, old_capacity);
711  ++this->size_;
712 }
713 
714 template <class T, class Alloc>
715 inline void ArrayVector<T, Alloc>::clear()
716 {
717  detail::destroy_n(this->data_, this->size_);
718  this->size_ = 0;
719 }
720 
721 template <class T, class Alloc>
722 typename ArrayVector<T, Alloc>::iterator
723 ArrayVector<T, Alloc>::insert(iterator p, value_type const & v)
724 {
725  difference_type pos = p - this->begin();
726  if(p == this->end())
727  {
728  push_back(v);
729  p = this->begin() + pos;
730  }
731  else
732  {
733  T lastElement = this->back();
734  push_back(lastElement);
735  p = this->begin() + pos;
736  std::copy_backward(p, this->end() - 2, this->end() - 1);
737  *p = v;
738  }
739  return p;
740 }
741 
742 template <class T, class Alloc>
743 typename ArrayVector<T, Alloc>::iterator
744 ArrayVector<T, Alloc>::insert(iterator p, size_type n, value_type const & v)
745 {
746  difference_type pos = p - this->begin();
747  size_type new_size = this->size() + n;
748  if(new_size > capacity_)
749  {
750  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
751  pointer new_data = reserve_raw(new_capacity);
752  try
753  {
754  std::uninitialized_copy(this->begin(), p, new_data);
755  std::uninitialized_fill(new_data + pos, new_data + pos + n, v);
756  std::uninitialized_copy(p, this->end(), new_data + pos + n);
757  }
758  catch(...)
759  {
760  alloc_.deallocate(new_data, new_capacity);
761  throw;
762  }
763  deallocate(this->data_, this->size_, this->capacity_);
764  capacity_ = new_capacity;
765  this->data_ = new_data;
766  }
767  else if(pos + n > this->size_)
768  {
769  size_type diff = pos + n - this->size_;
770  std::uninitialized_copy(p, this->end(), this->end() + diff);
771  std::uninitialized_fill(this->end(), this->end() + diff, v);
772  std::fill(p, this->end(), v);
773  }
774  else
775  {
776  size_type diff = this->size_ - (pos + n);
777  std::uninitialized_copy(this->end() - n, this->end(), this->end());
778  std::copy_backward(p, p + diff, this->end());
779  std::fill(p, p + n, v);
780  }
781  this->size_ = new_size;
782  return this->begin() + pos;
783 }
784 
785 template <class T, class Alloc>
786 template <class InputIterator>
787 typename ArrayVector<T, Alloc>::iterator
788 ArrayVector<T, Alloc>::insert(iterator p, InputIterator i, InputIterator iend)
789 {
790  size_type n = std::distance(i, iend);
791  size_type pos = p - this->begin();
792  size_type new_size = this->size() + n;
793  if(new_size > capacity_)
794  {
795  size_type new_capacity = std::max(new_size, resizeFactor*capacity_);
796  pointer new_data = reserve_raw(new_capacity);
797  try
798  {
799  std::uninitialized_copy(this->begin(), p, new_data);
800  std::uninitialized_copy(i, iend, new_data + pos);
801  std::uninitialized_copy(p, this->end(), new_data + pos + n);
802  }
803  catch(...)
804  {
805  alloc_.deallocate(new_data, new_capacity);
806  throw;
807  }
808  deallocate(this->data_, this->size_, this->capacity_);
809  capacity_ = new_capacity;
810  this->data_ = new_data;
811  }
812  else if(pos + n > this->size_)
813  {
814  size_type diff = pos + n - this->size_;
815  std::uninitialized_copy(p, this->end(), this->end() + diff);
816  InputIterator split = i;
817  std::advance(split, n - diff);
818  std::uninitialized_copy(split, iend, this->end());
819  std::copy(i, split, p);
820  }
821  else
822  {
823  size_type diff = this->size_ - (pos + n);
824  std::uninitialized_copy(this->end() - n, this->end(), this->end());
825  std::copy_backward(p, p + diff, this->end());
826  std::copy(i, iend, p);
827  }
828  this->size_ = new_size;
829  return this->begin() + pos;
830 }
831 
832 template <class T, class Alloc>
833 typename ArrayVector<T, Alloc>::iterator
834 ArrayVector<T, Alloc>::erase(iterator p)
835 {
836  std::copy(p+1, this->end(), p);
837  pop_back();
838  return p;
839 }
840 
841 template <class T, class Alloc>
842 typename ArrayVector<T, Alloc>::iterator
843 ArrayVector<T, Alloc>::erase(iterator p, iterator q)
844 {
845  std::copy(q, this->end(), p);
846  difference_type eraseCount = q - p;
847  detail::destroy_n(this->end() - eraseCount, eraseCount);
848  this->size_ -= eraseCount;
849  return p;
850 }
851 
852 template <class T, class Alloc>
853 typename ArrayVector<T, Alloc>::pointer
854 ArrayVector<T, Alloc>::reserveImpl( bool dealloc, size_type new_capacity)
855 {
856  if(new_capacity <= capacity_)
857  return 0;
858  pointer new_data = reserve_raw(new_capacity),
859  old_data = this->data_;
860  if(this->size_ > 0)
861  std::uninitialized_copy(old_data, old_data+this->size_, new_data);
862  this->data_ = new_data;
863  if(!dealloc)
864  {
865  this->capacity_ = new_capacity;
866  return old_data;
867  }
868  deallocate(old_data, this->size_, this->capacity_);
869  this->capacity_ = new_capacity;
870  return 0;
871 }
872 
873 template <class T, class Alloc>
874 inline typename ArrayVector<T, Alloc>::pointer
875 ArrayVector<T, Alloc>::reserveImpl(bool dealloc)
876 {
877  if(capacity_ == 0)
878  return reserveImpl(dealloc, minimumCapacity);
879  else if(this->size_ == capacity_)
880  return reserveImpl(dealloc, resizeFactor*capacity_);
881  else
882  return 0;
883 }
884 
885 template <class T, class Alloc>
886 inline void
887 ArrayVector<T, Alloc>::resize( size_type new_size, value_type const & initial)
888 {
889  if(new_size < this->size_)
890  erase(this->begin() + new_size, this->end());
891  else if(this->size_ < new_size)
892  {
893  insert(this->end(), new_size - this->size(), initial);
894  }
895 }
896 
897 template <class T, class Alloc>
898 inline void
899 ArrayVector<T, Alloc>::initImpl( size_type size, value_type const & initial, VigraTrueType /*isIntegral*/)
900 {
901  this->size_ = size;
902  capacity_ = size;
903  this->data_ = reserve_raw(capacity_);
904  if(this->size_ > 0)
905  std::uninitialized_fill(this->data_, this->data_+this->size_, initial);
906 }
907 
908 template <class T, class Alloc>
909 template <class Iter>
910 inline void
911 ArrayVector<T, Alloc>::initImpl( Iter i, Iter end, VigraFalseType /*isIntegral*/)
912 {
913  this->size_ = std::distance(i, end);
914  capacity_ = this->size_;
915  this->data_ = reserve_raw(capacity_);
916  if(this->size_ > 0)
917  detail::uninitializedCopy(i, end, this->data_);
918 }
919 
920 template <class T, class Alloc>
921 inline void
922 ArrayVector<T, Alloc>::swap(this_type & rhs)
923 {
924  std::swap(this->size_, rhs.size_);
925  std::swap(capacity_, rhs.capacity_);
926  std::swap(this->data_, rhs.data_);
927 }
928 
929 template <class T, class Alloc>
930 inline void
931 ArrayVector<T, Alloc>::deallocate(pointer data, size_type size, size_type capacity)
932 {
933  if(data)
934  {
935  detail::destroy_n(data, size);
936  alloc_.deallocate(data, capacity);
937  }
938 }
939 
940 template <class T, class Alloc>
941 inline typename ArrayVector<T, Alloc>::pointer
942 ArrayVector<T, Alloc>::reserve_raw(size_type capacity)
943 {
944  pointer data = 0;
945  if(capacity)
946  {
947  data = alloc_.allocate(capacity);
948  }
949  return data;
950 }
951 
952 } // namespace vigra
953 
954 namespace std {
955 
956 template <class T>
957 ostream & operator<<(ostream & s, vigra::ArrayVectorView<T> const & a)
958 {
959  for(std::ptrdiff_t k=0; k<(std::ptrdiff_t)a.size()-1; ++k)
960  s << a[k] << ", ";
961  if(a.size())
962  s << a.back();
963  return s;
964 }
965 
966 } // namespace std
967 
968 #undef VIGRA_ASSERT_INSIDE
969 #endif /* VIGRA_ARRAY_VECTOR_HXX */
iterator end()
Definition: array_vector.hxx:244
reference back()
Definition: array_vector.hxx:321
void swapData(this_type rhs)
Definition: array_vector.hxx:178
this_type & operator=(ArrayVectorView< U > const &rhs)
Definition: array_vector.hxx:137
ArrayVectorView(size_type size, pointer const &data)
Definition: array_vector.hxx:107
bool empty() const
Definition: array_vector.hxx:351
Definition: array_vector.hxx:76
const_iterator begin() const
Definition: array_vector.hxx:223
reverse_iterator rend()
Definition: array_vector.hxx:279
const_reverse_iterator crend() const
Definition: array_vector.hxx:300
bool isInside(difference_type const &p) const
Definition: array_vector.hxx:380
const_reverse_iterator rbegin() const
Definition: array_vector.hxx:272
const_reverse_iterator crbegin() const
Definition: array_vector.hxx:293
const_reference back() const
Definition: array_vector.hxx:328
ArrayVectorView & operator=(ArrayVectorView const &rhs)
void copy(ArrayVectorView< U > const &rhs)
Definition: array_vector.hxx:168
reference operator[](difference_type i)
Definition: array_vector.hxx:335
Definition: array_vector.hxx:58
reference front()
Definition: array_vector.hxx:307
ArrayVectorView()
Definition: array_vector.hxx:99
bool operator!=(ArrayVectorView< U > const &rhs) const
Definition: array_vector.hxx:373
void init(U const &initial)
Definition: array_vector.hxx:146
pointer data()
Definition: array_vector.hxx:216
const_reference front() const
Definition: array_vector.hxx:314
this_type subarray(size_type begin, size_type end) const
Definition: array_vector.hxx:200
iterator begin()
Definition: array_vector.hxx:230
const_iterator cend() const
Definition: array_vector.hxx:258
const_iterator cbegin() const
Definition: array_vector.hxx:251
T value_type
Definition: array_vector.hxx:83
void copy(this_type const &rhs)
Definition: array_vector.hxx:156
reverse_iterator rbegin()
Definition: array_vector.hxx:265
const_iterator end() const
Definition: array_vector.hxx:237
const_pointer data() const
Definition: array_vector.hxx:209
size_type size() const
Definition: array_vector.hxx:358
ArrayVectorView(this_type const &rhs)
Definition: array_vector.hxx:114
void swapData(ArrayVectorView< U > rhs)
Definition: array_vector.hxx:190
bool operator==(ArrayVectorView< U > const &rhs) const
Definition: array_vector.hxx:414
const_reference operator[](difference_type i) const
Definition: array_vector.hxx:343
const_reverse_iterator rend() const
Definition: array_vector.hxx:286

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)