From 6a0d1a968db4140315fac4f1336b1726c7c5819c Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Thu, 1 Oct 2015 15:43:17 +0200 Subject: [PATCH] Multi-level json pointers (retry) + synchronous-concise example --- spec/example/Makefile.in | 26 ++++++++---- spec/example/synchronous-concise.c | 65 ++++++++++++++++++++++++++++++ src/Makefile.in | 17 +++++--- src/dict.c | 63 ++++++++++++++++------------- src/dict.h | 3 ++ src/list.c | 38 +++++++++++++++++ src/list.h | 3 ++ src/types-internal.h | 16 ++++---- 8 files changed, 183 insertions(+), 48 deletions(-) create mode 100644 spec/example/synchronous-concise.c diff --git a/spec/example/Makefile.in b/spec/example/Makefile.in index 779a634a..f43eb33c 100644 --- a/spec/example/Makefile.in +++ b/spec/example/Makefile.in @@ -48,9 +48,9 @@ LDFLAGS=@LDFLAGS@ -L../../src 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 @@ -74,6 +74,12 @@ example-all-functions: example-all-functions.lo example-synchronous: 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): @echo "***" @echo "*** Three examples from the specification need libevent." @@ -147,16 +153,20 @@ depend: # Dependencies for the examples 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 \ - $(srcdir)/../../src/getdns/getdns_extra.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 $(srcdir)/../../src/getdns/getdns_extra.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 \ $(srcdir)/../../src/getdns/getdns_extra.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 \ - $(srcdir)/../../src/getdns/getdns_extra.h + ../../src/config.h ../../src/getdns/getdns.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 \ ../../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 \ $(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 diff --git a/spec/example/synchronous-concise.c b/spec/example/synchronous-concise.c new file mode 100644 index 00000000..98e257b2 --- /dev/null +++ b/spec/example/synchronous-concise.c @@ -0,0 +1,65 @@ +#include +#include + +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); +} diff --git a/src/Makefile.in b/src/Makefile.in index 470f6ff2..5389e0fc 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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 \ $(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)/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 \ 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 \ @@ -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 \ $(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)/list.h + $(srcdir)/list.h $(srcdir)/dict.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 \ $(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 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 -rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.h $(srcdir)/util/fptr_wlist.h \ - $(srcdir)/util/rbtree.h +rbtree.lo rbtree.o: $(srcdir)/util/rbtree.c config.h $(srcdir)/util/log.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)/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 \ - $(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 \ getdns/getdns_extra.h $(srcdir)/types-internal.h getdns/getdns.h \ getdns/getdns_extra.h $(srcdir)/util/rbtree.h config.h diff --git a/src/dict.c b/src/dict.c index a951e131..a6339cd2 100644 --- a/src/dict.c +++ b/src/dict.c @@ -43,6 +43,7 @@ #include "types-internal.h" #include "util-internal.h" #include "dict.h" +#include "list.h" #include "rr-dict.h" #include "const-info.h" #include "gldns/gbuffer.h" @@ -83,20 +84,26 @@ _find_dict_item(const getdns_dict *dict, const char *key) return d; } -/*---------------------------------------- getdns_dict_find */ -/** - * 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) +getdns_return_t +_getdns_dict_find(const getdns_dict *dict, const char *key, getdns_item **item) { - struct getdns_dict_item *d = _find_dict_item(dict, key); - return d ? &d->i : NULL; -} /* getdns_dict_find */ + const char *next; + struct getdns_dict_item *d; + + 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 * getdns_dict_find_and_add(struct getdns_dict *dict, const char *key) @@ -144,14 +151,14 @@ getdns_return_t getdns_dict_get_data_type( const getdns_dict *dict, const char *name, getdns_data_type *answer) { + getdns_return_t r; getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(dict, name); - if (!item) - return GETDNS_RETURN_NO_SUCH_DICT_NAME; + if ((r = _getdns_dict_find(dict, name, &item))) + return r; *answer = item->dtype; return GETDNS_RETURN_GOOD; @@ -162,20 +169,20 @@ getdns_return_t getdns_dict_get_dict( const getdns_dict *dict, const char *name, getdns_dict **answer) { + getdns_return_t r; getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(dict, name); - if (!item) - return GETDNS_RETURN_NO_SUCH_DICT_NAME; + if ((r = _getdns_dict_find(dict, name, &item))) + return r; if (item->dtype != t_dict) return GETDNS_RETURN_WRONG_TYPE_REQUESTED; *answer = item->data.dict; - return GETDNS_RETURN_GOOD; + return GETDNS_RETURN_GOOD; } /* getdns_dict_get_dict */ /*---------------------------------------- getdns_dict_get_list */ @@ -183,14 +190,14 @@ getdns_return_t getdns_dict_get_list( const getdns_dict *dict, const char *name, getdns_list **answer) { + getdns_return_t r; getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(dict, name); - if (!item) - return GETDNS_RETURN_NO_SUCH_DICT_NAME; + if ((r = _getdns_dict_find(dict, name, &item))) + return r; if (item->dtype != t_list) return GETDNS_RETURN_WRONG_TYPE_REQUESTED; @@ -204,13 +211,13 @@ getdns_return_t getdns_dict_get_bindata( const getdns_dict *dict, const char *name, getdns_bindata **answer) { + getdns_return_t r; getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(dict, name); - if (!item) + if ((r = _getdns_dict_find(dict, name, &item))) return GETDNS_RETURN_NO_SUCH_DICT_NAME; if (item->dtype != t_bindata) @@ -225,14 +232,14 @@ getdns_return_t getdns_dict_get_int( const getdns_dict *dict, const char *name, uint32_t *answer) { + getdns_return_t r; getdns_item *item; if (!dict || !name || !answer) return GETDNS_RETURN_INVALID_PARAMETER; - item = getdns_dict_find(dict, name); - if (!item) - return GETDNS_RETURN_NO_SUCH_DICT_NAME; + if ((r = _getdns_dict_find(dict, name, &item))) + return r; if (item->dtype != t_int) return GETDNS_RETURN_WRONG_TYPE_REQUESTED; diff --git a/src/dict.h b/src/dict.h index 0e3ab58e..8c8ebf9c 100644 --- a/src/dict.h +++ b/src/dict.h @@ -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( 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 /* dict.h */ diff --git a/src/list.c b/src/list.c index 44fa805e..0d6dea7e 100644 --- a/src/list.c +++ b/src/list.c @@ -35,9 +35,47 @@ */ #include +#include #include "types-internal.h" #include "util-internal.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_return_t diff --git a/src/list.h b/src/list.h index 46c8b92d..45a57667 100644 --- a/src/list.h +++ b/src/list.h @@ -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( 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 /* list.h */ diff --git a/src/types-internal.h b/src/types-internal.h index d6d6a05b..0048f9ce 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -44,15 +44,17 @@ /** * 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 { getdns_data_type dtype; - union - { - struct getdns_list *list; - struct getdns_dict *dict; - int n; - struct getdns_bindata *bindata; - } data; + getdns_union data; } getdns_item;