smack merge from tizen_2.1_smack
[external/ragel.git] / aapl / svector.h
1 /*
2  *  Copyright 2002, 2006 Adrian Thurston <thurston@complang.org>
3  */
4
5 /*  This file is part of Aapl.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #ifndef _AAPL_SVECTOR_H
23 #define _AAPL_SVECTOR_H
24
25 #include <new>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include "table.h"
30
31 #ifdef AAPL_NAMESPACE
32 namespace Aapl {
33 #endif
34
35 /**
36  * \addtogroup vector
37  * @{
38  */
39
40 /** \class SVector
41  * \brief Copy-on-write dynamic array.
42  *
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.
49  *
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.
53  *
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.
58  *
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.
66  */
67
68 /*@}*/
69
70 /* SVector */
71 template < class T, class Resize = ResizeExpn > class SVector :
72         public STable<T>, public Resize
73 {
74 private:
75         typedef STable<T> BaseTable;
76
77 public:
78         /**
79          * \brief Initialize an empty vector with no space allocated.  
80          *
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.
84          */
85         SVector() { }
86
87         /**
88          * \brief Create a vector that contains an initial element.
89          *
90          * The vector becomes one element in length. The element's copy
91          * constructor is used to place the value in the vector.
92          */
93         SVector(const T &val)             { setAs(&val, 1); }
94
95         /**
96          * \brief Create a vector that contains an array of elements.
97          *
98          * The vector becomes len elements in length.  Copy constructors are used
99          * to place the new elements in the vector. 
100          */
101         SVector(const T *val, long len)   { setAs(val, len); }
102
103         /* Shallow copy. */
104         SVector( const SVector &v );
105
106         /**
107          * \brief Free all memory used by the vector. 
108          *
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.
111          */
112         ~SVector() { empty(); }
113
114         /* Delete all items. */
115         void empty();
116
117         /**
118          * \brief Deep copy another vector into this vector.
119          *
120          * Copies the entire contents of the other vector into this vector. Any
121          * existing contents are first deleted. Equivalent to setAs.
122          */
123         void deepCopy( const SVector &v )     { setAs(v.data, v.length()); }
124
125         /* Perform a shallow copy of another vector. */
126         SVector &operator=( const SVector &v );
127
128
129         /*@{*/
130         /**
131          * \brief Insert one element at position pos.
132          *
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.
138          */
139         void insert(long pos, const T &val)     { insert(pos, &val, 1); }
140
141         /* Insert an array of values. */
142         void insert(long pos, const T *val, long len);
143
144         /**
145          * \brief Insert all the elements from another vector at position pos.
146          *
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()).
153          */
154         void insert(long pos, const SVector &v) { insert(pos, v.data, v.length()); }
155
156         /* Insert len copies of val into the vector. */
157         void insertDup(long pos, const T &val, long len);
158
159         /**
160          * \brief Insert one new element using the default constrcutor.
161          *
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.
167          */
168         void insertNew(long pos)                { insertNew(pos, 1); }
169
170         /* Insert len new items using default constructor. */
171         void insertNew(long pos, long len);
172         /*@}*/
173
174         /*@{*/
175         /** 
176          * \brief Remove one element at position pos.
177          *
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.
183          */
184         void remove(long pos)                   { remove(pos, 1); }
185
186         /* Delete a number of elements. */
187         void remove(long pos, long len);
188         /*@}*/
189
190         /*@{*/
191         /**
192          * \brief Replace one element at position pos.
193          *
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.
200          */
201         void replace(long pos, const T &val)     { replace(pos, &val, 1); }
202
203         /* Replace with an array of values. */
204         void replace(long pos, const T *val, long len);
205
206         /**
207          * \brief Replace at position pos with all the elements of another vector.
208          *
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.
218          */
219         void replace(long pos, const SVector &v) { replace(pos, v.data, v.length()); }
220
221         /* Replace len items with len copies of val. */
222         void replaceDup(long pos, const T &val, long len);
223
224         /**
225          * \brief Replace at position pos with one new element.
226          *
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.
233          */
234         void replaceNew(long pos)                { replaceNew(pos, 1); }
235
236         /* Replace len items at pos with newly constructed objects. */
237         void replaceNew(long pos, long len);
238         /*@}*/
239
240         /*@{*/
241
242         /**
243          * \brief Set the contents of the vector to be val exactly.
244          *
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.
248          */
249         void setAs(const T &val)             { setAs(&val, 1); }
250
251         /* Set to the contents of an array. */
252         void setAs(const T *val, long len);
253
254         /**
255          * \brief Set the vector to exactly the contents of another vector.
256          *
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.
260          */
261         void setAs(const SVector &v)         { setAs(v.data, v.length()); }
262
263         /* Set as len copies of item. */
264         void setAsDup(const T &item, long len);
265
266         /**
267          * \brief Set the vector to exactly one new item.
268          *
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.
272          */
273         void setAsNew()                      { setAsNew(1); }
274
275         /* Set as newly constructed objects using the default constructor. */
276         void setAsNew(long len);
277         /*@}*/
278
279         /*@{*/
280         /**
281          * \brief Append one elment to the end of the vector.
282          *
283          * Copy constructor is used to place the element in the vector.
284          */
285         void append(const T &val)                { replace(BaseTable::length(), &val, 1); }
286
287         /**
288          * \brief Append len elements to the end of the vector. 
289          *
290          * Copy constructors are used to place the elements in the vector. 
291          */
292         void append(const T *val, long len)       { replace(BaseTable::length(), val, len); }
293
294         /**
295          * \brief Append the contents of another vector.
296          *
297          * The other vector is left unchanged. Copy constructors are used to place
298          * the elements in the vector.
299          */
300         void append(const SVector &v)            
301                         { replace(BaseTable::length(), v.data, v.length()); }
302
303         /**
304          * \brief Append len copies of item.
305          *
306          * The copy constructor is used to place the item in the vector.
307          */
308         void appendDup(const T &item, long len)   { replaceDup(BaseTable::length(), item, len); }
309
310         /**
311          * \brief Append a single newly created item. 
312          *
313          * The new element is initialized with the default constructor.
314          */
315         void appendNew()                         { replaceNew(BaseTable::length(), 1); }
316
317         /**
318          * \brief Append len newly created items.
319          *
320          * The new elements are initialized with the default constructor.
321          */
322         void appendNew(long len)                  { replaceNew(BaseTable::length(), len); }
323         /*@}*/
324
325
326         /*@{*/
327         /**
328          * \brief Prepend one elment to the front of the vector.
329          *
330          * Copy constructor is used to place the element in the vector.
331          */
332         void prepend(const T &val)               { insert(0, &val, 1); }
333
334         /**
335          * \brief Prepend len elements to the front of the vector. 
336          *
337          * Copy constructors are used to place the elements in the vector. 
338          */
339         void prepend(const T *val, long len)      { insert(0, val, len); }
340
341         /**
342          * \brief Prepend the contents of another vector.
343          *
344          * The other vector is left unchanged. Copy constructors are used to place
345          * the elements in the vector.
346          */
347         void prepend(const SVector &v)           { insert(0, v.data, v.length()); }
348
349         /**
350          * \brief Prepend len copies of item.
351          *
352          * The copy constructor is used to place the item in the vector.
353          */
354         void prependDup(const T &item, long len)  { insertDup(0, item, len); }
355
356         /**
357          * \brief Prepend a single newly created item. 
358          *
359          * The new element is initialized with the default constructor.
360          */
361         void prependNew()                        { insertNew(0, 1); }
362
363         /**
364          * \brief Prepend len newly created items.
365          *
366          * The new elements are initialized with the default constructor.
367          */
368         void prependNew(long len)                 { insertNew(0, len); }
369         /*@}*/
370
371         /* Convenience access. */
372         T &operator[](int i) const { return BaseTable::data[i]; }
373         long size() const           { return BaseTable::length(); }
374
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; };
381
382         /** 
383          * \brief Shared Vector Iterator. 
384          * \ingroup iterators
385          */
386         struct Iter
387         {
388                 /* Construct, assign. */
389                 Iter() : ptr(0), ptrBeg(0), ptrEnd(0) { }
390
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 );
397
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 );
404
405                 /** \brief Less than end? */
406                 bool lte() const { return ptr != ptrEnd; }
407
408                 /** \brief At end? */
409                 bool end() const { return ptr == ptrEnd; }
410
411                 /** \brief Greater than beginning? */
412                 bool gtb() const { return ptr != ptrBeg; }
413
414                 /** \brief At beginning? */
415                 bool beg() const { return ptr == ptrBeg; }
416
417                 /** \brief At first element? */
418                 bool first() const { return ptr == ptrBeg+1; }
419
420                 /** \brief At last element? */
421                 bool last() const { return ptr == ptrEnd-1; }
422
423                 /* Return the position. */
424                 long pos() const { return ptr - ptrBeg - 1; }
425                 T &operator[](int i) const { return ptr[i]; }
426
427                 /** \brief Implicit cast to T*. */
428                 operator T*() const   { return ptr; }
429
430                 /** \brief Dereference operator returns T&. */
431                 T &operator *() const { return *ptr; }
432
433                 /** \brief Arrow operator returns T*. */
434                 T *operator->() const { return ptr; }
435
436                 /** \brief Move to next item. */
437                 T *operator++()       { return ++ptr; }
438
439                 /** \brief Move to next item. */
440                 T *operator++(int)    { return ptr++; }
441
442                 /** \brief Move to next item. */
443                 T *increment()        { return ++ptr; }
444
445                 /** \brief Move to previous item. */
446                 T *operator--()       { return --ptr; }
447
448                 /** \brief Move to previous item. */
449                 T *operator--(int)    { return ptr--; }
450
451                 /** \brief Move to previous item. */
452                 T *decrement()        { return --ptr; }
453
454                 /** \brief Return the next item. Does not modify this. */
455                 inline IterNext next() const { return IterNext(*this); }
456
457                 /** \brief Return the previous item. Does not modify this. */
458                 inline IterPrev prev() const { return IterPrev(*this); }
459
460                 /** \brief The iterator is simply a pointer. */
461                 T *ptr;
462
463                 /* For testing endpoints. */
464                 T *ptrBeg, *ptrEnd;
465         };
466
467         /** \brief Return first element. */
468         IterFirst first() { return IterFirst( *this ); }
469
470         /** \brief Return last element. */
471         IterLast last() { return IterLast( *this ); }
472
473 protected:
474         void makeRawSpaceFor(long pos, long len);
475
476         void setAsCommon(long len);
477         long replaceCommon(long pos, long len);
478         long insertCommon(long pos, long len);
479
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);
485 };
486
487 /**
488  * \brief Perform a shallow copy of the vector.
489  *
490  * Takes a reference to the contents of the other vector.
491  */
492 template <class T, class Resize> SVector<T, Resize>::
493                 SVector(const SVector<T, Resize> &v)
494 {
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);
503         }
504 }
505
506 /**
507  * \brief Shallow copy another vector into this vector.
508  *
509  * Takes a reference to the other vector. The contents of this vector are
510  * first emptied. 
511  *
512  * \returns A reference to this.
513  */
514 template <class T, class Resize> SVector<T, Resize> &
515                 SVector<T, Resize>:: operator=( const SVector &v )
516 {
517         /* First clean out the current contents. */
518         empty();
519
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);
528         }
529         return *this;
530 }
531
532 /* Init a vector iterator with just a vector. */
533 template <class T, class Resize> SVector<T, Resize>::
534                 Iter::Iter( const SVector &v ) 
535 {
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;
543         }
544 }
545
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 ) 
549 {
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;
557         }
558 }
559
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 ) 
563 {
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;
571         }
572 }
573
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 ) 
577 :
578         ptr(vn.i.ptr+1), 
579         ptrBeg(vn.i.ptrBeg),
580         ptrEnd(vn.i.ptrEnd)
581 {
582 }
583
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 ) 
587 :
588         ptr(vp.i.ptr-1),
589         ptrBeg(vp.i.ptrBeg),
590         ptrEnd(vp.i.ptrEnd)
591 {
592 }
593
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 )    
597 {
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; 
605         }
606         return *this;
607 }
608
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 )    
612 {
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; 
620         }
621         return *this;
622 }
623
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 )    
627 {
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; 
635         }
636         return *this;
637 }
638
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 )    
642 {
643         ptr = vn.i.ptr+1; 
644         ptrBeg = vn.i.ptrBeg;
645         ptrEnd = vn.i.ptrEnd;
646         return *this;
647 }
648
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 )    
652 {
653         ptr = vp.i.ptr-1; 
654         ptrBeg = vp.i.ptrBeg;
655         ptrEnd = vp.i.ptrEnd;
656         return *this;
657 }
658
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)
664 {
665         /* Get the current header. */
666         STabHead *head = ((STabHead*)BaseTable::data) - 1;
667
668         /* Ask the resizer what the new length will be. */
669         long newLen = Resize::upResize(head->allocLen, len);
670
671         /* Did the data grow? */
672         if ( newLen > head->allocLen ) {
673                 head->allocLen = newLen;
674
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();
680
681                 /* Save the data pointer. */
682                 BaseTable::data = (T*) (head + 1);
683         }
684 }
685
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)
692 {
693         /* Get the current header. */
694         STabHead *head = ((STabHead*)BaseTable::data) - 1;
695
696         /* Ask the resizer what the new length will be. */
697         long newLen = Resize::upResize(head->allocLen, len);
698
699         /* Dereferencing the existing data, decrement the refcount. */
700         head->refCount -= 1;
701
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();
706
707         head->refCount = 1;
708         head->allocLen = newLen;
709         head->tabLen = len;
710
711         /* Save the data pointer. */
712         BaseTable::data = (T*) (head + 1);
713 }
714
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)
720 {
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);
726
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();
732
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);
739         }
740 }
741
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)
746 {
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;
751
752                 /* Ask the resizer what the new length will be. */
753                 long newLen = Resize::downResize( head->allocLen, len );
754
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;
761                         }
762                         else {
763                                 /* Save the new allocated length. */
764                                 head->allocLen = newLen;
765
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();
771                                 
772                                 /* Save the new data ptr. */
773                                 BaseTable::data = (T*) (head + 1);
774                         }
775                 }
776         }
777 }
778
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)
785 {
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;
790
791                 /* Ask the resizer what the new length will be. */
792                 long newLen = Resize::downResize( head->allocLen, len );
793
794                 /* Detaching from the existing head, decrement the refcount. */
795                 head->refCount -= 1;
796
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();
801
802                 /* Save the new allocated length. */
803                 head->refCount = 1;
804                 head->allocLen = newLen;
805                 head->tabLen = len;
806
807                 /* Save the data pointer. */
808                 BaseTable::data = (T*) (head + 1);
809         }
810 }
811
812 /**
813  * \brief Free all memory used by the vector. 
814  *
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.
817  */
818 template <class T, class Resize> void SVector<T, Resize>::
819                 empty()
820 {
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;
825
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();
833
834                         /* Free the data space. */
835                         free( head );
836                 }
837
838                 /* Clear the pointer. */
839                 BaseTable::data = 0;
840         }
841 }
842
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)
848 {
849         if ( BaseTable::data != 0 ) {
850                 /* Get the header. */
851                 STabHead *head = ((STabHead*)BaseTable::data) - 1;
852
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();
860
861                         /* Adjust the allocated length. */
862                         if ( len < head->tabLen )
863                                 downResize( len );
864                         else if ( len > head->tabLen )
865                                 upResize( len );
866
867                         if ( BaseTable::data != 0 ) {
868                                 /* Get the header again and set the length. */
869                                 head = ((STabHead*)BaseTable::data) - 1;
870                                 head->tabLen = len;
871                         }
872                 }
873                 else {
874                         /* Just detach from the data. */
875                         head->refCount -= 1;
876                         BaseTable::data = 0;
877                         
878                         /* Make enough space. This will set the length. */
879                         upResizeFromEmpty( len );
880                 }
881         }
882         else {
883                 /* The table is currently empty. Make enough space. This will set the
884                  * length. */
885                 upResizeFromEmpty( len );
886         }
887 }
888
889 /**
890  * \brief Set the contents of the vector to be len elements exactly. 
891  *
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. 
895  */
896 template <class T, class Resize> void SVector<T, Resize>::
897                 setAs(const T *val, long len)
898 {
899         /* Common stuff for setting the array to len long. */
900         setAsCommon( len );
901
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);
907 }
908
909
910 /**
911  * \brief Set the vector to len copies of item.
912  *
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.
916  */
917 template <class T, class Resize> void SVector<T, Resize>::
918                 setAsDup(const T &item, long len)
919 {
920         /* Do the common stuff for setting the array to len long. */
921         setAsCommon( len );
922
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);
927 }
928
929 /**
930  * \brief Set the vector to exactly len new items.
931  *
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.
935  */
936 template <class T, class Resize> void SVector<T, Resize>::
937                 setAsNew(long len)
938 {
939         /* Do the common stuff for setting the array to len long. */
940         setAsCommon( len );
941
942         /* Create items using default constructor. */
943         T *dst = BaseTable::data;
944         for ( long i = 0; i < len; i++, dst++ )
945                 new(dst) T();
946 }
947
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)
952 {
953         if ( BaseTable::data != 0 ) {
954                 /* Get the header. */
955                 STabHead *head = ((STabHead*)BaseTable::data) - 1;
956
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;
962
963                 /* The end is the one past the last item that we want to write to. */
964                 long i, endPos = pos + len;
965
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 );
970
971                                 /* Get the header again, whose addr may have changed after
972                                  * resizing. */
973                                 head = ((STabHead*)BaseTable::data) - 1;
974
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();
979                 
980                                 /* We are extending the vector, set the new data length. */
981                                 head->tabLen = endPos;
982                         }
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();
988                         }
989                 }
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;
995
996                         /* Duplicate and grow up to endPos. This will set the length. */
997                         upResizeDup( newLen );
998
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);
1004
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);
1009                 }
1010         }
1011         else {
1012                 /* There is no data initially, must grow from zero. This will set the
1013                  * new length. */
1014                 upResizeFromEmpty( len );
1015         }
1016
1017         return pos;
1018 }
1019
1020
1021 /**
1022  * \brief Replace len elements at position pos.
1023  *
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.
1031  */
1032 template <class T, class Resize> void SVector<T, Resize>::
1033                 replace(long pos, const T *val, long len)
1034 {
1035         /* Common work for replacing in the vector. */
1036         pos = replaceCommon( pos, len );
1037
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);
1043 }
1044
1045 /**
1046  * \brief Replace at position pos with len copies of an item.
1047  *
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.
1055  */
1056 template <class T, class Resize> void SVector<T, Resize>::
1057                 replaceDup(long pos, const T &val, long len)
1058 {
1059         /* Common replacement stuff. */
1060         pos = replaceCommon( pos, len );
1061
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);
1066 }
1067
1068 /**
1069  * \brief Replace at position pos with len new elements.
1070  *
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.
1078  */
1079 template <class T, class Resize> void SVector<T, Resize>::
1080                 replaceNew(long pos, long len)
1081 {
1082         /* Do the common replacement stuff. */
1083         pos = replaceCommon( pos, len );
1084
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();
1089 }
1090
1091 /**
1092  * \brief Remove len elements at position pos.
1093  *
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.
1099  */
1100 template <class T, class Resize> void SVector<T, Resize>::
1101                 remove(long pos, long len)
1102 {
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;
1107
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;
1112
1113                 /* The first position after the last item deleted. */
1114                 long endPos = pos + len;
1115
1116                 /* The New data length. */
1117                 long i, newLen = head->tabLen - len;
1118
1119                 if ( head->refCount == 1 ) {
1120                         /* We are the only ones using the data. We can reuse 
1121                          * the existing space. */
1122
1123                         /* The place in the data we are deleting at. */
1124                         T *dst = BaseTable::data + pos;
1125
1126                         /* Call Destructors. */
1127                         T *item = BaseTable::data + pos;
1128                         for ( i = 0; i < len; i += 1, item += 1 )
1129                                 item->~T();
1130
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);
1135
1136                         /* Shrink the data if necessary. */
1137                         downResize( newLen );
1138
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;
1144                         }
1145                 }
1146                 else {
1147                         /* Must detach from the common data. Just copy the non-deleted
1148                          * items from the common data. */
1149
1150                         /* Duplicate and grow down to newLen. This will set the length. */
1151                         downResizeDup( newLen );
1152
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);
1158
1159                         /* ... and the second half. */
1160                         for ( i += len, src += len; i < head->tabLen; i++, src++, dst++ )
1161                                 new(dst) T(*src);
1162                 }
1163         }
1164 }
1165
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)
1170 {
1171         if ( BaseTable::data != 0 ) {
1172                 /* Get the header. */
1173                 STabHead *head = ((STabHead*)BaseTable::data) - 1;
1174
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;
1180
1181                 /* Calculate the new length. */
1182                 long i, newLen = head->tabLen + len;
1183
1184                 if ( head->refCount == 1 ) {
1185                         /* Up resize, we are growing. */
1186                         upResize( newLen );
1187
1188                         /* Get the header again, (the addr may have changed after
1189                          * resizing). */
1190                         head = ((STabHead*)BaseTable::data) - 1;
1191
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) );
1196                         }
1197
1198                         /* Grow the length by the len inserted. */
1199                         head->tabLen += len;
1200                 }
1201                 else {
1202                         /* Need to detach from the existing array. Copy over the other
1203                          * parts. This will set the length. */
1204                         upResizeDup( newLen );
1205
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);
1211
1212                         /* ... and the second half. */
1213                         for ( dst += len; i < head->tabLen; i++, src++, dst++ )
1214                                 new(dst) T(*src);
1215                 }
1216         }
1217         else {
1218                 /* There is no existing data. Start from zero. This will set the
1219                  * length. */
1220                 upResizeFromEmpty( len );
1221         }
1222
1223         return pos;
1224 }
1225
1226
1227 /**
1228  * \brief Insert len elements at position pos.
1229  *
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.
1235  */
1236 template <class T, class Resize> void SVector<T, Resize>::
1237                 insert(long pos, const T *val, long len)
1238 {
1239         /* Do the common insertion stuff. */
1240         pos = insertCommon( pos, len );
1241
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);
1247 }
1248
1249 /**
1250  * \brief Insert len copies of item at position pos.
1251  *
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.
1257  */
1258 template <class T, class Resize> void SVector<T, Resize>::
1259                 insertDup(long pos, const T &item, long len)
1260 {
1261         /* Do the common insertion stuff. */
1262         pos = insertCommon( pos, len );
1263
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);
1268 }
1269
1270
1271 /**
1272  * \brief Insert len new elements using the default constructor.
1273  *
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.
1278  */
1279 template <class T, class Resize> void SVector<T, Resize>::
1280                 insertNew(long pos, long len)
1281 {
1282         /* Do the common insertion stuff. */
1283         pos = insertCommon( pos, len );
1284
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();
1289 }
1290
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)
1296 {
1297         if ( BaseTable::data != 0 ) {
1298                 /* Get the header. */
1299                 STabHead *head = ((STabHead*)BaseTable::data) - 1;
1300
1301                 /* Calculate the new length. */
1302                 long i, newLen = head->tabLen + len;
1303
1304                 if ( head->refCount == 1 ) {
1305                         /* Up resize, we are growing. */
1306                         upResize( newLen );
1307
1308                         /* Get the header again, (the addr may have changed after
1309                          * resizing). */
1310                         head = ((STabHead*)BaseTable::data) - 1;
1311
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) );
1316                         }
1317
1318                         /* Grow the length by the len inserted. */
1319                         head->tabLen += len;
1320                 }
1321                 else {
1322                         /* Need to detach from the existing array. Copy over the other
1323                          * parts. This will set the length. */
1324                         upResizeDup( newLen );
1325
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);
1331
1332                         /* ... and the second half. */
1333                         for ( dst += len; i < head->tabLen; i++, src++, dst++ )
1334                                 new(dst) T(*src);
1335                 }
1336         }
1337         else {
1338                 /* There is no existing data. Start from zero. This will set the
1339                  * length. */
1340                 upResizeFromEmpty( len );
1341         }
1342 }
1343
1344
1345 #ifdef AAPL_NAMESPACE
1346 }
1347 #endif
1348
1349
1350 #endif /* _AAPL_SVECTOR_H */