[geocode-glib/wip/nominatim: 9/14] lib: Port reverse geocoding API to Nominatim
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geocode-glib/wip/nominatim: 9/14] lib: Port reverse geocoding API to Nominatim
- Date: Fri, 26 Jul 2013 00:27:22 +0000 (UTC)
commit 370faa15fbbb264bf6e2e2c219591ee9a178fd45
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Wed Jun 19 17:11:26 2013 +0200
lib: Port reverse geocoding API to Nominatim
https://bugzilla.gnome.org/show_bug.cgi?id=697218
geocode-glib/geocode-forward.c | 228 ++++++++++++++++++++++++++++++++-
geocode-glib/geocode-glib-private.h | 3 +-
geocode-glib/geocode-reverse.c | 244 +++++++++++++----------------------
geocode-glib/test-gcglib.c | 11 ++-
4 files changed, 325 insertions(+), 161 deletions(-)
---
diff --git a/geocode-glib/geocode-forward.c b/geocode-glib/geocode-forward.c
index 293d53d..d4b5602 100644
--- a/geocode-glib/geocode-forward.c
+++ b/geocode-glib/geocode-forward.c
@@ -96,6 +96,197 @@ is_search (GObject *object)
return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (object), "is-search"));
}
+static struct {
+ const char *pf_attr;
+ const char *xep_attr;
+} rev_attrs_map[] = {
+ { "longitude", "longitude" },
+ { "latitude", "latitude" },
+ { "offsetlat", NULL },
+ { "offsetlon", NULL },
+ { "name", "description" },
+ { "line1", "building" },
+ { "line2", NULL },
+ { "line3", NULL },
+ { "line4", NULL },
+ { "street", "street" },
+ { "postal", "postalcode" },
+ { "neighborhood", "area" },
+ { "city", "locality" },
+ { "county", NULL },
+ { "state", "region" },
+ { "country", "country" },
+ { "countrycode", "countrycode" },
+ { "countycode", NULL },
+ { "timezone", NULL },
+ { "uzip", NULL },
+};
+
+static const char *
+pf_to_xep (const char *attr)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (rev_attrs_map); i++) {
+ if (g_str_equal (attr, rev_attrs_map[i].pf_attr))
+ return rev_attrs_map[i].xep_attr;
+ }
+
+ g_debug ("Can't convert unknown attribute '%s'", attr);
+
+ return NULL;
+}
+
+GHashTable *
+_geocode_parse_resolve_json (const char *contents,
+ GError **error)
+{
+ GHashTable *ret;
+ JsonParser *parser;
+ JsonNode *root;
+ JsonReader *reader;
+ gint64 err_code, found;
+ guint i;
+ const GError *err = NULL;
+ char **members;
+
+ ret = NULL;
+
+ parser = json_parser_new ();
+ if (json_parser_load_from_data (parser, contents, -1, error) == FALSE) {
+ g_object_unref (parser);
+ return ret;
+ }
+
+ root = json_parser_get_root (parser);
+ reader = json_reader_new (root);
+
+ if (json_reader_read_member (reader, "ResultSet") == FALSE)
+ goto parse;
+
+ if (json_reader_read_member (reader, "Error") == FALSE)
+ goto parse;
+
+ err_code = json_reader_get_int_value (reader);
+ json_reader_end_member (reader);
+
+ if (err_code != 0) {
+ const char *msg;
+
+ json_reader_read_member (reader, "ErrorMessage");
+ msg = json_reader_get_string_value (reader);
+ json_reader_end_member (reader);
+ if (msg && *msg == '\0')
+ msg = NULL;
+
+ switch (err_code) {
+ case 1:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Query not supported");
+ break;
+ case 100:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"No input parameters");
+ break;
+ case 102:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Address data not recognized as valid UTF-8");
+ break;
+ case 103:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Insufficient address data");
+ break;
+ case 104:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Unknown language");
+ break;
+ case 105:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"No country detected");
+ break;
+ case 106:
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Country not supported");
+ break;
+ default:
+ if (msg == NULL)
+ g_set_error (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, "Unknown error code
%"G_GINT64_FORMAT, err_code);
+ else
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, msg);
+ break;
+ }
+ g_object_unref (parser);
+ g_object_unref (reader);
+ return NULL;
+ }
+
+ /* Check for the number of results */
+ if (json_reader_read_member (reader, "Found") == FALSE)
+ goto parse;
+
+ found = json_reader_get_int_value (reader);
+ json_reader_end_member (reader);
+
+ if (!found) {
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NO_MATCHES, "No matches found for
request");
+ g_object_unref (parser);
+ g_object_unref (reader);
+ return NULL;
+ }
+
+ if (json_reader_read_member (reader, "Results") == FALSE)
+ goto parse;
+
+ if (json_reader_read_element (reader, 0) == FALSE)
+ goto parse;
+
+ members = json_reader_list_members (reader);
+
+ /* Yay, start adding data */
+ ret = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+
+ for (i = 0; members[i] != NULL; i++) {
+ const char *value;
+
+ json_reader_read_member (reader, members[i]);
+
+ if (g_str_equal (members[i], "radius") ||
+ g_str_equal (members[i], "quality") ||
+ g_str_equal (members[i], "woeid")) {
+ gint64 num;
+
+ num = json_reader_get_int_value (reader);
+ g_hash_table_insert (ret, g_strdup (members[i]), g_strdup_printf ("%"G_GINT64_FORMAT,
num));
+ json_reader_end_member (reader);
+ continue;
+ }
+
+ value = json_reader_get_string_value (reader);
+ if (value && *value == '\0')
+ value = NULL;
+
+ if (value != NULL) {
+ const char *xep_attr;
+
+ xep_attr = pf_to_xep (members[i]);
+ if (xep_attr != NULL)
+ g_hash_table_insert (ret, g_strdup (xep_attr), g_strdup (value));
+ else
+ g_hash_table_insert (ret, g_strdup (members[i]), g_strdup (value));
+ }
+ json_reader_end_member (reader);
+ }
+ g_strfreev (members);
+
+ g_object_unref (parser);
+ g_object_unref (reader);
+
+ return ret;
+
+parse:
+ if (ret != NULL)
+ g_hash_table_destroy (ret);
+ err = json_reader_get_error (reader);
+ g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, err->message);
+ g_object_unref (parser);
+ g_object_unref (reader);
+ return NULL;
+}
+
static GList *
_geocode_parse_single_result_json (const char *contents,
GError **error)
@@ -398,6 +589,39 @@ get_search_query_for_params (GeocodeForward *forward,
return ret;
}
+static SoupMessage *
+get_resolve_query_for_params (GHashTable *orig_ht)
+{
+ SoupMessage *ret;
+ GHashTable *ht;
+ char *locale;
+ char *params, *uri;
+
+ ht = _geocode_glib_dup_hash_table (orig_ht);
+
+ g_hash_table_insert (ht, "appid", YAHOO_APPID);
+ g_hash_table_insert (ht, "flags", "QJT");
+
+ locale = NULL;
+ if (g_hash_table_lookup (ht, "locale") == NULL) {
+ locale = _geocode_object_get_lang ();
+ if (locale)
+ g_hash_table_insert (ht, "locale", locale);
+ }
+
+ params = soup_form_encode_hash (ht);
+ g_hash_table_destroy (ht);
+ g_free (locale);
+
+ uri = g_strdup_printf ("http://where.yahooapis.com/geocode?%s", params);
+ g_free (params);
+
+ ret = soup_message_new ("GET", uri);
+ g_free (uri);
+
+ return ret;
+}
+
/**
* geocode_forward_search_async:
* @forward: a #GeocodeForward representing a query
@@ -433,7 +657,7 @@ geocode_forward_search_async (GeocodeForward *forward,
if (forward->priv->answer_count != 1)
query = get_search_query_for_params (forward, &error);
else
- query = _get_resolve_query_for_params (forward->priv->ht, FALSE);
+ query = get_resolve_query_for_params (forward->priv->ht);
if (!query) {
g_simple_async_result_take_error (simple, error);
g_simple_async_result_complete_in_idle (simple);
@@ -850,7 +1074,7 @@ geocode_forward_search (GeocodeForward *forward,
if (forward->priv->answer_count != 1)
query = get_search_query_for_params (forward, error);
else
- query = _get_resolve_query_for_params (forward->priv->ht, FALSE);
+ query = get_resolve_query_for_params (forward->priv->ht);
if (!query)
return NULL;
diff --git a/geocode-glib/geocode-glib-private.h b/geocode-glib/geocode-glib-private.h
index a486ab9..c8f461f 100644
--- a/geocode-glib/geocode-glib-private.h
+++ b/geocode-glib/geocode-glib-private.h
@@ -41,8 +41,6 @@ GHashTable *_geocode_parse_resolve_json (const char *contents,
GError **error);
GList *_geocode_parse_search_json (const char *contents,
GError **error);
-SoupMessage *_get_resolve_query_for_params (GHashTable *orig_ht,
- gboolean reverse);
GeocodeLocation *_geocode_ip_json_to_location (const char *json,
GError **error);
@@ -53,6 +51,7 @@ gboolean _geocode_glib_cache_save (SoupMessage *query,
const char *contents);
gboolean _geocode_glib_cache_load (SoupMessage *query,
char **contents);
+GHashTable *_geocode_glib_dup_hash_table (GHashTable *ht);
G_END_DECLS
diff --git a/geocode-glib/geocode-reverse.c b/geocode-glib/geocode-reverse.c
index 5739984..ed7a9da 100644
--- a/geocode-glib/geocode-reverse.c
+++ b/geocode-glib/geocode-reverse.c
@@ -90,53 +90,50 @@ GeocodeReverse *
geocode_reverse_new_for_location (GeocodeLocation *location)
{
GeocodeReverse *object;
- char buf[16], buf2[16];
object = g_object_new (GEOCODE_TYPE_REVERSE, NULL);
- g_ascii_formatd (buf, sizeof (buf), "%g", geocode_location_get_latitude (location));
- g_ascii_formatd (buf2, sizeof (buf2), "%g", geocode_location_get_longitude (location));
-
g_hash_table_insert (object->priv->ht,
- g_strdup ("location"),
- g_strdup_printf ("%s, %s", buf, buf2));
+ g_strdup ("lat"),
+ g_strdup_printf ("%g", geocode_location_get_latitude (location)));
+ g_hash_table_insert (object->priv->ht,
+ g_strdup ("lon"),
+ g_strdup_printf ("%g", geocode_location_get_longitude (location)));
return object;
}
static struct {
- const char *pf_attr;
+ const char *nominatim_attr;
const char *xep_attr;
} attrs_map[] = {
- { "longitude", "longitude" },
- { "latitude", "latitude" },
- { "offsetlat", NULL },
- { "offsetlon", NULL },
- { "name", "description" },
- { "line1", "building" },
- { "line2", NULL },
- { "line3", NULL },
- { "line4", NULL },
- { "street", "street" },
- { "postal", "postalcode" },
- { "neighborhood", "area" },
- { "city", "locality" },
+ { "license", NULL },
+ { "osm_type", NULL },
+ { "osm_id", NULL },
+ { "lat", NULL },
+ { "lon", NULL },
+ { "display_name", "description" },
+ { "house_number", "building" },
+ { "road", "street" },
+ { "suburb", "area" },
+ { "city", "locality" },
{ "county", NULL },
+ { "state_district", NULL },
{ "state", "region" },
+ { "postcode", "postalcode" },
{ "country", "country" },
- { "countrycode", "countrycode" },
- { "countycode", NULL },
- { "timezone", NULL },
- { "uzip", NULL },
+ { "country_code", "countrycode" },
+ { "continent", NULL },
+ { "address", NULL },
};
static const char *
-pf_to_xep (const char *attr)
+nominatim_to_xep (const char *attr)
{
guint i;
for (i = 0; i < G_N_ELEMENTS (attrs_map); i++) {
- if (g_str_equal (attr, attrs_map[i].pf_attr))
+ if (g_str_equal (attr, attrs_map[i].nominatim_attr))
return attrs_map[i].xep_attr;
}
@@ -145,18 +142,47 @@ pf_to_xep (const char *attr)
return NULL;
}
-GHashTable *
-_geocode_parse_resolve_json (const char *contents,
- GError **error)
+static void
+add_nominatim_attributes (JsonReader *reader, GHashTable *hash_table)
+{
+ char **members;
+ guint i;
+
+ members = json_reader_list_members (reader);
+
+ for (i = 0; members[i] != NULL; i++) {
+ const char *value;
+
+ json_reader_read_member (reader, members[i]);
+
+ value = json_reader_get_string_value (reader);
+ if (value && *value == '\0')
+ value = NULL;
+
+ if (value != NULL) {
+ const char *xep_attr;
+
+ xep_attr = nominatim_to_xep (members[i]);
+ if (xep_attr != NULL)
+ g_hash_table_insert (hash_table, g_strdup (xep_attr), g_strdup (value));
+ else
+ g_hash_table_insert (hash_table, g_strdup (members[i]), g_strdup (value));
+ }
+
+ json_reader_end_member (reader);
+ }
+
+ g_strfreev (members);
+}
+
+static GHashTable *
+resolve_json (const char *contents,
+ GError **error)
{
GHashTable *ret;
JsonParser *parser;
JsonNode *root;
JsonReader *reader;
- gint64 err_code, found;
- guint i;
- const GError *err = NULL;
- char **members;
ret = NULL;
@@ -169,130 +195,38 @@ _geocode_parse_resolve_json (const char *contents,
root = json_parser_get_root (parser);
reader = json_reader_new (root);
- if (json_reader_read_member (reader, "ResultSet") == FALSE)
- goto parse;
-
- if (json_reader_read_member (reader, "Error") == FALSE)
- goto parse;
-
- err_code = json_reader_get_int_value (reader);
- json_reader_end_member (reader);
-
- if (err_code != 0) {
+ if (json_reader_read_member (reader, "error")) {
const char *msg;
- json_reader_read_member (reader, "ErrorMessage");
- msg = json_reader_get_string_value (reader);
- json_reader_end_member (reader);
+ msg = json_reader_get_string_value (reader);
+ json_reader_end_member (reader);
if (msg && *msg == '\0')
msg = NULL;
- switch (err_code) {
- case 1:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Query not supported");
- break;
- case 100:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"No input parameters");
- break;
- case 102:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Address data not recognized as valid UTF-8");
- break;
- case 103:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Insufficient address data");
- break;
- case 104:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Unknown language");
- break;
- case 105:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"No country detected");
- break;
- case 106:
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NOT_SUPPORTED, msg ? msg :
"Country not supported");
- break;
- default:
- if (msg == NULL)
- g_set_error (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, "Unknown error code
%"G_GINT64_FORMAT, err_code);
- else
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, msg);
- break;
- }
- g_object_unref (parser);
- g_object_unref (reader);
- return NULL;
- }
-
- /* Check for the number of results */
- if (json_reader_read_member (reader, "Found") == FALSE)
- goto parse;
-
- found = json_reader_get_int_value (reader);
- json_reader_end_member (reader);
-
- if (!found) {
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_NO_MATCHES, "No matches found for
request");
+ g_set_error_literal (error,
+ GEOCODE_ERROR,
+ GEOCODE_ERROR_NOT_SUPPORTED,
+ msg ? msg : "Query not supported");
g_object_unref (parser);
g_object_unref (reader);
return NULL;
}
- if (json_reader_read_member (reader, "Results") == FALSE)
- goto parse;
-
- if (json_reader_read_element (reader, 0) == FALSE)
- goto parse;
-
- members = json_reader_list_members (reader);
-
/* Yay, start adding data */
ret = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
- for (i = 0; members[i] != NULL; i++) {
- const char *value;
-
- json_reader_read_member (reader, members[i]);
-
- if (g_str_equal (members[i], "radius") ||
- g_str_equal (members[i], "quality") ||
- g_str_equal (members[i], "woeid")) {
- gint64 num;
-
- num = json_reader_get_int_value (reader);
- g_hash_table_insert (ret, g_strdup (members[i]), g_strdup_printf ("%"G_GINT64_FORMAT,
num));
- json_reader_end_member (reader);
- continue;
- }
-
- value = json_reader_get_string_value (reader);
- if (value && *value == '\0')
- value = NULL;
-
- if (value != NULL) {
- const char *xep_attr;
-
- xep_attr = pf_to_xep (members[i]);
- if (xep_attr != NULL)
- g_hash_table_insert (ret, g_strdup (xep_attr), g_strdup (value));
- else
- g_hash_table_insert (ret, g_strdup (members[i]), g_strdup (value));
- }
- json_reader_end_member (reader);
- }
- g_strfreev (members);
+ add_nominatim_attributes (reader, ret);
+
+ if (json_reader_read_member (reader, "address")) {
+ add_nominatim_attributes (reader, ret);
+ json_reader_end_member (reader);
+ }
g_object_unref (parser);
g_object_unref (reader);
return ret;
-
-parse:
- if (ret != NULL)
- g_hash_table_destroy (ret);
- err = json_reader_get_error (reader);
- g_set_error_literal (error, GEOCODE_ERROR, GEOCODE_ERROR_PARSE, err->message);
- g_object_unref (parser);
- g_object_unref (reader);
- return NULL;
}
static void
@@ -315,7 +249,7 @@ on_query_data_loaded (SoupSession *session,
}
contents = g_strndup (query->response_body->data, query->response_body->length);
- ret = _geocode_parse_resolve_json (contents, &error);
+ ret = resolve_json (contents, &error);
if (ret == NULL) {
g_simple_async_result_take_error (simple, error);
@@ -365,7 +299,7 @@ on_cache_data_loaded (GObject *source_object,
return;
}
- ret = _geocode_parse_resolve_json (contents, &error);
+ ret = resolve_json (contents, &error);
g_free (contents);
if (ret == NULL)
@@ -385,8 +319,8 @@ copy_item (char *key,
g_hash_table_insert (ret, key, value);
}
-static GHashTable *
-dup_ht (GHashTable *ht)
+GHashTable *
+_geocode_glib_dup_hash_table (GHashTable *ht)
{
GHashTable *ret;
@@ -396,34 +330,32 @@ dup_ht (GHashTable *ht)
return ret;
}
-SoupMessage *
-_get_resolve_query_for_params (GHashTable *orig_ht,
- gboolean reverse)
+static SoupMessage *
+get_resolve_query_for_params (GHashTable *orig_ht)
{
SoupMessage *ret;
GHashTable *ht;
char *locale;
char *params, *uri;
- ht = dup_ht (orig_ht);
+ ht = _geocode_glib_dup_hash_table (orig_ht);
- g_hash_table_insert (ht, "appid", YAHOO_APPID);
- g_hash_table_insert (ht, "flags", "QJT");
- if (reverse)
- g_hash_table_insert (ht, "gflags", "R");
+ g_hash_table_insert (ht, "format", "json");
+ g_hash_table_insert (ht, "email", "zeeshanak gnome org");
+ g_hash_table_insert (ht, "addressdetails", "1");
locale = NULL;
- if (g_hash_table_lookup (ht, "locale") == NULL) {
+ if (g_hash_table_lookup (ht, "accept-language") == NULL) {
locale = _geocode_object_get_lang ();
if (locale)
- g_hash_table_insert (ht, "locale", locale);
+ g_hash_table_insert (ht, "accept-language", locale);
}
params = soup_form_encode_hash (ht);
g_hash_table_destroy (ht);
g_free (locale);
- uri = g_strdup_printf ("http://where.yahooapis.com/geocode?%s", params);
+ uri = g_strdup_printf ("http://nominatim.openstreetmap.org/reverse?%s", params);
g_free (params);
ret = soup_message_new ("GET", uri);
@@ -463,7 +395,7 @@ geocode_reverse_resolve_async (GeocodeReverse *object,
user_data,
geocode_reverse_resolve_async);
- query = _get_resolve_query_for_params (object->priv->ht, TRUE);
+ query = get_resolve_query_for_params (object->priv->ht);
cache_path = _geocode_glib_cache_path_for_query (query);
if (cache_path == NULL) {
@@ -538,7 +470,7 @@ geocode_reverse_resolve (GeocodeReverse *object,
g_return_val_if_fail (GEOCODE_IS_REVERSE (object), NULL);
- query = _get_resolve_query_for_params (object->priv->ht, TRUE);
+ query = get_resolve_query_for_params (object->priv->ht);
if (_geocode_glib_cache_load (query, &contents) == FALSE) {
if (soup_session_send_message (object->priv->soup_session,
@@ -553,7 +485,7 @@ geocode_reverse_resolve (GeocodeReverse *object,
to_cache = TRUE;
}
- ret = _geocode_parse_resolve_json (contents, error);
+ ret = resolve_json (contents, error);
if (to_cache && ret != NULL)
_geocode_glib_cache_save (query, contents);
diff --git a/geocode-glib/test-gcglib.c b/geocode-glib/test-gcglib.c
index b93c4d6..2878fb5 100644
--- a/geocode-glib/test-gcglib.c
+++ b/geocode-glib/test-gcglib.c
@@ -113,7 +113,16 @@ test_rev (void)
g_assert (ht != NULL);
g_object_unref (rev);
- g_assert (g_strcmp0 (g_hash_table_lookup (ht, "area"), "Onslow Village") == 0);
+ g_assert_cmpstr (g_hash_table_lookup (ht, "postalcode"), ==, "GU2 7UP");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "area"), ==, "Guildford Park");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "countrycode"), ==, "gb");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "street"), ==, "Old Palace Road");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "county"), ==, "Surrey");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "locality"), ==, "Guildford");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "pub"), ==, "The Astolat");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "country"), ==, "United Kingdom");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "state_district"), ==, "South East England");
+ g_assert_cmpstr (g_hash_table_lookup (ht, "region"), ==, "England");
g_print ("Got geocode answer:\n");
g_hash_table_foreach (ht, (GHFunc) print_res, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]