2 * Copyright 2002, 2006 Adrian Thurston <thurston@cs.queensu.ca>
5 /* This file is part of Aapl.
7 * Aapl is free software; you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free
9 * Software Foundation; either version 2.1 of the License, or (at your option)
12 * Aapl is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Aapl; if not, write to the Free Software Foundation, Inc., 59
19 * Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifndef _AAPL_VECTOR_H
23 #define _AAPL_VECTOR_H
41 * \brief Dynamic array.
43 * This is typical vector implementation. It is a dynamic array that can be
44 * used to contain complex data structures that have constructors and
45 * destructors as well as simple types such as integers and pointers.
47 * Vector supports inserting, overwriting, and removing single or multiple
48 * elements at once. Constructors and destructors are called wherever
49 * appropriate. For example, before an element is overwritten, it's
50 * destructor is called.
52 * Vector provides automatic resizing of allocated memory as needed and offers
53 * different allocation schemes for controlling how the automatic allocation
54 * is done. Two senses of the the length of the data is maintained: the
55 * amount of raw memory allocated to the vector and the number of actual
56 * elements in the vector. The various allocation schemes control how the
57 * allocated space is changed in relation to the number of elements in the
60 * \include ex_vector.cpp
65 template < class T, class Resize = ResizeExpn > class Vector
66 : public Table<T>, public Resize
69 typedef Table<T> BaseTable;
73 * \brief Initialize an empty vector with no space allocated.
75 * If a linear resizer is used, the step defaults to 256 units of T. For a
76 * runtime vector both up and down allocation schemes default to
82 * \brief Create a vector that contains an initial element.
84 * The vector becomes one element in length. The element's copy
85 * constructor is used to place the value in the vector.
87 Vector(const T &val) { setAs(&val, 1); }
90 * \brief Create a vector that contains an array of elements.
92 * The vector becomes len elements in length. Copy constructors are used
93 * to place the new elements in the vector.
95 Vector(const T *val, long len) { setAs(val, len); }
98 Vector( const Vector &v );
100 /* Free all mem used by the vector. */
101 ~Vector() { empty(); }
103 /* Delete all items. */
106 /* Abandon the contents of the vector without deleteing. */
109 /* Performs a shallow copy of another vector into this vector. If this
110 * vector is non-empty then its contents are lost (not freed). */
111 void shallowCopy( const Vector &v );
113 /* Perform a deep copy of another vector into this vector. */
114 Vector &operator=( const Vector &v );
119 * \brief Insert one element at position pos.
121 * Elements in the vector from pos onward are shifted one space to the
122 * right. The copy constructor is used to place the element into this
123 * vector. If pos is greater than the length of the vector then undefined
124 * behaviour results. If pos is negative then it is treated as an offset
125 * relative to the length of the vector.
127 void insert(long pos, const T &val) { insert(pos, &val, 1); }
129 /* Insert an array of values. */
130 void insert(long pos, const T *val, long len);
133 * \brief Insert all the elements from another vector at position pos.
135 * Elements in this vector from pos onward are shifted v.tabLen spaces to
136 * the right. The element's copy constructor is used to copy the items
137 * into this vector. The other vector is left unchanged. If pos is off the
138 * end of the vector, then undefined behaviour results. If pos is negative
139 * then it is treated as an offset relative to the length of the vector.
140 * Equivalent to vector.insert(pos, other.data, other.tabLen).
142 void insert(long pos, const Vector &v) { insert(pos, v.data, v.tabLen); }
144 /* Insert len copies of val into the vector. */
145 void insertDup(long pos, const T &val, long len);
148 * \brief Insert one new element using the default constrcutor.
150 * Elements in the vector from pos onward are shifted one space to the
151 * right. The default constructor is used to init the new element. If pos
152 * is greater than the length of the vector then undefined behaviour
153 * results. If pos is negative then it is treated as an offset relative to
154 * the length of the vector.
156 void insertNew(long pos) { insertNew(pos, 1); }
158 /* Insert len new items using default constructor. */
159 void insertNew(long pos, long len);
164 * \brief Remove one element at position pos.
166 * The element's destructor is called. Elements to the right of pos are
167 * shifted one space to the left to take up the free space. If pos is greater
168 * than or equal to the length of the vector then undefined behavior results.
169 * If pos is negative then it is treated as an offset relative to the length
172 void remove(long pos) { remove(pos, 1); }
174 /* Delete a number of elements. */
175 void remove(long pos, long len);
180 * \brief Replace one element at position pos.
182 * If there is an existing element at position pos (if pos is less than
183 * the length of the vector) then its destructor is called before the
184 * space is used. The copy constructor is used to place the element into
185 * the vector. If pos is greater than the length of the vector then
186 * undefined behaviour results. If pos is negative then it is treated as
187 * an offset relative to the length of the vector.
189 void replace(long pos, const T &val) { replace(pos, &val, 1); }
191 /* Replace with an array of values. */
192 void replace(long pos, const T *val, long len);
195 * \brief Replace at position pos with all the elements of another vector.
197 * Replace at position pos with all the elements of another vector. The
198 * other vector is left unchanged. If there are existing elements at the
199 * positions to be replaced, then destructors are called before the space
200 * is used. Copy constructors are used to place the elements into this
201 * vector. It is allowable for the pos and length of the other vector to
202 * specify a replacement that overwrites existing elements and creates new
203 * ones. If pos is greater than the length of the vector then undefined
204 * behaviour results. If pos is negative, then it is treated as an offset
205 * relative to the length of the vector.
207 void replace(long pos, const Vector &v) { replace(pos, v.data, v.tabLen); }
209 /* Replace len items with len copies of val. */
210 void replaceDup(long pos, const T &val, long len);
213 * \brief Replace at position pos with one new element.
215 * If there is an existing element at the position to be replaced (pos is
216 * less than the length of the vector) then the element's destructor is
217 * called before the space is used. The default constructor is used to
218 * initialize the new element. If pos is greater than the length of the
219 * vector then undefined behaviour results. If pos is negative, then it is
220 * treated as an offset relative to the length of the vector.
222 void replaceNew(long pos) { replaceNew(pos, 1); }
224 /* Replace len items at pos with newly constructed objects. */
225 void replaceNew(long pos, long len);
230 * \brief Set the contents of the vector to be val exactly.
232 * The vector becomes one element in length. Destructors are called on any
233 * existing elements in the vector. The element's copy constructor is used
234 * to place the val in the vector.
236 void setAs(const T &val) { setAs(&val, 1); }
238 /* Set to the contents of an array. */
239 void setAs(const T *val, long len);
242 * \brief Set the vector to exactly the contents of another vector.
244 * The vector becomes v.tabLen elements in length. Destructors are called
245 * on any existing elements. Copy constructors are used to place the new
246 * elements in the vector.
248 void setAs(const Vector &v) { setAs(v.data, v.tabLen); }
250 /* Set as len copies of item. */
251 void setAsDup(const T &item, long len);
254 * \brief Set the vector to exactly one new item.
256 * The vector becomes one element in length. Destructors are called on any
257 * existing elements in the vector. The default constructor is used to
260 void setAsNew() { setAsNew(1); }
262 /* Set as newly constructed objects using the default constructor. */
263 void setAsNew(long len);
268 * \brief Append one elment to the end of the vector.
270 * Copy constructor is used to place the element in the vector.
272 void append(const T &val) { replace(BaseTable::tabLen, &val, 1); }
275 * \brief Append len elements to the end of the vector.
277 * Copy constructors are used to place the elements in the vector.
279 void append(const T *val, long len) { replace(BaseTable::tabLen, val, len); }
282 * \brief Append the contents of another vector.
284 * The other vector is left unchanged. Copy constructors are used to place the
285 * elements in the vector.
287 void append(const Vector &v) { replace(BaseTable::tabLen, v.data, v.tabLen); }
290 * \brief Append len copies of item.
292 * The copy constructor is used to place the item in the vector.
294 void appendDup(const T &item, long len) { replaceDup(BaseTable::tabLen, item, len); }
297 * \brief Append a single newly created item.
299 * The new element is initialized with the default constructor.
301 void appendNew() { replaceNew(BaseTable::tabLen, 1); }
304 * \brief Append len newly created items.
306 * The new elements are initialized with the default constructor.
308 void appendNew(long len) { replaceNew(BaseTable::tabLen, len); }
312 /** \fn Vector::prepend(const T &val)
313 * \brief Prepend one elment to the front of the vector.
315 * Copy constructor is used to place the element in the vector.
317 void prepend(const T &val) { insert(0, &val, 1); }
320 * \brief Prepend len elements to the front of the vector.
322 * Copy constructors are used to place the elements in the vector.
324 void prepend(const T *val, long len) { insert(0, val, len); }
327 * \brief Prepend the contents of another vector.
329 * The other vector is left unchanged. Copy constructors are used to place the
330 * elements in the vector.
332 void prepend(const Vector &v) { insert(0, v.data, v.tabLen); }
335 * \brief Prepend len copies of item.
337 * The copy constructor is used to place the item in the vector.
339 void prependDup(const T &item, long len) { insertDup(0, item, len); }
342 * \brief Prepend a single newly created item.
344 * The new element is initialized with the default constructor.
346 void prependNew() { insertNew(0, 1); }
349 * \brief Prepend len newly created items.
351 * The new elements are initialized with the default constructor.
353 void prependNew(long len) { insertNew(0, len); }
356 /* Convenience access. */
357 T &operator[](int i) const { return BaseTable::data[i]; }
358 long size() const { return BaseTable::tabLen; }
360 /* Forward this so a ref can be used. */
363 /* Various classes for setting the iterator */
364 struct IterFirst { IterFirst( const Vector &v ) : v(v) { } const Vector &v; };
365 struct IterLast { IterLast( const Vector &v ) : v(v) { } const Vector &v; };
366 struct IterNext { IterNext( const Iter &i ) : i(i) { } const Iter &i; };
367 struct IterPrev { IterPrev( const Iter &i ) : i(i) { } const Iter &i; };
370 * \brief Vector Iterator.
375 /* Construct, assign. */
376 Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
379 Iter( const Vector &v );
380 Iter( const IterFirst &vf );
381 Iter( const IterLast &vl );
382 inline Iter( const IterNext &vn );
383 inline Iter( const IterPrev &vp );
386 Iter &operator=( const Vector &v );
387 Iter &operator=( const IterFirst &vf );
388 Iter &operator=( const IterLast &vl );
389 inline Iter &operator=( const IterNext &vf );
390 inline Iter &operator=( const IterPrev &vl );
392 /** \brief Less than end? */
393 bool lte() const { return ptr != ptrEnd; }
395 /** \brief At end? */
396 bool end() const { return ptr == ptrEnd; }
398 /** \brief Greater than beginning? */
399 bool gtb() const { return ptr != ptrBeg; }
401 /** \brief At beginning? */
402 bool beg() const { return ptr == ptrBeg; }
404 /** \brief At first element? */
405 bool first() const { return ptr == ptrBeg+1; }
407 /** \brief At last element? */
408 bool last() const { return ptr == ptrEnd-1; }
410 /* Return the position. */
411 long pos() const { return ptr - ptrBeg - 1; }
412 T &operator[](int i) const { return ptr[i]; }
414 /** \brief Implicit cast to T*. */
415 operator T*() const { return ptr; }
417 /** \brief Dereference operator returns T&. */
418 T &operator *() const { return *ptr; }
420 /** \brief Arrow operator returns T*. */
421 T *operator->() const { return ptr; }
423 /** \brief Move to next item. */
424 T *operator++() { return ++ptr; }
426 /** \brief Move to next item. */
427 T *operator++(int) { return ptr++; }
429 /** \brief Move to next item. */
430 T *increment() { return ++ptr; }
432 /** \brief Move n items forward. */
433 T *operator+=(long n) { return ptr+=n; }
435 /** \brief Move to previous item. */
436 T *operator--() { return --ptr; }
438 /** \brief Move to previous item. */
439 T *operator--(int) { return ptr--; }
441 /** \brief Move to previous item. */
442 T *decrement() { return --ptr; }
444 /** \brief Move n items back. */
445 T *operator-=(long n) { return ptr-=n; }
447 /** \brief Return the next item. Does not modify this. */
448 inline IterNext next() const { return IterNext(*this); }
450 /** \brief Return the previous item. Does not modify this. */
451 inline IterPrev prev() const { return IterPrev(*this); }
453 /** \brief The iterator is simply a pointer. */
456 /* For testing endpoints. */
460 /** \brief Return first element. */
461 IterFirst first() { return IterFirst( *this ); }
463 /** \brief Return last element. */
464 IterLast last() { return IterLast( *this ); }
467 void makeRawSpaceFor(long pos, long len);
469 void upResize(long len);
470 void downResize(long len);
474 /* Create a vector with an intial number of elements and size. */
475 template<class T, class Resize> Vector<T, Resize>::
476 Vector( long size, long allocLen )
478 /* Allocate the space if we are given a positive allocLen. */
479 BaseTable::allocLen = allocLen;
480 if ( allocLen > 0 ) {
481 BaseTable::data = (T*) malloc(sizeof(T) * BaseTable::allocLen);
482 if ( BaseTable::data == 0 )
483 throw std::bad_alloc();
486 /* Grow to the size specified. If we did not have enough space
487 * allocated that is ok. Table will be grown to right size. */
492 /* Init a vector iterator with just a vector. */
493 template <class T, class Resize> Vector<T, Resize>::Iter::Iter( const Vector &v )
496 ptr = ptrBeg = ptrEnd = 0;
500 ptrEnd = v.data+v.tabLen;
504 /* Init a vector iterator with the first of a vector. */
505 template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
506 const IterFirst &vf )
508 if ( vf.v.tabLen == 0 )
509 ptr = ptrBeg = ptrEnd = 0;
512 ptrBeg = vf.v.data-1;
513 ptrEnd = vf.v.data+vf.v.tabLen;
517 /* Init a vector iterator with the last of a vector. */
518 template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
521 if ( vl.v.tabLen == 0 )
522 ptr = ptrBeg = ptrEnd = 0;
524 ptr = vl.v.data+vl.v.tabLen-1;
525 ptrBeg = vl.v.data-1;
526 ptrEnd = vl.v.data+vl.v.tabLen;
530 /* Init a vector iterator with the next of some other iterator. */
531 template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
540 /* Init a vector iterator with the prev of some other iterator. */
541 template <class T, class Resize> Vector<T, Resize>::Iter::Iter(
550 /* Set a vector iterator with some vector. */
551 template <class T, class Resize> typename Vector<T, Resize>::Iter &
552 Vector<T, Resize>::Iter::operator=( const Vector &v )
555 ptr = ptrBeg = ptrEnd = 0;
559 ptrEnd = v.data+v.tabLen;
564 /* Set a vector iterator with the first element in a vector. */
565 template <class T, class Resize> typename Vector<T, Resize>::Iter &
566 Vector<T, Resize>::Iter::operator=( const IterFirst &vf )
568 if ( vf.v.tabLen == 0 )
569 ptr = ptrBeg = ptrEnd = 0;
572 ptrBeg = vf.v.data-1;
573 ptrEnd = vf.v.data+vf.v.tabLen;
578 /* Set a vector iterator with the last element in a vector. */
579 template <class T, class Resize> typename Vector<T, Resize>::Iter &
580 Vector<T, Resize>::Iter::operator=( const IterLast &vl )
582 if ( vl.v.tabLen == 0 )
583 ptr = ptrBeg = ptrEnd = 0;
585 ptr = vl.v.data+vl.v.tabLen-1;
586 ptrBeg = vl.v.data-1;
587 ptrEnd = vl.v.data+vl.v.tabLen;
592 /* Set a vector iterator with the next of some other iterator. */
593 template <class T, class Resize> typename Vector<T, Resize>::Iter &
594 Vector<T, Resize>::Iter::operator=( const IterNext &vn )
597 ptrBeg = vn.i.ptrBeg;
598 ptrEnd = vn.i.ptrEnd;
602 /* Set a vector iterator with the prev of some other iterator. */
603 template <class T, class Resize> typename Vector<T, Resize>::Iter &
604 Vector<T, Resize>::Iter::operator=( const IterPrev &vp )
607 ptrBeg = vp.i.ptrBeg;
608 ptrEnd = vp.i.ptrEnd;
613 * \brief Forget all elements in the vector.
615 * The contents of the vector are reset to null without without the space
618 template<class T, class Resize> void Vector<T, Resize>::
622 BaseTable::tabLen = 0;
623 BaseTable::allocLen = 0;
627 * \brief Shallow copy another vector into this vector.
629 * The dynamic array of the other vector is copied into this vector by
630 * reference. If this vector is non-empty then its contents are lost. This
631 * routine must be used with care. After a shallow copy one vector should
632 * abandon its contents to prevent both destructors from attempting to free
635 template<class T, class Resize> void Vector<T, Resize>::
636 shallowCopy( const Vector &v )
638 BaseTable::data = v.data;
639 BaseTable::tabLen = v.tabLen;
640 BaseTable::allocLen = v.allocLen;
644 * \brief Deep copy another vector into this vector.
646 * Copies the entire contents of the other vector into this vector. Any
647 * existing contents are first deleted. Equivalent to setAs.
649 * \returns A reference to this.
651 template<class T, class Resize> Vector<T, Resize> &Vector<T, Resize>::
652 operator=( const Vector &v )
654 setAs(v.data, v.tabLen);
658 /* Up resize the data for len elements using Resize::upResize to tell us the
659 * new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
660 template<class T, class Resize> void Vector<T, Resize>::
663 /* Ask the resizer what the new tabLen will be. */
664 long newLen = Resize::upResize(BaseTable::allocLen, len);
666 /* Did the data grow? */
667 if ( newLen > BaseTable::allocLen ) {
668 BaseTable::allocLen = newLen;
669 if ( BaseTable::data != 0 ) {
670 /* Table exists already, resize it up. */
671 BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
672 if ( BaseTable::data == 0 )
673 throw std::bad_alloc();
676 /* Create the data. */
677 BaseTable::data = (T*) malloc( sizeof(T) * newLen );
678 if ( BaseTable::data == 0 )
679 throw std::bad_alloc();
684 /* Down resize the data for len elements using Resize::downResize to determine
685 * the new tabLen. Reads and writes allocLen. Does not read or write tabLen. */
686 template<class T, class Resize> void Vector<T, Resize>::
689 /* Ask the resizer what the new tabLen will be. */
690 long newLen = Resize::downResize( BaseTable::allocLen, len );
692 /* Did the data shrink? */
693 if ( newLen < BaseTable::allocLen ) {
694 BaseTable::allocLen = newLen;
696 /* Simply free the data. */
697 free( BaseTable::data );
701 /* Not shrinking to size zero, realloc it to the smaller size. */
702 BaseTable::data = (T*) realloc( BaseTable::data, sizeof(T) * newLen );
703 if ( BaseTable::data == 0 )
704 throw std::bad_alloc();
710 * \brief Perform a deep copy of the vector.
712 * The contents of the other vector are copied into this vector. This vector
713 * gets the same allocation size as the other vector. All items are copied
714 * using the element's copy constructor.
716 template<class T, class Resize> Vector<T, Resize>::
717 Vector(const Vector<T, Resize> &v)
719 BaseTable::tabLen = v.tabLen;
720 BaseTable::allocLen = v.allocLen;
722 if ( BaseTable::allocLen > 0 ) {
723 /* Allocate needed space. */
724 BaseTable::data = (T*) malloc(sizeof(T) * BaseTable::allocLen);
725 if ( BaseTable::data == 0 )
726 throw std::bad_alloc();
728 /* If there are any items in the src data, copy them in. */
729 T *dst = BaseTable::data, *src = v.data;
730 for (long pos = 0; pos < BaseTable::tabLen; pos++, dst++, src++ )
734 /* Nothing allocated. */
739 /** \fn Vector::~Vector()
740 * \brief Free all memory used by the vector.
742 * The vector is reset to zero elements. Destructors are called on all
743 * elements in the vector. The space allocated for the vector is freed.
748 * \brief Free all memory used by the vector.
750 * The vector is reset to zero elements. Destructors are called on all
751 * elements in the vector. The space allocated for the vector is freed.
753 template<class T, class Resize> void Vector<T, Resize>::
756 if ( BaseTable::data != 0 ) {
757 /* Call All destructors. */
758 T *pos = BaseTable::data;
759 for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
762 /* Free the data space. */
763 free( BaseTable::data );
765 BaseTable::tabLen = BaseTable::allocLen = 0;
770 * \brief Set the contents of the vector to be len elements exactly.
772 * The vector becomes len elements in length. Destructors are called on any
773 * existing elements in the vector. Copy constructors are used to place the
774 * new elements in the vector.
776 template<class T, class Resize> void Vector<T, Resize>::
777 setAs(const T *val, long len)
779 /* Call All destructors. */
781 T *pos = BaseTable::data;
782 for ( i = 0; i < BaseTable::tabLen; pos++, i++ )
785 /* Adjust the allocated length. */
786 if ( len < BaseTable::tabLen )
788 else if ( len > BaseTable::tabLen )
791 /* Set the new data length to exactly len. */
792 BaseTable::tabLen = len;
795 T *dst = BaseTable::data;
797 for ( i = 0; i < len; i++, dst++, src++ )
802 * \brief Set the vector to len copies of item.
804 * The vector becomes len elements in length. Destructors are called on any
805 * existing elements in the vector. The element's copy constructor is used to
806 * copy the item into the vector.
808 template<class T, class Resize> void Vector<T, Resize>::
809 setAsDup(const T &item, long len)
811 /* Call All destructors. */
812 T *pos = BaseTable::data;
813 for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
816 /* Adjust the allocated length. */
817 if ( len < BaseTable::tabLen )
819 else if ( len > BaseTable::tabLen )
822 /* Set the new data length to exactly len. */
823 BaseTable::tabLen = len;
825 /* Copy item in one spot at a time. */
826 T *dst = BaseTable::data;
827 for ( long i = 0; i < len; i++, dst++ )
832 * \brief Set the vector to exactly len new items.
834 * The vector becomes len elements in length. Destructors are called on any
835 * existing elements in the vector. Default constructors are used to init the
838 template<class T, class Resize> void Vector<T, Resize>::
841 /* Call All destructors. */
842 T *pos = BaseTable::data;
843 for ( long i = 0; i < BaseTable::tabLen; pos++, i++ )
846 /* Adjust the allocated length. */
847 if ( len < BaseTable::tabLen )
849 else if ( len > BaseTable::tabLen )
852 /* Set the new data length to exactly len. */
853 BaseTable::tabLen = len;
855 /* Create items using default constructor. */
856 T *dst = BaseTable::data;
857 for ( long i = 0; i < len; i++, dst++ )
863 * \brief Replace len elements at position pos.
865 * If there are existing elements at the positions to be replaced, then
866 * destructors are called before the space is used. Copy constructors are used
867 * to place the elements into the vector. It is allowable for the pos and
868 * length to specify a replacement that overwrites existing elements and
869 * creates new ones. If pos is greater than the length of the vector then
870 * undefined behaviour results. If pos is negative, then it is treated as an
871 * offset relative to the length of the vector.
873 template<class T, class Resize> void Vector<T, Resize>::
874 replace(long pos, const T *val, long len)
879 /* If we are given a negative position to replace at then
880 * treat it as a position relative to the length. */
882 pos = BaseTable::tabLen + pos;
884 /* The end is the one past the last item that we want
888 /* Make sure we have enough space. */
889 if ( endPos > BaseTable::tabLen ) {
892 /* Delete any objects we need to delete. */
893 item = BaseTable::data + pos;
894 for ( i = pos; i < BaseTable::tabLen; i++, item++ )
897 /* We are extending the vector, set the new data length. */
898 BaseTable::tabLen = endPos;
901 /* Delete any objects we need to delete. */
902 item = BaseTable::data + pos;
903 for ( i = pos; i < endPos; i++, item++ )
907 /* Copy data in using copy constructor. */
908 T *dst = BaseTable::data + pos;
910 for ( i = 0; i < len; i++, dst++, src++ )
915 * \brief Replace at position pos with len copies of an item.
917 * If there are existing elements at the positions to be replaced, then
918 * destructors are called before the space is used. The copy constructor is
919 * used to place the element into this vector. It is allowable for the pos and
920 * length to specify a replacement that overwrites existing elements and
921 * creates new ones. If pos is greater than the length of the vector then
922 * undefined behaviour results. If pos is negative, then it is treated as an
923 * offset relative to the length of the vector.
925 template<class T, class Resize> void Vector<T, Resize>::
926 replaceDup(long pos, const T &val, long len)
931 /* If we are given a negative position to replace at then
932 * treat it as a position relative to the length. */
934 pos = BaseTable::tabLen + pos;
936 /* The end is the one past the last item that we want
940 /* Make sure we have enough space. */
941 if ( endPos > BaseTable::tabLen ) {
944 /* Delete any objects we need to delete. */
945 item = BaseTable::data + pos;
946 for ( i = pos; i < BaseTable::tabLen; i++, item++ )
949 /* We are extending the vector, set the new data length. */
950 BaseTable::tabLen = endPos;
953 /* Delete any objects we need to delete. */
954 item = BaseTable::data + pos;
955 for ( i = pos; i < endPos; i++, item++ )
959 /* Copy data in using copy constructor. */
960 T *dst = BaseTable::data + pos;
961 for ( long i = 0; i < len; i++, dst++ )
966 * \brief Replace at position pos with len new elements.
968 * If there are existing elements at the positions to be replaced, then
969 * destructors are called before the space is used. The default constructor is
970 * used to initialize the new elements. It is allowable for the pos and length
971 * to specify a replacement that overwrites existing elements and creates new
972 * ones. If pos is greater than the length of the vector then undefined
973 * behaviour results. If pos is negative, then it is treated as an offset
974 * relative to the length of the vector.
976 template<class T, class Resize> void Vector<T, Resize>::
977 replaceNew(long pos, long len)
982 /* If we are given a negative position to replace at then
983 * treat it as a position relative to the length. */
985 pos = BaseTable::tabLen + pos;
987 /* The end is the one past the last item that we want
991 /* Make sure we have enough space. */
992 if ( endPos > BaseTable::tabLen ) {
995 /* Delete any objects we need to delete. */
996 item = BaseTable::data + pos;
997 for ( i = pos; i < BaseTable::tabLen; i++, item++ )
1000 /* We are extending the vector, set the new data length. */
1001 BaseTable::tabLen = endPos;
1004 /* Delete any objects we need to delete. */
1005 item = BaseTable::data + pos;
1006 for ( i = pos; i < endPos; i++, item++ )
1010 /* Copy data in using copy constructor. */
1011 T *dst = BaseTable::data + pos;
1012 for ( long i = 0; i < len; i++, dst++ )
1017 * \brief Remove len elements at position pos.
1019 * Destructor is called on all elements removed. Elements to the right of pos
1020 * are shifted len spaces to the left to take up the free space. If pos is
1021 * greater than or equal to the length of the vector then undefined behavior
1022 * results. If pos is negative then it is treated as an offset relative to the
1023 * length of the vector.
1025 template<class T, class Resize> void Vector<T, Resize>::
1026 remove(long pos, long len)
1028 long newLen, lenToSlideOver, endPos;
1031 /* If we are given a negative position to remove at then
1032 * treat it as a position relative to the length. */
1034 pos = BaseTable::tabLen + pos;
1036 /* The first position after the last item deleted. */
1039 /* The new data length. */
1040 newLen = BaseTable::tabLen - len;
1042 /* The place in the data we are deleting at. */
1043 dst = BaseTable::data + pos;
1045 /* Call Destructors. */
1047 for ( long i = 0; i < len; i += 1, item += 1 )
1050 /* Shift data over if necessary. */
1051 lenToSlideOver = BaseTable::tabLen - endPos;
1052 if ( len > 0 && lenToSlideOver > 0 )
1053 memmove(dst, dst + len, sizeof(T)*lenToSlideOver);
1055 /* Shrink the data if necessary. */
1056 downResize( newLen );
1058 /* Set the new data length. */
1059 BaseTable::tabLen = newLen;
1063 * \brief Insert len elements at position pos.
1065 * Elements in the vector from pos onward are shifted len spaces to the right.
1066 * The copy constructor is used to place the elements into this vector. If pos
1067 * is greater than the length of the vector then undefined behaviour results.
1068 * If pos is negative then it is treated as an offset relative to the length
1071 template<class T, class Resize> void Vector<T, Resize>::
1072 insert(long pos, const T *val, long len)
1074 /* If we are given a negative position to insert at then
1075 * treat it as a position relative to the length. */
1077 pos = BaseTable::tabLen + pos;
1079 /* Calculate the new length. */
1080 long newLen = BaseTable::tabLen + len;
1082 /* Up resize, we are growing. */
1085 /* Shift over data at insert spot if needed. */
1086 if ( len > 0 && pos < BaseTable::tabLen ) {
1087 memmove(BaseTable::data + pos + len, BaseTable::data + pos,
1088 sizeof(T)*(BaseTable::tabLen-pos));
1091 /* Copy data in element by element. */
1092 T *dst = BaseTable::data + pos;
1094 for ( long i = 0; i < len; i++, dst++, src++ )
1097 /* Set the new length. */
1098 BaseTable::tabLen = newLen;
1102 * \brief Insert len copies of item at position pos.
1104 * Elements in the vector from pos onward are shifted len spaces to the right.
1105 * The copy constructor is used to place the element into this vector. If pos
1106 * is greater than the length of the vector then undefined behaviour results.
1107 * If pos is negative then it is treated as an offset relative to the length
1110 template<class T, class Resize> void Vector<T, Resize>::
1111 insertDup(long pos, const T &item, long len)
1113 /* If we are given a negative position to insert at then
1114 * treat it as a position relative to the length. */
1116 pos = BaseTable::tabLen + pos;
1118 /* Calculate the new length. */
1119 long newLen = BaseTable::tabLen + len;
1121 /* Up resize, we are growing. */
1124 /* Shift over data at insert spot if needed. */
1125 if ( len > 0 && pos < BaseTable::tabLen ) {
1126 memmove(BaseTable::data + pos + len, BaseTable::data + pos,
1127 sizeof(T)*(BaseTable::tabLen-pos));
1130 /* Copy the data item in one at a time. */
1131 T *dst = BaseTable::data + pos;
1132 for ( long i = 0; i < len; i++, dst++ )
1135 /* Set the new length. */
1136 BaseTable::tabLen = newLen;
1140 * \brief Insert len new elements using the default constructor.
1142 * Elements in the vector from pos onward are shifted len spaces to the right.
1143 * Default constructors are used to init the new elements. If pos is off the
1144 * end of the vector then undefined behaviour results. If pos is negative then
1145 * it is treated as an offset relative to the length of the vector.
1147 template<class T, class Resize> void Vector<T, Resize>::
1148 insertNew(long pos, long len)
1150 /* If we are given a negative position to insert at then
1151 * treat it as a position relative to the length. */
1153 pos = BaseTable::tabLen + pos;
1155 /* Calculate the new length. */
1156 long newLen = BaseTable::tabLen + len;
1158 /* Up resize, we are growing. */
1161 /* Shift over data at insert spot if needed. */
1162 if ( len > 0 && pos < BaseTable::tabLen ) {
1163 memmove(BaseTable::data + pos + len, BaseTable::data + pos,
1164 sizeof(T)*(BaseTable::tabLen-pos));
1167 /* Init new data with default constructors. */
1168 T *dst = BaseTable::data + pos;
1169 for ( long i = 0; i < len; i++, dst++ )
1172 /* Set the new length. */
1173 BaseTable::tabLen = newLen;
1176 /* Makes space for len items, Does not init the items in any way. If pos is
1177 * greater than the length of the vector then undefined behaviour results.
1178 * Updates the length of the vector. */
1179 template<class T, class Resize> void Vector<T, Resize>::
1180 makeRawSpaceFor(long pos, long len)
1182 /* Calculate the new length. */
1183 long newLen = BaseTable::tabLen + len;
1185 /* Up resize, we are growing. */
1188 /* Shift over data at insert spot if needed. */
1189 if ( len > 0 && pos < BaseTable::tabLen ) {
1190 memmove(BaseTable::data + pos + len, BaseTable::data + pos,
1191 sizeof(T)*(BaseTable::tabLen-pos));
1194 /* Save the new length. */
1195 BaseTable::tabLen = newLen;
1198 #ifdef AAPL_NAMESPACE
1202 #endif /* _AAPL_VECTOR_H */