diff --git a/src/dict.c b/src/dict.c index 5c331104..a951e131 100644 --- a/src/dict.c +++ b/src/dict.c @@ -48,6 +48,41 @@ #include "gldns/gbuffer.h" #include "gldns/wire2str.h" + +static struct getdns_dict_item * +_find_dict_item(const getdns_dict *dict, const char *key) +{ + const char *next_ref, *k; + char json_key_spc[1024], *json_key, *j; + struct getdns_dict_item *d; + + if (*key != '/') + return (struct getdns_dict_item *) _getdns_rbtree_search( + (_getdns_rbtree_t *)&(dict->root), key); + key++; + if (!(next_ref = strchr(key, '/'))) + next_ref = key + strlen(key); + if (next_ref - key > sizeof(json_key_spc)) + json_key = GETDNS_XMALLOC(dict->mf, char, next_ref - key + 1); + else + json_key = json_key_spc; + + for (j = json_key, k = key; k < next_ref; j++, k++) + *j = k[0] == '~' && k[1] == '1' ? (k++, '/') : *k; + *j = '\0'; + for (j = json_key, k = json_key; *k; j++, k++) + *j = k[0] == '~' && k[1] == '0' ? (k++, '~') : *k; + *j = '\0'; + + d = (struct getdns_dict_item *) _getdns_rbtree_search( + (_getdns_rbtree_t *)&(dict->root), json_key); + + if (json_key != json_key_spc) + GETDNS_FREE(dict->mf, json_key); + + return d; +} + /*---------------------------------------- getdns_dict_find */ /** * private function used to locate a key in a dictionary @@ -56,29 +91,28 @@ * @return pointer to dictionary item, caller must not free storage associated with item * @return NULL if additnotfnd == FALSE and key is not in dictionary */ -static struct getdns_dict_item * -getdns_dict_find(const struct getdns_dict *dict, const char *key) +static inline getdns_item * +getdns_dict_find(const getdns_dict *dict, const char *key) { - return (struct getdns_dict_item *) - _getdns_rbtree_search((_getdns_rbtree_t *)&(dict->root), key); + struct getdns_dict_item *d = _find_dict_item(dict, key); + return d ? &d->i : NULL; } /* getdns_dict_find */ -static struct getdns_dict_item * +static getdns_item * getdns_dict_find_and_add(struct getdns_dict *dict, const char *key) { - struct getdns_dict_item *item; + struct getdns_dict_item *d; - item = (struct getdns_dict_item *) - _getdns_rbtree_search(&(dict->root), key); + d = _find_dict_item(dict, key); - if (!item) { + if (!d) { /* add a node */ - item = GETDNS_MALLOC(dict->mf, struct getdns_dict_item); - item->node.key = _getdns_strdup(&dict->mf, key); - item->data.n = 0; - _getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) item); + d = GETDNS_MALLOC(dict->mf, struct getdns_dict_item); + d->node.key = _getdns_strdup(&dict->mf, key); + d->i.data.n = 0; + _getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) d); } - return item; + return &d->i; } /* getdns_dict_find_and_add */ @@ -107,10 +141,10 @@ getdns_dict_get_names(const getdns_dict *dict, getdns_list **answer) /*---------------------------------------- getdns_dict_get_data_type */ getdns_return_t -getdns_dict_get_data_type(const struct getdns_dict * dict, const char *name, - getdns_data_type * answer) +getdns_dict_get_data_type( + const getdns_dict *dict, const char *name, getdns_data_type *answer) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; @@ -125,10 +159,10 @@ getdns_dict_get_data_type(const struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_get_dict */ getdns_return_t -getdns_dict_get_dict(const struct getdns_dict * dict, const char *name, - struct getdns_dict ** answer) +getdns_dict_get_dict( + const getdns_dict *dict, const char *name, getdns_dict **answer) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; @@ -146,10 +180,10 @@ getdns_dict_get_dict(const struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_get_list */ getdns_return_t -getdns_dict_get_list(const struct getdns_dict * dict, const char *name, - struct getdns_list ** answer) +getdns_dict_get_list( + const getdns_dict *dict, const char *name, getdns_list **answer) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; @@ -167,10 +201,10 @@ getdns_dict_get_list(const struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_get_bindata */ getdns_return_t -getdns_dict_get_bindata(const struct getdns_dict * dict, const char *name, - struct getdns_bindata ** answer) +getdns_dict_get_bindata( + const getdns_dict *dict, const char *name, getdns_bindata **answer) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; @@ -188,10 +222,10 @@ getdns_dict_get_bindata(const struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_get_int */ getdns_return_t -getdns_dict_get_int(const struct getdns_dict * dict, const char *name, - uint32_t * answer) +getdns_dict_get_int( + const getdns_dict *dict, const char *name, uint32_t *answer) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; @@ -307,25 +341,25 @@ _getdns_dict_copy(const struct getdns_dict * srcdict, RBTREE_FOR(item, struct getdns_dict_item *, (struct _getdns_rbtree_t *)&(srcdict->root)) { key = (char *) item->node.key; - switch (item->dtype) { + switch (item->i.dtype) { case t_bindata: retval = getdns_dict_set_bindata(*dstdict, key, - item->data.bindata); + item->i.data.bindata); break; case t_dict: retval = getdns_dict_set_dict(*dstdict, key, - item->data.dict); + item->i.data.dict); break; case t_int: retval = getdns_dict_set_int(*dstdict, key, - item->data.n); + item->i.data.n); break; case t_list: retval = getdns_dict_set_list(*dstdict, key, - item->data.list); + item->i.data.list); break; } if (retval != GETDNS_RETURN_GOOD) { @@ -354,15 +388,15 @@ getdns_dict_item_free(_getdns_rbnode_t * node, void *arg) if (!item) return; - switch (item->dtype) { + switch (item->i.dtype) { case t_bindata: - _getdns_bindata_destroy(&dict->mf, item->data.bindata); + _getdns_bindata_destroy(&dict->mf, item->i.data.bindata); break; case t_dict: - getdns_dict_destroy(item->data.dict); + getdns_dict_destroy(item->i.data.dict); break; case t_list: - getdns_list_destroy(item->data.list); + getdns_list_destroy(item->i.data.list); break; default: break; @@ -383,11 +417,11 @@ getdns_dict_destroy(struct getdns_dict *dict) /*---------------------------------------- getdns_dict_set_dict */ getdns_return_t -getdns_dict_set_dict(struct getdns_dict * dict, const char *name, - const struct getdns_dict * child_dict) +getdns_dict_set_dict( + getdns_dict *dict, const char *name, const getdns_dict *child_dict) { - struct getdns_dict_item *item; - struct getdns_dict *newdict; + getdns_item *item; + getdns_dict *newdict; getdns_return_t retval; if (!dict || !name || !child_dict) @@ -409,11 +443,11 @@ getdns_dict_set_dict(struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_set_list */ getdns_return_t -getdns_dict_set_list(struct getdns_dict * dict, const char *name, - const struct getdns_list * child_list) +getdns_dict_set_list( + getdns_dict *dict, const char *name, const getdns_list *child_list) { - struct getdns_dict_item *item; - struct getdns_list *newlist; + getdns_item *item; + getdns_list *newlist; getdns_return_t retval; if (!dict || !name || !child_list) @@ -435,11 +469,11 @@ getdns_dict_set_list(struct getdns_dict * dict, const char *name, /*---------------------------------------- getdns_dict_set_bindata */ getdns_return_t -getdns_dict_set_bindata(struct getdns_dict * dict, const char *name, - const struct getdns_bindata * child_bindata) +getdns_dict_set_bindata( + getdns_dict *dict, const char *name, const getdns_bindata *child_bindata) { - struct getdns_dict_item *item; - struct getdns_bindata *newbindata; + getdns_item *item; + getdns_bindata *newbindata; if (!dict || !name || !child_bindata) return GETDNS_RETURN_INVALID_PARAMETER; @@ -462,8 +496,8 @@ getdns_dict_set_bindata(struct getdns_dict * dict, const char *name, getdns_return_t getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value) { - struct getdns_dict_item *item; - getdns_bindata *newbindata; + getdns_item *item; + getdns_bindata *newbindata; if (!dict || !name || !value) return GETDNS_RETURN_INVALID_PARAMETER; @@ -489,10 +523,9 @@ error_free_bindata: /*---------------------------------------- getdns_dict_set_int */ getdns_return_t -getdns_dict_set_int(struct getdns_dict * dict, const char *name, - uint32_t child_uint32) +getdns_dict_set_int(getdns_dict *dict, const char *name, uint32_t child_uint32) { - struct getdns_dict_item *item; + getdns_item *item; if (!dict || !name) return GETDNS_RETURN_INVALID_PARAMETER; @@ -840,13 +873,13 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, buf, "\"%s\":",(const char *)item->node.key) < 0) return -1; - switch (item->dtype) { + switch (item->i.dtype) { case t_int: if (!json && (strcmp(item->node.key, "type") == 0 || strcmp(item->node.key, "type_covered") == 0 || strcmp(item->node.key, "qtype") == 0) && - (strval = _getdns_rr_type_name(item->data.n))) { + (strval = _getdns_rr_type_name(item->i.data.n))) { if (gldns_buffer_printf( buf, " GETDNS_RRTYPE_%s", strval) < 0) return -1; @@ -860,7 +893,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, strcmp(item->node.key, "follow_redirects") == 0 || strcmp(item->node.key, "resolution_type") == 0) && (strval = - _getdns_get_const_info(item->data.n)->name)) { + _getdns_get_const_info(item->i.data.n)->name)) { if (gldns_buffer_printf(buf, " %s", strval) < 0) return -1; break; @@ -868,16 +901,16 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if (!json && (strcmp(item->node.key, "class") == 0 || strcmp(item->node.key, "qclass") == 0) && - _getdns_print_class(buf, item->data.n)) + _getdns_print_class(buf, item->i.data.n)) break; if (!json && strcmp(item->node.key, "opcode") == 0 && - _getdns_print_opcode(buf, item->data.n)) + _getdns_print_opcode(buf, item->i.data.n)) break; if (!json && strcmp(item->node.key, "rcode") == 0 && - _getdns_print_rcode(buf, item->data.n)) + _getdns_print_rcode(buf, item->i.data.n)) break; if (gldns_buffer_printf( - buf,(json < 2 ? " %d" : "%d"), item->data.n) < 0) + buf,(json < 2 ? " %d" : "%d"), item->i.data.n) < 0) return -1; break; @@ -885,21 +918,21 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if ((strcmp(item->node.key, "address_data") == 0 || strcmp(item->node.key, "ipv4_address") == 0 || strcmp(item->node.key, "ipv6_address") == 0 ) && - (item->data.bindata->size == 4 || - item->data.bindata->size == 16 )) { + (item->i.data.bindata->size == 4 || + item->i.data.bindata->size == 16 )) { if (gldns_buffer_printf(buf, (json ? "\"%s\"" : " "), - inet_ntop(( item->data.bindata->size == 4 + inet_ntop(( item->i.data.bindata->size == 4 ? AF_INET : AF_INET6) - , item->data.bindata->data + , item->i.data.bindata->data , abuf , 40 )) < 0) return -1; } else if (getdns_pp_bindata( - buf, indent, item->data.bindata, + buf, indent, item->i.data.bindata, (strcmp(item->node.key, "rdata_raw") == 0), json) < 0) return -1; @@ -907,7 +940,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, case t_list: /* Don't put empty lists on a new line */ - if (getdns_list_get_length(item->data.list, &length) != + if (getdns_list_get_length(item->i.data.list, &length) != GETDNS_RETURN_GOOD) return -1; if (length == 0) { @@ -919,7 +952,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, if (json < 2 && gldns_buffer_printf(buf, "\n%s", getdns_indent(indent)) < 0) return -1; - if (getdns_pp_list(buf, indent, item->data.list, + if (getdns_pp_list(buf, indent, item->i.data.list, (strcmp(item->node.key, "namespaces") == 0 || strcmp(item->node.key, "dns_transport_list") == 0), json) < 0) @@ -931,7 +964,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent, getdns_indent(indent)) < 0) return -1; if (getdns_pp_dict( - buf, indent, item->data.dict, json) < 0) + buf, indent, item->i.data.dict, json) < 0) return -1; break; @@ -1099,21 +1132,18 @@ getdns_snprint_json_list( } getdns_return_t -getdns_dict_remove_name(struct getdns_dict *this_dict, const char *name) +getdns_dict_remove_name(getdns_dict *dict, const char *name) { - struct getdns_dict_item *item; + _getdns_rbnode_t *n; - if (!this_dict || !name) + if (!dict || !name) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(this_dict, name); - if (!item) + if ((n = _getdns_rbtree_delete(&dict->root, name))) + getdns_dict_item_free(n, dict); + else return GETDNS_RETURN_NO_SUCH_DICT_NAME; - /* cleanup */ - _getdns_rbtree_delete(&this_dict->root, name); - getdns_dict_item_free(&item->node, this_dict); - return GETDNS_RETURN_GOOD; } diff --git a/src/dict.h b/src/dict.h index a68619ac..0e3ab58e 100644 --- a/src/dict.h +++ b/src/dict.h @@ -39,22 +39,13 @@ #include "util/rbtree.h" #include "types-internal.h" -union getdns_item -{ - struct getdns_list *list; - struct getdns_dict *dict; - uint32_t n; - struct getdns_bindata *bindata; -}; - /** * this structure represents a single item in a dictionary type */ struct getdns_dict_item { _getdns_rbnode_t node; - getdns_data_type dtype; - union getdns_item data; + getdns_item i; }; /** diff --git a/src/list.c b/src/list.c index 9fe570f0..44fa805e 100644 --- a/src/list.c +++ b/src/list.c @@ -222,7 +222,7 @@ getdns_list_create_with_extended_memory_functions( list->numinuse = 0; if (!(list->items = GETDNS_XMALLOC( - list->mf, struct getdns_list_item, GETDNS_LIST_BLOCKSZ))) { + list->mf, getdns_item, GETDNS_LIST_BLOCKSZ))) { GETDNS_FREE(list->mf, list); return NULL; } @@ -308,7 +308,7 @@ getdns_list_destroy(struct getdns_list *list) static getdns_return_t _getdns_list_request_index(getdns_list *list, size_t index) { - struct getdns_list_item *newlist; + getdns_item *newlist; assert(list); @@ -325,7 +325,7 @@ _getdns_list_request_index(getdns_list *list, size_t index) return GETDNS_RETURN_GOOD; } if (!(newlist = GETDNS_XREALLOC(list->mf, list->items, - struct getdns_list_item, list->numalloc + GETDNS_LIST_BLOCKSZ))) + getdns_item, list->numalloc + GETDNS_LIST_BLOCKSZ))) return GETDNS_RETURN_MEMORY_ERROR; diff --git a/src/list.h b/src/list.h index 6d31d932..46c8b92d 100644 --- a/src/list.h +++ b/src/list.h @@ -42,21 +42,6 @@ #define GETDNS_LIST_BLOCKSZ 10 -/** - * this structure represents a single item in a list - */ -struct getdns_list_item -{ - getdns_data_type dtype; - union - { - struct getdns_list *list; - struct getdns_dict *dict; - int n; - struct getdns_bindata *bindata; - } data; -}; - /** * getdns list data type * Use helper functions getdns_list_* to manipulate and iterate lists @@ -70,7 +55,7 @@ struct getdns_list { size_t numalloc; size_t numinuse; - struct getdns_list_item *items; + struct getdns_item *items; struct mem_funcs mf; }; diff --git a/src/types-internal.h b/src/types-internal.h index 5750fdc5..d6d6a05b 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -41,6 +41,21 @@ #include "util/rbtree.h" +/** + * this structure represents a single item in a list or dict + */ +typedef struct getdns_item { + getdns_data_type dtype; + union + { + struct getdns_list *list; + struct getdns_dict *dict; + int n; + struct getdns_bindata *bindata; + } data; +} getdns_item; + + struct getdns_context; struct getdns_upstreams; struct getdns_upstream; diff --git a/src/util-internal.c b/src/util-internal.c index 5c7f88d3..d6e9299e 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -839,7 +839,7 @@ _getdns_validate_extensions(struct getdns_dict * extensions) if (!extformat) return GETDNS_RETURN_NO_SUCH_EXTENSION; - if (item->dtype != extformat->exttype) + if (item->i.dtype != extformat->exttype) return GETDNS_RETURN_EXTENSION_MISFORMAT; } return GETDNS_RETURN_GOOD;