1 #define _GNU_SOURCE 1
2
3 #include "bag.h"
4
5 /* need to use vlg etc. */
6 #define EX_UTILS_NO_FUNCS 1
7 #include "ex_utils.h"
8
9 #ifdef __GNUC__
10 # define BAG__ATTR_UNUSED(x) vstr__UNUSED_ ## x __attribute__((unused))
11 #elif defined(__LCLINT__)
12 # define BAG__ATTR_UNUSED(x) /*@unused@*/ vstr__UNUSED_ ## x
13 #else
14 # define BAG__ATTR_UNUSED(x) vstr__UNUSED_ ## x
15 #endif
16
17 #ifndef __GLIBC__ /* hack */
18 # define strverscmp(x, y) strcmp(x, y)
19 #endif
20
bag_del_all(Bag * bag)21 void bag_del_all(Bag *bag)
22 {
23 while (bag->num--)
24 {
25 bag->free_key_func((void *)bag->data[bag->num].key);
26 bag->free_val_func(bag->data[bag->num].val);
27 }
28 bag->num = 0;
29 }
30
bag_make(size_t sz,void (* free_key_func)(void *),void (* free_val_func)(void *))31 Bag *bag_make(size_t sz,
32 void (*free_key_func)(void *), void (*free_val_func)(void *))
33 {
34 Bag *bag = malloc(sizeof(Bag) + (sizeof(Bag_obj) * sz));
35
36 if (!bag)
37 return (NULL);
38
39 bag->num = 0;
40 bag->sz = sz;
41 bag->free_key_func = free_key_func;
42 bag->free_val_func = free_val_func;
43
44 bag->can_resize = FALSE;
45
46 return (bag);
47 }
48
bag_free(Bag * bag)49 void bag_free(Bag *bag)
50 {
51 if (!bag)
52 return;
53
54 bag_del_all(bag);
55
56 free(bag);
57 }
58
bag_add_obj(Bag * bag,const char * key,void * val)59 Bag *bag_add_obj(Bag *bag, const char *key, void *val)
60 {
61 ASSERT(bag);
62
63 ASSERT(bag->num <= bag->sz);
64
65 if ((bag->num >= bag->sz))
66 {
67 Bag *tmp = NULL;
68 size_t sz = bag->sz;
69
70 if (!bag->can_resize)
71 return (NULL);
72
73 sz <<= 1;
74 if (!(tmp = realloc(bag, sizeof(Bag) + (sizeof(Bag_obj) * sz))))
75 return (NULL);
76
77 bag = tmp;
78 bag->sz = sz;
79 }
80
81 bag->data[bag->num].key = key;
82 bag->data[bag->num].val = val;
83 ++bag->num;
84
85 return (bag);
86 }
87
bag_add_cstr(Bag * bag,const char * key,char * val)88 Bag *bag_add_cstr(Bag *bag, const char *key, char *val)
89 {
90 return (bag_add_obj(bag, key, val));
91 }
92
bag_sort(Bag * bag,int (* cmp)(const void *,const void *))93 void bag_sort(Bag *bag, int (*cmp)(const void *, const void *))
94 {
95 qsort(bag->data, bag->num, sizeof(Bag_obj), cmp);
96 }
97
bag_cb_sort_key_cmp(const void * passed_one,const void * passed_two)98 int bag_cb_sort_key_cmp(const void *passed_one, const void *passed_two)
99 {
100 const Bag_obj *const one = passed_one;
101 const Bag_obj *const two = passed_two;
102
103 return (strcmp(one->key, two->key));
104 }
105
bag_cb_sort_key_case(const void * passed_one,const void * passed_two)106 int bag_cb_sort_key_case(const void *passed_one, const void *passed_two)
107 {
108 const Bag_obj *const one = passed_one;
109 const Bag_obj *const two = passed_two;
110
111 return (strcasecmp(one->key, two->key));
112 }
113
bag_cb_sort_key_vers(const void * passed_one,const void * passed_two)114 int bag_cb_sort_key_vers(const void *passed_one, const void *passed_two)
115 {
116 const Bag_obj *const one = passed_one;
117 const Bag_obj *const two = passed_two;
118
119 return (strverscmp(one->key, two->key));
120 }
121
bag_cb_sort_key_coll(const void * passed_one,const void * passed_two)122 int bag_cb_sort_key_coll(const void *passed_one, const void *passed_two)
123 {
124 const Bag_obj *const one = passed_one;
125 const Bag_obj *const two = passed_two;
126
127 return (strcoll(one->key, two->key));
128 }
129
bag_iter_nxt(Bag_iter * iter)130 const Bag_obj *bag_iter_nxt(Bag_iter *iter)
131 {
132 ASSERT(iter);
133
134 if (iter->num >= iter->bag->num)
135 return (NULL);
136
137 return (iter->bag->data + iter->num++);
138 }
139
bag_iter_beg(Bag * bag,Bag_iter * iter)140 const Bag_obj *bag_iter_beg(Bag *bag, Bag_iter *iter)
141 {
142 ASSERT(bag && iter);
143
144 iter->bag = bag;
145 iter->num = 0;
146
147 return (bag_iter_nxt(iter));
148 }
149
bag_srch_eq(Bag * bag,int (* cmp_func)(const Bag_obj *,const void *),const void * val)150 const Bag_obj *bag_srch_eq(Bag *bag,
151 int (*cmp_func)(const Bag_obj *, const void *),
152 const void *val)
153 {
154 Bag_iter iter[1];
155 const Bag_obj *obj = bag_iter_beg(bag, iter);
156
157 while (obj)
158 {
159 if ((*cmp_func)(obj, val))
160 return (obj);
161
162 obj = bag_iter_nxt(iter);
163 }
164
165 return (NULL);
166 }
167
bag_cb_srch_eq_key_ptr(const Bag_obj * obj,const void * val)168 int bag_cb_srch_eq_key_ptr(const Bag_obj *obj, const void *val)
169 {
170 if (obj->key == val)
171 return (TRUE);
172
173 return (FALSE);
174 }
175
bag_cb_srch_eq_val_ptr(const Bag_obj * obj,const void * val)176 int bag_cb_srch_eq_val_ptr(const Bag_obj *obj, const void *val)
177 {
178 if (obj->val == val)
179 return (TRUE);
180
181 return (FALSE);
182 }
183
bag_cb_free_nothing(void * BAG__ATTR_UNUSED (val))184 void bag_cb_free_nothing(void *BAG__ATTR_UNUSED(val))
185 {
186 }
187
bag_cb_free_ref(void * val)188 void bag_cb_free_ref(void *val)
189 {
190 vstr_ref_del(val);
191 }
192
bag_cb_free_malloc(void * val)193 void bag_cb_free_malloc(void *val)
194 {
195 free(val);
196 }
197
198