File Coverage

hlist.c
Criterion Covered Total %
statement 106 137 77.3
branch 45 68 66.1
condition n/a
subroutine n/a
pod n/a
total 151 205 73.6


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #include "glog.h"
6             #include "gmem.h"
7             #include "header.h"
8             #include "plist.h"
9             #include "hlist.h"
10              
11             static void hlist_del_pos(HList* hlist, int pos, int clear);
12             static void hlist_grow(HList* hlist);
13             static int hlist_cmp(const void* v1, const void* v2);
14             static HNode* hlist_lookup(HList* hlist, const char* name, int type, int add, int del);
15              
16              
17 90           HList* hlist_create(void) {
18 90           HList* p = 0;
19 90           GMEM_NEW(p, HList*, sizeof(HList));
20 90 50         if (!p) {
21 0           return 0;
22             }
23              
24 90           hlist_init(p);
25 90           return p;
26             }
27              
28 90           void hlist_destroy(HList* hlist) {
29 90 50         if (!hlist) {
30 0           return;
31             }
32              
33 90           hlist_clear(hlist);
34 90           GMEM_DEL(hlist, HList*, sizeof(HList));
35             }
36              
37 13           HList* hlist_clone(HList* hlist) {
38 13 50         if (!hlist) {
39 0           return 0;
40             }
41              
42             GLOG(("=C= Cloning hlist %p", hlist));
43             /* hlist_dump(hlist, stderr); */
44 13           HList* p = hlist_create();
45 13           p->flags = hlist->flags;
46             int j;
47 59 100         for (j = 0; j < hlist->ulen; ++j) {
48 46           hlist_grow(p);
49 46           p->data[j].header = header_clone(hlist->data[j].header);
50 46           p->data[j].values = plist_clone(hlist->data[j].values);
51 46           ++p->ulen;
52             }
53 13           return p;
54             }
55              
56 186           void hlist_init(HList* hlist) {
57 186 50         if (!hlist) {
58 0           return;
59             }
60              
61 186           hlist->data = 0;
62 186           hlist->alen = hlist->ulen = 0;
63 186           hlist->flags = 0;
64             }
65              
66             /* TODO: perhaps we should leave hlist as empty but not delete the chunks we */
67             /* already allocated for it... */
68 96           void hlist_clear(HList* hlist) {
69 96 50         if (!hlist) {
70 0           return;
71             }
72              
73             int j;
74 257 100         for (j = 0; j < hlist->ulen; ++j) {
75 161           HNode* n = &hlist->data[j];
76 161           header_destroy(n->header);
77 161           plist_destroy(n->values);
78             }
79 96           GMEM_DELARR(hlist->data, HNode*, hlist->alen, sizeof(HNode));
80 96           hlist_init(hlist);
81             }
82              
83 29           int hlist_size(const HList* hlist)
84             {
85 29 50         return hlist ? hlist->ulen : 0;
86             }
87              
88 231           HNode* hlist_get(HList* hlist, const char* name) {
89 231 50         if (!hlist) {
90 0           return 0;
91             }
92              
93             GLOG(("=C= Getting [%s]", name));
94 231           return hlist_lookup(hlist, name, HEADER_TYPE_NONE, 0, 0);
95             }
96              
97 169           HNode* hlist_add(HList* hlist, const char* name, const void* obj) {
98 169 50         if (!hlist) {
99 0           return 0;
100             }
101              
102 169           HNode* n = hlist_lookup(hlist, name, HEADER_TYPE_NONE, 0, 0);
103 169 100         if (!n) {
104 135           Header* h = header_lookup_standard(HEADER_TYPE_NONE, name);
105 135 100         if (!h) {
106 61           h = header_create(name);
107             }
108 135           hlist_grow(hlist);
109 135           n = &hlist->data[hlist->ulen++];
110 135           n->header = h;
111 135           n->values = plist_create();
112 135           HLIST_FLAG_CLR(hlist, HLIST_FLAGS_SORTED);
113             }
114              
115 169           plist_add(n->values, obj);
116             GLOG(("=C= Added [%s] => %p (%d)", name, obj, n->header->order));
117 169           return n;
118             }
119              
120 20           void hlist_del(HList* hlist, const char* name) {
121 20 50         if (!hlist) {
122 0           return;
123             }
124              
125             GLOG(("=C= Deleting [%s]", name));
126 20           hlist_lookup(hlist, name, HEADER_TYPE_NONE, 0, 1);
127             }
128              
129 42           void hlist_sort(HList* hlist) {
130 42 50         if (!hlist) {
131 0           return;
132             }
133              
134 42 100         if (HLIST_FLAG_GET(hlist, HLIST_FLAGS_SORTED)) {
135             GLOG(("=C= Already sorted hlist"));
136             } else {
137             GLOG(("=C= Sorting hlist"));
138 27           qsort(hlist->data, hlist->ulen, sizeof(HNode), hlist_cmp);
139             GLOG(("=C= Sorted hlist"));
140 27           HLIST_FLAG_SET(hlist, HLIST_FLAGS_SORTED);
141             }
142             }
143              
144 0           void hlist_dump(const HList* hlist, FILE* fp) {
145 0 0         if (!hlist) {
146 0           return;
147             }
148              
149             int j;
150 0 0         for (j = 0; j < hlist->ulen; ++j) {
151 0           HNode* n = &hlist->data[j];
152 0           header_dump(n->header, fp);
153 0           plist_dump(n->values, fp);
154             }
155 0           fflush(fp);
156             }
157              
158 20           void hlist_transfer_header(HList* from, int pos, HList* to)
159             {
160 20 50         if (!from || !to) {
    50          
161 0           return;
162             }
163 20 50         if (pos >= hlist_size(from)) {
164 0           return;
165             }
166 20           hlist_grow(to);
167 20           to->data[to->ulen++] = from->data[pos];
168 20           hlist_del_pos(from, pos, 0);
169             }
170              
171              
172 40           static void hlist_del_pos(HList* hlist, int pos, int clear) {
173 40           HNode* n = &hlist->data[pos];
174 40           --hlist->ulen;
175 40 100         if (clear) {
176 20           header_destroy(n->header);
177 20           plist_destroy(n->values);
178             }
179             int j;
180 134 100         for (j = pos; j < hlist->ulen; ++j) {
181 94           hlist->data[j] = hlist->data[j+1];
182             }
183 40           }
184              
185 201           static void hlist_grow(HList* hlist) {
186 201 50         if (!hlist) {
187 0           return;
188             }
189 201 100         if (hlist->ulen < hlist->alen) {
190 99           return;
191             }
192              
193 102 100         int count = hlist->alen == 0 ? HLIST_INITIAL_SIZE : 2*hlist->alen;
194             GLOG(("=C= Growing HList from %d to %d", hlist->alen, count));
195 102           GMEM_REALLOC(hlist->data, HNode*, sizeof(HNode) * hlist->alen, sizeof(HNode) * count);
196 102           hlist->alen = count;
197             }
198              
199 107           static int hlist_cmp(const void* v1, const void* v2) {
200 107           const HNode* n1 = (const HNode*) v1;
201 107           const HNode* n2 = (const HNode*) v2;
202 107           const Header* h1 = n1->header;
203 107           const Header* h2 = n2->header;
204              
205 107           int delta = h1->order - h2->order;
206 107 100         return delta ? delta : header_compare(h1->name, h2->name);
207             }
208              
209             /*
210             * TODO: leave this as pure lookup, move insert and delete to the caller functions?
211             */
212 420           static HNode* hlist_lookup(HList* hlist, const char* name, int type, int add, int del) {
213 420 50         if (!hlist) {
214 0           return 0;
215             }
216              
217 420           int j = 0;
218 420           HNode* n = 0;
219 989 100         for (j = 0; j < hlist->ulen; ++j) {
220 727           n = &hlist->data[j];
221 727 100         if (header_matches_type_or_name(n->header, type, name)) {
222 158           break;
223             }
224             }
225 420 100         if (j >= hlist->ulen) {
226 262           n = 0;
227             }
228              
229             do {
230 420 50         if (add) {
231 0 0         if (n) {
232 0           break;
233             }
234 0           hlist_grow(hlist);
235 0           n = &hlist->data[hlist->ulen++];
236 0           Header* h = header_create(name);
237 0           n->header = h;
238 0           n->values = plist_create();
239 0           HLIST_FLAG_CLR(hlist, HLIST_FLAGS_SORTED);
240 0           break;
241             }
242              
243 420 100         if (del) {
244 20 50         if (!n) {
245 0           break;
246             }
247 20           hlist_del_pos(hlist, j, 1);
248 20           n = 0;
249 20           break;
250             }
251             } while (0);
252              
253 420           return n;
254             }