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