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_SVECTOR_H
23 #define _AAPL_SVECTOR_H
41 * \brief Copy-on-write dynamic array.
43 * SVector is a variant of Vector that employs copy-on-write behaviour. The
44 * SVector copy constructor and = operator make shallow copies. If a vector
45 * that references shared data is modified with insert, replace, append,
46 * prepend, setAs or remove, a new copy is made so as not to interfere with
47 * the shared data. However, shared individual elements may be modified by
48 * bypassing the SVector interface.
50 * SVector is a dynamic array that can be used to contain complex data
51 * structures that have constructors and destructors as well as simple types
52 * such as integers and pointers.
54 * SVector supports inserting, overwriting, and removing single or multiple
55 * elements at once. Constructors and destructors are called wherever
56 * appropriate. For example, before an element is overwritten, it's
57 * destructor is called.
59 * SVector provides automatic resizing of allocated memory as needed and
60 * offers different allocation schemes for controlling how the automatic
61 * allocation is done. Two senses of the the length of the data is
62 * maintained: the amount of raw memory allocated to the vector and the number
63 * of actual elements in the vector. The various allocation schemes control
64 * how the allocated space is changed in relation to the number of elements in
71 template < class T
, class Resize
= ResizeExpn
> class SVector
:
72 public STable
<T
>, public Resize
75 typedef STable
<T
> BaseTable
;
79 * \brief Initialize an empty vector with no space allocated.
81 * If a linear resizer is used, the step defaults to 256 units of T. For a
82 * runtime vector both up and down allocation schemes default to
88 * \brief Create a vector that contains an initial element.
90 * The vector becomes one element in length. The element's copy
91 * constructor is used to place the value in the vector.
93 SVector(const T
&val
) { setAs(&val
, 1); }
96 * \brief Create a vector that contains an array of elements.
98 * The vector becomes len elements in length. Copy constructors are used
99 * to place the new elements in the vector.
101 SVector(const T
*val
, long len
) { setAs(val
, len
); }
104 SVector( const SVector
&v
);
107 * \brief Free all memory used by the vector.
109 * The vector is reset to zero elements. Destructors are called on all
110 * elements in the vector. The space allocated for the vector is freed.
112 ~SVector() { empty(); }
114 /* Delete all items. */
118 * \brief Deep copy another vector into this vector.
120 * Copies the entire contents of the other vector into this vector. Any
121 * existing contents are first deleted. Equivalent to setAs.
123 void deepCopy( const SVector
&v
) { setAs(v
.data
, v
.length()); }
125 /* Perform a shallow copy of another vector. */
126 SVector
&operator=( const SVector
&v
);
131 * \brief Insert one element at position pos.
133 * Elements in the vector from pos onward are shifted one space to the
134 * right. The copy constructor is used to place the element into this
135 * vector. If pos is greater than the length of the vector then undefined
136 * behaviour results. If pos is negative then it is treated as an offset
137 * relative to the length of the vector.
139 void insert(long pos
, const T
&val
) { insert(pos
, &val
, 1); }
141 /* Insert an array of values. */
142 void insert(long pos
, const T
*val
, long len
);
145 * \brief Insert all the elements from another vector at position pos.
147 * Elements in this vector from pos onward are shifted v.length() spaces
148 * to the right. The element's copy constructor is used to copy the items
149 * into this vector. The other vector is left unchanged. If pos is off the
150 * end of the vector, then undefined behaviour results. If pos is negative
151 * then it is treated as an offset relative to the length of the vector.
152 * Equivalent to vector.insert(pos, other.data, other.length()).
154 void insert(long pos
, const SVector
&v
) { insert(pos
, v
.data
, v
.length()); }
156 /* Insert len copies of val into the vector. */
157 void insertDup(long pos
, const T
&val
, long len
);
160 * \brief Insert one new element using the default constrcutor.
162 * Elements in the vector from pos onward are shifted one space to the right.
163 * The default constructor is used to init the new element. If pos is greater
164 * than the length of the vector then undefined behaviour results. If pos is
165 * negative then it is treated as an offset relative to the length of the
168 void insertNew(long pos
) { insertNew(pos
, 1); }
170 /* Insert len new items using default constructor. */
171 void insertNew(long pos
, long len
);
176 * \brief Remove one element at position pos.
178 * The element's destructor is called. Elements to the right of pos are
179 * shifted one space to the left to take up the free space. If pos is greater
180 * than or equal to the length of the vector then undefined behavior results.
181 * If pos is negative then it is treated as an offset relative to the length
184 void remove(long pos
) { remove(pos
, 1); }
186 /* Delete a number of elements. */
187 void remove(long pos
, long len
);
192 * \brief Replace one element at position pos.
194 * If there is an existing element at position pos (if pos is less than the
195 * length of the vector) then its destructor is called before the space is
196 * used. The copy constructor is used to place the element into the vector.
197 * If pos is greater than the length of the vector then undefined behaviour
198 * results. If pos is negative then it is treated as an offset relative to
199 * the length of the vector.
201 void replace(long pos
, const T
&val
) { replace(pos
, &val
, 1); }
203 /* Replace with an array of values. */
204 void replace(long pos
, const T
*val
, long len
);
207 * \brief Replace at position pos with all the elements of another vector.
209 * Replace at position pos with all the elements of another vector. The other
210 * vector is left unchanged. If there are existing elements at the positions
211 * to be replaced, then destructors are called before the space is used. Copy
212 * constructors are used to place the elements into this vector. It is
213 * allowable for the pos and length of the other vector to specify a
214 * replacement that overwrites existing elements and creates new ones. If pos
215 * is greater than the length of the vector then undefined behaviour results.
216 * If pos is negative, then it is treated as an offset relative to the length
219 void replace(long pos
, const SVector
&v
) { replace(pos
, v
.data
, v
.length()); }
221 /* Replace len items with len copies of val. */
222 void replaceDup(long pos
, const T
&val
, long len
);
225 * \brief Replace at position pos with one new element.
227 * If there is an existing element at the position to be replaced (pos is
228 * less than the length of the vector) then the element's destructor is
229 * called before the space is used. The default constructor is used to
230 * initialize the new element. If pos is greater than the length of the
231 * vector then undefined behaviour results. If pos is negative, then it is
232 * treated as an offset relative to the length of the vector.
234 void replaceNew(long pos
) { replaceNew(pos
, 1); }
236 /* Replace len items at pos with newly constructed objects. */
237 void replaceNew(long pos
, long len
);
243 * \brief Set the contents of the vector to be val exactly.
245 * The vector becomes one element in length. Destructors are called on any
246 * existing elements in the vector. The element's copy constructor is used to
247 * place the val in the vector.
249 void setAs(const T
&val
) { setAs(&val
, 1); }
251 /* Set to the contents of an array. */
252 void setAs(const T
*val
, long len
);
255 * \brief Set the vector to exactly the contents of another vector.
257 * The vector becomes v.length() elements in length. Destructors are called
258 * on any existing elements. Copy constructors are used to place the new
259 * elements in the vector.
261 void setAs(const SVector
&v
) { setAs(v
.data
, v
.length()); }
263 /* Set as len copies of item. */
264 void setAsDup(const T
&item
, long len
);
267 * \brief Set the vector to exactly one new item.
269 * The vector becomes one element in length. Destructors are called on any
270 * existing elements in the vector. The default constructor is used to
273 void setAsNew() { setAsNew(1); }
275 /* Set as newly constructed objects using the default constructor. */
276 void setAsNew(long len
);
281 * \brief Append one elment to the end of the vector.
283 * Copy constructor is used to place the element in the vector.
285 void append(const T
&val
) { replace(BaseTable::length(), &val
, 1); }
288 * \brief Append len elements to the end of the vector.
290 * Copy constructors are used to place the elements in the vector.
292 void append(const T
*val
, long len
) { replace(BaseTable::length(), val
, len
); }
295 * \brief Append the contents of another vector.
297 * The other vector is left unchanged. Copy constructors are used to place
298 * the elements in the vector.
300 void append(const SVector
&v
)
301 { replace(BaseTable::length(), v
.data
, v
.length()); }
304 * \brief Append len copies of item.
306 * The copy constructor is used to place the item in the vector.
308 void appendDup(const T
&item
, long len
) { replaceDup(BaseTable::length(), item
, len
); }
311 * \brief Append a single newly created item.
313 * The new element is initialized with the default constructor.
315 void appendNew() { replaceNew(BaseTable::length(), 1); }
318 * \brief Append len newly created items.
320 * The new elements are initialized with the default constructor.
322 void appendNew(long len
) { replaceNew(BaseTable::length(), len
); }
328 * \brief Prepend one elment to the front of the vector.
330 * Copy constructor is used to place the element in the vector.
332 void prepend(const T
&val
) { insert(0, &val
, 1); }
335 * \brief Prepend len elements to the front of the vector.
337 * Copy constructors are used to place the elements in the vector.
339 void prepend(const T
*val
, long len
) { insert(0, val
, len
); }
342 * \brief Prepend the contents of another vector.
344 * The other vector is left unchanged. Copy constructors are used to place
345 * the elements in the vector.
347 void prepend(const SVector
&v
) { insert(0, v
.data
, v
.length()); }
350 * \brief Prepend len copies of item.
352 * The copy constructor is used to place the item in the vector.
354 void prependDup(const T
&item
, long len
) { insertDup(0, item
, len
); }
357 * \brief Prepend a single newly created item.
359 * The new element is initialized with the default constructor.
361 void prependNew() { insertNew(0, 1); }
364 * \brief Prepend len newly created items.
366 * The new elements are initialized with the default constructor.
368 void prependNew(long len
) { insertNew(0, len
); }
371 /* Convenience access. */
372 T
&operator[](int i
) const { return BaseTable::data
[i
]; }
373 long size() const { return BaseTable::length(); }
375 /* Various classes for setting the iterator */
377 struct IterFirst
{ IterFirst( const SVector
&v
) : v(v
) { } const SVector
&v
; };
378 struct IterLast
{ IterLast( const SVector
&v
) : v(v
) { } const SVector
&v
; };
379 struct IterNext
{ IterNext( const Iter
&i
) : i(i
) { } const Iter
&i
; };
380 struct IterPrev
{ IterPrev( const Iter
&i
) : i(i
) { } const Iter
&i
; };
383 * \brief Shared Vector Iterator.
388 /* Construct, assign. */
389 Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
392 Iter( const SVector
&v
);
393 Iter( const IterFirst
&vf
);
394 Iter( const IterLast
&vl
);
395 inline Iter( const IterNext
&vn
);
396 inline Iter( const IterPrev
&vp
);
399 Iter
&operator=( const SVector
&v
);
400 Iter
&operator=( const IterFirst
&vf
);
401 Iter
&operator=( const IterLast
&vl
);
402 inline Iter
&operator=( const IterNext
&vf
);
403 inline Iter
&operator=( const IterPrev
&vl
);
405 /** \brief Less than end? */
406 bool lte() const { return ptr
!= ptrEnd
; }
408 /** \brief At end? */
409 bool end() const { return ptr
== ptrEnd
; }
411 /** \brief Greater than beginning? */
412 bool gtb() const { return ptr
!= ptrBeg
; }
414 /** \brief At beginning? */
415 bool beg() const { return ptr
== ptrBeg
; }
417 /** \brief At first element? */
418 bool first() const { return ptr
== ptrBeg
+1; }
420 /** \brief At last element? */
421 bool last() const { return ptr
== ptrEnd
-1; }
423 /* Return the position. */
424 long pos() const { return ptr
- ptrBeg
- 1; }
425 T
&operator[](int i
) const { return ptr
[i
]; }
427 /** \brief Implicit cast to T*. */
428 operator T
*() const { return ptr
; }
430 /** \brief Dereference operator returns T&. */
431 T
&operator *() const { return *ptr
; }
433 /** \brief Arrow operator returns T*. */
434 T
*operator->() const { return ptr
; }
436 /** \brief Move to next item. */
437 T
*operator++() { return ++ptr
; }
439 /** \brief Move to next item. */
440 T
*operator++(int) { return ptr
++; }
442 /** \brief Move to next item. */
443 T
*increment() { return ++ptr
; }
445 /** \brief Move to previous item. */
446 T
*operator--() { return --ptr
; }
448 /** \brief Move to previous item. */
449 T
*operator--(int) { return ptr
--; }
451 /** \brief Move to previous item. */
452 T
*decrement() { return --ptr
; }
454 /** \brief Return the next item. Does not modify this. */
455 inline IterNext
next() const { return IterNext(*this); }
457 /** \brief Return the previous item. Does not modify this. */
458 inline IterPrev
prev() const { return IterPrev(*this); }
460 /** \brief The iterator is simply a pointer. */
463 /* For testing endpoints. */
467 /** \brief Return first element. */
468 IterFirst
first() { return IterFirst( *this ); }
470 /** \brief Return last element. */
471 IterLast
last() { return IterLast( *this ); }
474 void makeRawSpaceFor(long pos
, long len
);
476 void setAsCommon(long len
);
477 long replaceCommon(long pos
, long len
);
478 long insertCommon(long pos
, long len
);
480 void upResize(long len
);
481 void upResizeDup(long len
);
482 void upResizeFromEmpty(long len
);
483 void downResize(long len
);
484 void downResizeDup(long len
);
488 * \brief Perform a shallow copy of the vector.
490 * Takes a reference to the contents of the other vector.
492 template <class T
, class Resize
> SVector
<T
, Resize
>::
493 SVector(const SVector
<T
, Resize
> &v
)
495 /* Take a reference to other, if any data is allocated. */
499 /* Get the source header, up the refcount and ref it. */
500 STabHead
*srcHead
= ((STabHead
*) v
.data
) - 1;
501 srcHead
->refCount
+= 1;
502 BaseTable::data
= (T
*) (srcHead
+ 1);
507 * \brief Shallow copy another vector into this vector.
509 * Takes a reference to the other vector. The contents of this vector are
512 * \returns A reference to this.
514 template <class T
, class Resize
> SVector
<T
, Resize
> &
515 SVector
<T
, Resize
>:: operator=( const SVector
&v
)
517 /* First clean out the current contents. */
520 /* Take a reference to other, if any data is allocated. */
524 /* Get the source header, up the refcount and ref it. */
525 STabHead
*srcHead
= ((STabHead
*) v
.data
) - 1;
526 srcHead
->refCount
+= 1;
527 BaseTable::data
= (T
*) (srcHead
+ 1);
532 /* Init a vector iterator with just a vector. */
533 template <class T
, class Resize
> SVector
<T
, Resize
>::
534 Iter::Iter( const SVector
&v
)
537 if ( v
.data
== 0 || (length
=(((STabHead
*)v
.data
)-1)->tabLen
) == 0 )
538 ptr
= ptrBeg
= ptrEnd
= 0;
542 ptrEnd
= v
.data
+length
;
546 /* Init a vector iterator with the first of a vector. */
547 template <class T
, class Resize
> SVector
<T
, Resize
>::
548 Iter::Iter( const IterFirst
&vf
)
551 if ( vf
.v
.data
== 0 || (length
=(((STabHead
*)vf
.v
.data
)-1)->tabLen
) == 0 )
552 ptr
= ptrBeg
= ptrEnd
= 0;
555 ptrBeg
= vf
.v
.data
-1;
556 ptrEnd
= vf
.v
.data
+length
;
560 /* Init a vector iterator with the last of a vector. */
561 template <class T
, class Resize
> SVector
<T
, Resize
>::
562 Iter::Iter( const IterLast
&vl
)
565 if ( vl
.v
.data
== 0 || (length
=(((STabHead
*)vl
.v
.data
)-1)->tabLen
) == 0 )
566 ptr
= ptrBeg
= ptrEnd
= 0;
568 ptr
= vl
.v
.data
+length
-1;
569 ptrBeg
= vl
.v
.data
-1;
570 ptrEnd
= vl
.v
.data
+length
;
574 /* Init a vector iterator with the next of some other iterator. */
575 template <class T
, class Resize
> SVector
<T
, Resize
>::
576 Iter::Iter( const IterNext
&vn
)
584 /* Init a vector iterator with the prev of some other iterator. */
585 template <class T
, class Resize
> SVector
<T
, Resize
>::
586 Iter::Iter( const IterPrev
&vp
)
594 /* Set a vector iterator with some vector. */
595 template <class T
, class Resize
> typename SVector
<T
, Resize
>::Iter
&
596 SVector
<T
, Resize
>::Iter::operator=( const SVector
&v
)
599 if ( v
.data
== 0 || (length
=(((STabHead
*)v
.data
)-1)->tabLen
) == 0 )
600 ptr
= ptrBeg
= ptrEnd
= 0;
604 ptrEnd
= v
.data
+length
;
609 /* Set a vector iterator with the first element in a vector. */
610 template <class T
, class Resize
> typename SVector
<T
, Resize
>::Iter
&
611 SVector
<T
, Resize
>::Iter::operator=( const IterFirst
&vf
)
614 if ( vf
.v
.data
== 0 || (length
=(((STabHead
*)vf
.v
.data
)-1)->tabLen
) == 0 )
615 ptr
= ptrBeg
= ptrEnd
= 0;
618 ptrBeg
= vf
.v
.data
-1;
619 ptrEnd
= vf
.v
.data
+length
;
624 /* Set a vector iterator with the last element in a vector. */
625 template <class T
, class Resize
> typename SVector
<T
, Resize
>::Iter
&
626 SVector
<T
, Resize
>::Iter::operator=( const IterLast
&vl
)
629 if ( vl
.v
.data
== 0 || (length
=(((STabHead
*)vl
.v
.data
)-1)->tabLen
) == 0 )
630 ptr
= ptrBeg
= ptrEnd
= 0;
632 ptr
= vl
.v
.data
+length
-1;
633 ptrBeg
= vl
.v
.data
-1;
634 ptrEnd
= vl
.v
.data
+length
;
639 /* Set a vector iterator with the next of some other iterator. */
640 template <class T
, class Resize
> typename SVector
<T
, Resize
>::Iter
&
641 SVector
<T
, Resize
>::Iter::operator=( const IterNext
&vn
)
644 ptrBeg
= vn
.i
.ptrBeg
;
645 ptrEnd
= vn
.i
.ptrEnd
;
649 /* Set a vector iterator with the prev of some other iterator. */
650 template <class T
, class Resize
> typename SVector
<T
, Resize
>::Iter
&
651 SVector
<T
, Resize
>::Iter::operator=( const IterPrev
&vp
)
654 ptrBeg
= vp
.i
.ptrBeg
;
655 ptrEnd
= vp
.i
.ptrEnd
;
659 /* Up resize the data for len elements using Resize::upResize to tell us the
660 * new length. Reads and writes allocLen. Does not read or write length.
661 * Assumes that there is some data allocated already. */
662 template <class T
, class Resize
> void SVector
<T
, Resize
>::
665 /* Get the current header. */
666 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
668 /* Ask the resizer what the new length will be. */
669 long newLen
= Resize::upResize(head
->allocLen
, len
);
671 /* Did the data grow? */
672 if ( newLen
> head
->allocLen
) {
673 head
->allocLen
= newLen
;
675 /* Table exists already, resize it up. */
676 head
= (STabHead
*) realloc( head
, sizeof(STabHead
) +
677 sizeof(T
) * newLen
);
679 throw std::bad_alloc();
681 /* Save the data pointer. */
682 BaseTable::data
= (T
*) (head
+ 1);
686 /* Allocates a new buffer for an up resize that requires a duplication of the
687 * data. Uses Resize::upResize to get the allocation length. Reads and writes
688 * allocLen. This upResize does write the new length. Assumes that there is
689 * some data allocated already. */
690 template <class T
, class Resize
> void SVector
<T
, Resize
>::
691 upResizeDup(long len
)
693 /* Get the current header. */
694 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
696 /* Ask the resizer what the new length will be. */
697 long newLen
= Resize::upResize(head
->allocLen
, len
);
699 /* Dereferencing the existing data, decrement the refcount. */
702 /* Table exists already, resize it up. */
703 head
= (STabHead
*) malloc( sizeof(STabHead
) + sizeof(T
) * newLen
);
705 throw std::bad_alloc();
708 head
->allocLen
= newLen
;
711 /* Save the data pointer. */
712 BaseTable::data
= (T
*) (head
+ 1);
715 /* Up resize the data for len elements using Resize::upResize to tell us the
716 * new length. Reads and writes allocLen. This upresize DOES write length.
717 * Assumes that no data is allocated. */
718 template <class T
, class Resize
> void SVector
<T
, Resize
>::
719 upResizeFromEmpty(long len
)
721 /* There is no table yet. If the len is zero, then there is no need to
724 /* Ask the resizer what the new length will be. */
725 long newLen
= Resize::upResize(0, len
);
727 /* If len is greater than zero then we are always allocating the table. */
728 STabHead
*head
= (STabHead
*) malloc( sizeof(STabHead
) +
729 sizeof(T
) * newLen
);
731 throw std::bad_alloc();
733 /* Set up the header and save the data pointer. Note that we set the
734 * length here. This differs from the other upResizes. */
736 head
->allocLen
= newLen
;
738 BaseTable::data
= (T
*) (head
+ 1);
742 /* Down resize the data for len elements using Resize::downResize to determine
743 * the new length. Reads and writes allocLen. Does not read or write length. */
744 template <class T
, class Resize
> void SVector
<T
, Resize
>::
747 /* If there is already no length, then there is nothing we can do. */
748 if ( BaseTable::data
!= 0 ) {
749 /* Get the current header. */
750 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
752 /* Ask the resizer what the new length will be. */
753 long newLen
= Resize::downResize( head
->allocLen
, len
);
755 /* Did the data shrink? */
756 if ( newLen
< head
->allocLen
) {
758 /* Simply free the data. */
763 /* Save the new allocated length. */
764 head
->allocLen
= newLen
;
766 /* Not shrinking to size zero, realloc it to the smaller size. */
767 head
= (STabHead
*) realloc( head
, sizeof(STabHead
) +
768 sizeof(T
) * newLen
);
770 throw std::bad_alloc();
772 /* Save the new data ptr. */
773 BaseTable::data
= (T
*) (head
+ 1);
779 /* Allocate a new buffer for a down resize and duplication of the array. The
780 * new array will be len long and allocation size will be determined using
781 * Resize::downResize with the old array's allocLen. Does not actually copy
782 * any data. Reads and writes allocLen and writes the new len. */
783 template <class T
, class Resize
> void SVector
<T
, Resize
>::
784 downResizeDup(long len
)
786 /* If there is already no length, then there is nothing we can do. */
787 if ( BaseTable::data
!= 0 ) {
788 /* Get the current header. */
789 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
791 /* Ask the resizer what the new length will be. */
792 long newLen
= Resize::downResize( head
->allocLen
, len
);
794 /* Detaching from the existing head, decrement the refcount. */
797 /* Not shrinking to size zero, malloc it to the smaller size. */
798 head
= (STabHead
*) malloc( sizeof(STabHead
) + sizeof(T
) * newLen
);
800 throw std::bad_alloc();
802 /* Save the new allocated length. */
804 head
->allocLen
= newLen
;
807 /* Save the data pointer. */
808 BaseTable::data
= (T
*) (head
+ 1);
813 * \brief Free all memory used by the vector.
815 * The vector is reset to zero elements. Destructors are called on all
816 * elements in the vector. The space allocated for the vector is freed.
818 template <class T
, class Resize
> void SVector
<T
, Resize
>::
821 if ( BaseTable::data
!= 0 ) {
822 /* Get the header and drop the refcount on the data. */
823 STabHead
*head
= ((STabHead
*) BaseTable::data
) - 1;
826 /* If the refcount just went down to zero nobody else is referencing
828 if ( head
->refCount
== 0 ) {
829 /* Call All destructors. */
830 T
*pos
= BaseTable::data
;
831 for ( long i
= 0; i
< head
->tabLen
; pos
++, i
++ )
834 /* Free the data space. */
838 /* Clear the pointer. */
843 /* Prepare for setting the contents of the vector to some array len long.
844 * Handles reusing the existing space, detaching from a common space or
845 * growing from zero length automatically. */
846 template <class T
, class Resize
> void SVector
<T
, Resize
>::
847 setAsCommon(long len
)
849 if ( BaseTable::data
!= 0 ) {
850 /* Get the header. */
851 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
853 /* If the refCount is one, then we can reuse the space. Otherwise we
854 * must detach from the referenced data create new space. */
855 if ( head
->refCount
== 1 ) {
856 /* Call All destructors. */
857 T
*pos
= BaseTable::data
;
858 for ( long i
= 0; i
< head
->tabLen
; pos
++, i
++ )
861 /* Adjust the allocated length. */
862 if ( len
< head
->tabLen
)
864 else if ( len
> head
->tabLen
)
867 if ( BaseTable::data
!= 0 ) {
868 /* Get the header again and set the length. */
869 head
= ((STabHead
*)BaseTable::data
) - 1;
874 /* Just detach from the data. */
878 /* Make enough space. This will set the length. */
879 upResizeFromEmpty( len
);
883 /* The table is currently empty. Make enough space. This will set the
885 upResizeFromEmpty( len
);
890 * \brief Set the contents of the vector to be len elements exactly.
892 * The vector becomes len elements in length. Destructors are called on any
893 * existing elements in the vector. Copy constructors are used to place the
894 * new elements in the vector.
896 template <class T
, class Resize
> void SVector
<T
, Resize
>::
897 setAs(const T
*val
, long len
)
899 /* Common stuff for setting the array to len long. */
903 T
*dst
= BaseTable::data
;
905 for ( long i
= 0; i
< len
; i
++, dst
++, src
++ )
911 * \brief Set the vector to len copies of item.
913 * The vector becomes len elements in length. Destructors are called on any
914 * existing elements in the vector. The element's copy constructor is used to
915 * copy the item into the vector.
917 template <class T
, class Resize
> void SVector
<T
, Resize
>::
918 setAsDup(const T
&item
, long len
)
920 /* Do the common stuff for setting the array to len long. */
923 /* Copy item in one spot at a time. */
924 T
*dst
= BaseTable::data
;
925 for ( long i
= 0; i
< len
; i
++, dst
++ )
930 * \brief Set the vector to exactly len new items.
932 * The vector becomes len elements in length. Destructors are called on any
933 * existing elements in the vector. Default constructors are used to init the
936 template <class T
, class Resize
> void SVector
<T
, Resize
>::
939 /* Do the common stuff for setting the array to len long. */
942 /* Create items using default constructor. */
943 T
*dst
= BaseTable::data
;
944 for ( long i
= 0; i
< len
; i
++, dst
++ )
948 /* Make space in vector for a replacement at pos of len items. Handles reusing
949 * existing space, detaching or growing from zero space. */
950 template <class T
, class Resize
> long SVector
<T
, Resize
>::
951 replaceCommon(long pos
, long len
)
953 if ( BaseTable::data
!= 0 ) {
954 /* Get the header. */
955 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
957 /* If we are given a negative position to replace at then treat it as
958 * a position relative to the length. This doesn't have any meaning
959 * unless the length is at least one. */
961 pos
= head
->tabLen
+ pos
;
963 /* The end is the one past the last item that we want to write to. */
964 long i
, endPos
= pos
+ len
;
966 if ( head
->refCount
== 1 ) {
967 /* We can reuse the space. Make sure we have enough space. */
968 if ( endPos
> head
->tabLen
) {
971 /* Get the header again, whose addr may have changed after
973 head
= ((STabHead
*)BaseTable::data
) - 1;
975 /* Delete any objects we need to delete. */
976 T
*item
= BaseTable::data
+ pos
;
977 for ( i
= pos
; i
< head
->tabLen
; i
++, item
++ )
980 /* We are extending the vector, set the new data length. */
981 head
->tabLen
= endPos
;
984 /* Delete any objects we need to delete. */
985 T
*item
= BaseTable::data
+ pos
;
986 for ( i
= pos
; i
< endPos
; i
++, item
++ )
991 /* Use endPos to calc the end of the vector. */
992 long newLen
= endPos
;
993 if ( newLen
< head
->tabLen
)
994 newLen
= head
->tabLen
;
996 /* Duplicate and grow up to endPos. This will set the length. */
997 upResizeDup( newLen
);
999 /* Copy from src up to pos. */
1000 const T
*src
= (T
*) (head
+ 1);
1001 T
*dst
= BaseTable::data
;
1002 for ( i
= 0; i
< pos
; i
++, dst
++, src
++)
1005 /* Copy any items after the replace range. */
1006 for ( i
+= len
, src
+= len
, dst
+= len
;
1007 i
< head
->tabLen
; i
++, dst
++, src
++ )
1012 /* There is no data initially, must grow from zero. This will set the
1014 upResizeFromEmpty( len
);
1022 * \brief Replace len elements at position pos.
1024 * If there are existing elements at the positions to be replaced, then
1025 * destructors are called before the space is used. Copy constructors are used
1026 * to place the elements into the vector. It is allowable for the pos and
1027 * length to specify a replacement that overwrites existing elements and
1028 * creates new ones. If pos is greater than the length of the vector then
1029 * undefined behaviour results. If pos is negative, then it is treated as an
1030 * offset relative to the length of the vector.
1032 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1033 replace(long pos
, const T
*val
, long len
)
1035 /* Common work for replacing in the vector. */
1036 pos
= replaceCommon( pos
, len
);
1038 /* Copy data in using copy constructor. */
1039 T
*dst
= BaseTable::data
+ pos
;
1041 for ( long i
= 0; i
< len
; i
++, dst
++, src
++ )
1046 * \brief Replace at position pos with len copies of an item.
1048 * If there are existing elements at the positions to be replaced, then
1049 * destructors are called before the space is used. The copy constructor is
1050 * used to place the element into this vector. It is allowable for the pos and
1051 * length to specify a replacement that overwrites existing elements and
1052 * creates new ones. If pos is greater than the length of the vector then
1053 * undefined behaviour results. If pos is negative, then it is treated as an
1054 * offset relative to the length of the vector.
1056 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1057 replaceDup(long pos
, const T
&val
, long len
)
1059 /* Common replacement stuff. */
1060 pos
= replaceCommon( pos
, len
);
1062 /* Copy data in using copy constructor. */
1063 T
*dst
= BaseTable::data
+ pos
;
1064 for ( long i
= 0; i
< len
; i
++, dst
++ )
1069 * \brief Replace at position pos with len new elements.
1071 * If there are existing elements at the positions to be replaced, then
1072 * destructors are called before the space is used. The default constructor is
1073 * used to initialize the new elements. It is allowable for the pos and length
1074 * to specify a replacement that overwrites existing elements and creates new
1075 * ones. If pos is greater than the length of the vector then undefined
1076 * behaviour results. If pos is negative, then it is treated as an offset
1077 * relative to the length of the vector.
1079 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1080 replaceNew(long pos
, long len
)
1082 /* Do the common replacement stuff. */
1083 pos
= replaceCommon( pos
, len
);
1085 /* Copy data in using copy constructor. */
1086 T
*dst
= BaseTable::data
+ pos
;
1087 for ( long i
= 0; i
< len
; i
++, dst
++ )
1092 * \brief Remove len elements at position pos.
1094 * Destructor is called on all elements removed. Elements to the right of pos
1095 * are shifted len spaces to the left to take up the free space. If pos is
1096 * greater than or equal to the length of the vector then undefined behavior
1097 * results. If pos is negative then it is treated as an offset relative to the
1098 * length of the vector.
1100 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1101 remove(long pos
, long len
)
1103 /* If there is no data, we can't delete anything anyways. */
1104 if ( BaseTable::data
!= 0 ) {
1105 /* Get the header. */
1106 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
1108 /* If we are given a negative position to remove at then
1109 * treat it as a position relative to the length. */
1111 pos
= head
->tabLen
+ pos
;
1113 /* The first position after the last item deleted. */
1114 long endPos
= pos
+ len
;
1116 /* The New data length. */
1117 long i
, newLen
= head
->tabLen
- len
;
1119 if ( head
->refCount
== 1 ) {
1120 /* We are the only ones using the data. We can reuse
1121 * the existing space. */
1123 /* The place in the data we are deleting at. */
1124 T
*dst
= BaseTable::data
+ pos
;
1126 /* Call Destructors. */
1127 T
*item
= BaseTable::data
+ pos
;
1128 for ( i
= 0; i
< len
; i
+= 1, item
+= 1 )
1131 /* Shift data over if necessary. */
1132 long lenToSlideOver
= head
->tabLen
- endPos
;
1133 if ( len
> 0 && lenToSlideOver
> 0 )
1134 memmove(BaseTable::data
+ pos
, dst
+ len
, sizeof(T
)*lenToSlideOver
);
1136 /* Shrink the data if necessary. */
1137 downResize( newLen
);
1139 if ( BaseTable::data
!= 0 ) {
1140 /* Get the header again (because of the resize) and set the
1141 * new data length. */
1142 head
= ((STabHead
*)BaseTable::data
) - 1;
1143 head
->tabLen
= newLen
;
1147 /* Must detach from the common data. Just copy the non-deleted
1148 * items from the common data. */
1150 /* Duplicate and grow down to newLen. This will set the length. */
1151 downResizeDup( newLen
);
1153 /* Copy over just the non-deleted parts. */
1154 const T
*src
= (T
*) (head
+ 1);
1155 T
*dst
= BaseTable::data
;
1156 for ( i
= 0; i
< pos
; i
++, dst
++, src
++ )
1159 /* ... and the second half. */
1160 for ( i
+= len
, src
+= len
; i
< head
->tabLen
; i
++, src
++, dst
++ )
1166 /* Shift over existing data. Handles reusing existing space, detaching or
1167 * growing from zero space. */
1168 template <class T
, class Resize
> long SVector
<T
, Resize
>::
1169 insertCommon(long pos
, long len
)
1171 if ( BaseTable::data
!= 0 ) {
1172 /* Get the header. */
1173 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
1175 /* If we are given a negative position to insert at then treat it as a
1176 * position relative to the length. This only has meaning if there is
1179 pos
= head
->tabLen
+ pos
;
1181 /* Calculate the new length. */
1182 long i
, newLen
= head
->tabLen
+ len
;
1184 if ( head
->refCount
== 1 ) {
1185 /* Up resize, we are growing. */
1188 /* Get the header again, (the addr may have changed after
1190 head
= ((STabHead
*)BaseTable::data
) - 1;
1192 /* Shift over data at insert spot if needed. */
1193 if ( len
> 0 && pos
< head
->tabLen
) {
1194 memmove( BaseTable::data
+ pos
+ len
, BaseTable::data
+ pos
,
1195 sizeof(T
)*(head
->tabLen
- pos
) );
1198 /* Grow the length by the len inserted. */
1199 head
->tabLen
+= len
;
1202 /* Need to detach from the existing array. Copy over the other
1203 * parts. This will set the length. */
1204 upResizeDup( newLen
);
1206 /* Copy over the parts around the insert. */
1207 const T
*src
= (T
*) (head
+ 1);
1208 T
*dst
= BaseTable::data
;
1209 for ( i
= 0; i
< pos
; i
++, dst
++, src
++ )
1212 /* ... and the second half. */
1213 for ( dst
+= len
; i
< head
->tabLen
; i
++, src
++, dst
++ )
1218 /* There is no existing data. Start from zero. This will set the
1220 upResizeFromEmpty( len
);
1228 * \brief Insert len elements at position pos.
1230 * Elements in the vector from pos onward are shifted len spaces to the right.
1231 * The copy constructor is used to place the elements into this vector. If pos
1232 * is greater than the length of the vector then undefined behaviour results.
1233 * If pos is negative then it is treated as an offset relative to the length
1236 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1237 insert(long pos
, const T
*val
, long len
)
1239 /* Do the common insertion stuff. */
1240 pos
= insertCommon( pos
, len
);
1242 /* Copy data in element by element. */
1243 T
*dst
= BaseTable::data
+ pos
;
1245 for ( long i
= 0; i
< len
; i
++, dst
++, src
++ )
1250 * \brief Insert len copies of item at position pos.
1252 * Elements in the vector from pos onward are shifted len spaces to the right.
1253 * The copy constructor is used to place the element into this vector. If pos
1254 * is greater than the length of the vector then undefined behaviour results.
1255 * If pos is negative then it is treated as an offset relative to the length
1258 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1259 insertDup(long pos
, const T
&item
, long len
)
1261 /* Do the common insertion stuff. */
1262 pos
= insertCommon( pos
, len
);
1264 /* Copy the data item in one at a time. */
1265 T
*dst
= BaseTable::data
+ pos
;
1266 for ( long i
= 0; i
< len
; i
++, dst
++ )
1272 * \brief Insert len new elements using the default constructor.
1274 * Elements in the vector from pos onward are shifted len spaces to the right.
1275 * Default constructors are used to init the new elements. If pos is off the
1276 * end of the vector then undefined behaviour results. If pos is negative then
1277 * it is treated as an offset relative to the length of the vector.
1279 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1280 insertNew(long pos
, long len
)
1282 /* Do the common insertion stuff. */
1283 pos
= insertCommon( pos
, len
);
1285 /* Init new data with default constructors. */
1286 T
*dst
= BaseTable::data
+ pos
;
1287 for ( long i
= 0; i
< len
; i
++, dst
++ )
1291 /* Makes space for len items, Does not init the items in any way. If pos is
1292 * greater than the length of the vector then undefined behaviour results.
1293 * Updates the length of the vector. */
1294 template <class T
, class Resize
> void SVector
<T
, Resize
>::
1295 makeRawSpaceFor(long pos
, long len
)
1297 if ( BaseTable::data
!= 0 ) {
1298 /* Get the header. */
1299 STabHead
*head
= ((STabHead
*)BaseTable::data
) - 1;
1301 /* Calculate the new length. */
1302 long i
, newLen
= head
->tabLen
+ len
;
1304 if ( head
->refCount
== 1 ) {
1305 /* Up resize, we are growing. */
1308 /* Get the header again, (the addr may have changed after
1310 head
= ((STabHead
*)BaseTable::data
) - 1;
1312 /* Shift over data at insert spot if needed. */
1313 if ( len
> 0 && pos
< head
->tabLen
) {
1314 memmove( BaseTable::data
+ pos
+ len
, BaseTable::data
+ pos
,
1315 sizeof(T
)*(head
->tabLen
- pos
) );
1318 /* Grow the length by the len inserted. */
1319 head
->tabLen
+= len
;
1322 /* Need to detach from the existing array. Copy over the other
1323 * parts. This will set the length. */
1324 upResizeDup( newLen
);
1326 /* Copy over the parts around the insert. */
1327 const T
*src
= (T
*) (head
+ 1);
1328 T
*dst
= BaseTable::data
;
1329 for ( i
= 0; i
< pos
; i
++, dst
++, src
++ )
1332 /* ... and the second half. */
1333 for ( dst
+= len
; i
< head
->tabLen
; i
++, src
++, dst
++ )
1338 /* There is no existing data. Start from zero. This will set the
1340 upResizeFromEmpty( len
);
1345 #ifdef AAPL_NAMESPACE
1350 #endif /* _AAPL_SVECTOR_H */