From fdb977717b907ddb43b4948a00cfacf154ed1eb9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sat, 8 Dec 2012 12:18:37 +0100 Subject: [PATCH] finished geonames.org lookup --- src/Makefile.am | 8 +++- src/geonames.c | 106 ++++++++++++++++++++++++++++++++++++++++++++ src/geonames.h | 16 +++++++ src/geonames_test.c | 19 ++++++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 src/geonames.c create mode 100644 src/geonames.h create mode 100644 src/geonames_test.c diff --git a/src/Makefile.am b/src/Makefile.am index 93ae07e..bc1016b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,10 @@ -bin_PROGRAMS = astro +bin_PROGRAMS = astro sun geonames astro_SOURCES = calendar.c astro.c astro_LDADD = -lm + +sun_SOURCES = sun.c +sun_LDADD = -lm + +geonames_SOURCES = geonames_test.c geonames.c +geonames_LDADD = -lcurl -ljson diff --git a/src/geonames.c b/src/geonames.c new file mode 100644 index 0000000..29d05e1 --- /dev/null +++ b/src/geonames.c @@ -0,0 +1,106 @@ +#include +#include + +#include +#include + +#include "geonames.h" + +const char* username = "libastro"; +const char* request_url_tpl = "http://api.geonames.org/search?name=%s&maxRows=1&username=%s&type=json&orderby=relevance"; + +struct memory_block { + char *address; + size_t size; +}; + +static size_t json_parse_callback(void *contents, size_t size, size_t nmemb, void *userp) { + static struct json_tokener *jtok; + static struct json_object *jobj; + size_t realsize = size * nmemb; + + /* initialize tokener */ + if (jtok == NULL) { + jtok = json_tokener_new(); + jtok->err = json_tokener_continue; + } + + if (jtok->err == json_tokener_continue) { +#ifdef DEBUG + printf("got chunk: %d * %d = %d bytes\r\n", size, nmemb, realsize); +#endif + + jobj = json_tokener_parse_ex(jtok, (char *) contents, realsize); + + if (jtok->err == json_tokener_success) { + *(struct json_object **) userp = jobj; + json_tokener_free(jtok); + } + else if (jtok->err != json_tokener_continue) { + fprintf(stderr, "parse error: %s\r\n", json_tokener_errors[jtok->err]); + *(void **) userp = NULL; + json_tokener_free(jtok); + } + } + + return realsize; +} + +int geonames_lookup(const char *place, struct coords *result) { + CURL *ch; + CURLcode res; + + struct json_object *jobj; + + /* setup curl */ + ch = curl_easy_init(); + if (!ch) return -1; + + /* prepare url */ + int len = strlen(place) + strlen(request_url_tpl) + 1; + char *request_url = malloc(len); + if (!request_url) { + return -2; + } + + snprintf(request_url, len, request_url_tpl, place, username); + +#ifdef DEBUG + printf("request url: %s\r\n", request_url); +#endif + + curl_easy_setopt(ch, CURLOPT_URL, request_url); + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, json_parse_callback); + curl_easy_setopt(ch, CURLOPT_WRITEDATA, (void *) &jobj); + curl_easy_setopt(ch, CURLOPT_USERAGENT, "libastro/1.0"); + + /* perform request */ + res = curl_easy_perform(ch); + + /* always cleanup */ + curl_easy_cleanup(ch); + + if (res != CURLE_OK) { + fprintf(stderr, "request failed: %s\n", curl_easy_strerror(res)); + return EXIT_FAILURE; + } + + if (jobj) { + return geonames_parse(jobj, result);; + } + else { + return EXIT_FAILURE; + } +} + +int geonames_parse(struct json_object *jobj, struct coords *result) { + struct json_object *jobj_place = json_object_array_get_idx(json_object_object_get(jobj, "geonames"), 0); + + result->lat = json_object_get_double(json_object_object_get(jobj_place, "lat")); + result->lon = json_object_get_double(json_object_object_get(jobj_place, "lng")); + + /* cleanup */ + json_object_put(jobj); + + return EXIT_SUCCESS; +} diff --git a/src/geonames.h b/src/geonames.h new file mode 100644 index 0000000..29c36e1 --- /dev/null +++ b/src/geonames.h @@ -0,0 +1,16 @@ +#ifndef _GEONAMES_H_ +#define _GEONAMES_H_ + +//#define DEBUG 1 + +#include + +struct coords { + double lat; + double lon; +}; + +int geonames_lookup(const char *place, struct coords *coords); +int geonames_parse(struct json_object *jobj, struct coords *result); + +#endif /* _GEONAMES_H_ */ diff --git a/src/geonames_test.c b/src/geonames_test.c new file mode 100644 index 0000000..6d13277 --- /dev/null +++ b/src/geonames_test.c @@ -0,0 +1,19 @@ +#include + +#include "geonames.h" + +int main(int argc, char *argv[]) { + struct coords res; + char *name = "Aachen"; + + if (argc == 2) { + name = argv[1]; + } + + if (geonames_lookup(name, &res) == 0) { + printf("%s is at (%.4f, %.4f)\r\n", name, res.lat, res.lon); + return 0; + } + + return 0; +}