1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_gsa.c - generic sorted arrays
6 (C) Copyright 2001-2004 by Pavel Pisa - Originator
8 The uLan utilities library can be used, copied and modified under
10 - GPL - GNU General Public License
11 - LGPL - GNU Lesser General Public License
12 - MPL - Mozilla Public License
13 - and other licenses added by project originators
14 Code can be modified and re-distributed under any combination
15 of the above listed licenses. If contributor does not agree with
16 some of the licenses, he/she can delete appropriate line.
17 Warning, if you delete all lines, you are not allowed to
18 distribute source code and/or binaries utilizing code.
20 See files COPYING and README for details.
22 *******************************************************************/
25 #include "ul_utmalloc.h"
30 #define GSA_ALLOC_STEP 8
31 #define GSA_DEALLOC_STEP 32
34 gsa_struct_init(gsa_array_t *array, int key_offs,
35 gsa_cmp_fnc_t *cmp_fnc)
37 array->key_offs=key_offs;
38 array->cmp_fnc=cmp_fnc;
45 gsa_delete_all(gsa_array_t *array)
47 if(array->items) free(array->items);
55 gsa_bsearch_indx(gsa_array_t *array, void *key, int key_offs,
56 gsa_cmp_fnc_t *cmp_fnc, int mode, unsigned *indx)
60 if(!array->items || !array->count || !cmp_fnc){
70 r=cmp_fnc((char*)array->items[c]+key_offs,key);
82 /* equal items can be in range a to b-1 */
83 /* routine looks for first one */
87 r=cmp_fnc((char*)array->items[c]+key_offs,key);
94 } else if(mode&GSA_FAFTER) {
95 /* equal items can be in range a to b-1 */
96 /* return index after last one */
100 r=cmp_fnc((char*)array->items[c]+key_offs,key);
113 gsa_find(gsa_array_t *array, void *key)
116 if(gsa_bsearch_indx(array,key,array->key_offs,
117 array->cmp_fnc,0,&indx))
118 return array->items[indx];
123 gsa_find_first(gsa_array_t *array, void *key)
126 if(gsa_bsearch_indx(array,key,array->key_offs,
127 array->cmp_fnc,GSA_FFIRST,&indx))
128 return array->items[indx];
133 gsa_find_indx(gsa_array_t *array, void *key, int *indx)
135 if(gsa_bsearch_indx(array,key,array->key_offs,
136 array->cmp_fnc,GSA_FFIRST,indx))
137 return array->items[*indx];
142 gsa_insert_at(gsa_array_t *array, void *item, unsigned where)
144 unsigned acnt=array->alloc_count;
145 unsigned cnt=array->count;
147 if(where>cnt) where=cnt;
148 if((cnt+1>=acnt)||!array->items)
150 acnt+=GSA_ALLOC_STEP;
152 items=malloc(acnt*sizeof(void*));
154 items=realloc(array->items,acnt*sizeof(void*));
155 if(!items) return -1;
156 array->alloc_count=acnt;
159 else items=array->items;
161 memmove(p+1,p,(char*)(items+cnt)-(char*)p);
168 gsa_insert(gsa_array_t *array, void *item, int mode)
172 res=gsa_bsearch_indx(array,(char*)item+array->key_offs,
173 array->key_offs,array->cmp_fnc,mode,&indx);
177 if(gsa_insert_at(array,item,indx)<0)
183 gsa_delete_at(gsa_array_t *array, unsigned indx)
185 unsigned acnt=array->alloc_count;
186 unsigned cnt=array->count;
187 void **items=array->items;
189 if(indx>=cnt) return -1;
192 memmove(p,p+1,(items+cnt-p)*sizeof(void *));
193 if(acnt-cnt>GSA_DEALLOC_STEP+GSA_ALLOC_STEP)
195 acnt-=GSA_DEALLOC_STEP;
196 items=realloc(array->items,acnt*sizeof(void*));
198 array->alloc_count=acnt;
206 gsa_delete(gsa_array_t *array, void *item)
209 int key_offs=array->key_offs;
210 gsa_cmp_fnc_t *cmp_fnc=array->cmp_fnc;
211 if(!gsa_bsearch_indx(array,(char*)item+key_offs,
212 key_offs,cmp_fnc,GSA_FFIRST,&indx))
215 while(array->items[indx]!=item){
216 if(++indx>=array->count) return -1;
218 if(cmp_fnc((char*)(array->items[indx])+key_offs,
219 (char*)item+key_offs))
223 return gsa_delete_at(array,indx);
227 gsa_resort_buble(gsa_array_t *array, int key_offs,
228 gsa_cmp_fnc_t *cmp_fnc)
233 if(array->count<2) return 0;
234 a=(char**)array->items; m=0;
235 b=(char**)&array->items[array->count-1];
242 if(cmp_fnc(k1,k2)>0) {
250 if((a==--b)||!m1) return m;
256 if(cmp_fnc(k1,k2)<0) {
264 if((++a==b)||!m1) return m;
269 gsa_setsort(gsa_array_t *array, int key_offs,
270 gsa_cmp_fnc_t *cmp_fnc)
272 if(key_offs>=0) array->key_offs=key_offs;
273 if(cmp_fnc!=NULL) array->cmp_fnc=cmp_fnc;
274 return gsa_resort_buble(array,array->key_offs,array->cmp_fnc);
277 int gsa_cmp_int(const void *a, const void *b)
279 return *(int*)a-*(int*)b;
282 int gsa_cmp_ulong(const void *a, const void *b)
284 return *(unsigned long*)a-*(unsigned long*)b;