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