ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/GVec.hh
Revision: 248
Committed: Wed May 23 22:10:55 2012 UTC (7 years, 2 months ago) by gpertea
File size: 20755 byte(s)
Log Message:
put GVec and GPVec in GVec.hh, added GIntervalTree.hh

Line User Rev File contents
1 gpertea 248 //---------------------------------------------------------------------------
2     /*
3     Sortable collection of pointers to objects
4     */
5    
6     #ifndef _GVec_HH
7     #define _GVec_HH
8    
9     #include "GBase.h"
10     //#include "assert.h"
11    
12     #ifdef __LINE__
13     #define GVEC_INDEX_ERR "GVec error (%s:%d):Invalid index: %d\n"
14     #define TEST_INDEX(x) \
15     if (x<0 || x>=fCount) GError(GVEC_INDEX_ERR, __FILE__,__LINE__, x)
16     #else
17     #define GVEC_INDEX_ERR "GVec error: invalid index: %d\n"
18     #define TEST_INDEX(x) \
19     if (x<0 || x>=fCount) GError(GVEC_INDEX_ERR, x, __FILE__,__LINE__)
20     #endif
21    
22     #define GVEC_CAPACITY_ERR "GVec error: invalid capacity: %d\n"
23     #define GVEC_COUNT_ERR "GVec error: invalid count: %d\n"
24    
25     #define MAXLISTSIZE INT_MAX-1
26    
27     #define FREEDATA (fFreeProc!=NULL)
28    
29     //basic template for array of objects;
30     //so it doesn't require comparison operators to be defined
31     template <class OBJ> class GVec {
32     protected:
33     OBJ* fArray;
34     int fCount;
35     int fCapacity;
36     public:
37     GVec(int init_capacity=2);
38     GVec(GVec<OBJ>& array); //copy constructor
39     const GVec<OBJ>& operator=(GVec<OBJ>& array); //copy operator
40     virtual ~GVec();
41     void idxInsert(int idx, OBJ& item);
42     void Grow();
43     void Grow(int idx, OBJ& item);
44     void Reverse(); //WARNING: will break the sort order if SORTED!
45     int Add(OBJ* item); // simply append to the end of fArray, reallocating as needed
46     int Add(OBJ item) { return Add(&item); } //both will CREATE a new OBJ and COPY to it
47     // using OBJ copy operator=
48     // -- stack/queue usage:
49     //int Push(OBJ& item) { return Add(&item); }
50     int Push(OBJ item) { return Add(&item); }
51     OBJ Pop();// Stack use; removes and returns a copy of the last item
52     OBJ Shift(); //Queue use: removes and returns a copy of the first item
53    
54     void Add(GVec<OBJ>& list); //append copies of all items from another list
55     OBJ& Get(int idx) {
56     TEST_INDEX(idx);
57     return fArray[idx];
58     }
59     OBJ& operator[](int i) {
60     TEST_INDEX(i);
61     return fArray[i];
62     }
63     OBJ& Last() {
64     TEST_INDEX(fCount-1);
65     return fArray[fCount-1];
66     }
67     OBJ& First() {
68     TEST_INDEX(0);
69     return fArray[0];
70     }
71     void Clear();
72     void Insert(int idx, OBJ* item);
73     void Delete(int index);
74     void Replace(int idx, OBJ& item); //Put, use operator= to copy
75     void Exchange(int idx1, int idx2);
76     void Swap(int idx1, int idx2) { Exchange(idx1, idx2); }
77     int Capacity() { return fCapacity; }
78     //this will reject identical items in sorted lists only!
79     void setCapacity(int NewCapacity);
80     int Count() { return fCount; }
81    
82     void setCount(int NewCount); // will trim or expand the array as needed
83     void setCount(int NewCount, OBJ& v); //same as setCount(), but if expanding, new objects are set to v
84     void Resize(int NewCount) { setCount(NewCount); }
85     void Resize(int NewCount, OBJ& v) { setCount(NewCount, v); }
86    
87     void Move(int curidx, int newidx);
88     bool isEmpty() { return fCount==0; }
89     bool notEmpty() { return fCount>0; }
90     };
91    
92     //---- template for dynamic array of object pointers
93     //---- it's faster than GVec<OBJ*> and has item deallocation awareness
94     template <class OBJ> class GPVec {
95     protected:
96     OBJ** fList; //pointer to an array of pointers to objects
97     int fCount; //total number of entries in list
98     int fCapacity; //current allocated size
99     GFreeProc* fFreeProc; //useful for deleting objects
100     //---
101     void Expand();
102     void Grow();
103     void Grow(int idx, OBJ* newitem);
104     void setCount(int NewCount); //will trim/expand the array as needed
105     public:
106     static void DefaultFreeProc(pointer item) {
107     delete (OBJ*)item;
108     }
109     virtual ~GPVec();
110     GPVec(int init_capacity=2, bool free_elements=true); //also the default constructor
111     GPVec(GPVec<OBJ>& list); //copy constructor?
112     GPVec(GPVec<OBJ>* list); //kind of a copy constructor
113     const GPVec<OBJ>& operator=(GPVec<OBJ>& list);
114     OBJ* Get(int i);
115     OBJ* operator[](int i) { return this->Get(i); }
116     void Reverse(); //reverse pointer array; WARNING: will break the sort order if sorted!
117     void freeItem(int idx); //calls fFreeProc (or DefaultFreeProc) on fList[idx] and sets NULL there, doesn't pack!
118     //it will free even if fFreeProc is NULL!
119     void setFreeItem(GFreeProc *freeProc) { fFreeProc=freeProc; }
120     void setFreeItem(bool doFree) {
121     if (doFree) fFreeProc=DefaultFreeProc;
122     else fFreeProc=NULL;
123     }
124     // -- stack usage:
125     int Push(OBJ* item) { return Add(item); }
126     OBJ* Pop();// Stack use; removes and returns last item,but does NOT FREE it
127     OBJ* Shift(); //Queue use: removes and returns first item, but does NOT FREE it
128     void deallocate_item(OBJ* item); //forcefully call fFreeProc or delete on item
129     void Clear();
130     void Exchange(int idx1, int idx2);
131     void Swap(int idx1, int idx2) { Exchange(idx1, idx2); }
132     OBJ* First() { return (fCount>0)?fList[0]:NULL; }
133     OBJ* Last() { return (fCount>0)?fList[fCount-1]:NULL;}
134     bool isEmpty() { return fCount==0; }
135     bool notEmpty() { return fCount>0; }
136     int Capacity() { return fCapacity; }
137     int Count() { return fCount; }
138     void setCapacity(int NewCapacity);
139     int Add(OBJ* item); //simply append the pointer copy
140     void Add(GPVec<OBJ>& list); //add all pointers from another list
141     void Insert(int idx, OBJ* item);
142     void Move(int curidx, int newidx);
143     void Put(int idx, OBJ* item);
144     void Pack();
145     void Delete(int index); //also frees the item if fFreeProc!=NULL, and shifts the successor items
146     void Forget(int idx); //simply places a NULL at fList[idx], nothing else
147     int RemovePtr(pointer item); //always use linear search to find the pointer! calls Delete() if found
148     int IndexOf(pointer item); //a linear search for pointer address only!
149     };
150    
151    
152    
153    
154     //-------------------- TEMPLATE IMPLEMENTATION-------------------------------
155    
156     template <class OBJ> GVec<OBJ>::GVec(int init_capacity) {
157     fCount=0;
158     fCapacity=0;
159     fArray=NULL;
160     setCapacity(init_capacity);
161     }
162    
163     template <class OBJ> GVec<OBJ>::GVec(GVec<OBJ>& array) { //copy constructor
164     this->fCount=array.fCount;
165     this->fCapacity=array.fCapacity;
166     this->fArray=NULL;
167     if (this->fCapacity>0) {
168     //GMALLOC(fArray, fCapacity*sizeof(OBJ));
169     fArray=new OBJ[this->fCapacity];
170     }
171     this->fCount=array.fCount;
172     // uses OBJ operator=
173     for (int i=0;i<this->fCount;i++) fArray[i]=array[i];
174     }
175    
176     template <class OBJ> const GVec<OBJ>& GVec<OBJ>::operator=(GVec<OBJ>& array) {
177     if (&array==this) return *this;
178     Clear();
179     fCount=array.fCount;
180     fCapacity=array.fCapacity;
181     if (fCapacity>0) {
182     //GMALLOC(fArray, fCapacity*sizeof(OBJ));
183     fArray=new OBJ[this->fCapacity];
184     }
185     fCount=array.fCount;
186     // uses OBJ operator=
187     for (int i=0;i<fCount;i++) {
188     fArray[i]=array[i];
189     }
190     return *this;
191     }
192    
193     template <class OBJ> GVec<OBJ>::~GVec() {
194     this->Clear();
195     }
196    
197    
198     template <class OBJ> void GVec<OBJ>::setCapacity(int NewCapacity) {
199     if (NewCapacity < fCount || NewCapacity > MAXLISTSIZE)
200     GError(GVEC_CAPACITY_ERR, NewCapacity);
201     //error: capacity not within range
202     if (NewCapacity!=fCapacity) {
203     if (NewCapacity==0) {
204     delete[] fArray;
205     }
206     else {
207     //GREALLOC(fArray, NewCapacity*sizeof(OBJ));
208     OBJ* oldArray=fArray;
209     fArray=new OBJ[NewCapacity];
210     for (int i=0;i<this->fCount;i++) {
211     fArray[i] = oldArray[i]; // operator=
212     }
213     delete[] oldArray;
214     }
215     fCapacity=NewCapacity;
216     }
217     }
218    
219     template <class OBJ> void GVec<OBJ>::Clear() {
220     setCount(0);
221     setCapacity(0); //so the array itself is deallocated too!
222     }
223    
224     template <class OBJ> void GVec<OBJ>::Grow() {
225     int delta;
226     if (fCapacity > 64 ) {
227     delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);
228     }
229     else {
230     delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;
231     }
232     setCapacity(fCapacity + delta);
233     }
234    
235     template <class OBJ> void GVec<OBJ>::Reverse() {
236     int l=0;
237     int r=fCount-1;
238     OBJ c;
239     while (l<r) {
240     c=fArray[l];fArray[l]=fArray[r];
241     fArray[r]=c;
242     l++;r--;
243     }
244     }
245    
246     template <class OBJ> void GVec<OBJ>::Grow(int idx, OBJ& item) {
247     int delta;
248     /*
249     if (fCapacity > 64) delta = fCapacity/4;
250     else if (fCapacity > 8) delta = 16;
251     else delta = 4;
252     */
253     if (fCapacity > 64 ) {
254     delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);
255     }
256     else {
257     delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;
258     }
259     int NewCapacity=fCapacity+delta;
260     if (NewCapacity <= fCount || NewCapacity >= MAXLISTSIZE)
261     GError(GVEC_CAPACITY_ERR, NewCapacity);
262     //error: capacity not within range
263    
264     if (NewCapacity!=fCapacity) {
265     if (NewCapacity==0) {
266     //GFREE(fArray);
267     delete[] fArray;
268     fArray=NULL;
269     }
270     else { //add the new item
271     if (idx==fCount) { //append item
272     //GREALLOC(fArray, NewCapacity*sizeof(OBJ));
273     setCapacity(NewCapacity);
274     fArray[idx]=item;
275     }
276     else { //insert item at idx
277     OBJ* newList;
278     //GMALLOC(newList, NewCapacity*sizeof(OBJ));
279     newList=new OBJ[NewCapacity];
280     //copy data before idx
281     //memmove(&newList[0],&fArray[0], idx*sizeof(OBJ));
282     // operator= required!
283     for (int i=0;i<idx;i++) {
284     newList[i]=fArray[i];
285     }
286     newList[idx]=item;
287     //copy data after idx
288     //memmove(&newList[idx+1],&fArray[idx], (fCount-idx)*sizeof(OBJ));
289     for (int i=idx+1;i<=fCount;i++) {
290     newList[i]=fArray[i-1];
291     }
292     //memset(&newList[fCount+1], 0, (NewCapacity-fCount-1)*sizeof(OBJ));
293     //data copied:
294     //GFREE(fArray);
295     delete[] fArray;
296     fArray=newList;
297     }
298     fCount++;
299     }
300     fCapacity=NewCapacity;
301     }
302     }
303    
304    
305     template <class OBJ> int GVec<OBJ>::Add(OBJ* item) {
306     if (item==NULL) return -1;
307     if (fCount==fCapacity) Grow();
308     fArray[fCount] = *item; //OBJ::operator= must copy OBJ properly!
309     fCount++;
310     return fCount-1;
311     }
312    
313    
314     template <class OBJ> void GVec<OBJ>::Add(GVec<OBJ>& list) {
315     if (list.Count()==0) return;
316     //simply copy
317     setCapacity(fCapacity+list.fCount);
318     int s=fCount;
319     for (int i=0;i<list.fCount;i++)
320     fArray[s+i]=list.fArray[i];
321     fCount+=list.fCount;
322     }
323    
324    
325     //Stack usage:
326     template <class OBJ> OBJ GVec<OBJ>::Pop() {
327     if (fCount<=0) GError("Error: invalid GVec::Pop() operation!\n");
328     fCount--;
329     //OBJ o(fArray[fCount]); //copy constructor
330     //o=fList[fCount];
331     //fArray[fCount]=NULL;
332     return fArray[fCount]; //copy of the last element
333     }
334    
335     //Queue usage:
336     template <class OBJ> OBJ GVec<OBJ>::Shift() {
337     if (fCount<=0) GError("Error: invalid GVec::Shift() operation!\n");
338     fCount--;
339     OBJ o(fArray[0]); //copy constructor
340     if (fCount>0)
341     memmove(&fArray[0], &fArray[1], (fCount)*sizeof(OBJ));
342     //fList[fCount]=NULL; //not that it matters..
343     return o;
344     }
345    
346     template <class OBJ> void GVec<OBJ>::idxInsert(int idx, OBJ& item) {
347     //idx must be the new position this new item must have
348     //so the allowed range is [0..fCount]
349     //the old idx item all the above will be shifted to idx+1
350     if (idx<0 || idx>fCount) GError(GVEC_INDEX_ERR, idx);
351     if (fCount==fCapacity) { //need to resize the array
352     Grow(idx, item); //expand and also copy/move data and insert the new item
353     return;
354     }
355     //move data around to make room for the new item
356     if (idx<fCount) {
357     //copy after-idx items (shift up)
358     //memmove(&newList[idx+1],&fArray[idx], (fCount-idx)*sizeof(OBJ));
359     for (int i=fCount; i>idx; i--) {
360     fArray[i]=fArray[i-1];
361     }
362     }
363     fArray[idx]=item;
364     fCount++;
365     }
366    
367     template <class OBJ> void GVec<OBJ>::Insert(int idx, OBJ* item) {
368     //idx can be [0..fCount] so an item can be actually added
369     idxInsert(idx, item);
370     }
371    
372    
373     template <class OBJ> void GVec<OBJ>::Move(int curidx, int newidx) {
374     if (curidx!=newidx || newidx>=fCount)
375     GError(GVEC_INDEX_ERR, newidx);
376     OBJ tmp=fArray[curidx]; //copy constructor here
377     fArray[curidx]=fArray[newidx];
378     fArray[newidx]=tmp;
379     }
380    
381    
382     template <class OBJ> void GVec<OBJ>::Replace(int idx, OBJ& item) {
383     TEST_INDEX(idx);
384     fArray[idx]=item;
385     }
386    
387     template <class OBJ> void GVec<OBJ>::Exchange(int idx1, int idx2) {
388     TEST_INDEX(idx1);
389     TEST_INDEX(idx2);
390     OBJ item=fArray[idx1];
391     fArray[idx1]=fArray[idx2];
392     fArray[idx2]=item;
393     }
394    
395    
396     template <class OBJ> void GVec<OBJ>::Delete(int index) {
397     TEST_INDEX(index);
398     fCount--;
399     while (index<fCount) {
400     //move higher elements if any (shift down)
401     //memmove(&fArray[index], &fArray[index+1], (fCount-index)*sizeof(OBJ));
402     fArray[index]=fArray[index+1];
403     index++;
404     }
405     }
406    
407     template <class OBJ> void GVec<OBJ>::setCount(int NewCount) {
408     if (NewCount<0 || NewCount > MAXLISTSIZE)
409     GError(GVEC_COUNT_ERR, NewCount);
410     if (NewCount > fCapacity) setCapacity(NewCount);
411     fCount = NewCount;
412     }
413    
414     template <class OBJ> void GVec<OBJ>::setCount(int NewCount, OBJ& v) {
415     if (NewCount<0 || NewCount > MAXLISTSIZE)
416     GError(GVEC_COUNT_ERR, NewCount);
417     if (NewCount > fCapacity) setCapacity(NewCount);
418     if (NewCount>fCount) {
419     for (int i=fCount;i<NewCount;i++)
420     fArray[i]=v;
421     }
422     fCount = NewCount;
423     }
424    
425     //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
426     //*=> GPVec implementation
427    
428     template <class OBJ> GPVec<OBJ>::GPVec(GPVec& list) { //copy constructor
429     fCount=list.fCount;
430     fCapacity=list.fCapacity;
431     if (fCapacity>0) {
432     GMALLOC(fList, fCapacity*sizeof(OBJ*));
433     }
434     fFreeProc=list.fFreeProc;
435     fCount=list.fCount;
436     memcpy(fList, list.fList, fCount*sizeof(OBJ*));
437     //for (int i=0;i<list.Count();i++) Add(list[i]);
438     }
439    
440     template <class OBJ> GPVec<OBJ>::GPVec(GPVec* plist) { //another copy constructor
441     fCount=0;
442     fCapacity=plist->fCapacity;
443     fList=NULL;
444     if (fCapacity>0) {
445     GMALLOC(fList, fCapacity*sizeof(OBJ*));
446     }
447     fFreeProc=plist->fFreeProc;
448     fCount=plist->fCount;
449     memcpy(fList, plist->fList, fCount*sizeof(OBJ*));
450     //for (int i=0;i<list->fCount;i++) Add(plist->Get(i));
451     }
452    
453     template <class OBJ> const GPVec<OBJ>& GPVec<OBJ>::operator=(GPVec& list) {
454     if (&list!=this) {
455     Clear();
456     fFreeProc=list.fFreeProc;
457     //Attention: the object *POINTERS* are copied,
458     // but the actual object content is NOT duplicated
459     for (int i=0;i<list.Count();i++) Add(list[i]);
460     }
461     return *this;
462     }
463    
464    
465     template <class OBJ> void GPVec<OBJ>::Add(GPVec<OBJ>& list) {
466     if (list.Count()==0) return;
467     //simply copy the pointers! -- the objects will be shared
468     setCapacity(fCapacity+list.fCount);
469     memcpy( & (fList[fCount]), list.fList, list.fCount*sizeof(OBJ*));
470     fCount+=list.fCount;
471     }
472    
473     template <class OBJ> void GPVec<OBJ>::Reverse() {
474     int l=0;
475     int r=fCount-1;
476     OBJ* c;
477     while (l<r) {
478     c=fList[l];fList[l]=fList[r];
479     fList[r]=c;
480     l++;r--;
481     }
482     }
483    
484     template <class OBJ> GPVec<OBJ>::GPVec(int init_capacity, bool free_elements) {
485     fCount=0;
486     fCapacity=0;
487     fList=NULL;
488     fFreeProc=(free_elements) ? DefaultFreeProc : NULL;
489     setCapacity(init_capacity);
490     }
491    
492     template <class OBJ> GPVec<OBJ>::~GPVec() {
493     this->Clear();//this will free the items if fFreeProc is defined
494     }
495    
496     template <class OBJ> void GPVec<OBJ>::setCapacity(int NewCapacity) {
497     if (NewCapacity < fCount || NewCapacity > MAXLISTSIZE)
498     GError(GVEC_CAPACITY_ERR, NewCapacity);
499     //error: capacity not within range
500     if (NewCapacity!=fCapacity) {
501     if (NewCapacity==0) {
502     GFREE(fList);
503     }
504     else {
505     GREALLOC(fList, NewCapacity*sizeof(OBJ*));
506     }
507     fCapacity=NewCapacity;
508     }
509     }
510    
511     template <class OBJ> void GPVec<OBJ>::deallocate_item(OBJ* item) {
512     if (item==NULL) return;
513     if (FREEDATA) {
514     (*fFreeProc)(item);
515     }
516     else {
517     delete item;
518     }
519     }
520    
521     template <class OBJ> void GPVec<OBJ>::Clear() {
522     if (FREEDATA) {
523     for (int i=0; i<fCount; i++) {
524     (*fFreeProc)(fList[i]);
525     }
526     }
527     setCount(0);
528     setCapacity(0); //so the array itself is deallocated too!
529     }
530    
531     template <class OBJ> void GPVec<OBJ>::Exchange(int idx1, int idx2) {
532     TEST_INDEX(idx1);
533     TEST_INDEX(idx2);
534     OBJ* item=fList[idx1];
535     fList[idx1]=fList[idx2];
536     fList[idx2]=item;
537     }
538    
539     template <class OBJ> void GPVec<OBJ>::Expand() {
540     if (fCount==fCapacity) Grow();
541     //return this;
542     }
543    
544     template <class OBJ> OBJ* GPVec<OBJ>::Get(int idx) {
545     TEST_INDEX(idx);
546     return fList[idx];
547     }
548    
549     template <class OBJ> void GPVec<OBJ>::Grow() {
550     int delta;
551     if (fCapacity > 64 ) {
552     delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);
553     }
554     else {
555     delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;
556     }
557     setCapacity(fCapacity + delta);
558     }
559    
560     template <class OBJ> void GPVec<OBJ>::Grow(int idx, OBJ* newitem) {
561     int delta;
562     if (fCapacity > 64 ) {
563     delta = (fCapacity > 0xFFF) ? 0x100 : (fCapacity>>4);
564     }
565     else {
566     delta = (fCapacity>8) ? (fCapacity>>2) : 1 ;
567     }
568     // setCapacity(fCapacity + delta);
569     int NewCapacity=fCapacity+delta;
570     if (NewCapacity <= fCount || NewCapacity > MAXLISTSIZE)
571     GError(GVEC_CAPACITY_ERR, NewCapacity);
572     //error: capacity not within range
573     if (NewCapacity!=fCapacity) {
574     if (NewCapacity==0) {
575     GFREE(fList);
576     }
577     else {//add the new item
578     if (idx==fCount) {
579     GREALLOC(fList, NewCapacity*sizeof(OBJ*));
580     fList[idx]=newitem;
581     }
582     else {
583     OBJ** newList;
584     GMALLOC(newList, NewCapacity*sizeof(OBJ*));
585     //copy data before idx
586     memmove(&newList[0],&fList[0], idx*sizeof(OBJ*));
587     newList[idx]=newitem;
588     //copy data after idx
589     memmove(&newList[idx+1],&fList[idx], (fCount-idx)*sizeof(OBJ*));
590     memset(&newList[fCount+1], 0, (NewCapacity-fCount-1)*sizeof(OBJ*));
591     //data copied:
592     GFREE(fList);
593     fList=newList;
594     }
595     fCount++;
596     }
597     fCapacity=NewCapacity;
598     }
599     }
600    
601     template <class OBJ> int GPVec<OBJ>::IndexOf(pointer item) {
602     int result=-1;
603     for (int i=0;i<fCount;i++) {
604     if (item==(pointer)fList[i]) return i;
605     }
606     return -1;
607     }
608    
609     template <class OBJ> int GPVec<OBJ>::Add(OBJ* item) {
610     int result;
611     if (item==NULL) return -1;
612     result = fCount;
613     if (result==fCapacity) this->Grow();
614     fList[result]=item;
615     fCount++;
616     return fCount-1;
617     }
618    
619     template <class OBJ> void GPVec<OBJ>::Insert(int idx, OBJ* item) {
620     //idx can be [0..fCount] so an item can be actually added
621     if (idx<0 || idx>fCount) GError(GVEC_INDEX_ERR, idx);
622     if (fCount==fCapacity) {
623     Grow(idx, item);
624     return;
625     }
626     if (idx<fCount)
627     memmove(&fList[idx+1], &fList[idx], (fCount-idx)*sizeof(OBJ*));
628     fList[idx]=item;
629     fCount++;
630     }
631    
632     template <class OBJ> void GPVec<OBJ>::Move(int curidx, int newidx) {
633     //BE_UNSORTED; //cannot do that in a sorted list!
634     if (curidx!=newidx || newidx>=fCount)
635     GError(GVEC_INDEX_ERR, newidx);
636     OBJ* p;
637     p=Get(curidx);
638     //this is a delete:
639     fCount--;
640     if (curidx<fCount)
641     memmove(&fList[curidx], &fList[curidx+1], (fCount-curidx)*sizeof(OBJ*));
642     //-this was instead of delete
643     Insert(newidx, p);
644     }
645    
646     template <class OBJ> void GPVec<OBJ>::Put(int idx, OBJ* item) {
647     //WARNING: this will never free the replaced item!
648     TEST_INDEX(idx);
649     fList[idx]=item;
650     }
651    
652     template <class OBJ> void GPVec<OBJ>::Forget(int idx) {
653     TEST_INDEX(idx);
654     fList[idx]=NULL; //user should free that somewhere else
655     }
656    
657     template <class OBJ> void GPVec<OBJ>::freeItem(int idx) {
658     TEST_INDEX(idx);
659     if (fFreeProc!=NULL) {
660     (*fFreeProc)(fList[idx]);
661     }
662     else this->DefaultFreeProc(fList[idx]);
663     fList[idx]=NULL;
664     }
665    
666     template <class OBJ> void GPVec<OBJ>::Delete(int index) {
667     TEST_INDEX(index);
668     if (fFreeProc!=NULL && fList[index]!=NULL) {
669     (*fFreeProc)(fList[index]); //freeItem
670     }
671     fList[index]=NULL;
672     fCount--;
673     if (index<fCount) //move higher elements if any
674     memmove(&fList[index], &fList[index+1], (fCount-index)*sizeof(OBJ*));
675     }
676    
677     //Stack usage:
678     template <class OBJ> OBJ* GPVec<OBJ>::Pop() {
679     if (fCount<=0) return NULL;
680     fCount--;
681     OBJ* o=fList[fCount];
682     fList[fCount]=NULL;
683     return o;
684     }
685    
686     //Queue usage:
687     template <class OBJ> OBJ* GPVec<OBJ>::Shift() {
688     if (fCount<=0) return NULL;
689     fCount--;
690     OBJ* o=fList[0];
691     if (fCount>0)
692     memmove(&fList[0], &fList[1], (fCount)*sizeof(OBJ*));
693     fList[fCount]=NULL; //not that it matters..
694     return o;
695     }
696    
697     //linear search for the pointer address
698     template <class OBJ> int GPVec<OBJ>::RemovePtr(pointer item) {
699     if (item==NULL) return -1;
700     for (int i=0;i<fCount;i++)
701     if ((pointer)fList[i] == item) {
702     Delete(i);
703     return i;
704     }
705     return -1; //not found
706     }
707    
708     template <class OBJ> void GPVec<OBJ>::Pack() {//also frees items!
709     for (int i=fCount-1; i>=0; i--)
710     if (fList[i]==NULL) Delete(i); //shift rest of fList content accordingly
711     }
712    
713     template <class OBJ> void GPVec<OBJ>::setCount(int NewCount) {
714     if (NewCount<0 || NewCount > MAXLISTSIZE)
715     GError(GVEC_COUNT_ERR, NewCount);
716     if (NewCount > fCapacity) setCapacity(NewCount);
717     if (NewCount > fCount)
718     memset(fList[fCount], 0, (NewCount - fCount) * sizeof(OBJ*));
719     fCount = NewCount;
720     }
721    
722     //---------------------------------------------------------------------------
723     #endif