X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/8c354c48ec90c997cc7213ce96ca97d882934166..0a03cd809dd45e3645a54feffe364d8f2b33d71e:/src/xbt/dict_multi.c diff --git a/src/xbt/dict_multi.c b/src/xbt/dict_multi.c index 0a506e8201..c3b7a5e733 100644 --- a/src/xbt/dict_multi.c +++ b/src/xbt/dict_multi.c @@ -2,246 +2,237 @@ /* dict_multi - dictionnaries of dictionnaries of ... of data */ -/* Copyright (c) 2004 Martin Quinson. All rights reserved. */ +/* Copyright (c) 2003-2005 Martin Quinson. All rights reserved. */ /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ -#include "gras_private.h" +#include "dict_private.h" -#include /* malloc() */ -#include /* strlen() */ +XBT_LOG_NEW_DEFAULT_SUBCATEGORY(xbt_dict_multi, xbt_dict, + "Dictionaries of multiple keys"); -/*####[ Multi dict functions ]##############################################*/ -/*###############################"##########################################*/ -/** - * gras_mutidict_set: +static void _free_dict(void *d) +{ + VERB1("free dict %p", d); + xbt_dict_free((xbt_dict_t *) & d); +} + +/** \brief Insert \e data under all the keys contained in \e keys, providing their sizes in \e lens. * - * @head: the head of dict - * @keycount: the number of the key - * @key: the key - * @data: the data to set - * @Returns: gras_error_t + * \arg mdict: the multi-dict + * \arg keys: dynar of (char *) containing all the keys + * \arg lens: length of each element of \e keys + * \arg data: what to store in the structure + * \arg free_ctn: function to use to free the pushed content on need * - * set the data in the structure under the @keycount @key. + * Dynars are not modified during the operation. */ -gras_error_t -gras_multidict_set_ext(gras_dict_t **pp_head, - int keycount, - char **key, - int *key_len, - void *data, - void_f_pvoid_t *free_ctn) { - gras_error_t errcode = no_error; - gras_dictelm_t *p_elm = NULL; - gras_dictelm_t *p_subdict = NULL; - int i = 0; - - CDEBUG2(dict_multi, "fast_multidict_set(%p,%d). Keys:", *pp_head, keycount); - - /* - for (i = 0; i < keycount; i++) { - CDEBUG1(dict_multi, "\"%s\"", key[i]); - } - */ +void +xbt_multidict_set_ext(xbt_dict_t mdict, + xbt_dynar_t keys, xbt_dynar_t lens, + void *data, void_f_pvoid_t free_ctn) +{ - gras_assert0(keycount >= 1, "Can't set less than one key in a multidict"); + xbt_dict_t thislevel, nextlevel = NULL; + int i; - if (keycount == 1) - return gras_dict_set_ext(pp_head, key[0], key_len[0], data, free_ctn); + unsigned long int thislen; + char *thiskey; + int keys_len = xbt_dynar_length(keys); - if (!*pp_head) { - TRY(_gras_dict_alloc(NULL, 0, 0, NULL, NULL, pp_head)); - } + xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens)); + xbt_assert0(keys_len, "Can't set a zero-long key set in a multidict"); - p_elm = *pp_head; + DEBUG2("xbt_multidict_set(%p,%d)", mdict, keys_len); - for (i = 0; i < keycount-1; i++) { + for (i = 0, thislevel = mdict; i < keys_len - 1; i++, thislevel = nextlevel) { - /* search the dict of next level */ - TRYCATCH(gras_dict_get(p_elm, key[i], (void*)&p_subdict), mismatch_error); + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); - /* make sure the dict of next level exists */ - if (errcode == mismatch_error) { - TRY(_gras_dict_alloc(NULL, 0, 0, NULL, NULL, &p_subdict)); - TRY(gras_dict_set_ext(&p_elm, key[i], key_len[i], &p_subdict, - _free_dict)); - } + DEBUG5("multi_set: at level %d, len=%ld, key=%p |%*s|", i, thislen, + thiskey, (int) thislen, thiskey); - p_elm = p_subdict; + /* search the dict of next level */ + nextlevel = xbt_dict_get_or_null_ext(thislevel, thiskey, thislen); + if (nextlevel == NULL) { + /* make sure the dict of next level exists */ + nextlevel = xbt_dict_new(); + VERB1("Create a dict (%p)", nextlevel); + xbt_dict_set_ext(thislevel, thiskey, thislen, nextlevel, &_free_dict); + } } - return gras_dict_set_ext(&p_elm, key[i], key_len[i], data, free_ctn); + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); + + xbt_dict_set_ext(thislevel, thiskey, thislen, data, free_ctn); } -gras_error_t -gras_multidict_set(gras_dictelm_t **pp_head, - int keycount, - char **key, - void *data, - void_f_pvoid_t *free_ctn) { - gras_error_t errcode = no_error; - int *key_len = NULL; - int i = 0; - - key_len = malloc(keycount * sizeof (int)); - if (!key_len) - RAISE_MALLOC; - - for (i = 0; i < keycount; i++) { - key_len[i] = 1+strlen(key[i]); +/** \brief Insert \e data under all the keys contained in \e keys + * + * \arg head: the head of dict + * \arg keys: dynar of null-terminated strings containing all the keys + * \arg data: what to store in the structure + * \arg free_ctn: function to use to free the pushed content on need + */ +void +xbt_multidict_set(xbt_dict_t mdict, + xbt_dynar_t keys, void *data, void_f_pvoid_t free_ctn) +{ + xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL); + unsigned long i; + xbt_ex_t e; + + for (i = 0; i < xbt_dynar_length(keys); i++) { + char *thiskey = xbt_dynar_get_as(keys, i, char *); + unsigned long int thislen = (unsigned long int) strlen(thiskey); + DEBUG2("Push %ld as level %lu length", thislen, i); + xbt_dynar_push(lens, &thislen); } - TRYCLEAN(gras_multidict_set_ext(pp_head, keycount, key, key_len, data, free_ctn), - gras_free(key_len)); - - gras_free(key_len); - - return errcode; + TRY { + xbt_multidict_set_ext(mdict, keys, lens, data, free_ctn); + } CLEANUP { + xbt_dynar_free(&lens); + } CATCH(e) { + RETHROW; + } } -/** - * gras_mutidict_get: +/** \brief Insert \e data under all the keys contained in \e keys, providing their sizes in \e lens. * - * @head: the head of dict - * @keycount: the number of the key - * @key: the key - * @data: where to put the got data - * @Returns: gras_error_t + * \arg mdict: the multi-dict + * \arg keys: dynar of (char *) containing all the keys + * \arg lens: length of each element of \e keys + * \arg data: where to put what was found in structure + * \arg free_ctn: function to use to free the pushed content on need * - * Search the given @key. data=NULL when not found + * Dynars are not modified during the operation. */ +void *xbt_multidict_get_ext(xbt_dict_t mdict, + xbt_dynar_t keys, xbt_dynar_t lens) +{ + xbt_dict_t thislevel, nextlevel; + int i; + unsigned long int thislen; + char *thiskey; + int keys_len = xbt_dynar_length(keys); -gras_error_t -gras_multidict_get_ext(gras_dictelm_t *p_head, - int keycount, - const char **key, - int *key_len, - /* OUT */void **data) { - gras_error_t errcode = no_error; - gras_dictelm_t *p_elm = p_head; - int i = 0; + xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens)); + xbt_assert0(xbt_dynar_length(keys) >= 1, + "Can't get a zero-long key set in a multidict"); - CDEBUG2(dict_multi, "fast_multidict_get(%p, %d). Keys:", p_head, keycount); + DEBUG2("xbt_multidict_get(%p, %ld)", mdict, xbt_dynar_length(keys)); - /* - for (i = 0; i < keycount; i++) { - CDEBUG1(dict_multi, "\"%s\"", key[i]); - } - */ - - i = 0; + for (i = 0, thislevel = mdict; i < keys_len - 1; i++, thislevel = nextlevel) { - while (p_elm && i < keycount-1) { + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); - TRY(gras_dict_get_ext(p_elm, key[i], key_len[i], (void**)p_elm)); - - /* - if (p_elm) { - CDEBUG3(dict_multi,"Found level %d for key %s in multitree %", i, key[i], p_head); - } else { - CDEBUG3(dict_multi,"NOT found level %d for key %s in multitree %p", i, key[i], p_head); - } - */ + DEBUG6("multi_get: at level %d (%p), len=%ld, key=%p |%*s|", + i, thislevel, thislen, thiskey, (int) thislen, thiskey); - i++; + /* search the dict of next level: let mismatch raise if not found */ + nextlevel = xbt_dict_get_ext(thislevel, thiskey, thislen); } - if (p_elm) { /* Found all dicts to the data */ - - /* gras_dict_dump(dict,&gras_dict_prints); */ - return gras_dict_get_ext(p_elm, key[i], key_len[i], data); - - } else { - - *data = NULL; - - return 1; - } + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); + return xbt_dict_get_ext(thislevel, thiskey, thislen); } -gras_error_t -gras_multidict_get(gras_dictelm_t *p_head, - int keycount, - const char **key, - /* OUT */void **data) { - gras_error_t errcode = no_error; - int *key_len = NULL; - int i = 0; - - key_len = malloc(keycount * sizeof (int)); - if (!key_len) - RAISE_MALLOC; - - for (i = 0; i < keycount; i++) { - key_len[i] = 1+strlen(key[i]); - } +void *xbt_multidict_get(xbt_dict_t mdict, xbt_dynar_t keys) +{ + xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL); + unsigned long i; + void *res; - TRYCLEAN(gras_multidict_get_ext(p_head, keycount, key, key_len, data), - gras_free(key_len)); - gras_free(key_len); + for (i = 0; i < xbt_dynar_length(keys); i++) { + char *thiskey = xbt_dynar_get_as(keys, i, char *); + unsigned long int thislen = (unsigned long int) strlen(thiskey); + xbt_dynar_push(lens, &thislen); + } - return errcode; + res = xbt_multidict_get_ext(mdict, keys, lens), xbt_dynar_free(&lens); + return res; } -/** - * gras_mutidict_remove: +/** \brief Remove the entry under all the keys contained in \e keys, providing their sizes in \e lens. * - * @head: the head of dict - * @keycount: the number of the key - * @key: the key - * @Returns: gras_error_t + * \arg mdict: the multi-dict + * \arg keys: dynar of (char *) containing all the keys + * \arg lens: length of each element of \e keys + * \arg data: what to store in the structure + * \arg free_ctn: function to use to free the pushed content on need + * + * Dynars are not modified during the operation. * - * Remove the entry associated with the given @key * Removing a non-existant key is ok. */ -gras_error_t -gras_multidict_remove_ext(gras_dictelm_t *p_head, - int keycount, - const char **key, - int *key_len) { - gras_dictelm_t *p_elm = p_head; - int i = 0; - - while (p_elm && i < keycount-1) { - if (!gras_dict_get_ext(p_elm, key[i], key_len[i], (void**)&p_elm)) { - return 0; +void +xbt_multidict_remove_ext(xbt_dict_t mdict, xbt_dynar_t keys, xbt_dynar_t lens) +{ + xbt_dict_t thislevel, nextlevel = NULL; + int i; + xbt_ex_t e; + + unsigned long int thislen; + char *thiskey; + int keys_len = xbt_dynar_length(keys); + + xbt_assert(xbt_dynar_length(keys) == xbt_dynar_length(lens)); + xbt_assert0(xbt_dynar_length(keys), + "Can't remove a zero-long key set in a multidict"); + + for (i = 0, thislevel = mdict; i < keys_len - 1; i++, thislevel = nextlevel) { + + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); + + /* search the dict of next level */ + TRY { + nextlevel = xbt_dict_get_ext(thislevel, thiskey, thislen); + } + CATCH(e) { + /* If non-existant entry, nothing to do */ + if (e.category == arg_error) + xbt_ex_free(e); + else + RETHROW; } } - if (p_elm) { - /* Found all dicts to the data */ - return gras_dict_remove_ext(p_elm, key[i], key_len[i]); - } else { - return 1; - } + xbt_dynar_get_cpy(keys, i, &thiskey); + xbt_dynar_get_cpy(lens, i, &thislen); + xbt_dict_remove_ext(thislevel, thiskey, thislen); } -gras_error_t -gras_multidict_remove(gras_dictelm_t *p_head, - int keycount, - const char **key) { - gras_error_t errcode = no_error; - int *key_len = NULL; - int i = 0; +void xbt_multidict_remove(xbt_dict_t mdict, xbt_dynar_t keys) +{ - key_len = malloc(keycount * sizeof (int)); - if (!key_len) - RAISE_MALLOC; + xbt_ex_t e; + xbt_dynar_t lens = xbt_dynar_new(sizeof(unsigned long int), NULL); + unsigned long i; - for (i = 0; i < keycount; i++) { - key_len[i] = 1+strlen(key[i]); + for (i = 0; i < xbt_dynar_length(keys); i++) { + char *thiskey = xbt_dynar_get_as(keys, i, char *); + unsigned long int thislen = strlen(thiskey); + xbt_dynar_push(lens, &thislen); } - TRYCLEAN(gras_multidict_remove_ext(p_head, keycount, key, key_len), - gras_free(key_len)); - gras_free(key_len); - - return errcode; + TRY { + xbt_multidict_remove_ext(mdict, keys, lens); + } CLEANUP { + xbt_dynar_free(&lens); + } CATCH(e) { + RETHROW; + } }