1275988Sngie/* Copyright (c) 2008 The NetBSD Foundation, Inc.
2240116Smarcel * All rights reserved.
3240116Smarcel *
4240116Smarcel * Redistribution and use in source and binary forms, with or without
5240116Smarcel * modification, are permitted provided that the following conditions
6240116Smarcel * are met:
7240116Smarcel * 1. Redistributions of source code must retain the above copyright
8240116Smarcel *    notice, this list of conditions and the following disclaimer.
9240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright
10240116Smarcel *    notice, this list of conditions and the following disclaimer in the
11240116Smarcel *    documentation and/or other materials provided with the distribution.
12240116Smarcel *
13240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
14240116Smarcel * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
15240116Smarcel * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16240116Smarcel * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17240116Smarcel * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
18240116Smarcel * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
20240116Smarcel * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21240116Smarcel * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
22240116Smarcel * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23240116Smarcel * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
24275988Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */
25240116Smarcel
26275988Sngie#include "atf-c/detail/map.h"
27275988Sngie
28240116Smarcel#include <errno.h>
29240116Smarcel#include <stdlib.h>
30240116Smarcel#include <string.h>
31240116Smarcel
32275988Sngie#include "atf-c/detail/sanity.h"
33240116Smarcel#include "atf-c/error.h"
34240116Smarcel#include "atf-c/utils.h"
35240116Smarcel
36240116Smarcel/* ---------------------------------------------------------------------
37240116Smarcel * Auxiliary functions.
38240116Smarcel * --------------------------------------------------------------------- */
39240116Smarcel
40240116Smarcelstruct map_entry {
41240116Smarcel    char *m_key;
42240116Smarcel    void *m_value;
43240116Smarcel    bool m_managed;
44240116Smarcel};
45240116Smarcel
46240116Smarcelstatic
47240116Smarcelstruct map_entry *
48240116Smarcelnew_entry(const char *key, void *value, bool managed)
49240116Smarcel{
50240116Smarcel    struct map_entry *me;
51240116Smarcel
52240116Smarcel    me = (struct map_entry *)malloc(sizeof(*me));
53240116Smarcel    if (me != NULL) {
54240116Smarcel        me->m_key = strdup(key);
55240116Smarcel        if (me->m_key == NULL) {
56240116Smarcel            free(me);
57240116Smarcel            me = NULL;
58240116Smarcel        } else {
59240116Smarcel            me->m_value = value;
60240116Smarcel            me->m_managed = managed;
61240116Smarcel        }
62240116Smarcel    }
63240116Smarcel
64240116Smarcel    return me;
65240116Smarcel}
66240116Smarcel
67240116Smarcel/* ---------------------------------------------------------------------
68240116Smarcel * The "atf_map_citer" type.
69240116Smarcel * --------------------------------------------------------------------- */
70240116Smarcel
71240116Smarcel/*
72240116Smarcel * Getters.
73240116Smarcel */
74240116Smarcel
75240116Smarcelconst char *
76240116Smarcelatf_map_citer_key(const atf_map_citer_t citer)
77240116Smarcel{
78240116Smarcel    const struct map_entry *me = citer.m_entry;
79240116Smarcel    PRE(me != NULL);
80240116Smarcel    return me->m_key;
81240116Smarcel}
82240116Smarcel
83240116Smarcelconst void *
84240116Smarcelatf_map_citer_data(const atf_map_citer_t citer)
85240116Smarcel{
86240116Smarcel    const struct map_entry *me = citer.m_entry;
87240116Smarcel    PRE(me != NULL);
88240116Smarcel    return me->m_value;
89240116Smarcel}
90240116Smarcel
91240116Smarcelatf_map_citer_t
92240116Smarcelatf_map_citer_next(const atf_map_citer_t citer)
93240116Smarcel{
94240116Smarcel    atf_map_citer_t newciter;
95240116Smarcel
96240116Smarcel    newciter = citer;
97240116Smarcel    newciter.m_listiter = atf_list_citer_next(citer.m_listiter);
98240116Smarcel    newciter.m_entry = ((const struct map_entry *)
99240116Smarcel                        atf_list_citer_data(newciter.m_listiter));
100240116Smarcel
101240116Smarcel    return newciter;
102240116Smarcel}
103240116Smarcel
104240116Smarcelbool
105240116Smarcelatf_equal_map_citer_map_citer(const atf_map_citer_t i1,
106240116Smarcel                              const atf_map_citer_t i2)
107240116Smarcel{
108240116Smarcel    return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry;
109240116Smarcel}
110240116Smarcel
111240116Smarcel/* ---------------------------------------------------------------------
112240116Smarcel * The "atf_map_iter" type.
113240116Smarcel * --------------------------------------------------------------------- */
114240116Smarcel
115240116Smarcel/*
116240116Smarcel * Getters.
117240116Smarcel */
118240116Smarcel
119240116Smarcelconst char *
120240116Smarcelatf_map_iter_key(const atf_map_iter_t iter)
121240116Smarcel{
122240116Smarcel    const struct map_entry *me = iter.m_entry;
123240116Smarcel    PRE(me != NULL);
124240116Smarcel    return me->m_key;
125240116Smarcel}
126240116Smarcel
127240116Smarcelvoid *
128240116Smarcelatf_map_iter_data(const atf_map_iter_t iter)
129240116Smarcel{
130240116Smarcel    const struct map_entry *me = iter.m_entry;
131240116Smarcel    PRE(me != NULL);
132240116Smarcel    return me->m_value;
133240116Smarcel}
134240116Smarcel
135240116Smarcelatf_map_iter_t
136240116Smarcelatf_map_iter_next(const atf_map_iter_t iter)
137240116Smarcel{
138240116Smarcel    atf_map_iter_t newiter;
139240116Smarcel
140240116Smarcel    newiter = iter;
141240116Smarcel    newiter.m_listiter = atf_list_iter_next(iter.m_listiter);
142240116Smarcel    newiter.m_entry = ((struct map_entry *)
143240116Smarcel                       atf_list_iter_data(newiter.m_listiter));
144240116Smarcel
145240116Smarcel    return newiter;
146240116Smarcel}
147240116Smarcel
148240116Smarcelbool
149240116Smarcelatf_equal_map_iter_map_iter(const atf_map_iter_t i1,
150240116Smarcel                            const atf_map_iter_t i2)
151240116Smarcel{
152240116Smarcel    return i1.m_map == i2.m_map && i1.m_entry == i2.m_entry;
153240116Smarcel}
154240116Smarcel
155240116Smarcel/* ---------------------------------------------------------------------
156240116Smarcel * The "atf_map" type.
157240116Smarcel * --------------------------------------------------------------------- */
158240116Smarcel
159240116Smarcel/*
160240116Smarcel * Constructors and destructors.
161240116Smarcel */
162240116Smarcel
163240116Smarcelatf_error_t
164240116Smarcelatf_map_init(atf_map_t *m)
165240116Smarcel{
166240116Smarcel    return atf_list_init(&m->m_list);
167240116Smarcel}
168240116Smarcel
169240116Smarcelatf_error_t
170240116Smarcelatf_map_init_charpp(atf_map_t *m, const char *const *array)
171240116Smarcel{
172240116Smarcel    atf_error_t err;
173240116Smarcel    const char *const *ptr = array;
174240116Smarcel
175240116Smarcel    err = atf_map_init(m);
176240116Smarcel    if (array != NULL) {
177240116Smarcel        while (!atf_is_error(err) && *ptr != NULL) {
178240116Smarcel            const char *key, *value;
179240116Smarcel
180240116Smarcel            key = *ptr;
181240116Smarcel            INV(key != NULL);
182240116Smarcel            ptr++;
183240116Smarcel
184240116Smarcel            if ((value = *ptr) == NULL) {
185240116Smarcel                err = atf_libc_error(EINVAL, "List too short; no value for "
186240116Smarcel                    "key '%s' provided", key);  /* XXX: Not really libc_error */
187240116Smarcel                break;
188240116Smarcel            }
189240116Smarcel            ptr++;
190240116Smarcel
191240116Smarcel            err = atf_map_insert(m, key, strdup(value), true);
192240116Smarcel        }
193240116Smarcel    }
194240116Smarcel
195240116Smarcel    if (atf_is_error(err))
196240116Smarcel        atf_map_fini(m);
197240116Smarcel
198240116Smarcel    return err;
199240116Smarcel}
200240116Smarcel
201240116Smarcelvoid
202240116Smarcelatf_map_fini(atf_map_t *m)
203240116Smarcel{
204240116Smarcel    atf_list_iter_t iter;
205240116Smarcel
206240116Smarcel    atf_list_for_each(iter, &m->m_list) {
207240116Smarcel        struct map_entry *me = atf_list_iter_data(iter);
208240116Smarcel
209240116Smarcel        if (me->m_managed)
210240116Smarcel            free(me->m_value);
211240116Smarcel        free(me->m_key);
212240116Smarcel        free(me);
213240116Smarcel    }
214240116Smarcel    atf_list_fini(&m->m_list);
215240116Smarcel}
216240116Smarcel
217240116Smarcel/*
218240116Smarcel * Getters.
219240116Smarcel */
220240116Smarcel
221240116Smarcelatf_map_iter_t
222240116Smarcelatf_map_begin(atf_map_t *m)
223240116Smarcel{
224240116Smarcel    atf_map_iter_t iter;
225240116Smarcel    iter.m_map = m;
226240116Smarcel    iter.m_listiter = atf_list_begin(&m->m_list);
227240116Smarcel    iter.m_entry = atf_list_iter_data(iter.m_listiter);
228240116Smarcel    return iter;
229240116Smarcel}
230240116Smarcel
231240116Smarcelatf_map_citer_t
232240116Smarcelatf_map_begin_c(const atf_map_t *m)
233240116Smarcel{
234240116Smarcel    atf_map_citer_t citer;
235240116Smarcel    citer.m_map = m;
236240116Smarcel    citer.m_listiter = atf_list_begin_c(&m->m_list);
237240116Smarcel    citer.m_entry = atf_list_citer_data(citer.m_listiter);
238240116Smarcel    return citer;
239240116Smarcel}
240240116Smarcel
241240116Smarcelatf_map_iter_t
242240116Smarcelatf_map_end(atf_map_t *m)
243240116Smarcel{
244240116Smarcel    atf_map_iter_t iter;
245240116Smarcel    iter.m_map = m;
246240116Smarcel    iter.m_entry = NULL;
247240116Smarcel    iter.m_listiter = atf_list_end(&m->m_list);
248240116Smarcel    return iter;
249240116Smarcel}
250240116Smarcel
251240116Smarcelatf_map_citer_t
252240116Smarcelatf_map_end_c(const atf_map_t *m)
253240116Smarcel{
254240116Smarcel    atf_map_citer_t iter;
255240116Smarcel    iter.m_map = m;
256240116Smarcel    iter.m_entry = NULL;
257240116Smarcel    iter.m_listiter = atf_list_end_c(&m->m_list);
258240116Smarcel    return iter;
259240116Smarcel}
260240116Smarcel
261240116Smarcelatf_map_iter_t
262240116Smarcelatf_map_find(atf_map_t *m, const char *key)
263240116Smarcel{
264240116Smarcel    atf_list_iter_t iter;
265240116Smarcel
266240116Smarcel    atf_list_for_each(iter, &m->m_list) {
267240116Smarcel        struct map_entry *me = atf_list_iter_data(iter);
268240116Smarcel
269240116Smarcel        if (strcmp(me->m_key, key) == 0) {
270240116Smarcel            atf_map_iter_t i;
271240116Smarcel            i.m_map = m;
272240116Smarcel            i.m_entry = me;
273240116Smarcel            i.m_listiter = iter;
274240116Smarcel            return i;
275240116Smarcel        }
276240116Smarcel    }
277240116Smarcel
278240116Smarcel    return atf_map_end(m);
279240116Smarcel}
280240116Smarcel
281240116Smarcelatf_map_citer_t
282240116Smarcelatf_map_find_c(const atf_map_t *m, const char *key)
283240116Smarcel{
284240116Smarcel    atf_list_citer_t iter;
285240116Smarcel
286240116Smarcel    atf_list_for_each_c(iter, &m->m_list) {
287240116Smarcel        const struct map_entry *me = atf_list_citer_data(iter);
288240116Smarcel
289240116Smarcel        if (strcmp(me->m_key, key) == 0) {
290240116Smarcel            atf_map_citer_t i;
291240116Smarcel            i.m_map = m;
292240116Smarcel            i.m_entry = me;
293240116Smarcel            i.m_listiter = iter;
294240116Smarcel            return i;
295240116Smarcel        }
296240116Smarcel    }
297240116Smarcel
298240116Smarcel    return atf_map_end_c(m);
299240116Smarcel}
300240116Smarcel
301240116Smarcelsize_t
302240116Smarcelatf_map_size(const atf_map_t *m)
303240116Smarcel{
304240116Smarcel    return atf_list_size(&m->m_list);
305240116Smarcel}
306240116Smarcel
307240116Smarcelchar **
308240116Smarcelatf_map_to_charpp(const atf_map_t *l)
309240116Smarcel{
310240116Smarcel    char **array;
311240116Smarcel    atf_map_citer_t iter;
312240116Smarcel    size_t i;
313240116Smarcel
314240116Smarcel    array = malloc(sizeof(char *) * (atf_map_size(l) * 2 + 1));
315240116Smarcel    if (array == NULL)
316240116Smarcel        goto out;
317240116Smarcel
318240116Smarcel    i = 0;
319240116Smarcel    atf_map_for_each_c(iter, l) {
320240116Smarcel        array[i] = strdup(atf_map_citer_key(iter));
321240116Smarcel        if (array[i] == NULL) {
322240116Smarcel            atf_utils_free_charpp(array);
323240116Smarcel            array = NULL;
324240116Smarcel            goto out;
325240116Smarcel        }
326240116Smarcel
327240116Smarcel        array[i + 1] = strdup((const char *)atf_map_citer_data(iter));
328240116Smarcel        if (array[i + 1] == NULL) {
329240116Smarcel            atf_utils_free_charpp(array);
330240116Smarcel            array = NULL;
331240116Smarcel            goto out;
332240116Smarcel        }
333240116Smarcel
334240116Smarcel        i += 2;
335240116Smarcel    }
336240116Smarcel    array[i] = NULL;
337240116Smarcel
338240116Smarcelout:
339240116Smarcel    return array;
340240116Smarcel}
341240116Smarcel
342240116Smarcel/*
343240116Smarcel * Modifiers.
344240116Smarcel */
345240116Smarcel
346240116Smarcelatf_error_t
347240116Smarcelatf_map_insert(atf_map_t *m, const char *key, void *value, bool managed)
348240116Smarcel{
349240116Smarcel    struct map_entry *me;
350240116Smarcel    atf_error_t err;
351240116Smarcel    atf_map_iter_t iter;
352240116Smarcel
353240116Smarcel    iter = atf_map_find(m, key);
354240116Smarcel    if (atf_equal_map_iter_map_iter(iter, atf_map_end(m))) {
355240116Smarcel        me = new_entry(key, value, managed);
356240116Smarcel        if (me == NULL)
357240116Smarcel            err = atf_no_memory_error();
358240116Smarcel        else {
359240116Smarcel            err = atf_list_append(&m->m_list, me, false);
360240116Smarcel            if (atf_is_error(err)) {
361240116Smarcel                if (managed)
362240116Smarcel                    free(value);
363240116Smarcel            }
364240116Smarcel        }
365240116Smarcel    } else {
366240116Smarcel        me = iter.m_entry;
367240116Smarcel        if (me->m_managed)
368240116Smarcel            free(me->m_value);
369240116Smarcel
370240116Smarcel        INV(strcmp(me->m_key, key) == 0);
371240116Smarcel        me->m_value = value;
372240116Smarcel        me->m_managed = managed;
373240116Smarcel
374240116Smarcel        err = atf_no_error();
375240116Smarcel    }
376240116Smarcel
377240116Smarcel    return err;
378240116Smarcel}
379