1 level JSON pointer reference lookup

This commit is contained in:
Willem Toorop 2015-09-30 16:05:19 +02:00
parent 3bec89bee5
commit ca50a984c8
6 changed files with 130 additions and 109 deletions

View File

@ -48,6 +48,41 @@
#include "gldns/gbuffer.h" #include "gldns/gbuffer.h"
#include "gldns/wire2str.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 */ /*---------------------------------------- getdns_dict_find */
/** /**
* private function used to locate a key in a dictionary * 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 pointer to dictionary item, caller must not free storage associated with item
* @return NULL if additnotfnd == FALSE and key is not in dictionary * @return NULL if additnotfnd == FALSE and key is not in dictionary
*/ */
static struct getdns_dict_item * static inline getdns_item *
getdns_dict_find(const struct getdns_dict *dict, const char *key) getdns_dict_find(const getdns_dict *dict, const char *key)
{ {
return (struct getdns_dict_item *) struct getdns_dict_item *d = _find_dict_item(dict, key);
_getdns_rbtree_search((_getdns_rbtree_t *)&(dict->root), key); return d ? &d->i : NULL;
} /* getdns_dict_find */ } /* getdns_dict_find */
static struct getdns_dict_item * static getdns_item *
getdns_dict_find_and_add(struct getdns_dict *dict, const char *key) 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 *) d = _find_dict_item(dict, key);
_getdns_rbtree_search(&(dict->root), key);
if (!item) { if (!d) {
/* add a node */ /* add a node */
item = GETDNS_MALLOC(dict->mf, struct getdns_dict_item); d = GETDNS_MALLOC(dict->mf, struct getdns_dict_item);
item->node.key = _getdns_strdup(&dict->mf, key); d->node.key = _getdns_strdup(&dict->mf, key);
item->data.n = 0; d->i.data.n = 0;
_getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) item); _getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) d);
} }
return item; return &d->i;
} /* getdns_dict_find_and_add */ } /* 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_dict_get_data_type */
getdns_return_t getdns_return_t
getdns_dict_get_data_type(const struct getdns_dict * dict, const char *name, getdns_dict_get_data_type(
getdns_data_type * answer) const getdns_dict *dict, const char *name, getdns_data_type *answer)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; 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_dict_get_dict */
getdns_return_t getdns_return_t
getdns_dict_get_dict(const struct getdns_dict * dict, const char *name, getdns_dict_get_dict(
struct getdns_dict ** answer) const getdns_dict *dict, const char *name, getdns_dict **answer)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; 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_dict_get_list */
getdns_return_t getdns_return_t
getdns_dict_get_list(const struct getdns_dict * dict, const char *name, getdns_dict_get_list(
struct getdns_list ** answer) const getdns_dict *dict, const char *name, getdns_list **answer)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; 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_dict_get_bindata */
getdns_return_t getdns_return_t
getdns_dict_get_bindata(const struct getdns_dict * dict, const char *name, getdns_dict_get_bindata(
struct getdns_bindata ** answer) const getdns_dict *dict, const char *name, getdns_bindata **answer)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; 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_dict_get_int */
getdns_return_t getdns_return_t
getdns_dict_get_int(const struct getdns_dict * dict, const char *name, getdns_dict_get_int(
uint32_t * answer) const getdns_dict *dict, const char *name, uint32_t *answer)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
@ -307,25 +341,25 @@ _getdns_dict_copy(const struct getdns_dict * srcdict,
RBTREE_FOR(item, struct getdns_dict_item *, RBTREE_FOR(item, struct getdns_dict_item *,
(struct _getdns_rbtree_t *)&(srcdict->root)) { (struct _getdns_rbtree_t *)&(srcdict->root)) {
key = (char *) item->node.key; key = (char *) item->node.key;
switch (item->dtype) { switch (item->i.dtype) {
case t_bindata: case t_bindata:
retval = getdns_dict_set_bindata(*dstdict, key, retval = getdns_dict_set_bindata(*dstdict, key,
item->data.bindata); item->i.data.bindata);
break; break;
case t_dict: case t_dict:
retval = getdns_dict_set_dict(*dstdict, key, retval = getdns_dict_set_dict(*dstdict, key,
item->data.dict); item->i.data.dict);
break; break;
case t_int: case t_int:
retval = getdns_dict_set_int(*dstdict, key, retval = getdns_dict_set_int(*dstdict, key,
item->data.n); item->i.data.n);
break; break;
case t_list: case t_list:
retval = getdns_dict_set_list(*dstdict, key, retval = getdns_dict_set_list(*dstdict, key,
item->data.list); item->i.data.list);
break; break;
} }
if (retval != GETDNS_RETURN_GOOD) { if (retval != GETDNS_RETURN_GOOD) {
@ -354,15 +388,15 @@ getdns_dict_item_free(_getdns_rbnode_t * node, void *arg)
if (!item) if (!item)
return; return;
switch (item->dtype) { switch (item->i.dtype) {
case t_bindata: case t_bindata:
_getdns_bindata_destroy(&dict->mf, item->data.bindata); _getdns_bindata_destroy(&dict->mf, item->i.data.bindata);
break; break;
case t_dict: case t_dict:
getdns_dict_destroy(item->data.dict); getdns_dict_destroy(item->i.data.dict);
break; break;
case t_list: case t_list:
getdns_list_destroy(item->data.list); getdns_list_destroy(item->i.data.list);
break; break;
default: default:
break; break;
@ -383,11 +417,11 @@ getdns_dict_destroy(struct getdns_dict *dict)
/*---------------------------------------- getdns_dict_set_dict */ /*---------------------------------------- getdns_dict_set_dict */
getdns_return_t getdns_return_t
getdns_dict_set_dict(struct getdns_dict * dict, const char *name, getdns_dict_set_dict(
const struct getdns_dict * child_dict) getdns_dict *dict, const char *name, const getdns_dict *child_dict)
{ {
struct getdns_dict_item *item; getdns_item *item;
struct getdns_dict *newdict; getdns_dict *newdict;
getdns_return_t retval; getdns_return_t retval;
if (!dict || !name || !child_dict) 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_dict_set_list */
getdns_return_t getdns_return_t
getdns_dict_set_list(struct getdns_dict * dict, const char *name, getdns_dict_set_list(
const struct getdns_list * child_list) getdns_dict *dict, const char *name, const getdns_list *child_list)
{ {
struct getdns_dict_item *item; getdns_item *item;
struct getdns_list *newlist; getdns_list *newlist;
getdns_return_t retval; getdns_return_t retval;
if (!dict || !name || !child_list) 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_dict_set_bindata */
getdns_return_t getdns_return_t
getdns_dict_set_bindata(struct getdns_dict * dict, const char *name, getdns_dict_set_bindata(
const struct getdns_bindata * child_bindata) getdns_dict *dict, const char *name, const getdns_bindata *child_bindata)
{ {
struct getdns_dict_item *item; getdns_item *item;
struct getdns_bindata *newbindata; getdns_bindata *newbindata;
if (!dict || !name || !child_bindata) if (!dict || !name || !child_bindata)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
@ -462,7 +496,7 @@ getdns_dict_set_bindata(struct getdns_dict * dict, const char *name,
getdns_return_t getdns_return_t
getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value) getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
{ {
struct getdns_dict_item *item; getdns_item *item;
getdns_bindata *newbindata; getdns_bindata *newbindata;
if (!dict || !name || !value) if (!dict || !name || !value)
@ -489,10 +523,9 @@ error_free_bindata:
/*---------------------------------------- getdns_dict_set_int */ /*---------------------------------------- getdns_dict_set_int */
getdns_return_t getdns_return_t
getdns_dict_set_int(struct getdns_dict * dict, const char *name, getdns_dict_set_int(getdns_dict *dict, const char *name, uint32_t child_uint32)
uint32_t child_uint32)
{ {
struct getdns_dict_item *item; getdns_item *item;
if (!dict || !name) if (!dict || !name)
return GETDNS_RETURN_INVALID_PARAMETER; 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) buf, "\"%s\":",(const char *)item->node.key) < 0)
return -1; return -1;
switch (item->dtype) { switch (item->i.dtype) {
case t_int: case t_int:
if (!json && if (!json &&
(strcmp(item->node.key, "type") == 0 || (strcmp(item->node.key, "type") == 0 ||
strcmp(item->node.key, "type_covered") == 0 || strcmp(item->node.key, "type_covered") == 0 ||
strcmp(item->node.key, "qtype") == 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( if (gldns_buffer_printf(
buf, " GETDNS_RRTYPE_%s", strval) < 0) buf, " GETDNS_RRTYPE_%s", strval) < 0)
return -1; 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, "follow_redirects") == 0 ||
strcmp(item->node.key, "resolution_type") == 0) && strcmp(item->node.key, "resolution_type") == 0) &&
(strval = (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) if (gldns_buffer_printf(buf, " %s", strval) < 0)
return -1; return -1;
break; break;
@ -868,16 +901,16 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
if (!json && if (!json &&
(strcmp(item->node.key, "class") == 0 || (strcmp(item->node.key, "class") == 0 ||
strcmp(item->node.key, "qclass") == 0) && strcmp(item->node.key, "qclass") == 0) &&
_getdns_print_class(buf, item->data.n)) _getdns_print_class(buf, item->i.data.n))
break; break;
if (!json && strcmp(item->node.key, "opcode") == 0 && if (!json && strcmp(item->node.key, "opcode") == 0 &&
_getdns_print_opcode(buf, item->data.n)) _getdns_print_opcode(buf, item->i.data.n))
break; break;
if (!json && strcmp(item->node.key, "rcode") == 0 && if (!json && strcmp(item->node.key, "rcode") == 0 &&
_getdns_print_rcode(buf, item->data.n)) _getdns_print_rcode(buf, item->i.data.n))
break; break;
if (gldns_buffer_printf( 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; return -1;
break; break;
@ -885,21 +918,21 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
if ((strcmp(item->node.key, "address_data") == 0 || if ((strcmp(item->node.key, "address_data") == 0 ||
strcmp(item->node.key, "ipv4_address") == 0 || strcmp(item->node.key, "ipv4_address") == 0 ||
strcmp(item->node.key, "ipv6_address") == 0 ) && strcmp(item->node.key, "ipv6_address") == 0 ) &&
(item->data.bindata->size == 4 || (item->i.data.bindata->size == 4 ||
item->data.bindata->size == 16 )) { item->i.data.bindata->size == 16 )) {
if (gldns_buffer_printf(buf, if (gldns_buffer_printf(buf,
(json ? "\"%s\"" : " <bindata for %s>"), (json ? "\"%s\"" : " <bindata for %s>"),
inet_ntop(( item->data.bindata->size == 4 inet_ntop(( item->i.data.bindata->size == 4
? AF_INET : AF_INET6) ? AF_INET : AF_INET6)
, item->data.bindata->data , item->i.data.bindata->data
, abuf , abuf
, 40 , 40
)) < 0) )) < 0)
return -1; return -1;
} else if (getdns_pp_bindata( } else if (getdns_pp_bindata(
buf, indent, item->data.bindata, buf, indent, item->i.data.bindata,
(strcmp(item->node.key, "rdata_raw") == 0), (strcmp(item->node.key, "rdata_raw") == 0),
json) < 0) json) < 0)
return -1; 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 */ 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) GETDNS_RETURN_GOOD)
return -1; return -1;
if (length == 0) { 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", if (json < 2 && gldns_buffer_printf(buf, "\n%s",
getdns_indent(indent)) < 0) getdns_indent(indent)) < 0)
return -1; 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, "namespaces") == 0 ||
strcmp(item->node.key, "dns_transport_list") == 0), strcmp(item->node.key, "dns_transport_list") == 0),
json) < 0) json) < 0)
@ -931,7 +964,7 @@ getdns_pp_dict(gldns_buffer * buf, size_t indent,
getdns_indent(indent)) < 0) getdns_indent(indent)) < 0)
return -1; return -1;
if (getdns_pp_dict( if (getdns_pp_dict(
buf, indent, item->data.dict, json) < 0) buf, indent, item->i.data.dict, json) < 0)
return -1; return -1;
break; break;
@ -1099,21 +1132,18 @@ getdns_snprint_json_list(
} }
getdns_return_t 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; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(this_dict, name); if ((n = _getdns_rbtree_delete(&dict->root, name)))
if (!item) getdns_dict_item_free(n, dict);
else
return GETDNS_RETURN_NO_SUCH_DICT_NAME; 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; return GETDNS_RETURN_GOOD;
} }

View File

@ -39,22 +39,13 @@
#include "util/rbtree.h" #include "util/rbtree.h"
#include "types-internal.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 * this structure represents a single item in a dictionary type
*/ */
struct getdns_dict_item struct getdns_dict_item
{ {
_getdns_rbnode_t node; _getdns_rbnode_t node;
getdns_data_type dtype; getdns_item i;
union getdns_item data;
}; };
/** /**

View File

@ -222,7 +222,7 @@ getdns_list_create_with_extended_memory_functions(
list->numinuse = 0; list->numinuse = 0;
if (!(list->items = GETDNS_XMALLOC( 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); GETDNS_FREE(list->mf, list);
return NULL; return NULL;
} }
@ -308,7 +308,7 @@ getdns_list_destroy(struct getdns_list *list)
static getdns_return_t static getdns_return_t
_getdns_list_request_index(getdns_list *list, size_t index) _getdns_list_request_index(getdns_list *list, size_t index)
{ {
struct getdns_list_item *newlist; getdns_item *newlist;
assert(list); assert(list);
@ -325,7 +325,7 @@ _getdns_list_request_index(getdns_list *list, size_t index)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
if (!(newlist = GETDNS_XREALLOC(list->mf, list->items, 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; return GETDNS_RETURN_MEMORY_ERROR;

View File

@ -42,21 +42,6 @@
#define GETDNS_LIST_BLOCKSZ 10 #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 * getdns list data type
* Use helper functions getdns_list_* to manipulate and iterate lists * Use helper functions getdns_list_* to manipulate and iterate lists
@ -70,7 +55,7 @@ struct getdns_list
{ {
size_t numalloc; size_t numalloc;
size_t numinuse; size_t numinuse;
struct getdns_list_item *items; struct getdns_item *items;
struct mem_funcs mf; struct mem_funcs mf;
}; };

View File

@ -41,6 +41,21 @@
#include "util/rbtree.h" #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_context;
struct getdns_upstreams; struct getdns_upstreams;
struct getdns_upstream; struct getdns_upstream;

View File

@ -839,7 +839,7 @@ _getdns_validate_extensions(struct getdns_dict * extensions)
if (!extformat) if (!extformat)
return GETDNS_RETURN_NO_SUCH_EXTENSION; 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_EXTENSION_MISFORMAT;
} }
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;