Multi-level json pointers (retry)

+ synchronous-concise example
This commit is contained in:
Willem Toorop 2015-10-01 15:43:17 +02:00
parent 074344fbf9
commit 6a0d1a968d
8 changed files with 183 additions and 48 deletions

View File

@ -48,9 +48,9 @@ LDFLAGS=@LDFLAGS@ -L../../src
LDLIBS=../../src/libgetdns.la @LIBS@ LDLIBS=../../src/libgetdns.la @LIBS@
OBJS=example-all-functions.lo example-simple-answers.lo example-tree.lo example-synchronous.lo example-reverse.lo OBJS=example-all-functions.lo example-simple-answers.lo example-tree.lo example-synchronous.lo example-reverse.lo synchronous-json-pointer.lo synchronous-concise.lo
PROGRAMS=example-all-functions example-synchronous example-simple-answers example-tree example-reverse PROGRAMS=example-all-functions example-synchronous example-simple-answers example-tree example-reverse synchronous-json-pointer synchronous-concise
.SUFFIXES: .c .o .a .lo .h .SUFFIXES: .c .o .a .lo .h
@ -74,6 +74,12 @@ example-all-functions: example-all-functions.lo
example-synchronous: example-synchronous.lo example-synchronous: example-synchronous.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ example-synchronous.lo $(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ example-synchronous.lo
synchronous-json-pointer: synchronous-json-pointer.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ synchronous-json-pointer.lo
synchronous-concise: synchronous-concise.lo
$(LIBTOOL) --tag=CC --mode=link $(CC) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ synchronous-concise.lo
$(EXTENSION_LIBEVENT_LIB): $(EXTENSION_LIBEVENT_LIB):
@echo "***" @echo "***"
@echo "*** Three examples from the specification need libevent." @echo "*** Three examples from the specification need libevent."
@ -147,16 +153,20 @@ depend:
# Dependencies for the examples # Dependencies for the examples
example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \ example-all-functions.lo example-all-functions.o: $(srcdir)/example-all-functions.c $(srcdir)/getdns_libevent.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/config.h ../../src/getdns/getdns.h \
$(srcdir)/../../src/getdns/getdns_extra.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h $(srcdir)/../../src/getdns/getdns_extra.h
example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h \ example-reverse.lo example-reverse.o: $(srcdir)/example-reverse.c $(srcdir)/getdns_libevent.h ../../src/config.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
$(srcdir)/../../src/getdns/getdns_extra.h $(srcdir)/../../src/getdns/getdns_extra.h
example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \ example-simple-answers.lo example-simple-answers.o: $(srcdir)/example-simple-answers.c $(srcdir)/getdns_libevent.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/config.h ../../src/getdns/getdns.h \
$(srcdir)/../../src/getdns/getdns_extra.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h $(srcdir)/../../src/getdns/getdns_extra.h
example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \ example-synchronous.lo example-synchronous.o: $(srcdir)/example-synchronous.c $(srcdir)/getdns_core_only.h \
../../src/getdns/getdns.h ../../src/getdns/getdns.h
example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h \ example-tree.lo example-tree.o: $(srcdir)/example-tree.c $(srcdir)/getdns_libevent.h ../../src/config.h \
../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \ ../../src/getdns/getdns.h $(srcdir)/../../src/getdns/getdns_ext_libevent.h \
$(srcdir)/../../src/getdns/getdns_extra.h $(srcdir)/../../src/getdns/getdns_extra.h
synchronous-concise.lo synchronous-concise.o: $(srcdir)/synchronous-concise.c $(srcdir)/getdns_core_only.h \
../../src/getdns/getdns.h
synchronous-json-pointer.lo synchronous-json-pointer.o: $(srcdir)/synchronous-json-pointer.c $(srcdir)/getdns_core_only.h \
../../src/getdns/getdns.h

View File

@ -0,0 +1,65 @@
#include <stdio.h>
#include <getdns_core_only.h>
int main()
{
getdns_return_t r;
getdns_context *context = NULL;
getdns_dict *response = NULL;
uint32_t status;
getdns_list *just_address_answers;
size_t length, i;
/* Create the DNS context for this call */
if ((r = getdns_context_create(&context, 1)))
fprintf(stderr, "Trying to create the context failed");
else if ((r = getdns_address_sync(context, "example.com", NULL, &response)))
fprintf(stderr, "Error scheduling synchronous request");
else if ((r = getdns_dict_get_int(response, "status", &status)))
fprintf(stderr, "Could not get \"status\" from reponse");
else if (status != GETDNS_RESPSTATUS_GOOD)
fprintf(stderr, "The search had no results, and a return value of %zu.\n", status);
else if ((r = getdns_dict_get_list(response, "just_address_answers", &just_address_answers)))
fprintf(stderr, "Could not get \"just_address_answers\" from reponse");
else if ((r = getdns_list_get_length(just_address_answers, &length)))
fprintf(stderr, "Could not get just_address_answers\' length");
else for (i = 0; i < length && r == GETDNS_RETURN_GOOD; i++) {
getdns_dict *address;
getdns_bindata *address_data;
char *address_str;
if ((r = getdns_list_get_dict(just_address_answers, i, &address)))
fprintf(stderr, "Could not get address %zu from just_address_answers", i);
else if ((r = getdns_dict_get_bindata(address, "address_data", &address_data)))
fprintf(stderr, "Could not get \"address_data\" from address");
else if (!(address_str = getdns_display_ip_address(address_data))) {
fprintf(stderr, "Could not convert address to string");
r = GETDNS_RETURN_MEMORY_ERROR;
}
else {
printf("The address is %s\n", address_str);
free(address_str);
}
}
/* Clean up */
if (response)
getdns_dict_destroy(response);
if (context)
getdns_context_destroy(context);
if (r) {
fprintf(stderr, ": %d\n", r);
exit(EXIT_FAILURE);
}
/* Assuming we get here, leave gracefully */
exit(EXIT_SUCCESS);
}

View File

@ -235,7 +235,7 @@ dict.lo dict.o: $(srcdir)/dict.c $(srcdir)/types-internal.h getdns/getdns.h getd
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/dict.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h $(srcdir)/dict.h $(srcdir)/list.h $(srcdir)/const-info.h $(srcdir)/gldns/wire2str.h
dnssec.lo dnssec.o: $(srcdir)/dnssec.c getdns/getdns.h config.h $(srcdir)/context.h \ dnssec.lo dnssec.o: $(srcdir)/dnssec.c getdns/getdns.h config.h $(srcdir)/context.h \
getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \ getdns/getdns_extra.h getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h \
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
@ -252,7 +252,7 @@ list.lo list.o: $(srcdir)/list.c $(srcdir)/types-internal.h getdns/getdns.h getd
getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \ getdns/getdns.h $(srcdir)/util/rbtree.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h \
$(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ $(srcdir)/extension/libmini_event.h config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
$(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \ $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h $(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h \
$(srcdir)/list.h $(srcdir)/list.h $(srcdir)/dict.h
request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \ request-internal.lo request-internal.o: $(srcdir)/request-internal.c config.h $(srcdir)/types-internal.h \
getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \ getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h $(srcdir)/util/rbtree.h \
$(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \ $(srcdir)/util-internal.h $(srcdir)/context.h $(srcdir)/extension/libmini_event.h config.h \
@ -305,10 +305,17 @@ sha512.lo sha512.o: $(srcdir)/compat/sha512.c config.h
strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h strlcpy.lo strlcpy.o: $(srcdir)/compat/strlcpy.c config.h
mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \ mini_event.lo mini_event.o: $(srcdir)/util/mini_event.c config.h $(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h \
$(srcdir)/util/fptr_wlist.h $(srcdir)/util/fptr_wlist.h
rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \ rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util-internal.h config.h \
$(srcdir)/util/rbtree.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h getdns/getdns.h \
$(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/util/fptr_wlist.h
val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \ val_secalgo.lo val_secalgo.o: $(srcdir)/util/val_secalgo.c config.h $(srcdir)/util/val_secalgo.h $(srcdir)/util/log.h \
$(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h $(srcdir)/gldns/gbuffer.h $(srcdir)/util-internal.h config.h $(srcdir)/context.h getdns/getdns.h getdns/getdns_extra.h \
getdns/getdns.h $(srcdir)/types-internal.h $(srcdir)/util/rbtree.h $(srcdir)/extension/libmini_event.h \
$(srcdir)/util/mini_event.h $(srcdir)/util/rbtree.h $(srcdir)/types-internal.h $(srcdir)/rr-iter.h $(srcdir)/rr-dict.h \
$(srcdir)/gldns/gbuffer.h $(srcdir)/gldns/pkthdr.h $(srcdir)/gldns/rrdef.h $(srcdir)/gldns/keyraw.h \
$(srcdir)/gldns/gbuffer.h
libev.lo libev.o: $(srcdir)/extension/libev.c $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns.h \ libev.lo libev.o: $(srcdir)/extension/libev.c $(srcdir)/getdns/getdns_ext_libev.h getdns/getdns.h \
getdns/getdns_extra.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h $(srcdir)/types-internal.h getdns/getdns.h \
getdns/getdns_extra.h $(srcdir)/util/rbtree.h config.h getdns/getdns_extra.h $(srcdir)/util/rbtree.h config.h

View File

@ -43,6 +43,7 @@
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include "dict.h" #include "dict.h"
#include "list.h"
#include "rr-dict.h" #include "rr-dict.h"
#include "const-info.h" #include "const-info.h"
#include "gldns/gbuffer.h" #include "gldns/gbuffer.h"
@ -83,20 +84,26 @@ _find_dict_item(const getdns_dict *dict, const char *key)
return d; return d;
} }
/*---------------------------------------- getdns_dict_find */ getdns_return_t
/** _getdns_dict_find(const getdns_dict *dict, const char *key, getdns_item **item)
* private function used to locate a key in a dictionary
* @param dict dicitonary to search
* @param key key to search for
* @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 inline getdns_item *
getdns_dict_find(const getdns_dict *dict, const char *key)
{ {
struct getdns_dict_item *d = _find_dict_item(dict, key); const char *next;
return d ? &d->i : NULL; struct getdns_dict_item *d;
} /* getdns_dict_find */
if (!(d = _find_dict_item(dict, key)))
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
if (*key != '/' || !(next = strchr(key + 1, '/')))
*item = &d->i;
else switch (d->i.dtype) {
case t_dict: return _getdns_dict_find(d->i.data.dict, next, item);
case t_list: return _getdns_list_find(d->i.data.list, next, item);
default : *item = &d->i;
break;
}
return GETDNS_RETURN_GOOD;
}
static getdns_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)
@ -144,14 +151,14 @@ getdns_return_t
getdns_dict_get_data_type( getdns_dict_get_data_type(
const getdns_dict *dict, const char *name, getdns_data_type *answer) const getdns_dict *dict, const char *name, getdns_data_type *answer)
{ {
getdns_return_t r;
getdns_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(dict, name); if ((r = _getdns_dict_find(dict, name, &item)))
if (!item) return r;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
*answer = item->dtype; *answer = item->dtype;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
@ -162,20 +169,20 @@ getdns_return_t
getdns_dict_get_dict( getdns_dict_get_dict(
const getdns_dict *dict, const char *name, getdns_dict **answer) const getdns_dict *dict, const char *name, getdns_dict **answer)
{ {
getdns_return_t r;
getdns_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(dict, name); if ((r = _getdns_dict_find(dict, name, &item)))
if (!item) return r;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
if (item->dtype != t_dict) if (item->dtype != t_dict)
return GETDNS_RETURN_WRONG_TYPE_REQUESTED; return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
*answer = item->data.dict; *answer = item->data.dict;
return GETDNS_RETURN_GOOD; return GETDNS_RETURN_GOOD;
} /* getdns_dict_get_dict */ } /* getdns_dict_get_dict */
/*---------------------------------------- getdns_dict_get_list */ /*---------------------------------------- getdns_dict_get_list */
@ -183,14 +190,14 @@ getdns_return_t
getdns_dict_get_list( getdns_dict_get_list(
const getdns_dict *dict, const char *name, getdns_list **answer) const getdns_dict *dict, const char *name, getdns_list **answer)
{ {
getdns_return_t r;
getdns_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(dict, name); if ((r = _getdns_dict_find(dict, name, &item)))
if (!item) return r;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
if (item->dtype != t_list) if (item->dtype != t_list)
return GETDNS_RETURN_WRONG_TYPE_REQUESTED; return GETDNS_RETURN_WRONG_TYPE_REQUESTED;
@ -204,13 +211,13 @@ getdns_return_t
getdns_dict_get_bindata( getdns_dict_get_bindata(
const getdns_dict *dict, const char *name, getdns_bindata **answer) const getdns_dict *dict, const char *name, getdns_bindata **answer)
{ {
getdns_return_t r;
getdns_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(dict, name); if ((r = _getdns_dict_find(dict, name, &item)))
if (!item)
return GETDNS_RETURN_NO_SUCH_DICT_NAME; return GETDNS_RETURN_NO_SUCH_DICT_NAME;
if (item->dtype != t_bindata) if (item->dtype != t_bindata)
@ -225,14 +232,14 @@ getdns_return_t
getdns_dict_get_int( getdns_dict_get_int(
const getdns_dict *dict, const char *name, uint32_t *answer) const getdns_dict *dict, const char *name, uint32_t *answer)
{ {
getdns_return_t r;
getdns_item *item; getdns_item *item;
if (!dict || !name || !answer) if (!dict || !name || !answer)
return GETDNS_RETURN_INVALID_PARAMETER; return GETDNS_RETURN_INVALID_PARAMETER;
item = getdns_dict_find(dict, name); if ((r = _getdns_dict_find(dict, name, &item)))
if (!item) return r;
return GETDNS_RETURN_NO_SUCH_DICT_NAME;
if (item->dtype != t_int) if (item->dtype != t_int)
return GETDNS_RETURN_WRONG_TYPE_REQUESTED; return GETDNS_RETURN_WRONG_TYPE_REQUESTED;

View File

@ -65,6 +65,9 @@ inline static getdns_dict *_getdns_dict_create_with_mf(struct mem_funcs *mf)
{ return getdns_dict_create_with_extended_memory_functions( { return getdns_dict_create_with_extended_memory_functions(
mf->mf_arg, mf->mf.ext.malloc, mf->mf.ext.realloc, mf->mf.ext.free); } mf->mf_arg, mf->mf.ext.malloc, mf->mf.ext.realloc, mf->mf.ext.free); }
getdns_return_t _getdns_dict_find(
const getdns_dict *dict, const char *key, getdns_item **item);
#endif #endif
/* dict.h */ /* dict.h */

View File

@ -35,9 +35,47 @@
*/ */
#include <string.h> #include <string.h>
#include <ctype.h>
#include "types-internal.h" #include "types-internal.h"
#include "util-internal.h" #include "util-internal.h"
#include "list.h" #include "list.h"
#include "dict.h"
getdns_return_t
_getdns_list_find(const getdns_list *list, const char *key, getdns_item **item)
{
const char *next;
char *endptr;
size_t index;
if (*key == '/')
key += 1;
if (!(next = strchr(key + 1, '/')))
next = key + strlen(key);
if (*key == '-')
return GETDNS_RETURN_NO_SUCH_LIST_ITEM;
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 (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 : break;
}
*item = &list->items[index];
return GETDNS_RETURN_GOOD;
}
/*---------------------------------------- getdns_list_get_length */ /*---------------------------------------- getdns_list_get_length */
getdns_return_t getdns_return_t

View File

@ -63,6 +63,9 @@ inline static getdns_list *_getdns_list_create_with_mf(struct mem_funcs *mf)
{ return getdns_list_create_with_extended_memory_functions( { return getdns_list_create_with_extended_memory_functions(
mf->mf_arg, mf->mf.ext.malloc, mf->mf.ext.realloc, mf->mf.ext.free); } mf->mf_arg, mf->mf.ext.malloc, mf->mf.ext.realloc, mf->mf.ext.free); }
getdns_return_t _getdns_list_find(
const getdns_list *dict, const char *key, getdns_item **item);
#endif #endif
/* list.h */ /* list.h */

View File

@ -44,15 +44,17 @@
/** /**
* this structure represents a single item in a list or dict * this structure represents a single item in a list or dict
*/ */
typedef union getdns_union {
void *ptr;
getdns_dict *dict;
getdns_list *list;
getdns_bindata *bindata;
uint32_t n;
} getdns_union;
typedef struct getdns_item { typedef struct getdns_item {
getdns_data_type dtype; getdns_data_type dtype;
union getdns_union data;
{
struct getdns_list *list;
struct getdns_dict *dict;
int n;
struct getdns_bindata *bindata;
} data;
} getdns_item; } getdns_item;