[geocode-glib/gnome-maps: 3/6] lib: geocode_ipclient_search* should return location
- From: Zeeshan Ali Khattak <zeeshanak src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geocode-glib/gnome-maps: 3/6] lib: geocode_ipclient_search* should return location
- Date: Mon, 25 Mar 2013 17:16:50 +0000 (UTC)
commit e6b882c3d4b7251154a2f11125279fdc4cda64ca
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date: Fri Mar 22 02:28:18 2013 +0200
lib: geocode_ipclient_search* should return location
This API will be a lot more useful if we provide a parsed GeocodeLocation
object to the caller rather than just the raw JSON string we get as
response from server.
https://bugzilla.gnome.org/show_bug.cgi?id=696526
geocode-glib/geocode-ipclient.c | 115 +++++++++++++++++++++++++++++++++++----
geocode-glib/geocode-ipclient.h | 11 ++--
geocode-glib/test-geoip.c | 22 ++++----
3 files changed, 121 insertions(+), 27 deletions(-)
---
diff --git a/geocode-glib/geocode-ipclient.c b/geocode-glib/geocode-ipclient.c
index b52ef88..c74b045 100644
--- a/geocode-glib/geocode-ipclient.c
+++ b/geocode-glib/geocode-ipclient.c
@@ -23,7 +23,9 @@
#include <stdlib.h>
#include <glib.h>
#include <libsoup/soup.h>
+#include <json-glib/json-glib.h>
#include "geocode-ipclient.h"
+#include "geocode-error.h"
/**
* SECTION:geocode-ipclient
@@ -39,6 +41,12 @@ enum {
N_PROPERTIES
};
+typedef enum {
+ SERVER_ERROR_INVALID_IP_ADDRESS = 0,
+ SERVER_INVALID_ENTRY,
+ SERVER_DATABASE
+} ServerError;
+
struct _GeocodeIpclientPrivate {
char *ip;
char *server;
@@ -280,6 +288,87 @@ geocode_ipclient_search_async (GeocodeIpclient *ipclient,
g_object_unref (query);
}
+static gboolean
+parse_server_error (JsonObject *object, GError **error) {
+ ServerError server_error_code;
+ int error_code;
+ const char *error_message;
+
+ if (!json_object_has_member (object, "error_code"))
+ return FALSE;
+
+ server_error_code = json_object_get_int_member (object, "error_code");
+ switch (server_error_code) {
+ case SERVER_ERROR_INVALID_IP_ADDRESS:
+ error_code = GEOCODE_ERROR_INVALID_ARGUMENTS;
+ break;
+ case SERVER_INVALID_ENTRY:
+ error_code = GEOCODE_ERROR_NO_MATCHES;
+ break;
+ case SERVER_DATABASE:
+ error_code = GEOCODE_ERROR_INTERNAL_SERVER;
+ break;
+ }
+
+ error_message = json_object_get_string_member (object, "error_message");
+
+ g_set_error_literal (error,
+ GEOCODE_ERROR,
+ error_code,
+ error_message);
+
+ return TRUE;
+}
+
+static GeocodeLocation *
+json_to_location (const char *json, GError **error) {
+ JsonParser *parser;
+ JsonNode *node;
+ JsonObject *object;
+ GeocodeLocation *location;
+ GString *string;
+
+ parser = json_parser_new ();
+
+ if (!json_parser_load_from_data (parser, json, -1, error))
+ return NULL;
+
+ node = json_parser_get_root (parser);
+ object = json_node_get_object (node);
+
+ if (parse_server_error (object, error))
+ return NULL;
+
+ location = geocode_location_new (0, 0);
+ location->latitude = json_object_get_double_member (object, "latitude");
+ location->longitude = json_object_get_double_member (object, "longitude");
+
+ string = g_string_new ("");
+ if (json_object_has_member (object, "city")) {
+ g_string_append (string,
+ json_object_get_string_member (object, "city"));
+ }
+
+ if (json_object_has_member (object, "region")) {
+ if (string->len > 0)
+ g_string_append_c (string, ',');
+ g_string_append (string,
+ json_object_get_string_member (object, "region"));
+ }
+
+ if (json_object_has_member (object, "country_name")) {
+ if (string->len > 0)
+ g_string_append_c (string, ',');
+ g_string_append (string,
+ json_object_get_string_member (object, "country_name"));
+ }
+
+ location->description = g_string_free (string, FALSE);
+ g_object_unref (parser);
+
+ return location;
+}
+
/**
* geocode_ipclient_search_finish:
* @ipclient: a #GeocodeIpclient representing a query
@@ -288,17 +377,17 @@ geocode_ipclient_search_async (GeocodeIpclient *ipclient,
*
* Finishes a geolocation search operation. See geocode_ipclient_search_async().
*
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: A #GeocodeLocation object or %NULL in case of errors.
+ * Free the returned object with g_object_unref() when done.
**/
-char *
+GeocodeLocation *
geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
GAsyncResult *res,
GError **error)
{
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
char *contents = NULL;
+ GeocodeLocation *location;
g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
@@ -308,7 +397,10 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
return NULL;
contents = g_simple_async_result_get_op_res_gpointer (simple);
- return contents;
+ location = json_to_location (contents, error);
+ g_free (contents);
+
+ return location;
}
/**
@@ -318,16 +410,16 @@ geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
*
* Gets the geolocation data for an IP address from the server.
*
- * Returns: a string containing the result of the query in JSON format
- * or %NULL in case of errors.
- * Free the returned string with g_free() when done.
+ * Returns: A #GeocodeLocation object or %NULL in case of errors.
+ * Free the returned object with g_object_unref() when done.
**/
-char *
+GeocodeLocation *
geocode_ipclient_search (GeocodeIpclient *ipclient,
GError **error)
{
char *contents;
GFile *query;
+ GeocodeLocation *location;
g_return_val_if_fail (GEOCODE_IS_IPCLIENT (ipclient), NULL);
g_return_val_if_fail (ipclient->priv->server != NULL, NULL);
@@ -347,5 +439,8 @@ geocode_ipclient_search (GeocodeIpclient *ipclient,
}
g_object_unref (query);
- return contents;
+ location = json_to_location (contents, error);
+ g_free (contents);
+
+ return location;
}
diff --git a/geocode-glib/geocode-ipclient.h b/geocode-glib/geocode-ipclient.h
index ab9e7d9..7bd26da 100644
--- a/geocode-glib/geocode-ipclient.h
+++ b/geocode-glib/geocode-ipclient.h
@@ -25,6 +25,7 @@
#include <glib.h>
#include <gio/gio.h>
+#include "geocode-location.h"
G_BEGIN_DECLS
@@ -71,12 +72,12 @@ void geocode_ipclient_search_async (GeocodeIpclient *ipclient,
GAsyncReadyCallback callback,
gpointer user_data);
-char *geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
- GAsyncResult *res,
- GError **error);
+GeocodeLocation *geocode_ipclient_search_finish (GeocodeIpclient *ipclient,
+ GAsyncResult *res,
+ GError **error);
-char *geocode_ipclient_search (GeocodeIpclient *ipclient,
- GError **error);
+GeocodeLocation *geocode_ipclient_search (GeocodeIpclient *ipclient,
+ GError **error);
G_END_DECLS
diff --git a/geocode-glib/test-geoip.c b/geocode-glib/test-geoip.c
index b119ee1..19ca905 100644
--- a/geocode-glib/test-geoip.c
+++ b/geocode-glib/test-geoip.c
@@ -14,7 +14,7 @@ test_search (gconstpointer data)
{
GeocodeIpclient *ipclient;
GError *error = NULL;
- char *contents;
+ GeocodeLocation *location;
const char *ip;
ip = (const char *) data;
@@ -23,16 +23,14 @@ test_search (gconstpointer data)
else {
ipclient = geocode_ipclient_new ();
}
- contents = geocode_ipclient_search (ipclient, &error);
- if (!contents) {
+ location = geocode_ipclient_search (ipclient, &error);
+ if (!location) {
g_warning ("Failed at getting the geolocation information: %s", error->message);
g_error_free (error);
}
- g_assert (contents != NULL);
- g_assert (strstr (contents, "\"ERROR\"") == NULL);
+ g_assert (location != NULL);
+ g_object_unref (location);
g_object_unref (ipclient);
- g_print ("%s\n", contents);
- g_free (contents);
}
static void
@@ -42,17 +40,17 @@ print_geolocation_info_cb (GObject *source_object,
{
GeocodeIpclient *object = (GeocodeIpclient *) source_object;
GError *error = NULL;
- char *results;
+ GeocodeLocation *location;
- results = geocode_ipclient_search_finish (object, res, &error);
- if (results == NULL) {
+ location = geocode_ipclient_search_finish (object, res, &error);
+ if (location == NULL) {
g_message ("Failed to search the geolocation info: %s", error->message);
g_error_free (error);
exit (1);
}
- g_print ("%s\n", results);
- g_free (results);
+ g_print ("Location: %s (%f,%f)\n", location->description, location->latitude, location->longitude);
+ g_object_unref (location);
g_object_unref (object);
exit (0);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]