Adds base from the mapquests plugin 09/77709/1
authorKevin Kreiser <kevinkreiser@gmail.com>
Thu, 16 Jun 2016 15:46:59 +0000 (11:46 -0400)
committerBaldur Gudbjornsson <baldur@mapzen.com>
Thu, 30 Jun 2016 13:45:07 +0000 (09:45 -0400)
Change-Id: I8999fd8fac54ba9bde4f746fb18dbe529e9c8172

33 files changed:
.gitmodules [new file with mode: 0644]
CMakeLists.txt
README.md
inc/mapzen_api.h [new file with mode: 0644]
inc/mapzen_constants.h [new file with mode: 0644]
inc/mapzen_plugin.h [new file with mode: 0644]
inc/mapzen_plugin_internal.h [new file with mode: 0644]
inc/mapzen_utils.h
rapidjson [new submodule]
src/mapzen/mapzen_api.c [new file with mode: 0644]
src/mapzen/mapzen_api.h [new file with mode: 0644]
src/mapzen/mapzen_debug.h [new file with mode: 0644]
src/mapzen/mapzen_geocode.c [new file with mode: 0644]
src/mapzen/mapzen_geocode.h [new file with mode: 0644]
src/mapzen/mapzen_jsonparser.c [new file with mode: 0644]
src/mapzen/mapzen_jsonparser.h [moved from src/mapzen_utils.cpp with 74% similarity]
src/mapzen/mapzen_place.c [new file with mode: 0644]
src/mapzen/mapzen_place.h [new file with mode: 0644]
src/mapzen/mapzen_queue.c [new file with mode: 0644]
src/mapzen/mapzen_queue.h [new file with mode: 0644]
src/mapzen/mapzen_restcurl.c [new file with mode: 0644]
src/mapzen/mapzen_restcurl.h [new file with mode: 0644]
src/mapzen/mapzen_revgeocode.c [new file with mode: 0644]
src/mapzen/mapzen_revgeocode.h [new file with mode: 0644]
src/mapzen/mapzen_route.c [new file with mode: 0644]
src/mapzen/mapzen_route.h [new file with mode: 0644]
src/mapzen/mapzen_server_private.h [new file with mode: 0644]
src/mapzen/mapzen_types.h [new file with mode: 0644]
src/mapzen/mapzen_util.c [new file with mode: 0644]
src/mapzen/mapzen_util.h [new file with mode: 0644]
src/mapzen_api.cpp [new file with mode: 0644]
src/mapzen_plugin.c [new file with mode: 0644]
src/mapzen_plugin.cpp [deleted file]

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..21ec3ff
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "rapidjson"]
+       path = rapidjson
+       url = https://github.com/miloyip/rapidjson
index 6a0b313..0373c39 100644 (file)
@@ -61,6 +61,7 @@ SET(SRCS
        # Maps API
        src/mapzen_utils.cpp
        src/mapzen_plugin.cpp
+       src/mapzen_api.cpp
 )
 
 ADD_LIBRARY(${pkg_name} SHARED ${SRCS})
index 908d14d..4147a0b 100644 (file)
--- a/README.md
+++ b/README.md
@@ -10,6 +10,8 @@ gbs build --include-all -A i586
 # to push to device
 sdb push ~/GBS-ROOT/local/BUILD-ROOTS/scratch.<arc>.0/home/abuild/rpmbuild/RPMS/<arc>/maps-plugin-mapzen-0.0.1-1.<arc>.rpm /mnt/
 
+sdb shell
+
 # install
 rpm -Uvh --force /mnt/maps-plugin-mapzen-0.0.1-1.<arc>.rpm
 
