mirror of https://github.com/getdnsapi/getdns.git
1 level JSON pointer reference lookup
This commit is contained in:
parent
3bec89bee5
commit
ca50a984c8
188
src/dict.c
188
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\"" : " <bindata for %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;
|
||||
}
|
||||
|
||||
|
|
11
src/dict.h
11
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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
17
src/list.h
17
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue