1 //---------------------------------------------------------------------------
2 /*
3 Sortable collections of objects and object pointers
4 */
5 #ifndef _GList_HH
6 #define _GList_HH
7 
8 #include "GVec.hh"
9 
10 #define GLIST_SORTED_ERR "Operation not allowed on a sorted list!\n"
11 #define GLIST_UNSORTED_ERR "Operation not allowed on an unsorted list!\n"
12 
13 //------ useful macros:
14 #define BE_UNSORTED if (fCompareProc!=NULL) { GError(GLIST_SORTED_ERR); return; }
15 #define BE_SORTED if (fCompareProc==NULL) { GError(GLIST_UNSORTED_ERR); return; }
16 
17 #define SORTED (fCompareProc!=NULL)
18 #define UNSORTED (fCompareProc==NULL)
19 
20 // GArray is the sortable array type, requires the comparison operator < to be defined
21 template <class OBJ> class GArray:public GVec<OBJ> {
22   protected:
23     bool fUnique;
DefaultCompareProc(const pointer item1,const pointer item2)24     static int DefaultCompareProc(const pointer item1, const pointer item2) {
25       //operator< MUST be defined for OBJ class!
26       if (*((OBJ*)item2) < *((OBJ*)item1)) return 1;
27         else if (*((OBJ*)item1) < *((OBJ*)item2)) return -1;
28                                              else return  0;
29       }
30     GCompareProc* fCompareProc;
31   public:
32     GArray(GCompareProc* cmpFunc=NULL);
33     GArray(bool sorted, bool unique=false);
34     GArray(int init_capacity, bool sorted, bool unique=false);
35     GArray(GArray<OBJ>& array); //copy constructor
36     const GArray<OBJ>& operator=(GArray<OBJ>& array);
37     //~GArray();
38     //assignment operator
39     void setSorted(GCompareProc* cmpFunc);
setSorted(bool sorted)40     void setSorted(bool sorted) {
41      if (sorted) {
42          if (fCompareProc!=&DefaultCompareProc) {
43              fCompareProc=&DefaultCompareProc;
44              Sort();
45              }
46           }
47       else fCompareProc=NULL;
48       }
49     //sort the array if cmpFunc not NULL or changes
50     int Add(OBJ* item); // specific implementation if sorted
Add(OBJ & item)51     int Add(OBJ& item) { return Add(&item); } //both will CREATE a new OBJ and COPY to it
52                        // using OBJ new operator=
cAdd(OBJ item)53     int cAdd(OBJ item) { return Add(&item); }
cPush(OBJ item)54     int cPush(OBJ item) { return Add(&item); }
Push(OBJ & item)55     int Push(OBJ& item) { return Add(&item); }
56 
57     void Add(GArray<OBJ>& list); //add copies of all items from another list
58     //this will reject identical items in sorted lists only!
setUnique(bool beUnique)59     void setUnique(bool beUnique) { fUnique = beUnique; };
60     void Sort(); //explicit sort may be requested
Sorted()61     bool Sorted() { return fCompareProc!=NULL; }
62     void Replace(int idx, OBJ& item); //Put, use operator= to copy
Unique()63     int  Unique() { return fUnique; }
64     int IndexOf(OBJ& item);
65          //this needs the == operator to have been defined for OBJ
66     bool Found(OBJ& item, int& idx); // for sorted arrays only;
67          //search by content; if found, returns true and idx will be the index
68          //of the first item found matching for which fCompareProc returns 0
69     bool Exists(OBJ& item); //same as above without existing index info
70     //unsorted only, place item at position idx:
71     void Move(int curidx, int newidx);
72     void Insert(int idx, OBJ* item);
Insert(int idx,OBJ item)73     void Insert(int idx, OBJ item) { Insert(idx,&item); }
74 };
75 
76 //GList is a sortable collection of pointers to objects; requires operator< to be defined, or a custom compare function
77 template <class OBJ> class GList:public GPVec<OBJ> {
78   protected:
79     bool fUnique;
80     GCompareProc* fCompareProc; //a pointer to a Compare function
81 
DefaultCompareProc(const pointer item1,const pointer item2)82     static int DefaultCompareProc(const pointer item1, const pointer item2) {
83       //operator< MUST be defined for OBJ class!
84       if (*((OBJ*)item2) < *((OBJ*)item1)) return 1;
85         else if (*((OBJ*)item1) < *((OBJ*)item2)) return -1;
86                                              else return  0;
87       }
88   public:
89     void sortInsert(int idx, OBJ* item); //special insert in sorted lists
90          //WARNING: the caller must know the insert index such that the sort order is preserved!
91     GList(GCompareProc* compareProc=NULL); //free by default
92     GList(GCompareProc* compareProc, //unsorted by default
93         GFreeProc *freeProc,
94         bool beUnique=false);
95     GList(bool sorted, bool free_elements=true, bool beUnique=false);
96     GList(int init_capacity, bool sorted, bool free_elements=true, bool beUnique=false);
97     GList(GList<OBJ>& list); //copy constructor?
98     GList(GList<OBJ>* list); //kind of a copy constructor
99     const GList<OBJ>& operator=(GList<OBJ>& list);
100     //void Clear();
101     //~GList();
102     void setSorted(GCompareProc* compareProc);
103        //sorted if compareProc not NULL; sort the list if compareProc changes !
Sorted()104     bool Sorted() { return fCompareProc!=NULL; }
setSorted(bool sorted)105     void setSorted(bool sorted) {
106      if (sorted) {
107          if (fCompareProc!=&DefaultCompareProc) {
108              fCompareProc=&DefaultCompareProc;
109              Sort();
110              }
111           }
112       else fCompareProc=NULL;
113       }
114     int Add(OBJ* item); //-- specific implementation if sorted - may become an Insert()
115     void Add(GList<OBJ>& list); //add all pointers from another list
116 
117     OBJ* AddIfNew(OBJ* item, bool deleteIfFound=true, int* fidx=NULL);
118     // default: delete item if Found() (and pointers are not equal)!
119     //returns the equal (==) object if it's in the list already
120     //or the item itself if it is unique and actually added
121 
122     int AddedIfNew(OBJ* item);
123     // if Found(item) (and pointers are not equal) delete item and returns -1
124     // if added, returns the new item index
125 
126 
Unique()127     int Unique() { return fUnique; }
128     //this will reject identical items in sorted lists only!
setUnique(bool beUnique)129     void setUnique(bool beUnique) { fUnique = beUnique; };
130 
GetCompareProc()131     GCompareProc* GetCompareProc() {return fCompareProc;}
132     int IndexOf(OBJ* item); //this has a specific implementation for sorted lists
133                //if list is sorted, item data is located by binary search
134                //based on the Compare function
135                //if not, a linear search is performed, but
136                //this needs the == operator to have been defined for OBJ
137 
138     void Put(int idx, OBJ* item, bool re_sort=false);
139     bool Found(OBJ* item, int & idx); // sorted only;
140                //search by content; if found, returns true and idx will be the index
141                //of the first item found matching for which GTCompareProc returns 0
142     bool Exists(OBJ* item); //same as above without existing index info
143     bool Exists(OBJ& item); //same as above without existing index info
144     void Sort(); //explicit sort may be requested using this function
145     int Remove(OBJ* item); //search for pointer, using binary search if sorted
146     void Insert(int idx, OBJ* item); //unsorted only, place item at position idx
147     void Move(int curidx, int newidx);
148 }; //GList
149 
150 
151 
152 //-------------------- TEMPLATE IMPLEMENTATION-------------------------------
153 
GArray(GArray<OBJ> & array)154 template <class OBJ> GArray<OBJ>::GArray(GArray<OBJ>& array):GVec<OBJ>(0) { //copy constructor
155  this->fCount=array.fCount;
156  this->fCapacity=array.fCapacity;
157  this->fArray=NULL;
158  if (this->fCapacity>0) {
159     //GMALLOC(this->fArray, this->fCapacity*sizeof(OBJ));
160     this->fArray=new OBJ[this->fCapacity];
161     }
162  this->fCount=array.fCount;
163  fUnique=array.fUnique;
164  fCompareProc=array.fCompareProc;
165  // uses OBJ operator=
166  for (int i=0;i<this->fCount;i++) this->fArray[i]=array[i];
167  }
168 
operator =(GArray<OBJ> & array)169 template <class OBJ> const GArray<OBJ>& GArray<OBJ>::operator=(GArray<OBJ>& array) {
170  if (&array==this) return *this;
171  GVec<OBJ>::Clear();
172  this->fCount=array.fCount;
173  this->fUnique=array.fUnique;
174  this->fCapacity=array.fCapacity;
175  if (this->fCapacity>0) {
176     //GMALLOC(this->fArray, this->fCapacity*sizeof(OBJ));
177     this->fArray=new OBJ[this->fCapacity];
178     }
179  this->fCompareProc=array.fCompareProc;
180  this->fCount=array.fCount;
181  // uses OBJ operator=
182  for (int i=0;i<this->fCount;i++) {
183    this->fArray[i]=array[i];
184    }
185  return *this;
186 }
187 
GArray(GCompareProc * cmpFunc)188 template <class OBJ> GArray<OBJ>::GArray(GCompareProc* cmpFunc):GVec<OBJ>(0) {
189   fCompareProc = cmpFunc;
190   fUnique = false; //only affects sorted lists
191 }
192 
GArray(bool sorted,bool unique)193 template <class OBJ> GArray<OBJ>::GArray(bool sorted, bool unique):GVec<OBJ>(0) {
194   fUnique=unique;
195   fCompareProc = sorted ? DefaultCompareProc : NULL;
196 }
197 
GArray(int init_capacity,bool sorted,bool unique)198 template <class OBJ> GArray<OBJ>::GArray(int init_capacity,
199                         bool sorted, bool unique):GVec<OBJ>(init_capacity) {
200   fUnique=unique;
201   fCompareProc=sorted ? DefaultCompareProc : NULL;
202 }
203 
setSorted(GCompareProc * cmpFunc)204 template <class OBJ> void GArray<OBJ>::setSorted(GCompareProc* cmpFunc) {
205   GCompareProc* old_proc=fCompareProc;
206   fCompareProc=cmpFunc;
207   if (fCompareProc!=old_proc && fCompareProc!=NULL)
208        Sort(); //new compare method
209 }
210 
IndexOf(OBJ & item)211 template <class OBJ> int GArray<OBJ>::IndexOf(OBJ& item) {
212  int result=0;
213  if (Found(item, result)) return result;
214                      else return -1;
215  }
216 
Exists(OBJ & item)217 template <class OBJ> bool GArray<OBJ>::Exists(OBJ& item) {
218  int result=0;
219  if (Found(item, result)) return true;
220                      else return false;
221  }
222 
223 
Add(OBJ * item)224 template <class OBJ> int GArray<OBJ>::Add(OBJ* item) {
225  if (item==NULL) return -1;
226  int result;
227  if (SORTED) {
228    if (Found(*item, result))
229       if (fUnique) return -1; //cannot add a duplicate!
230    //Found sets result to the position where the item should be!
231    GVec<OBJ>::Insert(result, *item);
232    }
233   else {
234    if (fUnique && Found(*item,result)) return -1; //set behaviour
235    result = this->fCount;
236    if (result==this->fCapacity) GVec<OBJ>::Grow();
237    this->fArray[result] = *item; //operator=, copies the item
238    this->fCount++;
239    }
240  return result;
241 }
242 
243 
Add(GArray<OBJ> & list)244 template <class OBJ> void GArray<OBJ>::Add(GArray<OBJ>& list) {
245   if (list.Count()==0) return;
246   if (SORTED) {
247     for (int i=0;i<list.fCount;i++) Add(&list[i]);
248     }
249   else { //simply copy
250     this->setCapacity(this->fCapacity+list.fCount);
251     int s=this->fCount;
252     for (int i=0;i<list.fCount;i++)
253            this->fArray[s+i]=list.fArray[i];
254     this->fCount+=list.fCount;
255     }
256 }
257 
Found(OBJ & item,int & idx)258 template <class OBJ> bool GArray<OBJ>::Found(OBJ& item, int& idx) {
259  //search the list by using fCompareProc (if defined)
260  //or == operator for a non-sortable list
261  //for sorted lists, even when the result is false, the idx is
262  //set to the closest matching object!
263  int i;
264  idx=-1;
265  if (this->fCount==0) { idx=0;return false;}
266  if (SORTED) { //binary search based on fCompareProc
267    //do the simplest tests first:
268    if ((*fCompareProc)(&(this->fArray[0]),&item)>0) {
269                        idx=0;
270                        return false;
271                        }
272    if ((*fCompareProc)(&item, &(this->fArray[this->fCount-1]))>0) {
273                        idx=this->fCount;
274                        return false;
275                        }
276 
277    int l=0;
278    int h = this->fCount - 1;
279    int c;
280    while (l <= h) {
281        i = (l + h) >> 1;
282        c = (*fCompareProc)(&(this->fArray[i]), &item);
283        if (c < 0)  l = i + 1;
284          else {
285             h = i - 1;
286             if (c == 0) { //found!
287                  idx=i;
288                  return true;
289                 }
290             }
291        } //while
292    idx = l;
293    return false;
294    }
295  else {//not sorted: use linear search
296    // needs == operator to compare user defined objects !
297    i=0;
298    while (i<this->fCount) {
299       if (this->fArray[i]==item) { //requires operator==
300          idx=i;
301          return true;
302          }
303       i++;
304       }
305    return false;
306    }
307 }
308 
Insert(int idx,OBJ * item)309 template <class OBJ> void GArray<OBJ>::Insert(int idx, OBJ* item) {
310  //idx can be [0..fCount] so an item can be actually added
311  BE_UNSORTED; //forbid this operation on sorted data
312  GVec<OBJ>::Insert(idx, item);
313 }
314 
315 
Move(int curidx,int newidx)316 template <class OBJ> void GArray<OBJ>::Move(int curidx, int newidx) {
317  BE_UNSORTED; //cannot do this in a sorted list!
318  if (curidx!=newidx || newidx>=this->fCount)
319      GError(GVEC_INDEX_ERR, newidx);
320 
321  OBJ tmp=this->fArray[curidx]; //copy constructor here
322  this->fArray[curidx]=this->fArray[newidx];
323  this->fArray[newidx]=tmp;
324 }
325 
Replace(int idx,OBJ & item)326 template <class OBJ> void GArray<OBJ>::Replace(int idx, OBJ& item) {
327  //TEST_INDEX(idx);
328  if (idx<0 || idx>=this->fCount) GError(GVEC_INDEX_ERR, __FILE__,__LINE__, idx);
329  this->fArray[idx]=item;
330  if ( SORTED ) Sort(); //re-sort ! this could be very expensive, don't do it
331 }
332 
Sort()333 template <class OBJ> void GArray<OBJ>::Sort() {
334  if (fCompareProc==NULL) { fCompareProc=DefaultCompareProc; }
335  if (this->fArray!=NULL && this->fCount>0)
336      this->qSort(0, this->fCount-1, fCompareProc);
337 }
338 
339 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
340 //*=> GList implementation -- sortable array of pointers to OBJ
341 
GList(GList<OBJ> & list)342 template <class OBJ> GList<OBJ>::GList(GList<OBJ>& list):GPVec<OBJ>(list) { //copy constructor
343  fUnique=list.fUnique;
344  fCompareProc=list.fCompareProc;
345 }
346 
GList(GList<OBJ> * plist)347 template <class OBJ> GList<OBJ>::GList(GList<OBJ>* plist):GPVec<OBJ>(0) { //another copy constructor
348  this->fCapacity=plist->fCapacity;
349  this->fList=NULL;
350  if (this->fCapacity>0) {
351      GMALLOC(this->fList, this->fCapacity*sizeof(OBJ*));
352      }
353  fUnique=plist->fUnique;
354  fCompareProc=plist->fCompareProc;
355  this->fFreeProc=plist->fFreeProc;
356  this->fCount=plist->fCount;
357  memcpy(this->fList, plist->fList, this->fCount*sizeof(OBJ*));
358  //for (int i=0;i<list->fCount;i++) Add(plist->Get(i));
359 }
360 
Add(GList<OBJ> & list)361 template <class OBJ> void GList<OBJ>::Add(GList<OBJ>& list) {
362   if (list.Count()==0) return;
363   if (SORTED) {
364     for (int i=0;i<list.Count();i++) Add(list[i]);
365     }
366   else { //simply copy
367     this->setCapacity(this->fCapacity+list.fCount);
368     memcpy( & (this->fList[this->fCount]), list.fList, list.fCount*sizeof(OBJ*));
369     this->fCount+=list.fCount;
370     }
371 }
372 
373 
GList(GCompareProc * compareProc,GFreeProc * freeProc,bool beUnique)374 template <class OBJ> GList<OBJ>::GList(GCompareProc* compareProc,
375        GFreeProc* freeProc, bool beUnique) {
376   fCompareProc = compareProc;
377   this->fFreeProc    = freeProc;
378   fUnique = beUnique; //only affects sorted lists
379 }
380 
GList(GCompareProc * compareProc)381 template <class OBJ> GList<OBJ>::GList(GCompareProc* compareProc) {
382   fCompareProc = compareProc;
383   this->fFreeProc = GPVec<OBJ>::DefaultFreeProc;
384   fUnique = false; //only affects sorted lists
385 }
386 
GList(bool sorted,bool free_elements,bool beUnique)387 template <class OBJ> GList<OBJ>::GList(bool sorted,
388     bool free_elements, bool beUnique) {
389   if (sorted) {
390      if (free_elements) {
391         fCompareProc=&DefaultCompareProc;
392         this->fFreeProc = GPVec<OBJ>::DefaultFreeProc;
393         fUnique=beUnique;
394         }
395        else {
396         fCompareProc=&DefaultCompareProc;
397         this->fFreeProc=NULL;
398         fUnique=beUnique;
399         }
400      }
401    else {
402      if (free_elements) {
403         fCompareProc=NULL;
404         this->fFreeProc=GPVec<OBJ>::DefaultFreeProc;
405         fUnique=beUnique;
406         }
407       else {
408         fCompareProc=NULL;
409         this->fFreeProc=NULL;
410         fUnique=beUnique;
411         }
412      }
413 }
414 
415 
GList(int init_capacity,bool sorted,bool free_elements,bool beUnique)416 template <class OBJ> GList<OBJ>::GList(int init_capacity, bool sorted,
417     bool free_elements, bool beUnique):GPVec<OBJ>(init_capacity, free_elements) {
418   if (sorted) {
419       fCompareProc=&DefaultCompareProc;
420       fUnique=beUnique;
421       }
422    else {
423       fCompareProc=NULL;
424       fUnique=beUnique;
425       }
426 }
427 
operator =(GList & list)428 template <class OBJ> const GList<OBJ>& GList<OBJ>::operator=(GList& list) {
429  if (&list!=this) {
430      GPVec<OBJ>::Clear();
431      fCompareProc=list.fCompareProc;
432      this->fFreeProc=list.fFreeProc;
433      //Attention: the object pointers are copied directly,
434      //but the actual objects are NOT duplicated
435      for (int i=0;i<list.Count();i++) Add(list[i]);
436      }
437  return *this;
438 }
439 
setSorted(GCompareProc * compareProc)440 template <class OBJ> void GList<OBJ>::setSorted(GCompareProc* compareProc) {
441  GCompareProc* old_proc=fCompareProc;
442  fCompareProc=compareProc;
443  if (fCompareProc!=old_proc && fCompareProc!=NULL)
444        Sort(); //new compare method
445 }
446 
IndexOf(OBJ * item)447 template <class OBJ> int GList<OBJ>::IndexOf(OBJ* item) {
448  int result=0;
449  if (Found(item, result)) return result;
450                      else return -1;
451  }
452 
Exists(OBJ & item)453 template <class OBJ> bool GList<OBJ>::Exists(OBJ& item) {
454  int result=0;
455  if (Found(&item, result)) return true;
456                       else return false;
457  }
458 
Exists(OBJ * item)459 template <class OBJ> bool GList<OBJ>::Exists(OBJ* item) {
460  int result=0;
461  if (Found(item, result)) return true;
462                       else return false;
463  }
464 
Add(OBJ * item)465 template <class OBJ> int GList<OBJ>::Add(OBJ* item) {
466  int result;
467  if (item==NULL) return -1;
468  if (SORTED) {
469    if (Found(item, result))
470       if (fUnique) return -1; //duplicates forbidden
471    //Found sets result to the position where the item should be!
472    sortInsert(result, item);
473    }
474   else {
475    if (fUnique && Found(item,result)) return -1; //set behaviour
476    result = this->fCount;
477    if (result==this->fCapacity) GPVec<OBJ>::Grow();
478    this->fList[result]=item;
479    this->fCount++;
480    }
481  return result;
482 }
483 
484 //by default, it deletes the item if it has an equal in the list!
485 //returns the existing equal (==) object if it's in the list already
486 //or returns the item itself if it's unique (and adds it)
AddIfNew(OBJ * item,bool deleteIfFound,int * fidx)487 template <class OBJ> OBJ* GList<OBJ>::AddIfNew(OBJ* item,
488                                      bool deleteIfFound, int* fidx) {
489  int r;
490  if (Found(item, r)) {
491     if (deleteIfFound && (pointer)item != (pointer)(this->fList[r])) {
492        this->deallocate_item(item);
493        }
494     if (fidx!=NULL) *fidx=r;
495     return this->fList[r]; //found
496     }
497  //not found:
498  if (SORTED) {
499    //Found() set result to the position where the item should be inserted:
500    sortInsert(r, item);
501    }
502   else {
503    r = this->fCount;
504    if (r==this->fCapacity) GPVec<OBJ>::Grow();
505    this->fList[r]=item;
506    this->fCount++;
507    }
508  if (fidx!=NULL) *fidx=r;
509  return item;
510 }
511 
512 //if item is found already in the list DELETE it and return -1
513 //otherwise the item is added and its index is returned
AddedIfNew(OBJ * item)514 template <class OBJ> int GList<OBJ>::AddedIfNew(OBJ* item) {
515  int r;
516  if (Found(item, r)) {
517     if ((pointer)item != (pointer)(this->fList[r])) {
518         this->deallocate_item(item);
519         }
520     return -1;
521     }
522  //not found:
523  if (SORTED) {
524    //Found() set r to the position where the item should be inserted:
525    sortInsert(r, item);
526    }
527   else {
528    r = this->fCount;
529    if (r==this->fCapacity) GPVec<OBJ>::Grow();
530    this->fList[r]=item;
531    this->fCount++;
532    }
533  return r;
534 }
535 
536 
Found(OBJ * item,int & idx)537 template <class OBJ> bool GList<OBJ>::Found(OBJ* item, int& idx) {
538  //search the list by using fCompareProc (if defined)
539  //or == operator for a non-sortable list
540  //for sorted lists, even when the result is false, the idx is
541  //set to the closest matching object!
542  int i;
543  idx=-1;
544  if (this->fCount==0) { idx=0;return false;}
545  if (SORTED) { //binary search based on fCompareProc
546    //do the simple test first:
547 
548    if ((*fCompareProc)(this->fList[0],item)>0) {
549                        idx=0;
550                        return false;
551                        }
552    if ((*fCompareProc)(item, this->fList[this->fCount-1])>0) {
553                        idx=this->fCount;
554                        return false;
555                        }
556 
557    int l, h, c;
558    l = 0;
559    h = this->fCount - 1;
560    while (l <= h) {
561        i = (l + h) >> 1;
562        c = (*fCompareProc)(this->fList[i], item);
563        if (c < 0)  l = i + 1;
564          else {
565             h = i - 1;
566             if (c == 0) {
567                  idx=i;
568                  return true;
569                 }
570             }
571        } //while
572    idx = l;
573    return false;
574    }
575  else {//not sorted: use linear search
576    // needs == operator to compare user defined objects !
577    i=0;
578    while (i<this->fCount) {
579       if (*this->fList[i]==*item) {
580          idx=i;
581          return true;
582          }
583       i++;
584       }
585    return false;
586    }
587 }
588 
sortInsert(int idx,OBJ * item)589 template <class OBJ> void GList<OBJ>::sortInsert(int idx, OBJ* item) {
590  //idx must be the new position this new item must have
591  //so the allowed range is [0..fCount]
592  //the current fList[idx] and all the above will be shifted +1
593  if (idx<0 || idx>this->fCount) GError(GVEC_INDEX_ERR, idx);
594  if (this->fCount==this->fCapacity) {
595     GPVec<OBJ>::Grow(idx, item);
596     //expand and also copy/move data and insert the new item
597     return;
598     }
599  //room still left, just move data around and insert the new one
600  if (idx<this->fCount) //copy/move pointers only!
601       memmove(&(this->fList[idx+1]), &(this->fList[idx]), (this->fCount-idx)*sizeof(OBJ*));
602  this->fList[idx]=item;
603  this->fCount++;
604 }
605 
Insert(int idx,OBJ * item)606 template <class OBJ> void GList<OBJ>::Insert(int idx, OBJ* item) {
607  //idx can be [0..fCount] so an item can be actually added
608  BE_UNSORTED; //cannot do that with a sorted list!
609  GPVec<OBJ>::Insert(idx,item);
610 }
611 
Move(int curidx,int newidx)612 template <class OBJ> void GList<OBJ>::Move(int curidx, int newidx) {
613  BE_UNSORTED; //cannot do this in a sorted list!
614  GPVec<OBJ>::Move(curidx,newidx);
615 }
616 
Put(int idx,OBJ * item,bool re_sort)617 template <class OBJ> void GList<OBJ>::Put(int idx, OBJ* item, bool re_sort) {
618  //WARNING: this will never free the replaced item!
619  // this may BREAK the sort order unless the "re_sort" parameter is given
620  if (idx<0 || idx>this->fCount) GError(GVEC_INDEX_ERR, idx);
621  this->fList[idx]=item;
622  if (SORTED && item!=NULL && re_sort) Sort(); //re-sort
623 }
624 
Remove(OBJ * item)625 template <class OBJ> int GList<OBJ>::Remove(OBJ* item) {
626 //removes an item if it's in our list
627  int result=IndexOf(item);
628  if (result>=0) GPVec<OBJ>::Delete(result);
629  return result;
630 }
631 
Sort()632 template <class OBJ> void GList<OBJ>::Sort() {
633  if (fCompareProc==NULL) fCompareProc = DefaultCompareProc;
634  if (this->fList!=NULL && this->fCount>0)
635      this->qSort(0, this->fCount-1, fCompareProc);
636 }
637 
638 //---------------------------------------------------------------------------
639 #endif
640