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