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 free(me); 364240116Smarcel } 365240116Smarcel } 366240116Smarcel } else { 367240116Smarcel me = iter.m_entry; 368240116Smarcel if (me->m_managed) 369240116Smarcel free(me->m_value); 370240116Smarcel 371240116Smarcel INV(strcmp(me->m_key, key) == 0); 372240116Smarcel me->m_value = value; 373240116Smarcel me->m_managed = managed; 374240116Smarcel 375240116Smarcel err = atf_no_error(); 376240116Smarcel } 377240116Smarcel 378240116Smarcel return err; 379240116Smarcel} 380