xref: /minix3/external/bsd/bind/dist/unit/atf-src/atf-c/detail/map.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1 /*	$NetBSD: map.c,v 1.3 2014/12/10 04:38:03 christos Exp $	*/
2 
3 /*
4  * Automated Testing Framework (atf)
5  *
6  * Copyright (c) 2008 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
19  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "atf-c/error.h"
37 #include "atf-c/utils.h"
38 
39 #include "map.h"
40 #include "sanity.h"
41 
42 /* ---------------------------------------------------------------------
43  * Auxiliary functions.
44  * --------------------------------------------------------------------- */
45 
46 struct map_entry {
47     char *m_key;
48     void *m_value;
49     bool m_managed;
50 };
51 
52 static
53 struct map_entry *
new_entry(const char * key,void * value,bool managed)54 new_entry(const char *key, void *value, bool managed)
55 {
56     struct map_entry *me;
57 
58     me = (struct map_entry *)malloc(sizeof(*me));
59     if (me != NULL) {
60         me->m_key = strdup(key);
61         if (me->m_key == NULL) {
62             free(me);
63             me = NULL;
64         } else {
65             me->m_value = value;
66             me->m_managed = managed;
67         }
68     }
69 
70     return me;
71 }
72 
73 /* ---------------------------------------------------------------------
74  * The "atf_map_citer" type.
75  * --------------------------------------------------------------------- */
76 
77 /*
78  * Getters.
79  */
80 
81 const char *
atf_map_citer_key(const atf_map_citer_t citer)82 atf_map_citer_key(const atf_map_citer_t citer)
83 {
84     const struct map_entry *me = citer.m_entry;
85     PRE(me != NULL);
86     return me->m_key;
87 }
88 
89 const void *
atf_map_citer_data(const atf_map_citer_t citer)90 atf_map_citer_data(const atf_map_citer_t citer)
91 {
92     const struct map_entry *me = citer.m_entry;
93     PRE(me != NULL);
94     return me->m_value;
95 }
96 
97 atf_map_citer_t
atf_map_citer_next(const atf_map_citer_t citer)98 atf_map_citer_next(const atf_map_citer_t citer)
99 {
100     atf_map_citer_t newciter;
101 
102     newciter = citer;
103     newciter.m_listiter = atf_list_citer_next(citer.m_listiter);
104     newciter.m_entry = ((const struct map_entry *)
105                         atf_list_citer_data(newciter.m_listiter));
106 
107     return newciter;
108 }
109 
110 bool
atf_equal_map_citer_map_citer(const atf_map_citer_t i1,const atf_map_citer_t i2)111 atf_equal_map_citer_map_citer(const atf_map_citer_t i1,
112                               const atf_map_citer_t i2)
113 {
114     return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry;
115 }
116 
117 /* ---------------------------------------------------------------------
118  * The "atf_map_iter" type.
119  * --------------------------------------------------------------------- */
120 
121 /*
122  * Getters.
123  */
124 
125 const char *
atf_map_iter_key(const atf_map_iter_t iter)126 atf_map_iter_key(const atf_map_iter_t iter)
127 {
128     const struct map_entry *me = iter.m_entry;
129     PRE(me != NULL);
130     return me->m_key;
131 }
132 
133 void *
atf_map_iter_data(const atf_map_iter_t iter)134 atf_map_iter_data(const atf_map_iter_t iter)
135 {
136     const struct map_entry *me = iter.m_entry;
137     PRE(me != NULL);
138     return me->m_value;
139 }
140 
141 atf_map_iter_t
atf_map_iter_next(const atf_map_iter_t iter)142 atf_map_iter_next(const atf_map_iter_t iter)
143 {
144     atf_map_iter_t newiter;
145 
146     newiter = iter;
147     newiter.m_listiter = atf_list_iter_next(iter.m_listiter);
148     newiter.m_entry = ((struct map_entry *)
149                        atf_list_iter_data(newiter.m_listiter));
150 
151     return newiter;
152 }
153 
154 bool
atf_equal_map_iter_map_iter(const atf_map_iter_t i1,const atf_map_iter_t i2)155 atf_equal_map_iter_map_iter(const atf_map_iter_t i1,
156                             const atf_map_iter_t i2)
157 {
158     return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry;
159 }
160 
161 /* ---------------------------------------------------------------------
162  * The "atf_map" type.
163  * --------------------------------------------------------------------- */
164 
165 /*
166  * Constructors and destructors.
167  */
168 
169 atf_error_t
atf_map_init(atf_map_t * m)170 atf_map_init(atf_map_t *m)
171 {
172     return atf_list_init(&m->m_list);
173 }
174 
175 atf_error_t
atf_map_init_charpp(atf_map_t * m,const char * const * array)176 atf_map_init_charpp(atf_map_t *m, const char *const *array)
177 {
178     atf_error_t err;
179     const char *const *ptr = array;
180 
181     err = atf_map_init(m);
182     if (array != NULL) {
183         while (!atf_is_error(err) && *ptr != NULL) {
184             const char *key, *value;
185 
186             key = *ptr;
187             INV(key != NULL);
188             ptr++;
189 
190             if ((value = *ptr) == NULL) {
191                 err = atf_libc_error(EINVAL, "List too short; no value for "
192                     "key '%s' provided", key);  /* XXX: Not really libc_error */
193                 break;
194             }
195             ptr++;
196 
197             err = atf_map_insert(m, key, strdup(value), true);
198         }
199     }
200 
201     if (atf_is_error(err))
202         atf_map_fini(m);
203 
204     return err;
205 }
206 
207 void
atf_map_fini(atf_map_t * m)208 atf_map_fini(atf_map_t *m)
209 {
210     atf_list_iter_t iter;
211 
212     atf_list_for_each(iter, &m->m_list) {
213         struct map_entry *me = atf_list_iter_data(iter);
214 
215         if (me->m_managed)
216             free(me->m_value);
217         free(me->m_key);
218         free(me);
219     }
220     atf_list_fini(&m->m_list);
221 }
222 
223 /*
224  * Getters.
225  */
226 
227 atf_map_iter_t
atf_map_begin(atf_map_t * m)228 atf_map_begin(atf_map_t *m)
229 {
230     atf_map_iter_t iter;
231     iter.m_map = m;
232     iter.m_listiter = atf_list_begin(&m->m_list);
233     iter.m_entry = atf_list_iter_data(iter.m_listiter);
234     return iter;
235 }
236 
237 atf_map_citer_t
atf_map_begin_c(const atf_map_t * m)238 atf_map_begin_c(const atf_map_t *m)
239 {
240     atf_map_citer_t citer;
241     citer.m_map = m;
242     citer.m_listiter = atf_list_begin_c(&m->m_list);
243     citer.m_entry = atf_list_citer_data(citer.m_listiter);
244     return citer;
245 }
246 
247 atf_map_iter_t
atf_map_end(atf_map_t * m)248 atf_map_end(atf_map_t *m)
249 {
250     atf_map_iter_t iter;
251     iter.m_map = m;
252     iter.m_entry = NULL;
253     iter.m_listiter = atf_list_end(&m->m_list);
254     return iter;
255 }
256 
257 atf_map_citer_t
atf_map_end_c(const atf_map_t * m)258 atf_map_end_c(const atf_map_t *m)
259 {
260     atf_map_citer_t iter;
261     iter.m_map = m;
262     iter.m_entry = NULL;
263     iter.m_listiter = atf_list_end_c(&m->m_list);
264     return iter;
265 }
266 
267 atf_map_iter_t
atf_map_find(atf_map_t * m,const char * key)268 atf_map_find(atf_map_t *m, const char *key)
269 {
270     atf_list_iter_t iter;
271 
272     atf_list_for_each(iter, &m->m_list) {
273         struct map_entry *me = atf_list_iter_data(iter);
274 
275         if (strcmp(me->m_key, key) == 0) {
276             atf_map_iter_t i;
277             i.m_map = m;
278             i.m_entry = me;
279             i.m_listiter = iter;
280             return i;
281         }
282     }
283 
284     return atf_map_end(m);
285 }
286 
287 atf_map_citer_t
atf_map_find_c(const atf_map_t * m,const char * key)288 atf_map_find_c(const atf_map_t *m, const char *key)
289 {
290     atf_list_citer_t iter;
291 
292     atf_list_for_each_c(iter, &m->m_list) {
293         const struct map_entry *me = atf_list_citer_data(iter);
294 
295         if (strcmp(me->m_key, key) == 0) {
296             atf_map_citer_t i;
297             i.m_map = m;
298             i.m_entry = me;
299             i.m_listiter = iter;
300             return i;
301         }
302     }
303 
304     return atf_map_end_c(m);
305 }
306 
307 size_t
atf_map_size(const atf_map_t * m)308 atf_map_size(const atf_map_t *m)
309 {
310     return atf_list_size(&m->m_list);
311 }
312 
313 char **
atf_map_to_charpp(const atf_map_t * l)314 atf_map_to_charpp(const atf_map_t *l)
315 {
316     char **array;
317     atf_map_citer_t iter;
318     size_t i;
319 
320     array = malloc(sizeof(char *) * (atf_map_size(l) * 2 + 1));
321     if (array == NULL)
322         goto out;
323 
324     i = 0;
325     atf_map_for_each_c(iter, l) {
326         array[i] = strdup(atf_map_citer_key(iter));
327         if (array[i] == NULL) {
328             atf_utils_free_charpp(array);
329             array = NULL;
330             goto out;
331         }
332 
333         array[i + 1] = strdup((const char *)atf_map_citer_data(iter));
334         if (array[i + 1] == NULL) {
335             atf_utils_free_charpp(array);
336             array = NULL;
337             goto out;
338         }
339 
340         i += 2;
341     }
342     array[i] = NULL;
343 
344 out:
345     return array;
346 }
347 
348 /*
349  * Modifiers.
350  */
351 
352 atf_error_t
atf_map_insert(atf_map_t * m,const char * key,void * value,bool managed)353 atf_map_insert(atf_map_t *m, const char *key, void *value, bool managed)
354 {
355     struct map_entry *me;
356     atf_error_t err;
357     atf_map_iter_t iter;
358 
359     iter = atf_map_find(m, key);
360     if (atf_equal_map_iter_map_iter(iter, atf_map_end(m))) {
361         me = new_entry(key, value, managed);
362         if (me == NULL)
363             err = atf_no_memory_error();
364         else {
365             err = atf_list_append(&m->m_list, me, false);
366             if (atf_is_error(err)) {
367                 if (managed)
368                     free(value);
369                 free(me);
370             }
371         }
372     } else {
373         me = iter.m_entry;
374         if (me->m_managed)
375             free(me->m_value);
376 
377         INV(strcmp(me->m_key, key) == 0);
378         me->m_value = value;
379         me->m_managed = managed;
380 
381         err = atf_no_error();
382     }
383 
384     return err;
385 }
386