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 File contents
1 //---------------------------------------------------------------------------
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