Renaming to avoid name conflicts following the merge of the frontend and backend.
[ragel.git] / aapl / svector.h
blobdb3a56569c51fef8cbb06aa8cc63d7b1ee971907
1 /*
2 * Copyright 2002, 2006 Adrian Thurston <thurston@cs.queensu.ca>
3 */
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)
10 * any later version.
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
15 * more details.
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
25 #include <new>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include "table.h"
31 #ifdef AAPL_NAMESPACE
32 namespace Aapl {
33 #endif
35 /**
36 * \addtogroup vector
37 * @{
40 /** \class SVector
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
65 * the vector.
68 /*@}*/
70 /* SVector */
71 template < class T, class Resize = ResizeExpn > class SVector :
72 public STable<T>, public Resize
74 private:
75 typedef STable<T> BaseTable;
77 public:
78 /**
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
83 * Exponential.
85 SVector() { }
87 /**
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); }
95 /**
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); }
103 /* Shallow copy. */
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. */
115 void empty();
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 );
129 /*@{*/
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
166 * vector.
168 void insertNew(long pos) { insertNew(pos, 1); }
170 /* Insert len new items using default constructor. */
171 void insertNew(long pos, long len);
172 /*@}*/
174 /*@{*/
175 /**
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
182 * of the vector.
184 void remove(long pos) { remove(pos, 1); }
186 /* Delete a number of elements. */
187 void remove(long pos, long len);
188 /*@}*/
190 /*@{*/
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
217 * of the vector.
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);
238 /*@}*/
240 /*@{*/
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
271 * init the new item.
273 void setAsNew() { setAsNew(1); }
275 /* Set as newly constructed objects using the default constructor. */
276 void setAsNew(long len);
277 /*@}*/
279 /*@{*/
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); }
323 /*@}*/
326 /*@{*/
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); }
369 /*@}*/
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 */
376 struct Iter;
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; };
382 /**
383 * \brief Shared Vector Iterator.
384 * \ingroup iterators
386 struct Iter
388 /* Construct, assign. */
389 Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
391 /* Construct. */
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 );
398 /* Assign. */
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. */
461 T *ptr;
463 /* For testing endpoints. */
464 T *ptrBeg, *ptrEnd;
467 /** \brief Return first element. */
468 IterFirst first() { return IterFirst( *this ); }
470 /** \brief Return last element. */
471 IterLast last() { return IterLast( *this ); }
473 protected:
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. */
496 if ( v.data == 0 )
497 BaseTable::data = 0;
498 else {
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
510 * first emptied.
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. */
518 empty();
520 /* Take a reference to other, if any data is allocated. */
521 if ( v.data == 0 )
522 BaseTable::data = 0;
523 else {
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);
529 return *this;
532 /* Init a vector iterator with just a vector. */
533 template <class T, class Resize> SVector<T, Resize>::
534 Iter::Iter( const SVector &v )
536 long length;
537 if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
538 ptr = ptrBeg = ptrEnd = 0;
539 else {
540 ptr = v.data;
541 ptrBeg = v.data-1;
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 )
550 long length;
551 if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
552 ptr = ptrBeg = ptrEnd = 0;
553 else {
554 ptr = vf.v.data;
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 )
564 long length;
565 if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
566 ptr = ptrBeg = ptrEnd = 0;
567 else {
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 )
578 ptr(vn.i.ptr+1),
579 ptrBeg(vn.i.ptrBeg),
580 ptrEnd(vn.i.ptrEnd)
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 )
588 ptr(vp.i.ptr-1),
589 ptrBeg(vp.i.ptrBeg),
590 ptrEnd(vp.i.ptrEnd)
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 )
598 long length;
599 if ( v.data == 0 || (length=(((STabHead*)v.data)-1)->tabLen) == 0 )
600 ptr = ptrBeg = ptrEnd = 0;
601 else {
602 ptr = v.data;
603 ptrBeg = v.data-1;
604 ptrEnd = v.data+length;
606 return *this;
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 )
613 long length;
614 if ( vf.v.data == 0 || (length=(((STabHead*)vf.v.data)-1)->tabLen) == 0 )
615 ptr = ptrBeg = ptrEnd = 0;
616 else {
617 ptr = vf.v.data;
618 ptrBeg = vf.v.data-1;
619 ptrEnd = vf.v.data+length;
621 return *this;
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 )
628 long length;
629 if ( vl.v.data == 0 || (length=(((STabHead*)vl.v.data)-1)->tabLen) == 0 )
630 ptr = ptrBeg = ptrEnd = 0;
631 else {
632 ptr = vl.v.data+length-1;
633 ptrBeg = vl.v.data-1;
634 ptrEnd = vl.v.data+length;
636 return *this;
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 )
643 ptr = vn.i.ptr+1;
644 ptrBeg = vn.i.ptrBeg;
645 ptrEnd = vn.i.ptrEnd;
646 return *this;
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 )
653 ptr = vp.i.ptr-1;
654 ptrBeg = vp.i.ptrBeg;
655 ptrEnd = vp.i.ptrEnd;
656 return *this;
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>::
663 upResize(long len)
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 );
678 if ( head == 0 )
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. */
700 head->refCount -= 1;
702 /* Table exists already, resize it up. */
703 head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
704 if ( head == 0 )
705 throw std::bad_alloc();
707 head->refCount = 1;
708 head->allocLen = newLen;
709 head->tabLen = len;
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
722 * create a table. */
723 if ( len > 0 ) {
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 );
730 if ( head == 0 )
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. */
735 head->refCount = 1;
736 head->allocLen = newLen;
737 head->tabLen = len;
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>::
745 downResize(long len)
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 ) {
757 if ( newLen == 0 ) {
758 /* Simply free the data. */
759 free( head );
760 BaseTable::data = 0;
762 else {
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 );
769 if ( head == 0 )
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. */
795 head->refCount -= 1;
797 /* Not shrinking to size zero, malloc it to the smaller size. */
798 head = (STabHead*) malloc( sizeof(STabHead) + sizeof(T) * newLen );
799 if ( head == 0 )
800 throw std::bad_alloc();
802 /* Save the new allocated length. */
803 head->refCount = 1;
804 head->allocLen = newLen;
805 head->tabLen = len;
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>::
819 empty()
821 if ( BaseTable::data != 0 ) {
822 /* Get the header and drop the refcount on the data. */
823 STabHead *head = ((STabHead*) BaseTable::data) - 1;
824 head->refCount -= 1;
826 /* If the refcount just went down to zero nobody else is referencing
827 * the data. */
828 if ( head->refCount == 0 ) {
829 /* Call All destructors. */
830 T *pos = BaseTable::data;
831 for ( long i = 0; i < head->tabLen; pos++, i++ )
832 pos->~T();
834 /* Free the data space. */
835 free( head );
838 /* Clear the pointer. */
839 BaseTable::data = 0;
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++ )
859 pos->~T();
861 /* Adjust the allocated length. */
862 if ( len < head->tabLen )
863 downResize( len );
864 else if ( len > head->tabLen )
865 upResize( len );
867 if ( BaseTable::data != 0 ) {
868 /* Get the header again and set the length. */
869 head = ((STabHead*)BaseTable::data) - 1;
870 head->tabLen = len;
873 else {
874 /* Just detach from the data. */
875 head->refCount -= 1;
876 BaseTable::data = 0;
878 /* Make enough space. This will set the length. */
879 upResizeFromEmpty( len );
882 else {
883 /* The table is currently empty. Make enough space. This will set the
884 * length. */
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. */
900 setAsCommon( len );
902 /* Copy data in. */
903 T *dst = BaseTable::data;
904 const T *src = val;
905 for ( long i = 0; i < len; i++, dst++, src++ )
906 new(dst) T(*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. */
921 setAsCommon( len );
923 /* Copy item in one spot at a time. */
924 T *dst = BaseTable::data;
925 for ( long i = 0; i < len; i++, dst++ )
926 new(dst) T(item);
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
934 * new items.
936 template <class T, class Resize> void SVector<T, Resize>::
937 setAsNew(long len)
939 /* Do the common stuff for setting the array to len long. */
940 setAsCommon( len );
942 /* Create items using default constructor. */
943 T *dst = BaseTable::data;
944 for ( long i = 0; i < len; i++, dst++ )
945 new(dst) T();
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. */
960 if ( pos < 0 )
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 ) {
969 upResize( endPos );
971 /* Get the header again, whose addr may have changed after
972 * resizing. */
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++ )
978 item->~T();
980 /* We are extending the vector, set the new data length. */
981 head->tabLen = endPos;
983 else {
984 /* Delete any objects we need to delete. */
985 T *item = BaseTable::data + pos;
986 for ( i = pos; i < endPos; i++, item++ )
987 item->~T();
990 else {
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++)
1003 new(dst) T(*src);
1005 /* Copy any items after the replace range. */
1006 for ( i += len, src += len, dst += len;
1007 i < head->tabLen; i++, dst++, src++ )
1008 new(dst) T(*src);
1011 else {
1012 /* There is no data initially, must grow from zero. This will set the
1013 * new length. */
1014 upResizeFromEmpty( len );
1017 return pos;
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;
1040 const T *src = val;
1041 for ( long i = 0; i < len; i++, dst++, src++ )
1042 new(dst) T(*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++ )
1065 new(dst) T(val);
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++ )
1088 new(dst) T();
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. */
1110 if ( pos < 0 )
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 )
1129 item->~T();
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;
1146 else {
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++ )
1157 new(dst) T(*src);
1159 /* ... and the second half. */
1160 for ( i += len, src += len; i < head->tabLen; i++, src++, dst++ )
1161 new(dst) T(*src);
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
1177 * existing data. */
1178 if ( pos < 0 )
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. */
1186 upResize( newLen );
1188 /* Get the header again, (the addr may have changed after
1189 * resizing). */
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;
1201 else {
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++ )
1210 new(dst) T(*src);
1212 /* ... and the second half. */
1213 for ( dst += len; i < head->tabLen; i++, src++, dst++ )
1214 new(dst) T(*src);
1217 else {
1218 /* There is no existing data. Start from zero. This will set the
1219 * length. */
1220 upResizeFromEmpty( len );
1223 return pos;
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
1234 * of the vector.
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;
1244 const T *src = val;
1245 for ( long i = 0; i < len; i++, dst++, src++ )
1246 new(dst) T(*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
1256 * of the vector.
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++ )
1267 new(dst) T(item);
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++ )
1288 new(dst) T();
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. */
1306 upResize( newLen );
1308 /* Get the header again, (the addr may have changed after
1309 * resizing). */
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;
1321 else {
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++ )
1330 new(dst) T(*src);
1332 /* ... and the second half. */
1333 for ( dst += len; i < head->tabLen; i++, src++, dst++ )
1334 new(dst) T(*src);
1337 else {
1338 /* There is no existing data. Start from zero. This will set the
1339 * length. */
1340 upResizeFromEmpty( len );
1345 #ifdef AAPL_NAMESPACE
1347 #endif
1350 #endif /* _AAPL_SVECTOR_H */