JSON pointer setters

This commit is contained in:
Willem Toorop 2015-10-02 15:26:05 +02:00
parent 40269a241c
commit f6619d28d8
4 changed files with 131 additions and 44 deletions

View File

@ -105,21 +105,45 @@ _getdns_dict_find(const getdns_dict *dict, const char *key, getdns_item **item)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
static getdns_item * getdns_return_t
getdns_dict_find_and_add(struct getdns_dict *dict, const char *key) _getdns_dict_find_and_add(
getdns_dict *dict, const char *key, getdns_item **item)
{ {
const char *next;
struct getdns_dict_item *d; struct getdns_dict_item *d;
d = _find_dict_item(dict, key); if (!(d = _find_dict_item(dict, key))) {
if (!d) {
/* add a node */ /* add a node */
d = GETDNS_MALLOC(dict->mf, struct getdns_dict_item); d = GETDNS_MALLOC(dict->mf, struct getdns_dict_item);
d->node.key = _getdns_strdup(&dict->mf, key); d->node.key = _getdns_strdup(&dict->mf, key);
d->i.data.n = 0;
_getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) d); _getdns_rbtree_insert(&(dict->root), (_getdns_rbnode_t *) d);
if (*key != '/' || !(next = strchr(key + 1, '/'))) {
(void) memset(&d->i.data, 0, sizeof(d->i.data));
*item = &d->i;
return GETDNS_RETURN_GOOD;
}
if ((next[1] == '0' || next[1] == '-') &&
(next[2] == '/' || next[2] == '\0')) {
d->i.data.list =_getdns_list_create_with_mf(&dict->mf);
return _getdns_list_find_and_add(
d->i.data.list, next, item);
}
d->i.data.dict = _getdns_dict_create_with_mf(&dict->mf);
return _getdns_dict_find_and_add(
d->i.data.dict, next, item);
}
if (*key != '/' || !(next = strchr(key + 1, '/'))) {
*item = &d->i;
return GETDNS_RETURN_GOOD;
} else switch (d->i.dtype) {
case t_dict: return _getdns_dict_find_and_add(
d->i.data.dict, next, item);
case t_list: return _getdns_list_find_and_add(
d->i.data.list, next, item);
default : return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
} }
return &d->i;
} /* getdns_dict_find_and_add */ } /* getdns_dict_find_and_add */
@ -429,19 +453,17 @@ getdns_dict_set_dict(
{ {
getdns_item *item; getdns_item *item;
getdns_dict *newdict; getdns_dict *newdict;
getdns_return_t retval; getdns_return_t r;
if (!dict || !name || !child_dict) if (!dict || !name || !child_dict)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
retval = _getdns_dict_copy(child_dict, &newdict); if ((r = _getdns_dict_copy(child_dict, &newdict)))
if (retval != GETDNS_RETURN_GOOD) return r;
return retval;
item = getdns_dict_find_and_add(dict, name); if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
if (!item) {
getdns_dict_destroy(newdict); getdns_dict_destroy(newdict);
return GETDNS_RETURN_NO_SUCH_DICT_NAME; return r;
} }
item->dtype = t_dict; item->dtype = t_dict;
item->data.dict = newdict; item->data.dict = newdict;
@ -455,19 +477,17 @@ getdns_dict_set_list(
{ {
getdns_item *item; getdns_item *item;
getdns_list *newlist; getdns_list *newlist;
getdns_return_t retval; getdns_return_t r;
if (!dict || !name || !child_list) if (!dict || !name || !child_list)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
retval = _getdns_list_copy(child_list, &newlist); if ((r = _getdns_list_copy(child_list, &newlist)))
if (retval != GETDNS_RETURN_GOOD) return r;
return retval;
item = getdns_dict_find_and_add(dict, name); if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
if (!item) {
getdns_list_destroy(newlist); getdns_list_destroy(newlist);
return GETDNS_RETURN_NO_SUCH_DICT_NAME; return r;
} }
item->dtype = t_list; item->dtype = t_list;
item->data.list = newlist; item->data.list = newlist;
@ -481,18 +501,17 @@ getdns_dict_set_bindata(
{ {
getdns_item *item; getdns_item *item;
getdns_bindata *newbindata; getdns_bindata *newbindata;
getdns_return_t r;
if (!dict || !name || !child_bindata) if (!dict || !name || !child_bindata)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
newbindata = _getdns_bindata_copy(&dict->mf, child_bindata); if (!(newbindata = _getdns_bindata_copy(&dict->mf, child_bindata)))
if (!newbindata) return GETDNS_RETURN_MEMORY_ERROR;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
item = getdns_dict_find_and_add(dict, name); if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
if (!item) {
_getdns_bindata_destroy(&dict->mf, newbindata); _getdns_bindata_destroy(&dict->mf, newbindata);
return GETDNS_RETURN_NO_SUCH_DICT_NAME; return r;
} }
item->dtype = t_bindata; item->dtype = t_bindata;
item->data.bindata = newbindata; item->data.bindata = newbindata;
@ -505,6 +524,7 @@ getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
{ {
getdns_item *item; getdns_item *item;
getdns_bindata *newbindata; getdns_bindata *newbindata;
getdns_return_t r;
if (!dict || !name || !value) if (!dict || !name || !value)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
@ -513,33 +533,31 @@ getdns_dict_util_set_string(getdns_dict *dict, char *name, const char *value)
return GETDNS_RETURN_MEMORY_ERROR; return GETDNS_RETURN_MEMORY_ERROR;
newbindata->size = strlen(value); newbindata->size = strlen(value);
if (!(newbindata->data = (void *)_getdns_strdup(&dict->mf, value))) if (!(newbindata->data = (void *)_getdns_strdup(&dict->mf, value))) {
goto error_free_bindata; GETDNS_FREE(dict->mf, newbindata);
return GETDNS_RETURN_MEMORY_ERROR;
if ((item = getdns_dict_find_and_add(dict, name))) {
item->dtype = t_bindata;
item->data.bindata = newbindata;
return GETDNS_RETURN_GOOD;
} }
GETDNS_FREE(dict->mf, newbindata->data); if ((r = _getdns_dict_find_and_add(dict, name, &item))) {
error_free_bindata: _getdns_bindata_destroy(&dict->mf, newbindata);
GETDNS_FREE(dict->mf, newbindata); return r;
return GETDNS_RETURN_MEMORY_ERROR; }
item->dtype = t_bindata;
item->data.bindata = newbindata;
return GETDNS_RETURN_GOOD;
} /* getdns_dict_util_set_dict */ } /* getdns_dict_util_set_dict */
/*---------------------------------------- getdns_dict_set_int */ /*---------------------------------------- getdns_dict_set_int */
getdns_return_t getdns_return_t
getdns_dict_set_int(getdns_dict *dict, const char *name, uint32_t child_uint32) getdns_dict_set_int(getdns_dict *dict, const char *name, uint32_t child_uint32)
{ {
getdns_item *item; getdns_item *item;
getdns_return_t r;
if (!dict || !name) if (!dict || !name)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find_and_add(dict, name); if ((r = _getdns_dict_find_and_add(dict, name, &item)))
if (!item) return r;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
item->dtype = t_int; item->dtype = t_int;
item->data.n = child_uint32; item->data.n = child_uint32;

View File

@ -68,6 +68,9 @@ inline static getdns_dict *_getdns_dict_create_with_mf(struct mem_funcs *mf)
getdns_return_t _getdns_dict_find( getdns_return_t _getdns_dict_find(
const getdns_dict *dict, const char *key, getdns_item **item); const getdns_dict *dict, const char *key, getdns_item **item);
getdns_return_t _getdns_dict_find_and_add(
getdns_dict *dict, const char *key, getdns_item **item);
#endif #endif
/* dict.h */ /* dict.h */

View File

@ -54,7 +54,7 @@ _getdns_list_find(const getdns_list *list, const char *key, getdns_item **item)
if (!(next = strchr(key + 1, '/'))) if (!(next = strchr(key + 1, '/')))
next = key + strlen(key); next = key + strlen(key);
if (*key == '-') if (key[0] == '-' && (key[1] == '/' || key[1] == '\0'))
return GETDNS_RETURN_NO_SUCH_LIST_ITEM; return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
index = strtoul(key, &endptr, 10); index = strtoul(key, &endptr, 10);
@ -77,6 +77,69 @@ _getdns_list_find(const getdns_list *list, const char *key, getdns_item **item)
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} }
getdns_return_t
_getdns_list_find_and_add(
getdns_list *list, const char *key, getdns_item **item)
{
const char *next;
char *endptr;
size_t index;
getdns_item *newlist;
if (*key == '/')
key += 1;
if (!(next = strchr(key + 1, '/')))
next = key + strlen(key);
if (key[0] == '-' && key[1] == '/')
index = list->numinuse;
else {
index = strtoul(key, &endptr, 10);
if (!isdigit((int)*key) || endptr != next)
/* Not a list index, so it was assumed */
return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
if (*next && index == list->numinuse) {
if (list->numalloc < list->numinuse) {
if (!(newlist = GETDNS_XREALLOC(list->mf, list->items,
getdns_item, list->numalloc+GETDNS_LIST_BLOCKSZ)))
return GETDNS_RETURN_MEMORY_ERROR;
list->items = newlist;
list->numalloc += GETDNS_LIST_BLOCKSZ;
}
list->numinuse++;
if ((next[1] == '0' || next[1] == '-') &&
(next[2] == '/' || next[2] == '\0')) {
list->items[index].data.list =
_getdns_list_create_with_mf(&list->mf);
return _getdns_list_find_and_add(
list->items[index].data.list, next, item);
}
list->items[index].data.dict =
_getdns_dict_create_with_mf(&list->mf);
return _getdns_dict_find_and_add(
list->items[index].data.dict, next, item);
}
if (index >= list->numinuse)
return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
if (*next)
switch (list->items[index].dtype) {
case t_dict: return _getdns_dict_find(
list->items[index].data.dict, next, item);
case t_list: return _getdns_list_find(
list->items[index].data.list, next, item);
default : return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
}
*item = &list->items[index];
return GETDNS_RETURN_GOOD;
}
/*---------------------------------------- getdns_list_get_length */ /*---------------------------------------- getdns_list_get_length */
getdns_return_t getdns_return_t
getdns_list_get_length(const struct getdns_list * list, size_t * answer) getdns_list_get_length(const struct getdns_list * list, size_t * answer)

View File

@ -66,6 +66,9 @@ inline static getdns_list *_getdns_list_create_with_mf(struct mem_funcs *mf)
getdns_return_t _getdns_list_find( getdns_return_t _getdns_list_find(
const getdns_list *dict, const char *key, getdns_item **item); const getdns_list *dict, const char *key, getdns_item **item);
getdns_return_t _getdns_list_find_and_add(
getdns_list *list, const char *key, getdns_item **item);
#endif #endif
/* list.h */ /* list.h */