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