diff --git a/inc/mapzen_api.h b/inc/mapzen_api.h
new file mode 100644 (file)
index 0000000..fe46189
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_API_H_
+#define _MAPZEN_API_H_
+
+#include <maps_plugin.h>
+#include <maps_view.h>
+
+int MapzenPluginRoute(maps_coordinates_h origin, maps_coordinates_h destination,
+       maps_item_hashtable_h pref, maps_service_search_route_cb callback_function,
+       void* user_data, int* request_id);
+
+#endif // _MAPZEN_API_H_
diff --git a/inc/mapzen_constants.h b/inc/mapzen_constants.h
new file mode 100644 (file)
index 0000000..81f39c2
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_CONSTANTS_H_
+#define _MAPZEN_CONSTANTS_H_
+
+// Error types
+enum ErrorType {
+       kNone = 0,                              // Success
+       kPermissionDenied,              // Permission denied
+       kOutOfMemory,                   // Out of memory
+       kInvalidParameter,              // Invalid parameter
+       kNotSupported,                  // Unsupported operation
+       kConnectionTimeout,             // Connection timeout
+       kNetworkUnreachable,    // Network unavailable
+       kInvalidOperation,              // Invalid operation
+       kInvalidKey,            // Invalid key
+       kResourceBusy,                  // Resource busy
+       kCancelled,                             // Service cancelled
+       kUnknown,                               // Unknown error
+       kServiceUnavailable,    // Service unavailable
+       kResultNotFound                 // Result not found
+};
+
+#endif // _MAPZEN_CONSTANTS_H_
diff --git a/inc/mapzen_plugin.h b/inc/mapzen_plugin.h
new file mode 100644 (file)
index 0000000..acfb4d3
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_PLUGIN_H_
+#define _MAPZEN_PLUGIN_H_
+
+#include <maps_plugin.h>
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct callback_geocode {
+       maps_service_geocode_cb callback;
+       void *data;
+       int reqID;
+} callback_info_geocode;
+
+typedef struct callback_reverse_geocode {
+       maps_service_reverse_geocode_cb callback;
+       void *data;
+       int reqID;
+} callback_info_reverse_geocode;
+
+typedef struct callback_route {
+       maps_service_search_route_cb callback;
+       void *data;
+       int reqID;
+} callback_info_route;
+
+typedef struct callback_place {
+       maps_service_search_place_cb callback;
+       void *data;
+       int reqID;
+} callback_info_place;
+
+int maps_plugin_init(maps_plugin_h *plugin);
+
+int maps_plugin_shutdown(maps_plugin_h plugin);
+
+int maps_plugin_is_service_supported(maps_service_e service, bool *supported);
+
+int maps_plugin_is_data_supported(maps_service_data_e data, bool *supported);
+
+int maps_plugin_get_info(maps_plugin_info_h *info);
+
+int maps_plugin_set_provider_key(const char *provider_key);
+
+int maps_plugin_get_provider_key(char **provider_key);
+
+int maps_plugin_set_preference(maps_item_hashtable_h preference);
+
+int maps_plugin_get_preference(maps_item_hashtable_h *preference);
+
+/* Geocode */
+int maps_plugin_geocode(const char *address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id);
+
+/* Geocode inside area */
+int maps_plugin_geocode_inside_area(const char *address, const maps_area_h bounds, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id);
+
+/* Geocode by structured address */
+int maps_plugin_geocode_by_structured_address(const maps_address_h address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id);
+
+/* Rev Geocode */
+int maps_plugin_reverse_geocode(double latitude, double longitude, const maps_preference_h preference, maps_service_reverse_geocode_cb callback, void *user_data, int *request_id);
+
+/* Route search */
+int maps_plugin_search_route(const maps_coordinates_h origin, const maps_coordinates_h destination, maps_preference_h preference, maps_service_search_route_cb callback, void *user_data, int *request_id);
+
+/* Route search waypoints */
+int maps_plugin_search_route_waypoints(const maps_coordinates_h *waypoint_list, int waypoint_num, maps_preference_h preference, maps_service_search_route_cb callback, void *user_data, int *request_id);
+
+/* Place search */
+int maps_plugin_search_place(const maps_coordinates_h position, int distance, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id);
+
+/* Place search by area */
+int maps_plugin_search_place_by_area(const maps_area_h boundary, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id);
+
+/* Place search by address */
+int maps_plugin_search_place_by_address(const char *address, const maps_area_h boundary, const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id);
+
+/* Cancel Request */
+int maps_plugin_cancel_request(int request_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif                         /* _MAPZEN_PLUGIN_H_ */
diff --git a/inc/mapzen_plugin_internal.h b/inc/mapzen_plugin_internal.h
new file mode 100644 (file)
index 0000000..517bdc4
--- /dev/null
@@ -0,0 +1,61 @@
+/* Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MAPZEN_PLUGIN_INTERNAL_H__
+#define __MAPZEN_PLUGIN_INTERNAL_H__
+
+#include <dlog.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "MAPZEN_PLUGIN"
+
+/*
+ * Internal Macros
+ */
+#define MAPS_LOGD(fmt, args...)  LOGD(fmt, ##args)
+#define MAPS_LOGW(fmt, args...)  LOGW(fmt, ##args)
+#define MAPS_LOGI(fmt, args...)  LOGI(fmt, ##args)
+#define MAPS_LOGE(fmt, args...)  LOGE(fmt, ##args)
+#define MAPS_SECLOG(fmt, args...)  SECURE_LOGD(fmt, ##args)
+
+#define MAPS_CHECK_CONDITION(condition, error, msg)    \
+       do { \
+               if (condition) { \
+               } else { \
+                       MAPS_LOGE("%s(0x%08x)", msg, error); \
+                       return error; \
+               } \
+       } while (0)
+
+#define MAPS_NULL_ARG_CHECK_RETURN_FALSE(arg)\
+       do { \
+               if (arg != NULL) { \
+               } else  { \
+                       MAPS_LOGE("MAPS_ERROR_INVALID_PARAMETER");  \
+                       return false; };        \
+       } while (0)
+
+#define MAPS_NULL_ARG_CHECK(arg)       \
+       MAPS_CHECK_CONDITION(arg != NULL, MAPS_ERROR_INVALID_PARAMETER, "MAPS_ERROR_INVALID_PARAMETER")
+
+#define MAPS_PRINT_ERROR_CODE_RETURN(code) \
+       do { \
+               MAPS_LOGE("%s(0x%08x)", #code, code); \
+               return code;    \
+       } while (0)
+
+#endif /* __MAPZEN_PLUGIN_INTERNAL_H__ */
index 30646c5..e88abef 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <string>
+#include <vector>
 #include <maps_area.h>
 #include <maps_preference.h>
 #include <maps_route_maneuver.h>
 
 extern "C"
 {
+
 }
+constexpr double kPolylinePrecision = 1E6;
+constexpr double kInvPolylinePrecision = 1.0 / kPolylinePrecision;
+
 
 class MapzenUtils
 {
 public:
        MapzenUtils();
        ~MapzenUtils();
+
+       // Is the map coordinate valid (in valid latitude,longitude range)
+       static bool IsValid(maps_coordinates_s& coord);
+
+       // Decode the shape string returned in the route result
+       void DecodeShape(const std::string& encoded,
+                       std::vector<maps_coordinates_s>& output);
+
 private:
 };
+
diff --git a/rapidjson b/rapidjson
new file mode 160000 (submodule)
index 0000000..3d5848a
--- /dev/null
+++ b/rapidjson
@@ -0,0 +1 @@
+Subproject commit 3d5848a7cd3367c5cb451c6493165b7745948308
diff --git a/src/mapzen/mapzen_api.c b/src/mapzen/mapzen_api.c
new file mode 100644 (file)
index 0000000..4eb72b5
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mapzen_api.h"
+#include "mapzen_server_private.h"
+#include "mapzen_queue.h"
+#include "mapzen_debug.h"
+
+EXPORT_API int mapzen_init()
+{
+       int ret = mapzen_init_queue();
+
+       return ret;
+}
+
+EXPORT_API int mapzen_shutdown()
+{
+       int ret = mapzen_deinit_queue();
+
+       return ret;
+}
+
+EXPORT_API int mapzen_geocode(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_geocode_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
+
+EXPORT_API int mapzen_cancel_request(int request_id)
+{
+       int ret = remove_from_request_list(request_id);
+
+       return ret;
+}
+
+EXPORT_API int mapzen_reverse_geocode(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_reversegeocode_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
+
+EXPORT_API int mapzen_search_place(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_places_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
+
+EXPORT_API int mapzen_start_route(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data)
+{
+       int ret = MAPZEN_ERROR_NONE;
+       ret = start_route_service(req_details, callback, request_id, user_data);
+
+       return ret;
+}
diff --git a/src/mapzen/mapzen_api.h b/src/mapzen/mapzen_api.h
new file mode 100644 (file)
index 0000000..ceddc3a
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_API_H_
+#define _MAPZEN_API_H_
+
+#include "mapzen_types.h"
+#include <tizen_type.h>
+
+/**
+ * @ingroup    MAPZEN_ENGINE_MODULE
+ * @defgroup   MAPZEN_ENGINE_API_MODULE
+ *
+ * @file mapzen_api.h
+ * @brief This file contains the Mapzen engine API's that should be called by the plugin
+ *
+ * @addtogroup MAPZEN_ENGINE_MODULE
+ * @{
+ * @brief This provides APIs related to Mapzen engine.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  /* Callbacks */
+typedef void (*mapzen_geocode_cb) (mapzen_error_e result, int request_id, GList *co_ordinates, void *user_data);
+
+typedef void (*mapzen_reverse_geocode_cb) (mapzen_error_e result, int request_id, mapzen_address_resp_s *address, void *user_data);
+
+typedef void (*mapzen_place_search_cb) (mapzen_error_e result, int request_id, GList *places, void *user_data);
+
+typedef void (*mapzen_route_cb) (mapzen_error_e result, int request_id, mapzen_route_resp_s *route_info, void *user_data);
+
+typedef void (*mapzen_maptile_cb) (mapzen_error_e result, int request_id, char *buffer, void *user_data);
+
+int mapzen_init();
+
+int mapzen_shutdown();
+
+int mapzen_geocode(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data);
+
+int mapzen_cancel_request(int request_id);
+
+int mapzen_reverse_geocode(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data);
+
+int mapzen_search_place(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+
+int mapzen_start_route(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif                         /* _MAPZEN_API_H_ */
diff --git a/src/mapzen/mapzen_debug.h b/src/mapzen/mapzen_debug.h
new file mode 100644 (file)
index 0000000..78b8767
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef _MAPZEN_DEBUG_H_
+#define _MAPZEN_DEBUG_H_
+
+#include <dlog.h>
+#include <string.h>
+#include <assert.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define EXPORT_API __attribute__((visibility("default")))
+
+#define LOG_TAG "MAPZEN_ENGINE"
+
+/* normal log */
+#define MAP_DEBUG(fmt, args...) LOGD(fmt, ##args)
+#define MAP_ENTER() LOGD(WCOLOR_GREEN "BEGIN >>>>" WCOLOR_END)
+#define MAP_LEAVE() LOGD(WCOLOR_GREEN "END <<<<" WCOLOR_END)
+
+#endif /* _MAPZEN_DEBUG_H_ */
diff --git a/src/mapzen/mapzen_geocode.c b/src/mapzen/mapzen_geocode.c
new file mode 100644 (file)
index 0000000..c7719cf
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapzen_geocode.h"
+#include "mapzen_types.h"
+#include "mapzen_server_private.h"
+#include "mapzen_debug.h"
+#include "mapzen_queue.h"
+#include "mapzen_restcurl.h"
+#include "mapzen_util.h"
+
+#define GEOCODE_URL    "https://open.mapzenapi.com/geocoding/v1/address?key=%s&inFormat=kvp&outFormat=json"
+
+int query_geocode_within_bounds(gchar *maps_key, char *address, coords_s top_left, coords_s bottom_right, int num_results, gpointer user_data)
+{
+       char url[1024];
+       char tmpStr[512];
+
+       if (maps_key != NULL)
+               snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, maps_key);
+       else
+               snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, "null");
+
+       STRCPY(url, tmpStr);
+
+       snprintf(tmpStr, sizeof(tmpStr), "&boundingBox=%f,%f,%f,%f", top_left.latitude, top_left.longitude, bottom_right.latitude, bottom_right.longitude);
+       STRCAT(url, tmpStr);
+
+       snprintf(tmpStr, sizeof(tmpStr), "&maxResults=%d", num_results);
+       STRCAT(url, tmpStr);
+
+       snprintf(tmpStr, sizeof(tmpStr), "&location=%s", address);
+       STRCAT(url, tmpStr);
+
+       add_handle(url, REQ_TYPE_GEOCODE, user_data);
+
+       return 0;
+}
+
+int query_geocode(gchar *maps_key, char *address, int num_results, gpointer user_data)
+{
+       MAP_DEBUG("geocode address : %s", address);
+       char url[1024];
+       char tmpStr[512];
+
+       if (maps_key != NULL)
+               snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, maps_key);
+       else
+               snprintf(tmpStr, sizeof(tmpStr), GEOCODE_URL, "null");
+
+       STRCPY(url, tmpStr);
+
+       snprintf(tmpStr, sizeof(tmpStr), "&maxResults=%d", num_results);
+       STRCAT(url, tmpStr);
+
+       snprintf(tmpStr, sizeof(tmpStr), "&location=%s", address);
+       STRCAT(url, tmpStr);
+
+       add_handle(url, REQ_TYPE_GEOCODE, user_data);
+
+       return 0;
+}
diff --git a/src/mapzen/mapzen_geocode.h b/src/mapzen/mapzen_geocode.h
new file mode 100644 (file)
index 0000000..d4035ae
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_GEOCODE_H_
+#define _MAPZEN_GEOCODE_H_
+
+#include "mapzen_api.h"
+#include "mapzen_types.h"
+
+int query_geocode(gchar *maps_key, char *address, int num_results, gpointer user_data);
+int query_geocode_within_bounds(gchar *maps_key, char *address, coords_s top_left, coords_s bottom_right, int num_results, gpointer user_data);
+
+#endif /* MAPZEN_GEOCODE_H_ */
diff --git a/src/mapzen/mapzen_jsonparser.c b/src/mapzen/mapzen_jsonparser.c
new file mode 100644 (file)
index 0000000..62142a8
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include "rapidjson/rapidjson.h"
+#include "mapzen_jsonparser.h"
+#include "mapzen_queue.h"
+#include "mapzen_debug.h"
+#include "mapzen_util.h"
+
+#define ROUTE_UNIT_CONVERSION_MILE_TO_M(x)     (1609.34 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_KM(x)    (1.60934 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_FT(x)    (5280 * (x))
+#define ROUTE_UNIT_CONVERSION_MILE_TO_YD(x)    (1760 * (x))
+
+static route_unit __route_unit = ROUTE_UNIT_M;
+static int __maneuver_index = 0;
+static coords_s __destination_point;
+
+static mapzen_error_e __convert_status(int status)
+{
+       mapzen_error_e error = MAPZEN_ERROR_UNKNOWN;
+       switch (status) {
+       case 0:
+               {
+                       /* Successful Geocode call */
+                       error = MAPZEN_ERROR_NONE;
+                       break;
+               }
+       case 400:
+               {
+                       /* Error with input - Illegal argument from request */
+                       error = MAPZEN_ERROR_INVALID_PARAMETER;
+                       break;
+               }
+       case 403:
+               {
+                       /* Key related error - Invalid key */
+                       error = MAPZEN_ERROR_KEY_NOT_AVAILABLE;
+                       break;
+               }
+       case 500:
+               {
+                       /* Unknown error */
+                       error = MAPZEN_ERROR_UNKNOWN;
+                       break;
+               }
+       case -1:
+               {
+                       /* Network error */
+                       error = MAPZEN_ERROR_NETWORK_UNREACHABLE;
+                       break;
+               }
+       }
+
+       return error;
+}
+
+/************ GEOCODE ***************/
+
+
+static void __parse_geocode_response(char *response, int size, int *status, GList **coordsList)
+{
+       if (!response || !status || !coordsList) return;
+
+       *coordsList = NULL;
+
+       //TODO:
+}
+
+/****************** REVERSE GEOCODE *********************/
+
+static void __parse_revgeocode_response(char *response, int size, int *status, mapzen_address_resp_s **respAddr)
+{
+       if (!response || !status || !respAddr) return;
+
+       *respAddr = NULL;
+
+       //TODO:
+}
+
+/****************  PLACE SEARCH ********************/
+
+static void __parse_place_response(char *response, int size, GList **placeList)
+{
+       if (!response || !placeList) return;
+
+       *placeList = NULL;
+
+       //TODO
+}
+
+/********************* ROUTE RESPONSE ***********************/
+
+static void __parse_route_response(char *response, int size, int *status, mapzen_route_resp_s **routeResp)
+{
+       if (!response || !status || !routeResp) return;
+
+       *routeResp = NULL;
+
+}
+
+void post_curl_response(char *response, int size, mapzen_resp_type type, void *user_data)
+{
+       if (!response) return;
+
+       if (!user_data) {
+               MAP_DEBUG("Response data is NULL");
+               return;
+       }
+
+       MAP_DEBUG("Response received from Curl. [Size=%d]", size);
+       switch (type) {
+       case RESP_TYPE_GEOCODE:
+               {
+                       MAP_DEBUG("Inside Geocode JSON Parsing..");
+                       int status = -1;
+                       MapzenGeocodeQueryData *queryData = (MapzenGeocodeQueryData *)user_data;
+                       MapzenGeocodeResponseData *responseData = (MapzenGeocodeResponseData *)g_malloc(sizeof(MapzenGeocodeResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->geocode_cb = queryData->geocode_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       GList *coordsList = NULL;
+                                       __parse_geocode_response(response, size, &status, &coordsList);
+
+                                       if (coordsList != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = __convert_status(status);
+                                               responseData->coords = coordsList;
+                                       } else {
+                                               /* Response parsing failure */
+                                               responseData->error = __convert_status(status);
+                                               responseData->coords = NULL;
+                                       }
+                               } else {
+                                       responseData->error = __convert_status(status);
+                                       responseData->coords = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+                       break;
+               }
+       case RESP_TYPE_REVGEOCODE:
+               {
+                       MAP_DEBUG("Inside Rev Geocode JSON Parsing..");
+                       int status = -1;
+                       MapzenRevGeocodeQueryData *queryData = (MapzenRevGeocodeQueryData *)user_data;
+                       MapzenRevGeocodeResponseData *responseData = (MapzenRevGeocodeResponseData *)g_malloc(sizeof(MapzenRevGeocodeResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->reverse_geocode_cb = queryData->reverse_geocode_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       /* Coords Result GList */
+                                       mapzen_address_resp_s *addrResponse = NULL;
+
+                                       MAP_DEBUG("Rev Geocode :- Parsing json Response");
+                                       __parse_revgeocode_response(response, size, &status, &addrResponse);
+
+                                       if (addrResponse != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = __convert_status(status);
+                                               responseData->addressDetails = addrResponse;
+                                       } else {
+                                               /* REPSONSE PARSING FAILURE */
+                                               MAP_DEBUG("addr Response is NULL");
+                                               responseData->error = __convert_status(status);
+                                               responseData->addressDetails = NULL;
+                                       }
+                               } else {
+                                       MAP_DEBUG("JSON Response is NULL..");
+                                       responseData->error = __convert_status(status);
+                                       responseData->addressDetails = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+                       break;
+               }
+       case RESP_TYPE_PLACES:
+               {
+                       MAP_DEBUG("Inside Places JSON Parsing..");
+                       MapzenPlaceQueryData *queryData = (MapzenPlaceQueryData *)user_data;
+                       MapzenPlaceResponseData *responseData = (MapzenPlaceResponseData *)g_malloc(sizeof(MapzenPlaceResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->place_search_cb = queryData->place_search_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       /* Coords Result GList */
+                                       GList *placeList = NULL;
+
+                                       MAP_DEBUG("Search Places :- Parsing Json Response");
+                                       __parse_place_response(response, size, &placeList);
+
+                                       if (placeList != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = MAPZEN_ERROR_NONE;
+                                               responseData->places = placeList;
+                                       } else {
+                                               /* REPSONSE PARSING FAILURE */
+                                               MAP_DEBUG("addr Response is NULL");
+                                               responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                               responseData->places = NULL;
+                                       }
+                               } else {
+                                       responseData->error = MAPZEN_ERROR_UNKNOWN;
+                                       responseData->places = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+
+                       break;
+               }
+       case RESP_TYPE_ROUTE:
+               {
+                       MAP_DEBUG("Inside Route JSON Parsing..");
+                       int status = -1;
+                       MapzenRouteQueryData *queryData = (MapzenRouteQueryData *)user_data;
+                       __route_unit = queryData->unit;
+                       __maneuver_index = 0;
+                       __destination_point = queryData->destination;
+
+                       MapzenRouteResponseData *responseData = (MapzenRouteResponseData *)g_malloc(sizeof(MapzenRouteResponseData));
+
+                       if (responseData) {
+                               responseData->requestId = queryData->requestId;
+                               responseData->route_cb = queryData->route_cb;
+                               responseData->user_data = queryData->user_data;
+
+                               if (response && (size > 0)) {
+                                       /* Coords Result GList */
+                                       mapzen_route_resp_s *routeResponse = NULL;
+
+                                       MAP_DEBUG("Route :- Parsing Response");
+                                       __parse_route_response(response, size, &status, &routeResponse);
+
+                                       if (routeResponse != NULL) {
+                                               /* Put the response in queue */
+                                               responseData->error = __convert_status(status);
+                                               responseData->routeResponse = routeResponse;
+                                       } else {
+                                               /* REPSONSE PARSING FAILURE */
+                                               MAP_DEBUG("route Response is NULL");
+                                               responseData->error = __convert_status(status);
+                                               responseData->routeResponse = NULL;
+                                       }
+                               } else {
+                                       responseData->error = __convert_status(status);
+                                       responseData->routeResponse = NULL;
+                               }
+
+                               mapzen_push_to_queue(type, (gpointer)responseData);
+                       }
+
+                       if (queryData) {
+                               g_free(queryData);
+                               queryData = NULL;
+                       }
+
+                       break;
+               }
+       default:
+               {
+                       MAP_DEBUG("Inside default JSON Parsing..");
+                       break;
+               }
+       }
+}
similarity index 74%
rename from src/mapzen_utils.cpp
rename to src/mapzen/mapzen_jsonparser.h
index fff89d2..9a766eb 100644 (file)
  * limitations under the License.
  */
 
-#include "mapzen_utils.h"
+#ifndef _MAPZEN_JSONPARSER_H_
+#define _MAPZEN_JSONPARSER_H_
 
-MapzenUtils::MapzenUtils()
-{
-}
+#include "mapzen_server_private.h"
 
-MapzenUtils::~MapzenUtils()
-{
-}
+void post_curl_response(char *response, int size, mapzen_resp_type type, void *user_data);
+
+#endif /* _MAPZEN_JSONPARSER_H_ */
diff --git a/src/mapzen/mapzen_place.c b/src/mapzen/mapzen_place.c
new file mode 100644 (file)
index 0000000..8df590a
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapzen_place.h"
+#include "mapzen_types.h"
+#include "mapzen_server_private.h"
+#include "mapzen_debug.h"
+#include "mapzen_queue.h"
+#include "mapzen_restcurl.h"
+#include "mapzen_util.h"
+
+#define PLACES_URL     "https://open.mapzenapi.com/nominatim/v1/search.php?format=json"
+
+int query_places(gchar *maps_key, gchar *search_str, mapzen_boundary_s *boundary, int num_res, gpointer user_data)
+{
+       char url[1024];
+       char tmpStr[512];
+
+       STRCPY(url, PLACES_URL);
+
+       if (search_str != NULL) {
+               snprintf(tmpStr, sizeof(tmpStr), "&q=%s", search_str);
+               strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+       }
+
+       if (boundary != NULL) {
+               if (boundary->type == MAPZEN_BOUNDARY_RECT) {
+                       snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", boundary->rect.top_left.longitude, boundary->rect.top_left.latitude, boundary->rect.bottom_right.longitude, boundary->rect.bottom_right.latitude);
+
+                       strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+               } else if (boundary->type == MAPZEN_BOUNDARY_CIRCLE) {
+                       coords_s *top_left = NULL, *bottom_right = NULL;
+                       coords_s circle = boundary->circle.center;
+                       gdouble radius = (boundary->circle.radius) * 0.001;
+
+                       /* Calculate the top left coordinate of bounding box. */
+                       calculate_point(circle.latitude, circle.longitude, 315, radius, &top_left);
+
+                       /* Calculate the bottom right coordinate of bounding box. */
+                       calculate_point(circle.latitude, circle.longitude, 135, radius, &bottom_right);
+
+                       if (top_left && bottom_right) {
+                               snprintf(tmpStr, sizeof(tmpStr), "&viewbox=%f,%f,%f,%f", top_left->longitude, top_left->latitude, bottom_right->longitude, bottom_right->latitude);
+                               strncat(url, tmpStr, sizeof(url)-strlen(url)-1);
+                       }
+
+                       if (top_left) {
+                               g_free(top_left);
+                               top_left = NULL;
+                       }
+                       if (bottom_right) {
+                               g_free(bottom_right);
+                               bottom_right = NULL;
+                       }
+               }
+
+               STRCAT(url, "&bounded=1");
+       }
+
+       STRCAT(url, "&addressdetails=1");
+
+       if (num_res > 0) {
+               snprintf(tmpStr, sizeof(tmpStr), "&limit=%d", num_res);
+               STRCAT(url, tmpStr);
+       }
+
+       add_handle(url, REQ_TYPE_PLACES, user_data);
+
+       return 0;
+}
diff --git a/src/mapzen/mapzen_place.h b/src/mapzen/mapzen_place.h
new file mode 100644 (file)
index 0000000..ed122a1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_PLACES_H_
+#define _MAPZEN_PLACES_H_
+
+#include "mapzen_api.h"
+#include "mapzen_types.h"
+
+int query_places(gchar *maps_key, gchar *search_str, mapzen_boundary_s *boundary, int num_res, gpointer user_data);
+
+#endif /* _MAPZEN_PLACES_H_ */
diff --git a/src/mapzen/mapzen_queue.c b/src/mapzen/mapzen_queue.c
new file mode 100644 (file)
index 0000000..da8364a
--- /dev/null
@@ -0,0 +1,1263 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include<stdlib.h>
+#include "mapzen_queue.h"
+#include "mapzen_geocode.h"
+#include "mapzen_revgeocode.h"
+#include "mapzen_route.h"
+#include "mapzen_place.h"
+#include "mapzen_restcurl.h"
+#include "mapzen_util.h"
+#include "mapzen_debug.h"
+#include <json-glib/json-glib.h>
+
+pthread_mutex_t __requestLock;
+static GAsyncQueue *responseQueue = NULL;
+int __ResponseQueueLen = 0;
+bool __response_timer_running = false;
+
+/* Request List */
+GList *requestList = NULL;
+
+/* Request Cancel List */
+GList *reqCancelList = NULL;
+
+static void __free_geocode_response(void *ptr);
+static void __free_revgeocode_response(void *ptr);
+static void __free_place_response(void *ptr);
+static void __free_route_response(void *ptr);
+
+int add_to_geocode_list(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data)
+{
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_GEOCODE;
+
+               mapzen_geocode_req *data = (mapzen_geocode_req *)g_malloc0(sizeof(mapzen_geocode_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->geocode_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added GEOCODE REQUEST to geocode List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int add_to_revgeocode_list(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_REVGEOCODE;
+
+               mapzen_revgeocode_req *data = (mapzen_revgeocode_req *)g_malloc0(sizeof(mapzen_revgeocode_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->revgeocode_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added REVERSE GEOCODE request to geocode List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
+{
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_PLACES;
+
+               mapzen_search_place_req *data = (mapzen_search_place_req *)g_malloc0(sizeof(mapzen_search_place_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->search_place_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added PLACE request to places List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int add_to_route_list(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data)
+{
+       mapzen_request_s *req = (mapzen_request_s *)g_malloc0(sizeof(mapzen_request_s));
+
+       if (req != NULL) {
+
+               req->type = REQ_TYPE_ROUTE;
+
+               mapzen_route_req *data = (mapzen_route_req *)g_malloc0(sizeof(mapzen_route_req));
+
+               if (data != NULL) {
+                       data->req_details = req_details;
+                       data->requestId = request_id;
+                       data->route_cb = callback;
+                       data->user_data = user_data;
+
+                       req->request = data;
+
+                       MAP_DEBUG("Added request to route List");
+
+                       pthread_mutex_lock(&__requestLock);
+                       if (requestList == NULL)
+                               requestList = g_list_append(requestList, (gpointer)req);
+                       else
+                               requestList = g_list_insert_before(requestList, NULL, (gpointer)req);
+                       pthread_mutex_unlock(&__requestLock);
+               }
+
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+static int __add_to_cancel_list(int request_id)
+{
+       if (reqCancelList == NULL)
+               reqCancelList = g_list_append(reqCancelList, (gpointer) GINT_TO_POINTER(request_id));
+       else
+               reqCancelList = g_list_insert_before(reqCancelList, NULL, (gpointer) GINT_TO_POINTER(request_id));
+
+       return MAPZEN_ERROR_NONE;
+}
+
+static int __remove_from_cancel_list(int request_id)
+{
+       if (g_list_length(reqCancelList) != 0)
+               reqCancelList = g_list_remove(reqCancelList, (gpointer) GINT_TO_POINTER(request_id));
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int remove_from_request_list(int request_id)
+{
+       bool is_request_cancelled = false;
+       GList *list = NULL;
+       pthread_mutex_lock(&__requestLock);
+       list = g_list_first(requestList);
+       pthread_mutex_unlock(&__requestLock);
+       mapzen_request_s *req = NULL;
+
+       while (list != NULL) {
+               req = (mapzen_request_s *) list->data;
+
+               if (req != NULL) {
+                       if (req->type == REQ_TYPE_GEOCODE) {
+                               mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+
+                               if (geocode_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_geocode_req_s *geocode_req_details = (mapzen_geocode_req_s *)geocode_req->req_details;
+
+                                       if (geocode_req_details)
+                                               g_free(geocode_req_details);
+                                       geocode_req_details = NULL;
+
+                                       g_free(geocode_req);
+                                       geocode_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
+                       } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                               mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *)req->request;
+
+                               if (revgeocode_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_revgeocode_req_s *reverse_geocode_req_details = (mapzen_revgeocode_req_s *)revgeocode_req->req_details;
+
+                                       if (reverse_geocode_req_details)
+                                               g_free(reverse_geocode_req_details);
+                                       reverse_geocode_req_details = NULL;
+
+                                       g_free(revgeocode_req);
+                                       revgeocode_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
+                       } else if (req->type == REQ_TYPE_ROUTE) {
+                               mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+
+                               if (route_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_route_req_s *route_req_details = (mapzen_route_req_s *)route_req->req_details;
+
+                                       if (route_req_details)
+                                               g_free(route_req_details);
+                                       route_req_details = NULL;
+
+                                       g_free(route_req);
+                                       route_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
+                       } else if (req->type == REQ_TYPE_PLACES) {
+                               mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+
+                               if (places_req->requestId == request_id) {
+                                       /* Means the request is pending in queue. Not started yet */
+                                       /* Deleting the request from the request queue */
+                                       pthread_mutex_lock(&__requestLock);
+                                       requestList = g_list_remove(requestList, (gpointer)req);
+                                       pthread_mutex_unlock(&__requestLock);
+                                       mapzen_search_req_s *place_req_details = (mapzen_search_req_s *)places_req->req_details;
+
+                                       if (place_req_details)
+                                               g_free(place_req_details);
+                                       place_req_details = NULL;
+
+                                       g_free(places_req);
+                                       places_req = NULL;
+
+                                       g_free(req);
+                                       req = NULL;
+
+                                       __remove_from_cancel_list(request_id);
+
+                                       is_request_cancelled = true;
+                                       break;
+                               }
+                       }
+               }
+
+               list = g_list_next(list);
+       }
+
+       if (!is_request_cancelled) {
+               /* Means it is currently running. */
+               /* Cancel the request */
+               cancel_request(request_id);
+               /* add to cancel list */
+               __add_to_cancel_list(request_id);
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+static bool __is_request_in_cancel_list(int requestId)
+{
+       bool match_id = false;
+
+       GList *list = NULL;
+       list = g_list_first(reqCancelList);
+
+       while (list != NULL) {
+
+               int id = (int) GPOINTER_TO_INT(list->data);
+
+               if (id == requestId) {
+                       match_id = true;
+                       break;
+               }
+
+               list = g_list_next(list);
+       }
+
+       return match_id;
+}
+
+mapzen_request_s *get_next_request()
+{
+       if (g_list_length(requestList) > 0) {
+               pthread_mutex_lock(&__requestLock);
+               GList *list = g_list_first(requestList);
+               pthread_mutex_unlock(&__requestLock);
+
+               if (list) {
+                       mapzen_request_s *req = (mapzen_request_s *) list->data;
+                       return req;
+               } else {
+                       return NULL;
+               }
+       }
+
+       return NULL;
+}
+
+static gboolean __timeout_cb(gpointer data)
+{
+       MAP_DEBUG("timeout_cb");
+       __response_timer_running = true;
+       g_async_queue_ref(responseQueue);
+
+       __ResponseQueueLen = g_async_queue_length(responseQueue);
+       MAP_DEBUG("Queue Len :: [%d]", __ResponseQueueLen);
+       while (__ResponseQueueLen > 0) {
+               gpointer data = g_async_queue_try_pop(responseQueue);
+               if (!data)
+                       continue;
+
+               MapzenQueueData *response = (MapzenQueueData *) data;
+
+               switch (response->type) {
+               case RESP_TYPE_GEOCODE:
+                       {
+                               MAP_DEBUG("Got geocode response..");
+                               MapzenGeocodeResponseData *geocodeData = (MapzenGeocodeResponseData *) (response->data);
+                               if (geocodeData) {
+                                       if (__is_request_in_cancel_list(geocodeData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               geocodeData->geocode_cb(geocodeData->error, geocodeData->requestId, geocodeData->coords, geocodeData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(geocodeData->requestId);
+                                       }
+                                       __free_geocode_response(geocodeData);
+
+                                       g_free(geocodeData);
+                                       geocodeData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+
+               case RESP_TYPE_REVGEOCODE:
+                       {
+                               MapzenRevGeocodeResponseData *revGeocodeData = (MapzenRevGeocodeResponseData *) (response->data);
+                               if (revGeocodeData) {
+                                       if (__is_request_in_cancel_list(revGeocodeData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               revGeocodeData->reverse_geocode_cb(revGeocodeData->error, revGeocodeData->requestId, revGeocodeData->addressDetails, revGeocodeData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(revGeocodeData->requestId);
+                                       }
+                                       __free_revgeocode_response(revGeocodeData);
+
+                                       g_free(revGeocodeData);
+                                       revGeocodeData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               MAP_DEBUG(">> Condition Check <<");
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+
+               case RESP_TYPE_ROUTE:
+                       {
+                               MapzenRouteResponseData *routeData = (MapzenRouteResponseData *) (response->data);
+                               if (routeData != NULL) {
+                                       if (__is_request_in_cancel_list(routeData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               routeData->route_cb(routeData->error, routeData->requestId, routeData->routeResponse, routeData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(routeData->requestId);
+                                       }
+                                       __free_route_response(routeData);
+
+                                       g_free(routeData);
+                                       routeData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+
+               case RESP_TYPE_PLACES:
+                       {
+                               MapzenPlaceResponseData *placesData = (MapzenPlaceResponseData *) (response->data);
+                               if (placesData != NULL) {
+                                       MAP_DEBUG("Sending places result..");
+                                       if (__is_request_in_cancel_list(placesData->requestId) == false) {
+                                               /* Deliver results to consumer */
+                                               placesData->place_search_cb(placesData->error, placesData->requestId, placesData->places, placesData->user_data);
+                                       } else {
+                                               /* If present in cancel list, dont trigger the response. */
+                                               /* Remove the requestId from cancel list. */
+                                               __remove_from_cancel_list(placesData->requestId);
+                                       }
+                                       __free_place_response(placesData);
+
+                                       g_free(placesData);
+                                       placesData = NULL;
+                               }
+
+                               /* Start the Next valid request */
+                               if (get_num_running_requests() < CURL_MAX_CONNECTS) {
+                                       MAP_DEBUG("Fetching the next request from the request list....");
+                                       mapzen_request_s *req = get_next_request();
+                                       if (req) {
+                                               pthread_mutex_lock(&__requestLock);
+                                               requestList = g_list_remove(requestList, (gpointer)req);
+                                               pthread_mutex_unlock(&__requestLock);
+
+                                               if (req->type == REQ_TYPE_GEOCODE) {
+                                                       mapzen_geocode_req *geocode_req = (mapzen_geocode_req *) req->request;
+                                                       if (geocode_req != NULL) {
+                                                               start_geocode_service(geocode_req->req_details, geocode_req->geocode_cb, geocode_req->requestId, geocode_req->user_data);
+
+                                                               g_free(geocode_req);
+                                                               geocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_REVGEOCODE) {
+                                                       mapzen_revgeocode_req *revgeocode_req = (mapzen_revgeocode_req *) req->request;
+                                                       if (revgeocode_req != NULL) {
+                                                               start_reversegeocode_service(revgeocode_req->req_details, revgeocode_req->revgeocode_cb, revgeocode_req->requestId, revgeocode_req->user_data);
+
+                                                               g_free(revgeocode_req);
+                                                               revgeocode_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_PLACES) {
+                                                       mapzen_search_place_req *places_req = (mapzen_search_place_req *) req->request;
+                                                       if (places_req) {
+                                                               start_places_service(places_req->req_details, places_req->search_place_cb, places_req->requestId, places_req->user_data);
+
+                                                               g_free(places_req);
+                                                               places_req = NULL;
+                                                       }
+                                               } else if (req->type == REQ_TYPE_ROUTE) {
+                                                       mapzen_route_req *route_req = (mapzen_route_req *) req->request;
+                                                       if (route_req) {
+                                                               start_route_service(route_req->req_details, route_req->route_cb, route_req->requestId, route_req->user_data);
+
+                                                               g_free(route_req);
+                                                               route_req = NULL;
+                                                       }
+                                               }
+
+                                               g_free(req);
+                                               req = NULL;
+                                       } else {
+                                               MAP_DEBUG("No request in queue or request type is wrong");
+                                       }
+                               } else {
+                                       MAP_DEBUG("Libcurl request queue is FULL..");
+                               }
+                       }
+                       break;
+
+               default:
+                       MAP_DEBUG("UNKNOWN RESPONSE TYPE");
+                       break;
+               }
+
+               __ResponseQueueLen = g_async_queue_length(responseQueue);
+
+               if (response) {
+                       g_free(response);
+                       response = NULL;
+               }
+       };
+
+       g_async_queue_unref(responseQueue);
+
+       __response_timer_running = false;
+
+       return false;
+}
+
+static void __free_geocode_response(void *ptr)
+{
+       MapzenGeocodeResponseData *geocodeData = (MapzenGeocodeResponseData *) (ptr);
+
+       if (geocodeData) {
+               GList *coords = NULL;
+               coords = g_list_first(geocodeData->coords);
+
+               while (coords) {
+                       coords_s *data = (coords_s *) coords->data;
+
+                       if (data) {
+                               geocodeData->coords = g_list_remove(geocodeData->coords, (gpointer)data);
+
+                               g_free(data);
+                               data = NULL;
+                       }
+                       coords = g_list_first(geocodeData->coords);
+               }
+
+               g_list_free(geocodeData->coords);
+               geocodeData->coords = NULL;
+
+               if (geocodeData->user_data) {
+                       g_free(geocodeData->user_data);
+                       geocodeData->user_data = NULL;
+               }
+       }
+}
+
+static void __free_revgeocode_response(void *ptr)
+{
+       MapzenRevGeocodeResponseData *revGeocodeData = (MapzenRevGeocodeResponseData *) (ptr);
+       if (revGeocodeData) {
+               if (revGeocodeData->addressDetails) {
+                       if (revGeocodeData->addressDetails->street_add) {
+                               g_free(revGeocodeData->addressDetails->street_add);
+                               revGeocodeData->addressDetails->street_add = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->neighbourhood) {
+                               g_free(revGeocodeData->addressDetails->neighbourhood);
+                               revGeocodeData->addressDetails->neighbourhood = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->city) {
+                               g_free(revGeocodeData->addressDetails->city);
+                               revGeocodeData->addressDetails->city = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->county) {
+                               g_free(revGeocodeData->addressDetails->county);
+                               revGeocodeData->addressDetails->county = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->state) {
+                               g_free(revGeocodeData->addressDetails->state);
+                               revGeocodeData->addressDetails->state = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->country) {
+                               g_free(revGeocodeData->addressDetails->country);
+                               revGeocodeData->addressDetails->country = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->country_code) {
+                               g_free(revGeocodeData->addressDetails->country_code);
+                               revGeocodeData->addressDetails->country_code = NULL;
+                       }
+                       if (revGeocodeData->addressDetails->postal_code) {
+                               g_free(revGeocodeData->addressDetails->postal_code);
+                               revGeocodeData->addressDetails->postal_code = NULL;
+                       }
+
+                       g_free(revGeocodeData->addressDetails);
+                       revGeocodeData->addressDetails = NULL;
+               }
+
+               if (revGeocodeData->user_data) {
+                       g_free(revGeocodeData->user_data);
+                       revGeocodeData->user_data = NULL;
+               }
+       }
+}
+
+static void __free_place_response(void *ptr)
+{
+       MapzenPlaceResponseData *placeData = (MapzenPlaceResponseData *) (ptr);
+       if (placeData) {
+               GList *place = NULL;
+               place = g_list_first(placeData->places);
+
+               while (place) {
+                       mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) place->data;
+
+                       if (mapzen_place->address) {
+                                       if (mapzen_place->address->street_add) {
+                                               g_free(mapzen_place->address->street_add);
+                                               mapzen_place->address->street_add = NULL;
+                                       }
+                                       if (mapzen_place->address->neighbourhood) {
+                                               g_free(mapzen_place->address->neighbourhood);
+                                               mapzen_place->address->neighbourhood = NULL;
+                                       }
+                                       if (mapzen_place->address->building_number) {
+                                               g_free(mapzen_place->address->building_number);
+                                               mapzen_place->address->building_number = NULL;
+                                       }
+                                       if (mapzen_place->address->city) {
+                                               g_free(mapzen_place->address->city);
+                                               mapzen_place->address->city = NULL;
+                                       }
+                                       if (mapzen_place->address->county) {
+                                               g_free(mapzen_place->address->county);
+                                               mapzen_place->address->county = NULL;
+                                       }
+                                       if (mapzen_place->address->state) {
+                                               g_free(mapzen_place->address->state);
+                                               mapzen_place->address->state = NULL;
+                                       }
+                                       if (mapzen_place->address->country) {
+                                               g_free(mapzen_place->address->country);
+                                               mapzen_place->address->country = NULL;
+                                       }
+                                       if (mapzen_place->address->country_code) {
+                                               g_free(mapzen_place->address->country_code);
+                                               mapzen_place->address->country_code = NULL;
+                                       }
+                                       if (mapzen_place->address->postal_code) {
+                                               g_free(mapzen_place->address->postal_code);
+                                               mapzen_place->address->postal_code = NULL;
+                                       }
+                               g_free(mapzen_place->address);
+                               mapzen_place->address = NULL;
+                       }
+
+                       if (mapzen_place->category) {
+                               g_free(mapzen_place->category);
+                               mapzen_place->category = NULL;
+                       }
+                       if (mapzen_place->subcategory) {
+                               g_free(mapzen_place->subcategory);
+                               mapzen_place->subcategory = NULL;
+                       }
+                       if (mapzen_place->display_name) {
+                               g_free(mapzen_place->display_name);
+                               mapzen_place->display_name = NULL;
+                       }
+
+                       placeData->places = g_list_remove(placeData->places, (gpointer)mapzen_place);
+
+                       g_free(mapzen_place);
+                       mapzen_place = NULL;
+
+                       place = g_list_first(placeData->places);
+               }
+               g_list_free(placeData->places);
+               placeData->places = NULL;
+
+               if (placeData->user_data) {
+                       g_free(placeData->user_data);
+                       placeData->user_data = NULL;
+               }
+       }
+}
+
+static void __free_route_response(void *ptr)
+{
+       MapzenRouteResponseData *routeData = (MapzenRouteResponseData *) (ptr);
+       if (routeData) {
+                mapzen_route_resp_s *route_info = routeData->routeResponse;
+               if (route_info) {
+                       GList *maneuver_data = NULL;
+                       maneuver_data = g_list_first(route_info->maneuvers);
+                       while (maneuver_data) {
+                               mapzen_route_maneuver *maneuver = (mapzen_route_maneuver *) maneuver_data->data;
+
+                               if (maneuver->instruction) {
+                                       g_free(maneuver->instruction);
+                                       maneuver->instruction = NULL;
+                               }
+                               if (maneuver->formatted_time) {
+                                       g_free(maneuver->formatted_time);
+                                       maneuver->formatted_time = NULL;
+                               }
+                               if (maneuver->direction_name) {
+                                       g_free(maneuver->direction_name);
+                                       maneuver->direction_name = NULL;
+                               }
+                               if (maneuver->street_name) {
+                                       g_free(maneuver->street_name);
+                                       maneuver->street_name = NULL;
+                               }
+
+                               route_info->maneuvers = g_list_remove(route_info->maneuvers, (gpointer)maneuver);
+
+                               g_free(maneuver);
+                               maneuver = NULL;
+
+                               /* Fetching the next item from Maneuver/Segment list */
+                               maneuver_data = g_list_first(route_info->maneuvers);
+                       }
+                       g_list_free(route_info->maneuvers);
+                       route_info->maneuvers = NULL;
+
+                       GList *shapePoints = NULL;
+                       shapePoints = g_list_first(route_info->shapePoints);
+                       while (shapePoints) {
+                               coords_s *data = (coords_s *) shapePoints->data;
+
+                               route_info->shapePoints = g_list_remove(route_info->shapePoints, (gpointer)data);
+
+                               g_free(data);
+                               data = NULL;
+
+                               shapePoints = g_list_first(route_info->shapePoints);
+                       }
+                       g_list_free(route_info->shapePoints);
+                       route_info->shapePoints = NULL;
+
+                       if (route_info->formatted_time) {
+                               g_free(route_info->formatted_time);
+                               route_info->formatted_time = NULL;
+                       }
+                       g_free(route_info);
+                       route_info = NULL;
+               }
+               if (routeData->user_data) {
+                       g_free(routeData->user_data);
+                       routeData->user_data = NULL;
+               }
+       }
+}
+
+int mapzen_init_queue()
+{
+#if !GLIB_CHECK_VERSION(2, 35, 0)
+       g_type_init();          /* Needed for using json in Emulator */
+#endif
+
+       pthread_mutex_init(&__requestLock, NULL);
+
+       /* Queue initialize */
+       responseQueue = g_async_queue_new();
+
+       /* Initialise Curl Service */
+       int ret = init_curl();
+
+       if (ret != MAPZEN_ERROR_NONE)
+               return MAPZEN_ERROR_UNKNOWN;
+
+       pthread_mutex_lock(&__requestLock);
+       requestList = NULL;
+       pthread_mutex_unlock(&__requestLock);
+       reqCancelList = NULL;
+       __ResponseQueueLen = 0;
+       __response_timer_running = false;
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int mapzen_deinit_queue()
+{
+       deinit_curl();
+
+       g_list_free(reqCancelList);
+       reqCancelList = NULL;
+
+       pthread_mutex_destroy(&__requestLock);
+
+       /* Free the queue */
+       if (responseQueue) {
+               g_async_queue_ref(responseQueue);
+               __ResponseQueueLen = g_async_queue_length(responseQueue);
+               MAP_DEBUG("Queue len : %d", __ResponseQueueLen);
+
+               while (__ResponseQueueLen > 0) {
+                       gpointer data = g_async_queue_try_pop(responseQueue);
+                       if (!data) {
+                               __ResponseQueueLen = g_async_queue_length(responseQueue);
+                               continue;
+                       }
+
+                       MapzenQueueData *response = (MapzenQueueData *) data;
+
+                       switch (response->type) {
+                       case RESP_TYPE_GEOCODE:
+                               {
+                                       MapzenGeocodeResponseData *geocodeData = (MapzenGeocodeResponseData *) (response->data);
+                                       if (geocodeData) {
+                                               __free_geocode_response(geocodeData);
+
+                                               g_free(geocodeData);
+                                               geocodeData = NULL;
+                                       }
+                               }
+                               break;
+                       case RESP_TYPE_REVGEOCODE:
+                               {
+                                       MapzenRevGeocodeResponseData *revGeocodeData = (MapzenRevGeocodeResponseData *) (response->data);
+                                       if (revGeocodeData) {
+                                               __free_revgeocode_response(revGeocodeData);
+
+                                               g_free(revGeocodeData);
+                                               revGeocodeData = NULL;
+                                       }
+                               }
+                               break;
+                       case RESP_TYPE_PLACES:
+                               {
+                                       MapzenPlaceResponseData *placeData = (MapzenPlaceResponseData *) (response->data);
+                                       if (placeData != NULL) {
+                                               __free_place_response(placeData);
+
+                                               g_free(placeData);
+                                               placeData = NULL;
+                                       }
+                               }
+                               break;
+                       case RESP_TYPE_ROUTE:
+                               {
+                                       MapzenRouteResponseData *routeData = (MapzenRouteResponseData *) (response->data);
+                                       if (routeData != NULL) {
+                                               __free_route_response(routeData);
+
+                                               g_free(routeData);
+                                               routeData = NULL;
+                                       }
+                               }
+                               break;
+                       default:
+                               break;
+                       }
+
+                       __ResponseQueueLen = g_async_queue_length(responseQueue);
+
+                       if (response) {
+                               g_free(response);
+                               response = NULL;
+                       }
+               }
+               g_async_queue_unref(responseQueue);
+               responseQueue = NULL;
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int mapzen_push_to_queue(mapzen_resp_type type, gpointer data)
+{
+       MAP_DEBUG("Pushing to Queue....");
+
+       MapzenQueueData *queueData = (MapzenQueueData *)g_malloc0(sizeof(MapzenQueueData));
+       if (!queueData) return MAPZEN_ERROR_OUT_OF_MEMORY;
+
+       queueData->type = type;
+       queueData->data = data;
+
+       g_async_queue_ref(responseQueue);
+       g_async_queue_push(responseQueue, (gpointer)queueData);
+       g_async_queue_unref(responseQueue);
+
+       if (!__response_timer_running) {
+               MAP_DEBUG(">>>>>>>>>>>>>>>>>>>>>>> TRIGGER RESPONSE TIMER <<<<<<<<<<<<<<<<<<<<<<<<<");
+               g_timeout_add_seconds(1, __timeout_cb, NULL);   /* timeout : 1 sec */
+       } else {
+               __ResponseQueueLen = g_async_queue_length(responseQueue);
+               MAP_DEBUG(">>>>>>>>>>>>>>>>>> Timer already running. Response Queue Len [%d] <<<<<<<<<<<<<<<<<", __ResponseQueueLen);
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_geocode_service(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data)
+{
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_geocode_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenGeocodeQueryData *queryData = (MapzenGeocodeQueryData *)g_malloc0(sizeof(MapzenGeocodeQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->geocode_cb = callback;
+                       queryData->user_data = user_data;
+
+                       if (req_details->boundary != NULL) {
+                               if (req_details->boundary->type == MAPZEN_BOUNDARY_RECT) {
+                                       MAP_DEBUG("TOP LEFT >>><<< LATITUDE : %f, LONGITUDE : %f", req_details->boundary->rect.top_left.latitude, req_details->boundary->rect.top_left.longitude);
+                                       MAP_DEBUG("BOTTOM RIGHT >>><<< LATITUDE : %f, LONGITUDE : %f", req_details->boundary->rect.bottom_right.latitude, req_details->boundary->rect.bottom_right.longitude);
+
+                                       query_geocode_within_bounds(req_details->maps_key, req_details->address, req_details->boundary->rect.top_left, req_details->boundary->rect.bottom_right, req_details->num_res, queryData);
+
+                               } else if (req_details->boundary->type == MAPZEN_BOUNDARY_CIRCLE) {
+
+                                       coords_s *top_left = NULL, *bottom_right = NULL;
+                                       coords_s circle = req_details->boundary->circle.center;
+                                       gdouble radius = (req_details->boundary->circle.radius) * 0.001;
+
+                                       MAP_DEBUG("User input LATITUDE : %f, LONGITUDE : %f", circle.latitude, circle.longitude);
+
+                                       /* Calculate the top left coordinate of bounding box. */
+                                       calculate_point(circle.latitude, circle.longitude, 315, radius, &top_left);
+
+                                       /* Calculate the bottom right coordinate of bounding box. */
+                                       calculate_point(circle.latitude, circle.longitude, 135, radius, &bottom_right);
+
+                                       if ((top_left != NULL) && (bottom_right != NULL)) {
+                                               MAP_DEBUG("Top Left LATITUDE : %f, LONGITUDE : %f", top_left->latitude, top_left->longitude);
+                                               MAP_DEBUG("Bottom Right LATITUDE : %f, LONGITUDE : %f", bottom_right->latitude, bottom_right->longitude);
+
+                                               query_geocode_within_bounds(req_details->maps_key, req_details->address, *top_left, *bottom_right, req_details->num_res, queryData);
+
+                                               g_free(top_left);
+                                               top_left = NULL;
+
+                                               g_free(bottom_right);
+                                               bottom_right = NULL;
+                                       }
+
+                               } else {
+                                       query_geocode(req_details->maps_key, req_details->address, req_details->num_res, queryData);
+                               }
+
+                       } else {
+                               MAP_DEBUG("BOUNDARY is NULL.. NORMAL GEOCODE QUERY WITHOUT BOUNDS");
+
+                               query_geocode(req_details->maps_key, req_details->address, req_details->num_res, queryData);
+                       }
+               }
+
+               if (req_details) {
+                       if (req_details->address) {
+                               g_free(req_details->address);
+                               req_details->address = NULL;
+                       }
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       if (req_details->boundary) {
+                               g_free(req_details->boundary);
+                               req_details->boundary = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_reversegeocode_service(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data)
+{
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_revgeocode_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenRevGeocodeQueryData *queryData = (MapzenRevGeocodeQueryData *)g_malloc0(sizeof(MapzenRevGeocodeQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->reverse_geocode_cb = callback;
+                       queryData->user_data = user_data;
+
+                       coords_s coords = req_details->coordinates;
+
+                       query_revgeocode(req_details->maps_key, coords.latitude, coords.longitude, queryData);
+               }
+
+               if (req_details) {
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_route_service(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data)
+{
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_route_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenRouteQueryData *queryData = (MapzenRouteQueryData *)g_malloc0(sizeof(MapzenRouteQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->route_cb = callback;
+                       queryData->origin = req_details->from;
+                       queryData->destination = req_details->to;
+                       queryData->unit = req_details->unit;
+                       queryData->user_data = user_data;
+
+                       query_route(req_details->maps_key, req_details->from, req_details->to, req_details->type, req_details->avoids, req_details->driving_style, req_details->way_points, queryData);
+               }
+
+               if (req_details) {
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       if (req_details->way_points) {
+                               if (g_list_length(req_details->way_points) > 0) {
+                                       GList *list = NULL;
+                                       list = g_list_first(req_details->way_points);
+                                       while (list) {
+                                               coords_s *data = (coords_s *)list->data;
+                                               if (data) {
+                                                       req_details->way_points = g_list_remove(req_details->way_points, (gpointer)data);
+
+                                                       g_free(data);
+                                                       data = NULL;
+                                               }
+                                               list = g_list_first(req_details->way_points);
+                                       }
+                               }
+                               g_list_free(req_details->way_points);
+                               req_details->way_points = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
+
+int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data)
+{
+       int num_running_req = get_num_running_requests();
+
+       if (num_running_req >= CURL_MAX_CONNECTS) {
+               /* Add the request to queue */
+               add_to_places_list(req_details, callback, request_id, user_data);
+       } else {
+               MapzenPlaceQueryData *queryData = (MapzenPlaceQueryData *)g_malloc0(sizeof(MapzenPlaceQueryData));
+
+               if (queryData != NULL) {
+                       queryData->requestId = request_id;
+                       queryData->place_search_cb = callback;
+                       queryData->user_data = user_data;
+
+                       query_places(req_details->maps_key, req_details->search_string, req_details->boundary, req_details->num_res, queryData);
+               }
+
+               if (req_details) {
+                       if (req_details->maps_key) {
+                               g_free(req_details->maps_key);
+                               req_details->maps_key = NULL;
+                       }
+                       if (req_details->boundary) {
+                               g_free(req_details->boundary);
+                               req_details->boundary = NULL;
+                       }
+                       if (req_details->search_string) {
+                               g_free(req_details->search_string);
+                               req_details->search_string = NULL;
+                       }
+                       g_free(req_details);
+                       req_details = NULL;
+               }
+       }
+
+       return MAPZEN_ERROR_NONE;
+}
diff --git a/src/mapzen/mapzen_queue.h b/src/mapzen/mapzen_queue.h
new file mode 100644 (file)
index 0000000..3d0d73c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_QUEUE_H_
+#define _MAPZEN_QUEUE_H_
+
+#include <glib.h>
+#include "mapzen_server_private.h"
+
+typedef struct {
+       mapzen_req_type type;
+       void *request;
+} mapzen_request_s;
+
+typedef struct {
+       mapzen_geocode_req_s *req_details;
+       int requestId;
+       mapzen_geocode_cb geocode_cb;
+       void *user_data;
+} mapzen_geocode_req;
+
+typedef struct {
+       mapzen_revgeocode_req_s *req_details;
+       int requestId;
+       mapzen_reverse_geocode_cb revgeocode_cb;
+       void *user_data;
+} mapzen_revgeocode_req;
+
+typedef struct {
+       mapzen_route_req_s *req_details;
+       mapzen_route_cb route_cb;
+       int requestId;
+       void *user_data;
+} mapzen_route_req;
+
+typedef struct {
+       mapzen_search_req_s *req_details;
+       mapzen_place_search_cb search_place_cb;
+       int requestId;
+       void *user_data;
+} mapzen_search_place_req;
+
+int add_to_geocode_list(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data);
+int add_to_revgeocode_list(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data);
+int add_to_route_list(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
+int add_to_places_list(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+
+int remove_from_request_list(int request_id);
+
+int start_geocode_service(mapzen_geocode_req_s *req_details, mapzen_geocode_cb callback, int request_id, void *user_data);
+int start_reversegeocode_service(mapzen_revgeocode_req_s *req_details, mapzen_reverse_geocode_cb callback, int request_id, void *user_data);
+int start_route_service(mapzen_route_req_s *req_details, mapzen_route_cb callback, int request_id, void *user_data);
+int start_places_service(mapzen_search_req_s *req_details, mapzen_place_search_cb callback, int request_id, void *user_data);
+
+int mapzen_init_queue();
+int mapzen_deinit_queue();
+int mapzen_push_to_queue(mapzen_resp_type type, gpointer data);
+
+#endif /* _MAPZEN_QUEUE_H_ */
diff --git a/src/mapzen/mapzen_restcurl.c b/src/mapzen/mapzen_restcurl.c
new file mode 100644 (file)
index 0000000..8d41417
--- /dev/null
@@ -0,0 +1,671 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <curl/curl.h>
+#include <curl/easy.h>
+#include <pthread.h>
+#include <network/net_connection.h>
+#include "mapzen_restcurl.h"
+#include "mapzen_types.h"
+#include "mapzen_jsonparser.h"
+#include "mapzen_debug.h"
+
+#define RESTCURL_USE_MULTI_CURL
+
+CURLM *__cm_handle;
+pthread_t __CurlThread;
+pthread_mutex_t __MultiCurlArgsLock;
+pthread_mutex_t __CmHandleLock;
+static bool __thread_running_for_curlmulti = false;
+static int __MultiCurlArgsRemain = 0;
+pthread_cond_t __curl_delivered_cond;
+pthread_mutex_t __curl_deliver_mutex;
+static char *__proxy_address = NULL;
+GList *__cancel_req_list = NULL;
+
+typedef struct {
+       char *memory;
+       size_t size;
+} MemoryStruct_s;
+
+struct MultiCurlArg {
+       MemoryStruct_s m_chunk;
+       CURL *curl_handle;
+       mapzen_req_type req_type;
+       int request_id;
+       void *user_data;
+       char url[1024];
+};
+
+/****************** LIST for maintaining easy curl related data *******************/
+
+struct MultiCurlArg_List {
+       struct MultiCurlArg *mcArg;
+       struct MultiCurlArg_List *next;
+};
+
+struct MultiCurlArg_List *head = NULL;
+struct MultiCurlArg_List *curr = NULL;
+
+static struct MultiCurlArg_List *__create_list(struct MultiCurlArg *mcArg)
+{
+       MAP_DEBUG("\n creating list with headnode as [%p]\n", mcArg);
+       struct MultiCurlArg_List *ptr = (struct MultiCurlArg_List *)g_malloc0(sizeof(struct MultiCurlArg_List));
+       if (NULL == ptr) {
+               MAP_DEBUG("\n Node creation failed \n");
+               return NULL;
+       }
+       ptr->mcArg = mcArg;
+       ptr->next = NULL;
+
+       head = curr = ptr;
+       return ptr;
+}
+
+static struct MultiCurlArg_List *__add_to_list(struct MultiCurlArg *mcArg, bool add_to_end)
+{
+       if (NULL == head)
+               return (__create_list(mcArg));
+
+       struct MultiCurlArg_List *ptr = (struct MultiCurlArg_List *)g_malloc0(sizeof(struct MultiCurlArg_List));
+       if (NULL == ptr) {
+               MAP_DEBUG("\n Node creation failed \n");
+               return NULL;
+       }
+       ptr->mcArg = mcArg;
+       ptr->next = NULL;
+
+       if (add_to_end) {
+               curr->next = ptr;
+               curr = ptr;
+       } else {
+               ptr->next = head;
+               head = ptr;
+       }
+       return ptr;
+}
+
+static struct MultiCurlArg_List *__search_in_list(CURL * handle, struct MultiCurlArg_List **prev)
+{
+       struct MultiCurlArg_List *ptr = head;
+       struct MultiCurlArg_List *tmp = NULL;
+       bool found = false;
+
+       MAP_DEBUG("\n Searching the list for value\n");
+
+       while (ptr != NULL) {
+               if (ptr->mcArg->curl_handle == handle) {
+                       found = true;
+                       break;
+               } else {
+                       tmp = ptr;
+                       ptr = ptr->next;
+               }
+       }
+
+       if (true == found) {
+               if (prev)
+                       *prev = tmp;
+               return ptr;
+       } else {
+               return NULL;
+       }
+}
+
+static struct MultiCurlArg_List *__delete_from_list(CURL *handle)
+{
+       struct MultiCurlArg_List *prev = NULL;
+       struct MultiCurlArg_List *del = NULL;
+
+       MAP_DEBUG("\n Deleting value handle from list\n");
+
+       del = __search_in_list(handle, &prev);
+       if (del == NULL) {
+               return NULL;
+       } else {
+               if (prev != NULL)
+                       prev->next = del->next;
+
+               if (del == curr) {
+                       curr = prev;
+                       if (prev == NULL)
+                               head = NULL;
+               } else if (del == head) {
+                       head = del->next;
+               }
+       }
+
+       del->next = NULL;
+
+       return del;
+}
+
+/*****************************************/
+
+mapzen_error_e __get_proxy_address()
+{
+       mapzen_error_e err = MAPZEN_ERROR_NONE;
+
+       connection_h con = NULL;
+       int errorCode = CONNECTION_ERROR_NOT_SUPPORTED;
+       char *address = NULL;
+
+       errorCode = connection_create(&con);
+
+       if (errorCode == CONNECTION_ERROR_NONE)
+               errorCode = connection_get_proxy(con, CONNECTION_ADDRESS_FAMILY_IPV4, &address);
+
+       if (errorCode != CONNECTION_ERROR_NONE) {
+               err = MAPZEN_ERROR_UNKNOWN;
+               switch (errorCode) {
+               case CONNECTION_ERROR_INVALID_PARAMETER:
+                       MAP_DEBUG("Invalid parameter");
+                       err = MAPZEN_ERROR_INVALID_PARAMETER;
+                       break;
+               case CONNECTION_ERROR_OUT_OF_MEMORY:
+                       MAP_DEBUG("Out of memory error");
+                       err = MAPZEN_ERROR_OUT_OF_MEMORY;
+                       break;
+               case CONNECTION_ERROR_INVALID_OPERATION:
+                       MAP_DEBUG("Invalid Operation");
+                       err = MAPZEN_ERROR_INVALID_OPERATION;
+                       break;
+               case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+                       MAP_DEBUG("Address family not supported");
+                       err = MAPZEN_ERROR_NOT_SUPPORTED;
+                       break;
+               /*
+               case CONNECTION_ERROR_PERMISSION_DENIED:
+                       MAP_DEBUG("Permission denied");
+                       err = MAPZEN_ERROR_PERMISSION_DENIED;
+                       break;
+               */
+               case CONNECTION_ERROR_OPERATION_FAILED:
+                       MAP_DEBUG("Operation failed");
+                       err = MAPZEN_ERROR_INVALID_OPERATION;
+                       break;
+               case CONNECTION_ERROR_ITERATOR_END:
+                       MAP_DEBUG("End of iteration");
+                       break;
+               case CONNECTION_ERROR_NO_CONNECTION:
+                       MAP_DEBUG("There is no connection");
+                       err = MAPZEN_ERROR_NETWORK_UNREACHABLE;
+                       break;
+               case CONNECTION_ERROR_NOW_IN_PROGRESS:
+                       MAP_DEBUG("Now in progress");
+                       err = MAPZEN_ERROR_RESOURCE_BUSY;
+                       break;
+               case CONNECTION_ERROR_ALREADY_EXISTS:
+                       MAP_DEBUG("Already exists");
+                       break;
+               case CONNECTION_ERROR_OPERATION_ABORTED:
+                       MAP_DEBUG("Operation is aborted");
+                       err = MAPZEN_ERROR_CANCELED;
+                       break;
+               case CONNECTION_ERROR_DHCP_FAILED:
+                       MAP_DEBUG("DHCP failed");
+                       break;
+               case CONNECTION_ERROR_INVALID_KEY:
+                       MAP_DEBUG("Invalid key");
+                       err = MAPZEN_ERROR_KEY_NOT_AVAILABLE;
+                       break;
+               case CONNECTION_ERROR_NO_REPLY:
+                       MAP_DEBUG("No reply");
+                       err = MAPZEN_ERROR_RESOURCE_BUSY;
+                       break;
+               case CONNECTION_ERROR_NOT_SUPPORTED:
+                       MAP_DEBUG("Not Supported");
+                       err = MAPZEN_ERROR_NOT_SUPPORTED;
+                       break;
+               default:
+                       MAP_DEBUG("Unknown");
+                       break;
+               }
+               MAP_DEBUG("errorCode = %ld", (long)errorCode);
+       }
+
+       if (con)
+               connection_destroy(con);
+
+       if (err != MAPZEN_ERROR_NONE)
+               return err;
+
+       if (address) {
+               int len = strlen(address);
+               if (len > 0) {
+                       __proxy_address = (char *)g_malloc0(len+1);
+                       strncpy(__proxy_address, address, len);
+                       __proxy_address[len] = '\0';
+               }
+               g_free(address);
+               address = NULL;
+       }
+
+       MAP_DEBUG("Proxy = %s", (__proxy_address ? __proxy_address : "(null)"));
+
+       return MAPZEN_ERROR_NONE;
+}
+
+static size_t __write_memory_callback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+       size_t realsize = size * nmemb;
+#ifdef RESTCURL_USE_MULTI_CURL
+       MemoryStruct_s *mem = &(((struct MultiCurlArg *) userp)->m_chunk);
+#else
+       MemoryStruct_s *mem = (MemoryStruct_s *) userp;
+#endif
+
+       if (mem->memory == NULL)
+               mem->memory = g_malloc(realsize);
+       else
+               mem->memory = g_realloc(mem->memory, mem->size + realsize);
+
+       if (mem->memory == NULL)
+               return 0;
+
+       memcpy(mem->memory + mem->size, contents, realsize);
+
+       mem->size += realsize;
+
+       MAP_DEBUG("REal size : %d", realsize);
+       MAP_DEBUG("response size :: %d", strlen(mem->memory));
+
+       return realsize;
+}
+
+static int __xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow)
+{
+       struct MultiCurlArg *pMultiCurlArg = (struct MultiCurlArg *) p;
+
+       GList *list = NULL;
+       list = g_list_first(__cancel_req_list);
+       int req_id_to_be_cancelled = -1;
+       bool cancel_request = false;
+
+       while (list) {
+               req_id_to_be_cancelled = (int) GPOINTER_TO_INT(list->data);
+               MAP_DEBUG("Req id in the list waiting to get cancelled [%d]", req_id_to_be_cancelled);
+               if (pMultiCurlArg->request_id == req_id_to_be_cancelled) {
+                       MAP_DEBUG(">>>>>>>>>>>> Req id matched :: To be cancelled [%d]", req_id_to_be_cancelled);
+                       cancel_request = true;
+                       break;
+               }
+               list = list->next;
+       }
+
+       if (cancel_request) {
+               MAP_DEBUG(">>>>>>>> Req Id to be aborted :: [%d] <<<<<<<<<<<<<", req_id_to_be_cancelled);
+               /* Remove the request id from cancel list */
+               __cancel_req_list = g_list_remove(__cancel_req_list, (gpointer) GINT_TO_POINTER(req_id_to_be_cancelled));
+               MAP_DEBUG(">>>>>>>>>> Request removed from cancel list <<<<<<<<");
+               return 1;               /* Returning Non-Zero value will abort the transfer */
+       }
+
+       return 0;
+}
+
+static int __progress_info(void *p, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+       return __xferinfo(p, (curl_off_t)dltotal, (curl_off_t)dlnow, (curl_off_t)ultotal, (curl_off_t)ulnow);
+}
+
+int add_handle(char *url, mapzen_req_type type, void *user_data)
+{
+       if (!url || !user_data) return -1;
+
+       int req_id = -1;
+
+       switch (type) {
+       case REQ_TYPE_GEOCODE:
+               req_id = ((MapzenGeocodeQueryData *) user_data)->requestId;
+               break;
+       case REQ_TYPE_REVGEOCODE:
+               req_id = ((MapzenRevGeocodeQueryData *) user_data)->requestId;
+               break;
+       case REQ_TYPE_PLACES:
+               req_id = ((MapzenPlaceQueryData *) user_data)->requestId;
+               break;
+       case REQ_TYPE_ROUTE:
+               req_id = ((MapzenRouteQueryData *) user_data)->requestId;
+               break;
+       default:
+               break;
+       }
+
+#ifdef RESTCURL_USE_MULTI_CURL
+       MAP_DEBUG("HTTP Req URL [%s]", url);
+       CURL *curl_handle;
+
+       struct MultiCurlArg *pMultiCurlArg = (struct MultiCurlArg *)g_malloc0(sizeof(struct MultiCurlArg));
+
+       if (!pMultiCurlArg) return -1;
+
+       (pMultiCurlArg->m_chunk).memory = (char *) g_malloc0(1);        /* will be grown as needed by the realloc above */
+       (pMultiCurlArg->m_chunk).size = 0;      /* no data at this point */
+
+       /* init the curl session */
+       curl_handle = curl_easy_init();
+
+       /* set URL to get */
+       curl_easy_setopt(curl_handle, CURLOPT_URL, url);
+
+       curl_easy_setopt(curl_handle, CURLOPT_PROGRESSFUNCTION, __progress_info);
+       curl_easy_setopt(curl_handle, CURLOPT_PROGRESSDATA, NULL);
+
+#if LIBCURL_VERSION_NUM >= 0x72000
+       curl_easy_setopt(curl_handle, CURLOPT_XFERINFOFUNCTION, __xferinfo);
+       curl_easy_setopt(curl_handle, CURLOPT_XFERINFODATA, (void *)pMultiCurlArg);
+#endif
+
+       curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 0L);
+
+       curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
+
+       curl_easy_setopt(curl_handle, CURLOPT_PROXY , __proxy_address);
+
+       /* send all data to this function  */
+       curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, __write_memory_callback);
+
+       /* we want the headers to this file handle */
+       curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)pMultiCurlArg);
+
+       /* some servers don't like requests that are made without a user-agent field, so we provide one */
+       curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+
+       pMultiCurlArg->curl_handle = curl_handle;
+       pMultiCurlArg->req_type = type;
+       pMultiCurlArg->request_id = req_id;
+       pMultiCurlArg->user_data = user_data;
+       strncpy(pMultiCurlArg->url, url, sizeof(pMultiCurlArg->url)-1);
+
+       pthread_mutex_lock(&__MultiCurlArgsLock);
+       __MultiCurlArgsRemain++;
+       __add_to_list(pMultiCurlArg, true);
+       pthread_mutex_unlock(&__MultiCurlArgsLock);
+
+       pthread_mutex_lock(&__CmHandleLock);
+       curl_multi_add_handle(__cm_handle, curl_handle);
+       pthread_mutex_unlock(&__CmHandleLock);
+
+       pthread_mutex_lock(&__curl_deliver_mutex);
+       pthread_cond_signal(&__curl_delivered_cond);
+       pthread_mutex_unlock(&__curl_deliver_mutex);
+#endif
+       return 0;
+}
+
+static void __post_curl(mapzen_req_type type, MemoryStruct_s *m_chunk, void *user_data)
+{
+       mapzen_resp_type resp_type = RESP_TYPE_NONE;
+       switch (type) {
+       case REQ_TYPE_GEOCODE:
+               resp_type = RESP_TYPE_GEOCODE;
+               break;
+       case REQ_TYPE_REVGEOCODE:
+               resp_type = RESP_TYPE_REVGEOCODE;
+               break;
+       case REQ_TYPE_PLACES:
+               resp_type = RESP_TYPE_PLACES;
+               break;
+       case REQ_TYPE_ROUTE:
+               resp_type = RESP_TYPE_ROUTE;
+               break;
+       default:
+               resp_type = RESP_TYPE_NONE;
+               break;
+       }
+
+       post_curl_response(m_chunk->memory, m_chunk->size, resp_type, user_data);
+}
+
+static void *__curl_thread_handler(void *user_data)
+{
+       __thread_running_for_curlmulti = true;
+       pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+
+#ifdef RESTCURL_USE_MULTI_CURL
+       CURLMsg *msg;
+       int Q;
+       int still_running = -1;
+
+       while (__thread_running_for_curlmulti || __MultiCurlArgsRemain) {
+               while (__MultiCurlArgsRemain) {
+                       pthread_mutex_lock(&__CmHandleLock);
+                       curl_multi_perform(__cm_handle, &still_running);
+                       pthread_mutex_unlock(&__CmHandleLock);
+
+                       if (still_running != __MultiCurlArgsRemain) {
+                               pthread_mutex_lock(&__CmHandleLock);
+                               msg = curl_multi_info_read(__cm_handle, &Q);
+                               pthread_mutex_unlock(&__CmHandleLock);
+
+                               if (msg == 0)
+                                       break;
+
+                               if (msg->msg == CURLMSG_DONE) {
+                                       MAP_DEBUG("Transfer completed for one handle");
+                                       CURL *e = msg->easy_handle;
+
+                                       pthread_mutex_lock(&__MultiCurlArgsLock);
+                                       struct MultiCurlArg_List *del = NULL;
+                                       if ((del = __delete_from_list(e)) != NULL) {
+                                                       MAP_DEBUG("Decrementing the handle counter in multiCurl..");
+                                                       __MultiCurlArgsRemain--;
+                                       }
+                                       pthread_mutex_unlock(&__MultiCurlArgsLock);
+
+                                       if (del && del->mcArg) {
+                                               MAP_DEBUG("HTTP Url [%s]", del->mcArg->url);
+                                               MAP_DEBUG("Posting the result..");
+                                               __post_curl(del->mcArg->req_type, &(del->mcArg->m_chunk), del->mcArg->user_data);
+
+                                               if ((del->mcArg->m_chunk).memory) {
+                                                       g_free((del->mcArg->m_chunk).memory);
+                                                       (del->mcArg->m_chunk).memory = NULL;
+                                               }
+
+                                               pthread_mutex_lock(&__CmHandleLock);
+                                               curl_multi_remove_handle(__cm_handle, del->mcArg->curl_handle);
+                                               pthread_mutex_unlock(&__CmHandleLock);
+
+                                               curl_easy_cleanup(del->mcArg->curl_handle);
+
+                                               g_free(del->mcArg);
+                                               del->mcArg = NULL;
+
+                                               g_free(del);
+                                               del = NULL;
+                                       }
+                               } else {
+                                       MAP_DEBUG("E: CURLMsg (%d)\n", msg->msg);
+                               }
+                       }
+               }
+
+               if (__thread_running_for_curlmulti && !__MultiCurlArgsRemain) {
+                       pthread_mutex_lock(&__curl_deliver_mutex);
+                       pthread_cond_wait(&__curl_delivered_cond, &__curl_deliver_mutex);
+                       pthread_mutex_unlock(&__curl_deliver_mutex);
+               }
+       }
+
+#else
+       /* curl_easy_perform */
+#endif
+       pthread_exit(NULL);
+
+       return 0;
+}
+
+void cancel_request(int request_id)
+{
+       if (__cancel_req_list == NULL)
+               __cancel_req_list = g_list_append(__cancel_req_list, (gpointer) GINT_TO_POINTER(request_id));
+       else
+               __cancel_req_list = g_list_insert_before(__cancel_req_list, NULL, (gpointer) GINT_TO_POINTER(request_id));
+}
+
+int get_num_running_requests()
+{
+       MAP_DEBUG("Num of running requests :: >>>> [%d]", __MultiCurlArgsRemain);
+       return __MultiCurlArgsRemain;
+}
+
+int init_curl()
+{
+       __cancel_req_list = NULL;
+
+       head = NULL;
+       curr = NULL;
+
+       __get_proxy_address();
+
+#ifdef RESTCURL_USE_MULTI_CURL
+       pthread_mutex_init(&__MultiCurlArgsLock, NULL);
+       pthread_mutex_init(&__CmHandleLock, NULL);
+       pthread_mutex_init(&__curl_deliver_mutex, NULL);
+       pthread_cond_init(&__curl_delivered_cond, NULL);
+
+       curl_global_init(CURL_GLOBAL_ALL);
+
+       __cm_handle = curl_multi_init();
+       curl_multi_setopt(__cm_handle, CURLMOPT_MAXCONNECTS, (long)CURL_MAX_CONNECTS);
+
+       __MultiCurlArgsRemain = 0;
+       int ret = pthread_create(&__CurlThread, NULL, &__curl_thread_handler, NULL);
+       __thread_running_for_curlmulti = true;
+#endif
+
+       return ret;
+}
+
+int deinit_curl()
+{
+#ifdef RESTCURL_USE_MULTI_CURL
+       __thread_running_for_curlmulti = false;
+       __MultiCurlArgsRemain = 0;
+
+       pthread_mutex_lock(&__curl_deliver_mutex);
+       pthread_cond_signal(&__curl_delivered_cond);
+       pthread_mutex_unlock(&__curl_deliver_mutex);
+
+       pthread_cancel(__CurlThread);
+
+       pthread_join(__CurlThread, NULL);
+
+       curl_multi_cleanup(__cm_handle);
+       curl_global_cleanup();
+
+       pthread_mutex_destroy(&__MultiCurlArgsLock);
+       pthread_mutex_destroy(&__CmHandleLock);
+       pthread_cond_destroy(&__curl_delivered_cond);
+       pthread_mutex_destroy(&__curl_deliver_mutex);
+#endif
+
+       if (__proxy_address) {
+               g_free(__proxy_address);
+               __proxy_address = NULL;
+       }
+
+       struct MultiCurlArg_List *temp = head;
+       struct MultiCurlArg_List *next;
+
+       while (temp) {
+               next = temp->next;
+               struct MultiCurlArg *curlArg = temp->mcArg;
+
+               if (curlArg) {
+                       if ((curlArg->m_chunk).memory) {
+                               g_free((curlArg->m_chunk).memory);
+                               (curlArg->m_chunk).memory = NULL;
+                       }
+
+                       if (curlArg->user_data) {
+                               switch (curlArg->req_type) {
+                               case REQ_TYPE_GEOCODE:
+                               {
+                                       MapzenGeocodeQueryData *queryData = (MapzenGeocodeQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
+                               case REQ_TYPE_REVGEOCODE:
+                               {
+                                       MapzenRevGeocodeQueryData *queryData = (MapzenRevGeocodeQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
+                               case REQ_TYPE_PLACES:
+                               {
+                                       MapzenPlaceQueryData *queryData = (MapzenPlaceQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
+                               case REQ_TYPE_ROUTE:
+                               {
+                                       MapzenRouteQueryData *queryData = (MapzenRouteQueryData *)curlArg->user_data;
+                                       if (queryData) {
+                                               if (queryData->user_data) {
+                                                       g_free(queryData->user_data);
+                                                       queryData->user_data = NULL;
+                                               }
+                                               g_free(queryData);
+                                               queryData = NULL;
+                                       }
+                               }
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
+
+                       curl_easy_cleanup(curlArg->curl_handle);
+
+                       g_free(curlArg);
+                       curlArg  = NULL;
+               }
+               g_free(temp);
+
+               temp = next;
+       }
+       head = NULL;
+
+       g_list_free(__cancel_req_list);
+       __cancel_req_list = NULL;
+
+       return 0;
+}
diff --git a/src/mapzen/mapzen_restcurl.h b/src/mapzen/mapzen_restcurl.h
new file mode 100644 (file)
index 0000000..897993d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_RESTCURL_H_
+#define _MAPZEN_RESTCURL_H_
+
+#include "mapzen_server_private.h"
+
+#define CURL_MAX_CONNECTS      30
+
+int init_curl();
+
+int deinit_curl();
+
+int get_num_running_requests();
+
+int add_handle(char *url, mapzen_req_type type, void *user_data);
+
+void cancel_request(int request_id);
+
+#endif /* _MAPZEN_RESTCURL_H_ */
diff --git a/src/mapzen/mapzen_revgeocode.c b/src/mapzen/mapzen_revgeocode.c
new file mode 100644 (file)
index 0000000..ebe173c
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapzen_revgeocode.h"
+#include "mapzen_types.h"
+#include "mapzen_server_private.h"
+#include "mapzen_debug.h"
+#include "mapzen_queue.h"
+#include "mapzen_restcurl.h"
+#include "mapzen_util.h"
+
+#define REVERSE_GEOCODE_URL    "https://search.mapzen.com/v1/reverse?size=1&point.lat=%f&point.lon=%f&api_key=%s"
+
+int query_revgeocode(gchar *maps_key, gdouble latitude, gdouble longitude, gpointer user_data)
+{
+       char url[1024];
+
+       if (maps_key != NULL)
+               snprintf(url, sizeof(url), REVERSE_GEOCODE_URL, latitude, longitude, maps_key);
+       else
+               snprintf(url, sizeof(url), REVERSE_GEOCODE_URL, latitude, longitude, "null");
+
+       add_handle(url, REQ_TYPE_REVGEOCODE, user_data);
+
+       return 0;
+}
diff --git a/src/mapzen/mapzen_revgeocode.h b/src/mapzen/mapzen_revgeocode.h
new file mode 100644 (file)
index 0000000..e61546f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_REVGEOCODE_H_
+#define _MAPZEN_REVGEOCODE_H_
+
+#include "mapzen_api.h"
+#include "mapzen_types.h"
+
+int query_revgeocode(gchar *maps_key, gdouble latitude, gdouble longitude, gpointer user_data);
+
+#endif /* _MAPZEN_REVGEOCODE_H_ */
diff --git a/src/mapzen/mapzen_route.c b/src/mapzen/mapzen_route.c
new file mode 100644 (file)
index 0000000..b1d24ef
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include <pthread.h>
+#include "mapzen_route.h"
+#include "mapzen_types.h"
+#include "mapzen_server_private.h"
+#include "mapzen_debug.h"
+#include "mapzen_queue.h"
+#include "mapzen_restcurl.h"
+#include "mapzen_util.h"
+
+#define ROUTE_URL       "https://valhalla.mapzen.com/route?api_key=%s&json="
+
+int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, costing costing, feature_penalties avoids, route_driving_style style, GList *waypoints, gpointer user_data)
+{
+       char url[1024] = "";
+       char tmpStr[512];
+
+       if (maps_key != NULL)
+               snprintf(tmpStr, sizeof(tmpStr), ROUTE_URL, maps_key);
+       else
+               snprintf(tmpStr, sizeof(tmpStr), ROUTE_URL, "null");
+
+       STRCPY(url, tmpStr);
+
+       STRCAT(url, '"directions_options":{"units":"mi"}');     /* Keeping default as miles and conversion will be done later */
+
+       if (costing == COSTING_AUTO)
+               STRCAT(url, '"costing":"auto"');
+       else if (costing == COSTING_AUTO_SHORTER)
+               STRCAT(url, '"costing":"auto_shorter"');
+       else if (costing == COSTING_PEDESTRIAN)
+               STRCAT(url, '"costing":"pedestrian"');
+       else if (costing == COSTING_MULTIMODAL)
+               STRCAT(url, '"costing":"multimodal"');
+       else if (costing == COSTING_BICYCLE)
+               STRCAT(url, '"costing":"bicycle"');
+
+       if (avoids) {
+               STRCAT(url, '"costing_options":{' + costing + ':{');
+
+               if (avoids == PENALTY_LIMITED_ACCESS) {
+                       snprintf(tmpStr, sizeof(tmpStr), "");
+                       STRCAT(url, "");
+               }
+               else if (avoids == PENALTY_TOLL_ROADS) {
+                       snprintf(tmpStr, sizeof(tmpStr), ',"toll_booth_penalty":"1"');
+                       STRCAT(url, tmpStr);
+               }
+               else if (avoids == PENALTY_USE_FERRY){
+                       snprintf(tmpStr, sizeof(tmpStr), ',"use_ferry":"0"');
+                       STRCAT(url, tmpStr);
+               }
+               else if (avoids == PENALTY_USE_UNPAVED) {
+                       snprintf(tmpStr, sizeof(tmpStr), "");
+                       STRCAT(url, tmpStr);
+               }
+               else if (avoids == PENALTY_SEASONAL_CLOSURE) {
+                       snprintf(tmpStr, sizeof(tmpStr), "");
+                       STRCAT(url, tmpStr);
+               }
+               else if (avoids == PENALTY_COUNTRY_CROSSING) {
+                       snprintf(tmpStr, sizeof(tmpStr), ',"country_crossing_penalty":"1"');
+                       STRCAT(url, tmpStr);
+               }
+           STRCAT(url, '}}');
+       }
+
+       if (style == DRIVING_STYLE_NORMAL)
+               STRCAT(url, "");
+       else if (style == DRIVING_STYLE_CAUTIOUS)
+               STRCAT(url, "");
+       else if (style == DRIVING_STYLE_AGGRESSIVE)
+               STRCAT(url, "");
+
+       int length = g_list_length(waypoints);
+       if (length != 0) {
+               int index = 0;
+               GList *waypoints_list = NULL;
+               waypoints_list = g_list_first(waypoints);
+
+               while (waypoints_list) {
+
+                       coords_s *data = (coords_s *) waypoints_list->data;
+
+                       STRCAT(url, '"locations":[{"');
+
+                       for (i = 0; i < sizeof(data); i++) {
+                snprintf(tmpStr, sizeof(tmpStr), '"lat":%f,"lon":%f},', data[i].latitude, data[i].longitude);
+                               STRCAT(url, tmpStr);
+                       }
+                       STRCAT(url, ']');
+
+                       waypoints_list = g_list_next(waypoints_list);
+                       index++;
+               }
+       } else {
+               snprintf(tmpStr, sizeof(tmpStr), '"locations":[{"lat":%f,"lon":%f},{"lat":%f,"lon":%f}]', startPoint.latitude, startPoint.longitude, endPoint.latitude, endPoint.longitude);
+               STRCAT(url, tmpStr);
+       }
+
+       //TODO:  url encode (curl_escape) the json part of the request
+
+       add_handle(url, REQ_TYPE_ROUTE, user_data);
+
+       return 0;
+}
diff --git a/src/mapzen/mapzen_route.h b/src/mapzen/mapzen_route.h
new file mode 100644 (file)
index 0000000..810e0b2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_ROUTE_H_
+#define _MAPZEN_ROUTE_H_
+
+#include "mapzen_api.h"
+#include "mapzen_types.h"
+
+int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, costing costing, feature_penalties avoids, route_driving_style style, GList *waypoints, gpointer user_data);
+
+#endif /* _MAPZEN_ROUTE_H_ */
diff --git a/src/mapzen/mapzen_server_private.h b/src/mapzen/mapzen_server_private.h
new file mode 100644 (file)
index 0000000..c688b8e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_PRIVATE_H_
+#define _MAPZEN_PRIVATE_H_
+
+#include "mapzen_api.h"
+
+typedef enum {
+       REQ_TYPE_GEOCODE = 0,
+       REQ_TYPE_REVGEOCODE,
+       REQ_TYPE_PLACES,
+       REQ_TYPE_ROUTE,
+       REQ_TYPE_NONE
+} mapzen_req_type;
+
+typedef enum {
+       RESP_TYPE_GEOCODE = 0,
+       RESP_TYPE_REVGEOCODE,
+       RESP_TYPE_PLACES,
+       RESP_TYPE_ROUTE,
+       RESP_TYPE_NONE
+} mapzen_resp_type;
+
+typedef struct {
+       int requestId;
+       mapzen_geocode_cb geocode_cb;
+       void *user_data;
+} MapzenGeocodeQueryData;
+
+typedef struct {
+       int requestId;
+       mapzen_reverse_geocode_cb reverse_geocode_cb;
+       void *user_data;
+} MapzenRevGeocodeQueryData;
+
+typedef struct {
+       int requestId;
+       mapzen_route_cb route_cb;
+       coords_s origin;
+       coords_s destination;
+       route_unit unit;
+       void *user_data;
+} MapzenRouteQueryData;
+
+typedef struct {
+       int requestId;
+       mapzen_place_search_cb place_search_cb;
+       void *user_data;
+} MapzenPlaceQueryData;
+
+typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_geocode_cb geocode_cb;
+       GList *coords;
+       void *user_data;
+} MapzenGeocodeResponseData;
+
+typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_reverse_geocode_cb reverse_geocode_cb;
+       mapzen_address_resp_s *addressDetails;
+       void *user_data;
+} MapzenRevGeocodeResponseData;
+
+typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_route_cb route_cb;
+       mapzen_route_resp_s *routeResponse;
+       void *user_data;
+} MapzenRouteResponseData;
+
+typedef struct {
+       mapzen_error_e error;
+       int requestId;
+       mapzen_place_search_cb place_search_cb;
+       GList *places;
+       void *user_data;
+} MapzenPlaceResponseData;
+
+typedef struct {
+       mapzen_resp_type type;
+       void *data;
+} MapzenQueueData;
+
+#endif /* _MAPZEN_PRIVATE_H_ */
diff --git a/src/mapzen/mapzen_types.h b/src/mapzen/mapzen_types.h
new file mode 100644 (file)
index 0000000..356bf52
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_TYPES_H_
+#define _MAPZEN_TYPES_H_
+
+#include <glib.h>
+
+typedef enum {
+       MAPZEN_ERROR_NONE = 0,                /**< Successful */
+        MAPZEN_ERROR_PERMISSION_DENIED,       /**< Permission Denied */
+        MAPZEN_ERROR_OUT_OF_MEMORY,           /**< Out of memory */
+        MAPZEN_ERROR_INVALID_PARAMETER,       /**< Invalid parameter */
+        MAPZEN_ERROR_NOT_SUPPORTED,           /**< Not supported */
+        MAPZEN_ERROR_CONNECTION_TIMED_OUT,    /**< Timeout error, no answer */
+        MAPZEN_ERROR_NETWORK_UNREACHABLE,     /**< Network unavailable */
+        MAPZEN_ERROR_INVALID_OPERATION,       /**< Opeartion is not valid */
+        MAPZEN_ERROR_KEY_NOT_AVAILABLE,       /**< Invalid key */
+        MAPZEN_ERROR_RESOURCE_BUSY,           /**< Resource busy */
+        MAPZEN_ERROR_CANCELED,                /**< Service canceled */
+        MAPZEN_ERROR_UNKNOWN,                 /**< Unknown error */
+        MAPZEN_ERROR_SERVICE_NOT_AVAILABLE,   /**< Service unavailabe*/
+        MAPZEN_ERROR_NOT_FOUND,               /**< Result not found */
+} mapzen_error_e;
+
+typedef enum {
+       MAPZEN_BOUNDARY_NONE = 0,       /*  Undefined geographical area type. */
+       MAPZEN_BOUNDARY_RECT,           /*  Rectangular geographical area type. */
+       MAPZEN_BOUNDARY_CIRCLE, /*  Circle geographical area type. */
+} boundary_type;
+
+typedef enum {
+       COSTING_AUTO = 0,
+       COSTING_AUTO_SHORTER,
+       COSTING_BICYCLE,
+       COSTING_MULTIMODAL,
+       COSTING_PEDESTRIAN
+} route_type;
+
+typedef enum {
+       UNIT_M = 0,     /* for miles */
+       UNIT_KM /* for kilometers */
+} route_unit;
+
+typedef enum {
+       PENALTY_NONE = 0, //TODO: Mapzen does not have currently
+       PENALTY_LIMITED_ACCESS, //TODO: Mapzen does not have currently
+       PENALTY_TOLL_ROADS, //set to > 0 to avoid
+       PENALTY_USE_FERRY, //This is range of values between 0 and 1. Values near 0 attempt to avoid ferries and
+                                //values near 1 will favor ferries.
+       PENALTY_USE_UNPAVED, //TODO: Mapzen does not have currently
+       PENALTY_SEASONAL_CLOSURE, //TODO: Mapzen does not have currently
+       PENALTY_COUNTRY_CROSSING // set to > 0 to avoid
+} route_feature_avoids;
+
+typedef enum {
+       DRIVING_STYLE_NORMAL = 0,
+       DRIVING_STYLE_CAUTIOUS,
+       DRIVING_STYLE_AGGRESSIVE
+} route_driving_style;
+
+typedef struct {
+       gdouble latitude;
+       gdouble longitude;
+} coords_s;
+
+typedef struct {
+       coords_s top_left;
+       coords_s bottom_right;
+} rectangle_s;
+
+typedef struct {
+       coords_s center;
+       gdouble radius;
+} circle_s;
+
+typedef struct {
+       boundary_type type;
+       union {
+               rectangle_s rect;
+               circle_s circle;
+       };
+} mapzen_boundary_s;
+
+typedef struct {
+       gchar *maps_key;
+       gchar *address;
+       mapzen_boundary_s *boundary;
+       gint num_res;
+} mapzen_geocode_req_s;
+
+typedef struct {
+       gchar *maps_key;
+       gint num_res;
+       coords_s coordinates;
+} mapzen_revgeocode_req_s;
+
+typedef struct {
+       gchar *maps_key;
+       gchar *search_string;
+       gint num_res;
+       gchar *country_code;
+       mapzen_boundary_s *boundary;
+       GList *excludes;
+} mapzen_search_req_s;
+
+typedef struct {
+       gchar *maps_key;
+       coords_s from;
+       coords_s to;
+       route_unit unit;
+       route_type type;
+       route_feature_avoids avoids;            /* List of type strings. (Limited Access, Toll Road, Ferry, Unpaved, Seasonal Closure, Country Crossing) */
+       route_driving_style driving_style;      /* (1 - cautious, 2 - normal, 3 - aggressive) */
+       GList *way_points;                              /* List of type coords_s */
+} mapzen_route_req_s;
+
+typedef struct {
+       gint zoom_level;
+       coords_s center_coords;
+} mapzen_tiledata_req_s;
+
+typedef struct {
+       gchar *street_add;
+       gchar *neighbourhood;
+       gchar *building_number;
+       gchar *city;
+       gchar *county;
+       gchar *state;
+       gchar *country;
+       gchar *country_code;
+       gchar *postal_code;
+} mapzen_address_resp_s;
+
+typedef struct {
+       gchar *place_id;
+       gchar *display_name;
+       mapzen_address_resp_s *address;
+       rectangle_s bounding_box;
+       coords_s coordinates;
+       gchar *category;
+       gchar *subcategory;
+       gchar *icon_url;
+} mapzen_place_resp_s;
+
+typedef struct {
+       guint type;
+       guint direction;
+       guint text;
+       gchar *icon_url;
+} mapzen_route_maneuver_signs;
+
+typedef struct {
+       coords_s start_point;
+       coords_s end_point;
+       gdouble distance;
+       guint time;
+       gchar *formatted_time;
+       guint attribute;
+       guint turn_type;
+       guint direction;
+       gchar *instruction;
+       gchar *direction_name;
+       guint index;
+       gchar *street_name;
+} mapzen_route_maneuver;
+
+typedef struct {
+       rectangle_s bounding_box;
+       gdouble distance;
+       route_unit distance_unit;
+       guint time;
+       gchar *formatted_time;
+       route_type type;
+       GList *maneuvers;               /* List of type mapzen_route_maneuver */
+       GList *shapePoints;
+} mapzen_route_resp_s;
+
+#endif /* _MAPZEN_TYPES_H_ */
diff --git a/src/mapzen/mapzen_util.c b/src/mapzen/mapzen_util.c
new file mode 100644 (file)
index 0000000..593e32f
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mapzen_util.h"
+#include "mapzen_debug.h"
+#include <math.h>
+
+#define PI 3.14159265359
+#define EARTH_RADIUS   6371
+
+void calculate_point(gdouble Lat1, gdouble Lon1, int dBearing, gdouble dist, coords_s **coord)
+{
+       Lat1 = (Lat1 / 180.0) * PI;
+       Lon1 = (Lon1 / 180.0) * PI;
+
+       gdouble dLat = asin(sin(Lat1) * cos(dist / EARTH_RADIUS) + (cos(Lat1) * sin(dist / EARTH_RADIUS) * cos(dBearing)));
+
+       dLat = (180.0 * dLat) / PI;
+
+       gdouble dLon = Lon1 + atan2(sin(dBearing) * sin(dist / EARTH_RADIUS) * cos(Lat1), cos(dist / EARTH_RADIUS) - sin(Lat1) * sin((dLat / 180.0) * PI));
+
+       dLon = (180.0 * dLon) / PI;
+
+       if (*coord == NULL)
+               *coord = (coords_s *)g_malloc0(sizeof(coords_s));
+
+       if (*coord) {
+               (*coord)->latitude = dLat;
+               (*coord)->longitude = dLon;
+       }
+}
+
diff --git a/src/mapzen/mapzen_util.h b/src/mapzen/mapzen_util.h
new file mode 100644 (file)
index 0000000..36a6ca0
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _MAPZEN_UTIL_H_
+#define _MAPZEN_UTIL_H_
+
+#include "mapzen_types.h"
+
+#define STRCPY(buffer, string) strncpy(buffer, string, sizeof(buffer)-strlen(buffer)-1)
+#define STRCAT(buffer, string) strncat(buffer, string, sizeof(buffer)-strlen(buffer)-1)
+
+void calculate_point(gdouble Lat1, gdouble Lon1, int dBearing, gdouble dist, coords_s **coord);
+
+#endif /* _MAPZEN_UTIL_H_ */
diff --git a/src/mapzen_api.cpp b/src/mapzen_api.cpp
new file mode 100644 (file)
index 0000000..4455f96
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mapzen_api.h"
+#include "mapzen_constants.h"
+#include "mapzen_utils.h"
+
+int MapzenPluginRoute(maps_coordinates_h origin, maps_coordinates_h destination,
+       maps_item_hashtable_h pref, maps_service_search_route_cb callback_func,
+       void* user_data, int* request_id)
+{
+       // Make sure pointers are valid
+       if (!origin || !destination || !callback_func || !request_id)
+               return ErrorType::kInvalidParameter;
+
+       // Check if origin and destination coordinates are valid
+       if (!MapzenUtils::IsValid(*(maps_coordinates_s*)origin) ||
+           !MapzenUtils::IsValid(*(maps_coordinates_s*)destination))
+               return ErrorType::kInvalidParameter;
+
+       int error = 0;
+       return error;
+}
diff --git a/src/mapzen_plugin.c b/src/mapzen_plugin.c
new file mode 100644 (file)
index 0000000..c00bf8b
--- /dev/null
@@ -0,0 +1,1395 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "mapzen_plugin.h"
+#include "mapzen_plugin_internal.h"
+#include "mapzen_api.h"
+#include "mapzen_util.h"
+#include <maps_error.h>
+#include <maps_route_plugin.h>
+#include <maps_route_segment_plugin.h>
+#include <maps_route_maneuver_plugin.h>
+#include <maps_place_plugin.h>
+#include <maps_place_category.h>
+#include <maps_place_image_plugin.h>
+#include <maps_place_rating_plugin.h>
+
+#define DEFAULT_NUM_RESULTS    10
+#define _PROVIDER_KEY_MAX_SIZE 1024
+
+static const double LATITUDE_RANGE = 85.05113;
+static const double LONGITUDE_RANGE = 180.0;
+
+static int __request_id = 0;
+static maps_plugin_h __plugin = NULL;
+static char __provider_key[_PROVIDER_KEY_MAX_SIZE] = { 0 };
+
+static maps_item_hashtable_h preference_plugin = NULL;
+
+int __maps_service_instance_count = 0;
+
+static int __convert_to_maps_error(int ret)
+{
+       switch (ret) {
+       case MAPZEN_ERROR_NONE:
+               return MAPS_ERROR_NONE;
+       case MAPZEN_ERROR_PERMISSION_DENIED:
+               return MAPS_ERROR_PERMISSION_DENIED;
+       case MAPZEN_ERROR_OUT_OF_MEMORY:
+               return MAPS_ERROR_OUT_OF_MEMORY;
+       case MAPZEN_ERROR_INVALID_PARAMETER:
+               return MAPS_ERROR_INVALID_PARAMETER;
+       case MAPZEN_ERROR_NOT_SUPPORTED:
+               return MAPS_ERROR_NOT_SUPPORTED;
+       case MAPZEN_ERROR_CONNECTION_TIMED_OUT:
+               return MAPS_ERROR_CONNECTION_TIME_OUT;
+       case MAPZEN_ERROR_NETWORK_UNREACHABLE:
+               return MAPS_ERROR_NETWORK_UNREACHABLE;
+       case MAPZEN_ERROR_INVALID_OPERATION:
+               return MAPS_ERROR_INVALID_OPERATION;
+       case MAPZEN_ERROR_KEY_NOT_AVAILABLE:
+               return MAPS_ERROR_KEY_NOT_AVAILABLE;
+       case MAPZEN_ERROR_RESOURCE_BUSY:
+               return MAPS_ERROR_RESOURCE_BUSY;
+       case MAPZEN_ERROR_CANCELED:
+               return MAPS_ERROR_CANCELED;
+       case MAPZEN_ERROR_UNKNOWN:
+               return MAPS_ERROR_UNKNOWN;
+       case MAPZEN_ERROR_SERVICE_NOT_AVAILABLE:
+               return MAPS_ERROR_SERVICE_NOT_AVAILABLE;
+       case MAPZEN_ERROR_NOT_FOUND:
+               return MAPS_ERROR_NOT_FOUND;
+       default:
+               return MAPS_ERROR_UNKNOWN;
+       }
+}
+/*
+static maps_route_turn_type_e __convert_route_turn_type(int index)
+{
+       maps_route_turn_type_e type = MAPS_ROUTE_TURN_TYPE_NONE;
+
+       if (index == 0)
+               type = MAPS_ROUTE_TURN_TYPE_STRAIGHT;
+       else if (index == 1)
+               type = MAPS_ROUTE_TURN_TYPE_LIGHT_RIGHT;
+       else if (index == 2)
+               type = MAPS_ROUTE_TURN_TYPE_RIGHT;
+       else if (index == 3)
+               type = MAPS_ROUTE_TURN_TYPE_HARD_RIGHT;
+       else if (index == 5)
+               type = MAPS_ROUTE_TURN_TYPE_HARD_LEFT;
+       else if (index == 6)
+               type = MAPS_ROUTE_TURN_TYPE_LIGHT_LEFT;
+       else if (index == 7)
+               type = MAPS_ROUTE_TURN_TYPE_LIGHT_LEFT;
+       else if (index == 8)
+               type = MAPS_ROUTE_TURN_TYPE_UTURN_RIGHT;
+       else if (index == 9)
+               type = MAPS_ROUTE_TURN_TYPE_UTURN_LEFT;
+       else if (index == 16)
+               type = MAPS_ROUTE_TURN_TYPE_RIGHT_FORK;
+       else if (index == 17)
+               type = MAPS_ROUTE_TURN_TYPE_LEFT_FORK;
+       else if (index == 18)
+               type = MAPS_ROUTE_TURN_TYPE_STRAIGHT_FORK;
+       else
+               type = MAPS_ROUTE_TURN_TYPE_NONE;
+
+       return type;
+}*/
+
+static bool __replace_space(char *place_name, char **modified_place_name)
+{
+       if (!place_name) return false;
+
+       int new_str_len = 0;
+       char *ch;
+       for (ch = place_name; *ch != '\0'; ch++) {
+               if (*ch == ' ')
+                       new_str_len += 2;
+               new_str_len++;
+       }
+
+       if (strlen(place_name) < new_str_len) {
+               *modified_place_name = (char *)g_malloc((new_str_len + 1) * sizeof(char));
+               if (*modified_place_name) {
+                       char *ch1, *ch2;
+                       for (ch1 = place_name, ch2 = *modified_place_name; *ch1 != '\0'; ch1++) {
+                               if (*ch1 == ' ') {
+                                       ch2[0] = '%';
+                                       ch2[1] = '2';
+                                       ch2[2] = '0';
+                                       ch2 += 3;
+                               } else {
+                                       *ch2 = *ch1;
+                                       ch2++;
+                               }
+                       }
+                       *ch2 = '\0';
+
+                       return true;
+               }
+       }
+       return false;
+}
+
+EXPORT_API int maps_plugin_init(maps_plugin_h *plugin)
+{
+       if (!plugin)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       int ret = MAPS_ERROR_NONE;
+       if (!__plugin) {
+               ret = mapzen_init();
+       }
+
+       if (ret == MAPS_ERROR_NONE) {
+               __maps_service_instance_count++;
+               __plugin = plugin;
+       }
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_shutdown(maps_plugin_h plugin)
+{
+       MAPS_LOGD("PLUGIN SHUTDOWN");
+       if (!plugin)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       __maps_service_instance_count--;
+
+       int ret = MAPS_ERROR_NONE;
+       if (__maps_service_instance_count == 0) {
+               ret = mapzen_shutdown();
+               __plugin = NULL;
+       }
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *supported)
+{
+       if (!supported)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       switch (service) {
+       case MAPS_SERVICE_GEOCODE:
+       case MAPS_SERVICE_GEOCODE_INSIDE_AREA:
+       case MAPS_SERVICE_GEOCODE_BY_STRUCTURED_ADDRESS:
+       case MAPS_SERVICE_REVERSE_GEOCODE:
+       case MAPS_SERVICE_SEARCH_PLACE:
+       case MAPS_SERVICE_SEARCH_PLACE_BY_AREA:
+       case MAPS_SERVICE_SEARCH_PLACE_BY_ADDRESS:
+       case MAPS_SERVICE_SEARCH_ROUTE:
+       case MAPS_SERVICE_SEARCH_ROUTE_WAYPOINTS:
+       case MAPS_SERVICE_CANCEL_REQUEST:
+               *supported = true;
+               return MAPS_ERROR_NONE;
+       default:
+               *supported = false;
+               return MAPS_ERROR_NOT_SUPPORTED;
+       }
+}
+
+EXPORT_API int maps_plugin_is_data_supported(maps_service_data_e data, bool *supported)
+{
+       if (!supported)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       switch (data) {
+       case MAPS_PLACE_ADDRESS:
+       case MAPS_PLACE_CATEGORIES:
+       case MAPS_PLACE_IMAGE:
+               /* unsupported */
+               /* case MAPS_PLACE_RATING: */
+               /* case MAPS_PLACE_ATTRIBUTES: */
+               /* case MAPS_PLACE_CONTACTS: */
+               /* case MAPS_PLACE_EDITORIALS: */
+               /* case MAPS_PLACE_REVIEWS: */
+               /* case MAPS_PLACE_SUPPLIER: */
+               /* case MAPS_PLACE_RELATED: */
+
+       case MAPS_ROUTE_PATH:
+       case MAPS_ROUTE_SEGMENTS_PATH:
+       case MAPS_ROUTE_SEGMENTS_MANEUVERS:
+               *supported = true;
+               return MAPS_ERROR_NONE;
+       default:
+               *supported = false;
+               return MAPS_ERROR_NOT_SUPPORTED;
+       }
+}
+
+EXPORT_API int maps_plugin_get_info(maps_plugin_info_h *info)
+{
+       if (!info)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       maps_plugin_info_create(info);
+       maps_plugin_info_set_provider_name(*info, "MAPZEN");
+
+       return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_set_provider_key(const char *provider_key)
+{
+       if (!provider_key)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       g_snprintf(__provider_key, _PROVIDER_KEY_MAX_SIZE, "%s", provider_key);
+
+       return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_get_provider_key(char **provider_key)
+{
+       if (!provider_key)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       *provider_key = g_strndup(__provider_key, _PROVIDER_KEY_MAX_SIZE);
+
+       return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_set_preference(maps_item_hashtable_h preference)
+{
+       if (!preference)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       maps_item_hashtable_clone(preference, &preference_plugin);
+       return MAPS_ERROR_NONE;
+}
+
+EXPORT_API int maps_plugin_get_preference(maps_item_hashtable_h *preference)
+{
+       if (!preference)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       maps_item_hashtable_clone(preference_plugin, preference);
+       return MAPS_ERROR_NONE;
+}
+
+static void __mapzen_geocode_cb(mapzen_error_e result, int request_id, GList *co_ordinates, void *user_data)
+{
+       MAPS_LOGD("Got GEOCODE callback from ENGINE");
+
+       callback_info_geocode *calldata_geocode = (callback_info_geocode *) user_data;
+
+       if ((result != MAPZEN_ERROR_NONE) || (co_ordinates == NULL)) {
+               MAPS_LOGD(">>>>> Invalid GEOCODE result <<<<<");
+               calldata_geocode->callback((maps_error_e)__convert_to_maps_error(result), calldata_geocode->reqID, 0, 0, NULL, calldata_geocode->data);
+       } else {
+               int total_count = (int) g_list_length(co_ordinates);
+               int index = 0;
+
+               GList *coords = NULL;
+               coords = g_list_first(co_ordinates);
+
+               while (coords) {
+                       MAPS_LOGD("coordinate %d", index);
+                       coords_s *data = (coords_s *) coords->data;
+
+                       if (data != NULL) {
+                               maps_coordinates_h resultCoords;
+                               maps_coordinates_create(data->latitude, data->longitude, &resultCoords);
+                               bool b = calldata_geocode->callback(MAPS_ERROR_NONE, calldata_geocode->reqID, index, total_count, resultCoords, calldata_geocode->data);
+                               if (!b)
+                                       return;
+                       }
+                       index++;
+                       coords = coords->next;
+               }
+       }
+}
+
+EXPORT_API int maps_plugin_geocode(const char *address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+       if (!address || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+       if (calldata_geocode == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_geocode->callback = callback;
+       calldata_geocode->data = user_data;
+
+       mapzen_geocode_req_s *geocode_req = (mapzen_geocode_req_s *)g_malloc0(sizeof(mapzen_geocode_req_s));
+       if (geocode_req == NULL) {
+               g_free(calldata_geocode);
+               calldata_geocode = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       char *modified_address = NULL;
+       bool b_isAddress_modified = false;
+       b_isAddress_modified = __replace_space((char *)address, &modified_address);
+
+       if (b_isAddress_modified)
+               geocode_req->address = g_strdup((gchar *) modified_address);
+       else
+               geocode_req->address = g_strdup((gchar *) address);
+
+       if (modified_address) {
+               g_free(modified_address);
+               modified_address = NULL;
+       }
+
+       geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+       geocode_req->boundary = NULL;
+
+       int max_result = 0;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result <= 0)
+               geocode_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               geocode_req->num_res = max_result;
+
+       *request_id = ++__request_id;
+       calldata_geocode->reqID = __request_id;
+
+       int ret = mapzen_geocode(geocode_req, __mapzen_geocode_cb, __request_id, (void *) calldata_geocode);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_geocode_inside_area(const char *address, const maps_area_h bounds, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+       if (!bounds || !address || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+       if (calldata_geocode == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_geocode->callback = callback;
+       calldata_geocode->data = user_data;
+
+       mapzen_geocode_req_s *geocode_req = (mapzen_geocode_req_s *)g_malloc0(sizeof(mapzen_geocode_req_s));
+       if (geocode_req == NULL) {
+               free(calldata_geocode);
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       char *modified_address = NULL;
+       bool b_isAddress_modified = false;
+       b_isAddress_modified = __replace_space((char *)address, &modified_address);
+
+       if (b_isAddress_modified)
+               geocode_req->address = g_strdup((gchar *) modified_address);
+       else
+               geocode_req->address = g_strdup((gchar *) address);
+
+       if (modified_address) {
+               g_free(modified_address);
+               modified_address = NULL;
+       }
+
+       geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       int max_result = 0;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result <= 0)
+               geocode_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               geocode_req->num_res = max_result;
+
+       geocode_req->boundary = NULL;
+       geocode_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
+
+       maps_area_s *area = (maps_area_s *) bounds;
+
+       if (area && geocode_req->boundary) {
+               if (area->type == MAPS_AREA_RECTANGLE) {
+                       geocode_req->boundary->type = MAPZEN_BOUNDARY_RECT;
+                       geocode_req->boundary->rect.top_left.latitude = area->rect.top_left.latitude;
+                       geocode_req->boundary->rect.top_left.longitude = area->rect.top_left.longitude;
+                       geocode_req->boundary->rect.bottom_right.latitude = area->rect.bottom_right.latitude;
+                       geocode_req->boundary->rect.bottom_right.longitude = area->rect.bottom_right.longitude;
+               } else if (area->type == MAPS_AREA_CIRCLE) {
+                       geocode_req->boundary->type = MAPZEN_BOUNDARY_CIRCLE;
+                       geocode_req->boundary->circle.center.latitude = area->circle.center.latitude;
+                       geocode_req->boundary->circle.center.longitude = area->circle.center.longitude;
+                       geocode_req->boundary->circle.radius = area->circle.radius;
+               }
+       }
+
+       *request_id = ++__request_id;
+       calldata_geocode->reqID = __request_id;
+
+       int ret = mapzen_geocode(geocode_req, __mapzen_geocode_cb, __request_id, (void *) calldata_geocode);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_geocode_by_structured_address(const maps_address_h address, const maps_preference_h preference, maps_service_geocode_cb callback, void *user_data, int *request_id)
+{
+       if (!address || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_geocode *calldata_geocode = (callback_info_geocode *)g_malloc0(sizeof(callback_info_geocode));
+       if (calldata_geocode == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_geocode->callback = callback;
+       calldata_geocode->data = user_data;
+
+       mapzen_geocode_req_s *geocode_req = (mapzen_geocode_req_s *)g_malloc0(sizeof(mapzen_geocode_req_s));
+       if (geocode_req == NULL) {
+               free(calldata_geocode);
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       char resultAddressQuery[1024] = "";
+
+       char *street = NULL;
+       maps_address_get_street(address, &street);
+       if (street != NULL)
+               STRCAT(resultAddressQuery, street);
+
+       char *city = NULL;
+       maps_address_get_city(address, &city);
+       if ((strlen(resultAddressQuery) > 0) && (city != NULL)) {
+               STRCAT(resultAddressQuery, ",");
+               STRCAT(resultAddressQuery, city);
+       } else if (city != NULL) {
+               STRCAT(resultAddressQuery, city);
+       }
+
+       char *state = NULL;
+       maps_address_get_state(address, &state);
+       if ((strlen(resultAddressQuery) > 0) && (state != NULL)) {
+               STRCAT(resultAddressQuery, ",");
+               STRCAT(resultAddressQuery, state);
+       } else if (state != NULL) {
+               STRCAT(resultAddressQuery, state);
+       }
+
+#if 0
+       char *district = NULL;
+       maps_address_get_district(address, &district);
+       if ((strlen(resultAddressQuery) > 0) && (district != NULL)) {
+               STRCAT(resultAddressQuery, ", ");
+               STRCAT(resultAddressQuery, district);
+       }
+
+       char *country = NULL;
+       maps_address_get_country(address, &country);
+       if ((strlen(resultAddressQuery) > 0) && (country != NULL)) {
+               STRCAT(resultAddressQuery, ", ");
+               STRCAT(resultAddressQuery, country);
+       }
+
+       char *country_code = NULL;
+       maps_address_get_country_code(address, &country_code);
+       if ((strlen(resultAddressQuery) > 0) && (country_code != NULL)) {
+               STRCAT(resultAddressQuery, ", ");
+               STRCAT(resultAddressQuery, country_code);
+       } else if (country_code != NULL) {
+               STRCAT(resultAddressQuery, country_code);
+       }
+
+       char *county = NULL;
+       maps_address_get_county(address, &county);
+       if ((strlen(resultAddressQuery) > 0) && (county != NULL)) {
+               STRCAT(resultAddressQuery, ", ");
+               STRCAT(resultAddressQuery, county);
+       }
+#endif
+
+       char *postal_code = NULL;
+       maps_address_get_postal_code(address, &postal_code);
+       if ((strlen(resultAddressQuery) > 0) && (postal_code != NULL)) {
+               STRCAT(resultAddressQuery, ",");
+               STRCAT(resultAddressQuery, postal_code);
+       } else if (postal_code != NULL) {
+               STRCAT(resultAddressQuery, postal_code);
+       }
+
+       char *modified_address = NULL;
+       bool b_isAddress_modified = false;
+       b_isAddress_modified = __replace_space(resultAddressQuery, &modified_address);
+
+       if (b_isAddress_modified)
+               geocode_req->address = g_strdup((gchar *) modified_address);
+       else
+               geocode_req->address = g_strdup((gchar *) resultAddressQuery);
+
+       if (modified_address) {
+               g_free(modified_address);
+               modified_address = NULL;
+       }
+
+       geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+       geocode_req->boundary = NULL;
+
+       int max_result = 0;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result <= 0)
+               geocode_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               geocode_req->num_res = max_result;
+
+       *request_id = ++__request_id;
+       calldata_geocode->reqID = __request_id;
+
+       int ret = mapzen_geocode(geocode_req, __mapzen_geocode_cb, __request_id, (void *) calldata_geocode);
+
+       return __convert_to_maps_error(ret);
+}
+
+static void __mapzen_reverse_geocode_cb(mapzen_error_e result, int request_id, mapzen_address_resp_s *address, void *user_data)
+{
+       MAPS_LOGD("Got REV GEOCODE callback from ENGINE");
+       callback_info_reverse_geocode *calldata_reverse_geocode = (callback_info_reverse_geocode *) user_data;
+       if (result != MAPZEN_ERROR_NONE || address == NULL) {
+               calldata_reverse_geocode->callback((maps_error_e) __convert_to_maps_error(result), calldata_reverse_geocode->reqID, 0, 0, NULL, calldata_reverse_geocode->data);
+       } else {
+               int total_count = 1;
+               int index = 0;
+
+               maps_address_h addr = NULL;
+               maps_address_create(&addr);
+
+               maps_address_set_street(addr, address->street_add);
+               maps_address_set_city(addr, address->city);
+               maps_address_set_county(addr, address->county);
+               maps_address_set_state(addr, address->state);
+               maps_address_set_country(addr, address->country);
+               maps_address_set_country_code(addr, address->country_code);
+               maps_address_set_postal_code(addr, address->postal_code);
+
+               calldata_reverse_geocode->callback(MAPS_ERROR_NONE, calldata_reverse_geocode->reqID, index, total_count, addr, calldata_reverse_geocode->data);
+       }
+}
+
+EXPORT_API int maps_plugin_reverse_geocode(double latitude, double longitude, const maps_preference_h preference, maps_service_reverse_geocode_cb callback, void *user_data, int *request_id)
+{
+       if (!callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       if (latitude > LATITUDE_RANGE || latitude < -LATITUDE_RANGE)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       if (longitude > LONGITUDE_RANGE || longitude < -LONGITUDE_RANGE)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_reverse_geocode *calldata_reverse_geocode = (callback_info_reverse_geocode *)g_malloc0(sizeof(callback_info_reverse_geocode));
+       if (calldata_reverse_geocode == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_reverse_geocode->callback = callback;
+       calldata_reverse_geocode->data = user_data;
+
+       mapzen_revgeocode_req_s *reverse_geocode_req = (mapzen_revgeocode_req_s *)g_malloc0(sizeof(mapzen_revgeocode_req_s));
+       if (reverse_geocode_req == NULL) {
+               g_free(calldata_reverse_geocode);
+               calldata_reverse_geocode = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       reverse_geocode_req->maps_key = g_strdup((gchar *) __provider_key);
+       reverse_geocode_req->coordinates.latitude = latitude;
+       reverse_geocode_req->coordinates.longitude = longitude;
+
+       *request_id = ++__request_id;
+       calldata_reverse_geocode->reqID = __request_id;
+
+       int ret = mapzen_reverse_geocode(reverse_geocode_req, __mapzen_reverse_geocode_cb, __request_id, (void *) calldata_reverse_geocode);
+
+       return __convert_to_maps_error(ret);
+}
+
+static void __mapzen_route_cb(mapzen_error_e result, int request_id, mapzen_route_resp_s *route_info, void *user_data)
+{
+       MAPS_LOGD("__mapzen_route_cb");
+       callback_info_route *calldata_route = (callback_info_route *) user_data;
+
+       if (route_info) {
+/*             maps_route_h route;
+               maps_route_create(&route);
+
+               maps_coordinates_h top_left;
+               maps_coordinates_create(route_info->bounding_box.top_left.latitude, route_info->bounding_box.top_left.longitude, &top_left);
+
+               maps_coordinates_h bottom_right;
+               maps_coordinates_create(route_info->bounding_box.bottom_right.latitude, route_info->bounding_box.bottom_right.longitude, &bottom_right);
+
+               maps_area_h bounds = NULL;
+               maps_area_create_rectangle(top_left, bottom_right, &bounds);
+               maps_route_set_bounding_box(route, bounds);
+               maps_area_destroy(bounds);
+
+               maps_coordinates_destroy(top_left);
+               maps_coordinates_destroy(bottom_right);
+
+               maps_distance_unit_e unit = MAPS_DISTANCE_UNIT_M;
+
+               switch (route_info->distance_unit) {
+               case ROUTE_UNIT_M:
+                       unit = MAPS_DISTANCE_UNIT_M;
+                       break;
+               case ROUTE_UNIT_KM:
+                       unit = MAPS_DISTANCE_UNIT_KM;
+                       break;
+               case ROUTE_UNIT_FT:
+                       unit = MAPS_DISTANCE_UNIT_FT;
+                       break;
+               case ROUTE_UNIT_YD:
+                       unit = MAPS_DISTANCE_UNIT_YD;
+                       break;
+               }
+
+               maps_route_set_distance_unit(route, unit);
+               maps_route_set_total_distance(route, route_info->distance);
+               maps_route_set_total_duration(route, (long) route_info->time);
+               if (route_info->type == ROUTE_TYPE_FASTEST)
+                       maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_CAR);
+               else if (route_info->type == ROUTE_TYPE_PEDESTRIAN)
+                       maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN);
+               else if (route_info->type == ROUTE_TYPE_BICYCLE)
+                       maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_BICYCLE);
+               else if (route_info->type == ROUTE_TYPE_MULTIMODAL)
+                       maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT);
+               else
+                       maps_route_set_transport_mode(route, MAPS_ROUTE_TRANSPORT_MODE_CAR);
+
+               maps_item_list_h segment_list = NULL;
+               maps_item_list_create(&segment_list);
+
+               GList *maneuver_data = NULL;
+               maneuver_data = g_list_first(route_info->maneuvers);
+
+               while (maneuver_data) {
+                       maps_route_segment_h segment = NULL;
+                       maps_route_segment_create(&segment);
+
+                       maps_route_maneuver_h man = NULL;
+                       maps_route_maneuver_create(&man);
+                       mapzen_route_maneuver *maneuver = (mapzen_route_maneuver *) maneuver_data->data;
+
+                       // Segment Origin and Destination
+                       maps_coordinates_h segmentStartPoint;
+                       maps_coordinates_create(maneuver->start_point.latitude, maneuver->start_point.longitude, &segmentStartPoint);
+                       maps_route_segment_set_origin(segment, segmentStartPoint);      // origin
+                       maps_coordinates_destroy(segmentStartPoint);
+
+                       maps_coordinates_h segmentEndPoint;
+                       maps_coordinates_create(maneuver->end_point.latitude, maneuver->end_point.longitude, &segmentEndPoint);
+
+                       MAPS_LOGD(">>> Segment start : %f, %f <<<", maneuver->start_point.latitude, maneuver->start_point.longitude);
+                       MAPS_LOGD(">>> Segment end : %f, %f <<<", maneuver->end_point.latitude, maneuver->end_point.longitude);
+
+                       maps_route_segment_set_destination(segment, segmentEndPoint);   // destination
+                       maps_coordinates_destroy(segmentEndPoint);
+
+                       // Segment distance
+                       maps_route_segment_set_distance(segment, maneuver->distance);
+                       maps_route_segment_set_duration(segment, maneuver->time);
+
+                       // Maneuver distance
+                       maps_route_maneuver_set_distance_to_next_instruction(man, maneuver->distance);
+                       maps_route_maneuver_set_time_to_next_instruction(man, maneuver->time);
+
+                       maps_route_maneuver_set_turn_type(man, __convert_route_turn_type(maneuver->turn_type));
+
+                       // maneuver_set_traffic_direction(man, (traffic_direction_e)action_id);
+
+                       // Maneuver Instruction
+                       if (maneuver->instruction)
+                               maps_route_maneuver_set_instruction_text(man, (char *) maneuver->instruction);
+
+                       // Maneuver Street Name
+                       if (maneuver->street_name) {
+                               MAPS_LOGD("Street Name >>>> %s", maneuver->street_name);
+                               maps_route_maneuver_set_road_name(man, (char *) maneuver->street_name);
+                       } else {
+                               MAPS_LOGD("Street Name >>>> NIL");
+                       }
+
+                       /// Maneuver start position
+                       maps_coordinates_h coord;
+                       maps_coordinates_create(maneuver->start_point.latitude, maneuver->start_point.longitude, &coord);
+
+                       maps_route_maneuver_set_position(man, coord);
+                       maps_coordinates_destroy(coord);
+
+                       maps_item_list_h maneuver_list = NULL;
+                       maps_item_list_create(&maneuver_list);
+                       maps_item_list_append(maneuver_list, (gpointer) man, maps_route_maneuver_clone);
+                       maps_route_segment_set_maneuvers(segment, maneuver_list);
+
+                       maps_item_list_destroy(maneuver_list);
+                       maps_route_maneuver_destroy(man);
+
+                       maps_item_list_append(segment_list, (gpointer) segment, maps_route_segment_clone);
+                       maps_route_segment_destroy(segment);
+
+                       // Fetching the next item from Maneuver/Segment list
+                       maneuver_data = g_list_next(maneuver_data);
+               }
+               maps_route_set_segments(route, segment_list);
+               maps_item_list_destroy(segment_list);
+
+               // Shape points - path
+               maps_item_list_h path_list = NULL;
+               maps_item_list_create(&path_list);
+
+               GList *shapePoints = NULL;
+               shapePoints = g_list_first(route_info->shapePoints);
+
+               while (shapePoints) {
+                       coords_s *data = (coords_s *) shapePoints->data;
+
+                       maps_coordinates_h shapeCoords;
+                       maps_coordinates_create(data->latitude, data->longitude, &shapeCoords);
+
+                       maps_item_list_append(path_list, (gpointer) shapeCoords, maps_coordinates_clone);
+
+                       maps_coordinates_destroy(shapeCoords);
+
+                       shapePoints = g_list_next(shapePoints);
+               }
+               maps_route_set_path(route, path_list);
+               maps_item_list_destroy(path_list);
+
+               bool b = calldata_route->callback((maps_error_e)__convert_to_maps_error(result), calldata_route->reqID, 0, 1, route, calldata_route->data);
+               if (!b)
+                       return;
+                       */
+       } else {
+               calldata_route->callback((maps_error_e)__convert_to_maps_error(result), calldata_route->reqID, 0, 0, NULL, calldata_route->data);
+       }
+}
+
+EXPORT_API int maps_plugin_search_route(const maps_coordinates_h origin, const maps_coordinates_h destination, maps_preference_h preference,   maps_service_search_route_cb callback, void *user_data, int *request_id)
+{
+       if (!origin || !destination || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_route *calldata_route = (callback_info_route *)g_malloc0(sizeof(callback_info_route));
+       if (calldata_route == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_route->callback = callback;
+       calldata_route->data = user_data;
+
+       mapzen_route_req_s *route_req = (mapzen_route_req_s *)g_malloc0(sizeof(mapzen_route_req_s));
+       if (route_req == NULL) {
+               g_free(calldata_route);
+               calldata_route = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       route_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       double origin_lat, origin_lon;
+       double dest_lat, dest_lon;
+
+       maps_coordinates_get_latitude(origin, &origin_lat);
+       maps_coordinates_get_longitude(origin, &origin_lon);
+
+       maps_coordinates_get_latitude(destination, &dest_lat);
+       maps_coordinates_get_longitude(destination, &dest_lon);
+
+       route_req->from.latitude = origin_lat;
+       route_req->from.longitude = origin_lon;
+
+       route_req->to.latitude = dest_lat;
+       route_req->to.longitude = dest_lon;
+/*
+       MAPS_LOGD("getting transport mode..");
+       maps_route_transport_mode_e transport_mode;
+       maps_preference_get_route_transport_mode(preference, &transport_mode);
+
+       if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_CAR)
+               route_req->type = ROUTE_TYPE_FASTEST;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN)
+               route_req->type = ROUTE_TYPE_PEDESTRIAN;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_BICYCLE)
+               route_req->type = ROUTE_TYPE_BICYCLE;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT)
+               route_req->type = ROUTE_TYPE_MULTIMODAL;
+       else
+               route_req->type = ROUTE_TYPE_FASTEST;   // Keeping it as default
+
+       route_req->driving_style = DRIVING_STYLE_NORMAL;        // Keeping it as default
+
+       // Unit
+       maps_distance_unit_e unit;
+       maps_preference_get_distance_unit(preference, &unit);
+
+       switch (unit) {
+       case MAPS_DISTANCE_UNIT_M:
+               route_req->unit = ROUTE_UNIT_M;
+               break;
+       case MAPS_DISTANCE_UNIT_KM:
+               route_req->unit = ROUTE_UNIT_KM;
+               break;
+       case MAPS_DISTANCE_UNIT_FT:
+               route_req->unit = ROUTE_UNIT_FT;
+               break;
+       case MAPS_DISTANCE_UNIT_YD:
+               route_req->unit = ROUTE_UNIT_YD;
+               break;
+       }
+
+       route_req->avoids = ROUTE_AVOID_NONE;
+       maps_route_feature_weight_e routeWeight;
+       maps_preference_get_route_feature_weight(preference, &routeWeight);
+
+       if (routeWeight == MAPS_ROUTE_FEATURE_WEIGHT_AVOID) {
+               maps_route_feature_e routeFeature;
+               maps_preference_get_route_feature(preference, &routeFeature);
+
+               if (routeFeature == MAPS_ROUTE_FEATURE_TOLL)
+                       route_req->avoids = ROUTE_AVOID_TOLL_ROAD;
+               else if (routeFeature == MAPS_ROUTE_FEATURE_MOTORWAY)
+                       route_req->avoids = ROUTE_AVOID_LIMITED_ACCESS;
+               else if ((routeFeature == MAPS_ROUTE_FEATURE_BOATFERRY) || (routeFeature == MAPS_ROUTE_FEATURE_RAILFERRY))
+                       route_req->avoids = ROUTE_AVOID_FERRY;
+               else if (routeFeature == MAPS_ROUTE_FEATURE_DIRTROAD)
+                       route_req->avoids = ROUTE_AVOID_UNPAVED;
+               else
+                       route_req->avoids = ROUTE_AVOID_NONE;
+       }
+
+       route_req->way_points = NULL;
+
+       *request_id = ++__request_id;
+       calldata_route->reqID = __request_id;
+*/
+       int ret = mapzen_start_route(route_req, __mapzen_route_cb, __request_id, (void *)calldata_route);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_route_waypoints(const maps_coordinates_h *waypoint_list, int waypoint_num, maps_preference_h preference, maps_service_search_route_cb callback, void *user_data, int *request_id)
+{
+       if (!waypoint_list || waypoint_num < 2 || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_route *calldata_route = (callback_info_route *)g_malloc0(sizeof(callback_info_route));
+       if (calldata_route == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_route->callback = callback;
+       calldata_route->data = user_data;
+
+       mapzen_route_req_s *route_req = (mapzen_route_req_s *)g_malloc0(sizeof(mapzen_route_req_s));
+       if (route_req == NULL) {
+               g_free(calldata_route);
+               calldata_route = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       route_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       route_req->from.latitude = 0.0;
+       route_req->from.longitude = 0.0;
+
+       route_req->to.latitude = 0.0;
+       route_req->to.longitude = 0.0;
+/*
+       MAPS_LOGD("getting transport mode..");
+       maps_route_transport_mode_e transport_mode;
+       maps_preference_get_route_transport_mode(preference, &transport_mode);
+
+       if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_CAR)
+               route_req->type = ROUTE_TYPE_FASTEST;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PEDESTRIAN)
+               route_req->type = ROUTE_TYPE_PEDESTRIAN;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_BICYCLE)
+               route_req->type = ROUTE_TYPE_BICYCLE;
+       else if (transport_mode == MAPS_ROUTE_TRANSPORT_MODE_PUBLICTRANSIT)
+               route_req->type = ROUTE_TYPE_MULTIMODAL;
+       else
+               route_req->type = ROUTE_TYPE_FASTEST;   // Keeping it as default
+
+       route_req->driving_style = DRIVING_STYLE_NORMAL;        // Keeping it as default
+
+       // Unit
+       maps_distance_unit_e unit;
+       maps_preference_get_distance_unit(preference, &unit);
+
+       switch (unit) {
+       case MAPS_DISTANCE_UNIT_M:
+               route_req->unit = ROUTE_UNIT_M;
+               break;
+       case MAPS_DISTANCE_UNIT_KM:
+               route_req->unit = ROUTE_UNIT_KM;
+               break;
+       case MAPS_DISTANCE_UNIT_FT:
+               route_req->unit = ROUTE_UNIT_FT;
+               break;
+       case MAPS_DISTANCE_UNIT_YD:
+               route_req->unit = ROUTE_UNIT_YD;
+               break;
+       }
+
+       route_req->avoids = ROUTE_AVOID_NONE;
+       maps_route_feature_weight_e routeWeight;
+       maps_preference_get_route_feature_weight(preference, &routeWeight);
+
+       if (routeWeight == MAPS_ROUTE_FEATURE_WEIGHT_AVOID) {
+               maps_route_feature_e routeFeature;
+               maps_preference_get_route_feature(preference, &routeFeature);
+
+               if (routeFeature == MAPS_ROUTE_FEATURE_TOLL)
+                       route_req->avoids = ROUTE_AVOID_TOLL_ROAD;
+               else if (routeFeature == MAPS_ROUTE_FEATURE_MOTORWAY)
+                       route_req->avoids = ROUTE_AVOID_LIMITED_ACCESS;
+               else if ((routeFeature == MAPS_ROUTE_FEATURE_BOATFERRY) || (routeFeature == MAPS_ROUTE_FEATURE_RAILFERRY))
+                       route_req->avoids = ROUTE_AVOID_FERRY;
+               else if (routeFeature == MAPS_ROUTE_FEATURE_DIRTROAD)
+                       route_req->avoids = ROUTE_AVOID_UNPAVED;
+               else
+                       route_req->avoids = ROUTE_AVOID_NONE;
+       }
+
+       // Waypoints
+       route_req->way_points = NULL;
+       if (waypoint_num != 0) {
+               int index = 0;
+               double latitude = 0.0, longitude = 0.0;
+               for (index = 0; index < waypoint_num; index++) {
+                       if (waypoint_list[index] != NULL) {
+                               maps_coordinates_get_latitude(waypoint_list[index], &latitude);
+                               maps_coordinates_get_longitude(waypoint_list[index], &longitude);
+
+                               coords_s *data = (coords_s *)g_malloc0(sizeof(coords_s));
+                               if (data) {
+                                       data->latitude = latitude;
+                                       data->longitude = longitude;
+
+                                       if (route_req->way_points == NULL)
+                                               route_req->way_points = g_list_append(route_req->way_points, (gpointer) data);
+                                       else
+                                               route_req->way_points = g_list_insert_before(route_req->way_points, NULL, (gpointer) data);
+                               }
+                       }
+               }
+       }
+
+       *request_id = ++__request_id;
+       calldata_route->reqID = __request_id;
+*/
+       int ret = mapzen_start_route(route_req, __mapzen_route_cb, __request_id, (void *)calldata_route);
+
+       return __convert_to_maps_error(ret);
+}
+
+static void __mapzen_place_search_cb(mapzen_error_e result, int request_id, GList *places, void *user_data)
+{
+       MAPS_LOGD("Got places result from ENGINE...");
+
+       callback_info_place *calldata_place = (callback_info_place *) user_data;
+
+       if (result != MAPZEN_ERROR_NONE || places == NULL) {
+               MAPS_LOGD("Got places result from ENGINE...result is NULL");
+               calldata_place->callback((maps_error_e) __convert_to_maps_error(result), calldata_place->reqID, 0, 0, NULL, calldata_place->data);
+       } else {
+               guint total_count = 0;
+               int index = 0;
+               total_count = g_list_length(places);
+               if (total_count > 0) {
+                       maps_place_h place = NULL;
+                       MAPS_LOGD("Got places result from ENGINE... count -> %d", total_count);
+
+                       GList *temp_place = NULL;
+                       temp_place = g_list_first(places);
+
+                       while (temp_place) {
+                               maps_place_create(&place);
+                               mapzen_place_resp_s *mapzen_place = (mapzen_place_resp_s *) temp_place->data;
+                               maps_place_set_id(place, mapzen_place->place_id);
+                               maps_place_set_name(place, mapzen_place->display_name);
+
+                               MAPS_LOGD("Before address..");
+                               /* Address */
+                               if (mapzen_place->address) {
+                                       maps_address_h addr = NULL;
+                                       maps_address_create(&addr);
+
+                                       maps_address_set_street(addr, mapzen_place->address->street_add);
+                                       maps_address_set_building_number(addr, mapzen_place->address->building_number);
+                                       maps_address_set_city(addr, mapzen_place->address->city);
+                                       maps_address_set_county(addr, mapzen_place->address->county);
+                                       maps_address_set_state(addr, mapzen_place->address->state);
+                                       maps_address_set_country(addr, mapzen_place->address->country);
+                                       maps_address_set_country_code(addr, mapzen_place->address->country_code);
+                                       maps_address_set_postal_code(addr, mapzen_place->address->postal_code);
+                                       maps_address_set_freetext(addr, mapzen_place->display_name);
+
+                                       maps_place_set_address(place, addr);
+                                       maps_address_destroy(addr);
+                               } else {
+                                       maps_place_set_address(place, NULL);
+                               }
+
+                               maps_coordinates_h coord;
+                               maps_coordinates_create(mapzen_place->coordinates.latitude, mapzen_place->coordinates.longitude, &coord);
+
+                               maps_place_set_location(place, coord);
+                               maps_coordinates_destroy(coord);
+
+                               maps_place_category_h place_cat;
+                               maps_place_category_create(&place_cat);
+                               maps_place_category_set_name(place_cat, mapzen_place->category);
+
+                               maps_item_list_h cat_list;
+                               maps_item_list_create(&cat_list);
+                               maps_item_list_append(cat_list, (void *) place_cat, maps_place_category_clone);
+                               maps_place_set_categories(place, cat_list);
+
+                               maps_place_category_destroy(place_cat);
+                               maps_item_list_destroy(cat_list);
+
+                               maps_place_image_h place_image;
+                               maps_place_image_create(&place_image);
+                               maps_place_image_set_url(place_image, mapzen_place->icon_url);
+                               maps_item_list_h image_list;
+                               maps_item_list_create(&image_list);
+                               maps_item_list_append(image_list, (void *) place_image, maps_place_image_clone);
+                               maps_place_set_images(place, image_list);
+
+                               maps_place_image_destroy(place_image);
+                               maps_item_list_destroy(image_list);
+
+                               bool b = calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, index, total_count, place, calldata_place->data);
+                               if (!b)
+                                       return;
+
+                               index++;
+
+                               temp_place = temp_place->next;
+                       }
+               } else {
+                       calldata_place->callback((maps_error_e)__convert_to_maps_error(result), calldata_place->reqID, index, total_count, NULL, calldata_place->data);
+               }
+       }
+}
+
+EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int distance, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+       if (!position || !filter || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+       if (distance <= 0)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+       if (calldata_place == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_place->callback = callback;
+       calldata_place->data = user_data;
+
+       mapzen_search_req_s *place_req = (mapzen_search_req_s *)g_malloc0(sizeof(mapzen_search_req_s));
+       if (place_req == NULL) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       int max_result;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result == 0)
+               place_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               place_req->num_res = max_result;
+
+       MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+       char *categoryName = NULL;
+       char *place_name = NULL;
+
+       maps_place_category_h category = NULL;
+       maps_place_filter_get_category(filter, &category);
+
+       if (category)
+               maps_place_category_get_name(category, &categoryName);
+
+       maps_place_filter_get_place_name(filter, &place_name);
+
+       char *modified_place_name = NULL;
+       bool b_isPlaceName_modified = false;
+       if (place_name)
+               b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+
+       MAPS_LOGD("Modified Place String.. ");
+       MAPS_LOGD(" >>>> %s", modified_place_name);
+
+       if (categoryName && place_name) {
+               if (b_isPlaceName_modified)
+                       place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
+               else
+                       place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
+       } else if (categoryName) {
+               place_req->search_string = g_strdup_printf("[%s]", categoryName);
+       } else if (place_name) {
+               if (b_isPlaceName_modified)
+                       place_req->search_string = g_strdup_printf("%s", modified_place_name);
+               else
+                       place_req->search_string = g_strdup_printf("%s", place_name);
+       } else {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               g_free(place_req);
+               place_req = NULL;
+               return MAPS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (modified_place_name) {
+               g_free(modified_place_name);
+               modified_place_name = NULL;
+       }
+
+       MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+
+       place_req->boundary = NULL;
+       place_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
+
+       if (place_req->boundary) {
+               place_req->boundary->type = MAPZEN_BOUNDARY_CIRCLE;
+               double lat, lon;
+               maps_coordinates_get_latitude(position, &lat);
+               maps_coordinates_get_longitude(position, &lon);
+               place_req->boundary->circle.center.latitude = lat;
+               place_req->boundary->circle.center.longitude = lon;
+               place_req->boundary->circle.radius = distance;
+       }
+
+       *request_id = ++__request_id;
+       calldata_place->reqID = __request_id;
+
+       int ret = mapzen_search_place(place_req, __mapzen_place_search_cb, __request_id, (void *) calldata_place);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+       if (!boundary || !filter || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+       if (calldata_place == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_place->callback = callback;
+       calldata_place->data = user_data;
+
+       mapzen_search_req_s *place_req = (mapzen_search_req_s *)g_malloc0(sizeof(mapzen_search_req_s));
+       if (place_req == NULL) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       int max_result;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result == 0)
+               place_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               place_req->num_res = max_result;
+
+       MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+       char *categoryName = NULL;
+       char *place_name = NULL;
+
+       maps_place_category_h category = NULL;
+       maps_place_filter_get_category(filter, &category);
+
+       if (category)
+               maps_place_category_get_name(category, &categoryName);
+
+       maps_place_filter_get_place_name(filter, &place_name);
+
+       char *modified_place_name = NULL;
+       bool b_isPlaceName_modified = false;
+       if (place_name)
+               b_isPlaceName_modified = __replace_space(place_name, &modified_place_name);
+
+       if (categoryName && place_name) {
+               if (b_isPlaceName_modified)
+                       place_req->search_string = g_strdup_printf("%s[%s]", modified_place_name, categoryName);
+               else
+                       place_req->search_string = g_strdup_printf("%s[%s]", place_name, categoryName);
+       } else if (categoryName) {
+               place_req->search_string = g_strdup_printf("[%s]", categoryName);
+       } else if (place_name) {
+               if (b_isPlaceName_modified)
+                       place_req->search_string = g_strdup_printf("%s", modified_place_name);
+               else
+                       place_req->search_string = g_strdup_printf("%s", place_name);
+       } else {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               g_free(place_req);
+               place_req = NULL;
+               return MAPS_ERROR_INVALID_PARAMETER;
+       }
+
+       if (modified_place_name) {
+               g_free(modified_place_name);
+               modified_place_name = NULL;
+       }
+
+       MAPS_LOGD(">>>>>>>> Place search string :: %s <<<<<<<<<", place_req->search_string);
+       place_req->boundary = NULL;
+       maps_area_s *bound = (maps_area_s *) boundary;
+
+       if (bound->type != MAPS_AREA_NONE) {
+               place_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
+
+               if (place_req->boundary != NULL) {
+                       if (bound->type == MAPS_AREA_CIRCLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_CIRCLE;
+                               place_req->boundary->circle.center.latitude = bound->circle.center.latitude;
+                               place_req->boundary->circle.center.longitude = bound->circle.center.longitude;
+                               place_req->boundary->circle.radius = bound->circle.radius;
+                       } else if (bound->type == MAPS_AREA_RECTANGLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_RECT;
+                               place_req->boundary->rect.top_left.latitude = bound->rect.top_left.latitude;
+                               place_req->boundary->rect.top_left.longitude = bound->rect.top_left.longitude;
+                               place_req->boundary->rect.bottom_right.latitude = bound->rect.bottom_right.latitude;
+                               place_req->boundary->rect.bottom_right.longitude = bound->rect.bottom_right.longitude;
+                       }
+               }
+       }
+
+       *request_id = ++__request_id;
+       calldata_place->reqID = __request_id;
+
+       int ret = mapzen_search_place(place_req, __mapzen_place_search_cb, __request_id, (void *) calldata_place);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_search_place_by_address(const char *address, const maps_area_h boundary, const maps_place_filter_h filter, const maps_preference_h preference, maps_service_search_place_cb callback, void *user_data, int *request_id)
+{
+       if (!address || !boundary || !filter || !callback || !request_id)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       callback_info_place *calldata_place = (callback_info_place *)g_malloc0(sizeof(callback_info_place));
+       if (calldata_place == NULL)
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+
+       calldata_place->callback = callback;
+       calldata_place->data = user_data;
+
+       mapzen_search_req_s *place_req = (mapzen_search_req_s *)g_malloc0(sizeof(mapzen_search_req_s));
+       if (place_req == NULL) {
+               g_free(calldata_place);
+               calldata_place = NULL;
+               MAPS_PRINT_ERROR_CODE_RETURN(MAPS_ERROR_OUT_OF_MEMORY);
+       }
+
+       place_req->maps_key = g_strdup((gchar *) __provider_key);
+
+       int max_result;
+       maps_preference_get_max_results(preference, &max_result);
+
+       if (max_result == 0)
+               place_req->num_res = DEFAULT_NUM_RESULTS;
+       else
+               place_req->num_res = max_result;
+
+       MAPS_LOGD("Place Result limit :: %d", place_req->num_res);
+
+       char *categoryName = NULL;
+
+       maps_place_category_h category = NULL;
+       maps_place_filter_get_category(filter, &category);
+
+       if (category)
+               maps_place_category_get_name(category, &categoryName);
+
+       char *modified_address = NULL;
+       bool b_isAddress_modified = false;
+       if (address)
+               b_isAddress_modified = __replace_space((char *) address, &modified_address);
+
+       if (categoryName) {
+               if (b_isAddress_modified)
+                       place_req->search_string = g_strdup_printf("%s[%s]", modified_address, categoryName);
+               else
+                       place_req->search_string = g_strdup_printf("%s[%s]", address, categoryName);
+       } else {
+               if (b_isAddress_modified)
+                       place_req->search_string = g_strdup_printf("%s", modified_address);
+               else
+                       place_req->search_string = g_strdup_printf("%s", address);
+       }
+
+       if (modified_address) {
+               g_free(modified_address);
+               modified_address = NULL;
+       }
+
+       place_req->boundary = NULL;
+       maps_area_s *bound = (maps_area_s *) boundary;
+
+       if (bound->type != MAPS_AREA_NONE) {
+               place_req->boundary = (mapzen_boundary_s *)g_malloc0(sizeof(mapzen_boundary_s));
+
+               if (place_req->boundary != NULL) {
+                       if (bound->type == MAPS_AREA_CIRCLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_CIRCLE;
+                               place_req->boundary->circle.center.latitude = bound->circle.center.latitude;
+                               place_req->boundary->circle.center.longitude = bound->circle.center.longitude;
+                               place_req->boundary->circle.radius = bound->circle.radius;
+                       } else if (bound->type == MAPS_AREA_RECTANGLE) {
+                               place_req->boundary->type = MAPZEN_BOUNDARY_RECT;
+                               place_req->boundary->rect.top_left.latitude = bound->rect.top_left.latitude;
+                               place_req->boundary->rect.top_left.longitude = bound->rect.top_left.longitude;
+                               place_req->boundary->rect.bottom_right.latitude = bound->rect.bottom_right.latitude;
+                               place_req->boundary->rect.bottom_right.longitude = bound->rect.bottom_right.longitude;
+                       }
+               }
+       }
+
+       *request_id = ++__request_id;
+       calldata_place->reqID = __request_id;
+
+       int ret = mapzen_search_place(place_req, __mapzen_place_search_cb, __request_id, (void *) calldata_place);
+
+       return __convert_to_maps_error(ret);
+}
+
+EXPORT_API int maps_plugin_cancel_request(int request_id)
+{
+       MAPS_LOGD("Plugin_Cancel_Request...");
+       if (request_id < 0)
+               return MAPS_ERROR_INVALID_PARAMETER;
+
+       int ret = mapzen_cancel_request(request_id);
+
+       return __convert_to_maps_error(ret);
+}
diff --git a/src/mapzen_plugin.cpp b/src/mapzen_plugin.cpp
deleted file mode 100644 (file)
index 214ab49..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <maps_plugin.h>
-#include "mapzen_utils.h"
-
-extern "C"
-{
-
-EXPORT_API int maps_plugin_init(maps_plugin_h *plugin)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_init_module(maps_plugin_h *plugin, const char *module)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_shutdown(maps_plugin_h plugin)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_info(maps_plugin_info_h* info)
-{
-       int ret = maps_plugin_info_create(info);
-
-       if (ret == MAPS_ERROR_NONE)
-               ret = maps_plugin_info_set_provider_name(*info, "mapzen");
-
-       return ret;
-}
-
-EXPORT_API int maps_plugin_set_provider_key(const char* provider_key)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_provider_key(char** provider_key)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_set_preference(maps_preference_h preference)
-{
-        return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_preference(maps_preference_h* preference)
-{
-        return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_is_service_supported(maps_service_e service, bool *supported)
-{
-        return MAPS_ERROR_NONE;
-}
-EXPORT_API int maps_plugin_is_data_supported(maps_service_data_e service, bool *supported)
-{
-        return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_geocode(const char* address, const maps_preference_h preference,
-       maps_service_geocode_cb callback, void *user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_geocode_inside_area(const char* address, const maps_area_h bounds,
-       const maps_preference_h preference, maps_service_geocode_cb callback,
-       void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_geocode_by_structured_address(const maps_address_h address,
-       const maps_preference_h preference, maps_service_geocode_cb callback,
-       void *user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_reverse_geocode(double latitude, double longitude,
-       const maps_preference_h preference, maps_service_reverse_geocode_cb callback,
-       void *user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_multi_reverse_geocode(const maps_coordinates_list_h geocode_list,
-       const maps_preference_h preference, maps_service_multi_reverse_geocode_cb callback,
-       void *user_data, int *request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_place(const maps_coordinates_h position, int distance,
-       const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback,
-       void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_place_by_area(const maps_area_h boundary,
-       const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback,
-       void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_place_by_address(const char* address, const maps_area_h boundary,
-       const maps_place_filter_h filter, maps_preference_h preference, maps_service_search_place_cb callback,
-       void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_place_list(const maps_area_h boundary, const maps_place_filter_h filter,
-       maps_preference_h preference, maps_service_search_place_list_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_place_details(const char* url,
-       maps_service_get_place_details_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_route(const maps_coordinates_h origin, const maps_coordinates_h destination,
-       maps_preference_h preference, maps_service_search_route_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_search_route_waypoints(const maps_coordinates_h* waypoint_list, int waypoint_num,
-       maps_preference_h preference, maps_service_search_route_cb callback,
-       void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_cancel_request(int request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_create_map_view(maps_view_h hView, maps_plugin_map_view_ready_cb pCbFunc)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_destroy_map_view(maps_view_h hView)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_render_map(maps_view_h hView,
-       const maps_coordinates_h coordinates, double zoom_factor, double rotation_angle,
-       maps_plugin_render_map_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_render_map_area(maps_view_h hView, const maps_area_h area,
-       double zoom_factor, double rotation_angle,
-       maps_plugin_render_map_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_move_center(maps_view_h hView, int delta_x, int delta_y,
-       maps_plugin_render_map_cb callback, void* user_data, int* request_id)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_set_scalebar(maps_view_h hView, bool enable)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_scalebar(maps_view_h hView, bool *enabled)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_draw_map(maps_view_h hView, Evas* canvas, int x, int y, int w, int h)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_center(maps_view_h hView, maps_coordinates_h *center)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_screen_to_geography(maps_view_h hView, int x, int y, maps_coordinates_h *mapsCoord)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_geography_to_screen(maps_view_h hView, const maps_coordinates_h mapsCoord, int* x, int* y)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_min_zoom_level(maps_view_h hView, int *min_zoom_level)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_get_max_zoom_level(maps_view_h hView, int *max_zoom_level)
-{
-       return MAPS_ERROR_NONE;
-}
-
-EXPORT_API int maps_plugin_on_object(maps_view_h hView, const maps_view_object_h object, maps_view_object_operation_e operation)
-{
-       return MAPS_ERROR_NONE;
-}
-
-} // end of extern "C"
-