#include <stdio.h>
#include <glib.h>
#include <pthread.h>
+#include <dlog.h>
#include "mapzen_route.hpp"
#include "mapzen_types.h"
#include "mapzen_server_private.h"
#include "mapzen_restcurl.h"
#include "mapzen_util.h"
-#define ROUTE_URL "https://valhalla.mapzen.com/route?api_key=%s&json="
+#include "rapidjson/rapidjson.h"
+#include "rapidjson/allocators.h"
+#include "rapidjson/document.h"
+#include "rapidjson/stringbuffer.h"
+#include "rapidjson/writer.h"
+#include <curl/curl.h>
-int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, route_type type, route_feature_avoids 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");
+#ifdef __cplusplus
+extern "C" {
+#endif
- STRCPY(url, tmpStr);
+#define ROUTE_URL "https://valhalla.mapzen.com/route?api_key=%s&json=%s"
- /*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"');
+std::string url_encode(const std::string& unencoded) {
+ char* encoded = curl_escape(unencoded.c_str(), static_cast<int>(unencoded.size()));
+ dlog_print(DLOG_DEBUG, "URL:*","json after url encoding: " + *encoded);
+ std::string encoded_str(encoded);
+ curl_free(encoded);
+ return encoded_str;
+ }
- 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, '}}');
- }
+int query_route(gchar *maps_key, coords_s startPoint, coords_s endPoint, route_type type, route_feature_avoids avoids, route_driving_style style, GList *waypoints, gpointer user_data)
+{
+ rapidjson::Document document;
+ rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
- if (style == DRIVING_STYLE_NORMAL)
- STRCAT(url, "");
- else if (style == DRIVING_STYLE_CAUTIOUS)
- STRCAT(url, "");
- else if (style == DRIVING_STYLE_AGGRESSIVE)
- STRCAT(url, "");
+ rapidjson::Value& locations = document.AddMember(rapidjson::Value("locations", allocator).Move(),
+ rapidjson::Value(rapidjson::kArrayType).Move(), allocator);
+ rapidjson::Value& location = locations.AddMember(rapidjson::Value("", allocator).Move(),
+ rapidjson::Value(rapidjson::kObjectType).Move(), allocator);
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);
+ for (unsigned i = 0; i < sizeof(data); i++) {
+ location.AddMember<double>("lat", data[i].latitude, allocator);
+ location.AddMember<double>("lon", data[i].longitude, allocator);
}
- 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);
+ location.AddMember<double>("lat", startPoint.latitude, allocator);
+ location.AddMember<double>("lon", startPoint.longitude, allocator);
+ location.AddMember<double>("lat", endPoint.latitude, allocator);
+ location.AddMember<double>("lon", endPoint.longitude, allocator);
+ }
+
+ rapidjson::Value& costing = document.AddMember(rapidjson::Value("costing", allocator).Move(),
+ rapidjson::Value(rapidjson::kStringType).Move(), allocator);
+ switch (type) {
+ case COSTING_AUTO:
+ costing.SetString("auto");
+ break;
+ case COSTING_AUTO_SHORTER:
+ costing.SetString("auto_shorter");
+ break;
+ case COSTING_PEDESTRIAN:
+ costing.SetString("pedestrian");
+ break;
+ case COSTING_MULTIMODAL:
+ costing.SetString("multimodal");
+ break;
+ case COSTING_BICYCLE:
+ costing.SetString("bicycle");
+ break;
+ default:
+ costing.SetString("auto");
+ }
+
+ rapidjson::Value& directions_options = document.AddMember(rapidjson::Value("directions_options", allocator).Move(),
+ rapidjson::Value(rapidjson::kObjectType).Move(), allocator);
+ directions_options.AddMember("unit","mi",allocator);
+
+ if (avoids) {
+ rapidjson::Value& costing_options = document.AddMember(rapidjson::Value("costing_options", allocator).Move(),
+ rapidjson::Value(rapidjson::kObjectType).Move(), allocator);
+
+ switch (avoids) {
+ case PENALTY_NONE:
+ //TODO
+ break;
+ case PENALTY_LIMITED_ACCESS:
+ //TODO
+ break;
+ case PENALTY_TOLL_ROADS:
+ costing_options.AddMember("toll_booth_penalty","1", allocator);
+ break;
+ case PENALTY_USE_FERRY:
+ costing_options.AddMember("use_ferry","0", allocator);
+ break;
+ case PENALTY_USE_UNPAVED:
+ //TODO
+ break;
+ case PENALTY_SEASONAL_CLOSURE:
+ //TODO
+ break;
+ case PENALTY_COUNTRY_CROSSING:
+ costing_options.AddMember("country_crossing_penalty","1", allocator);
+ break;
+ }
+ }
+
+ /*rapidjson::Value& drive_style = document.AddMember(rapidjson::Value("drive_style", allocator).Move(),
+ * rapidjson::Value(rapidjson::kStringType).Move(), allocator);
+ switch (style) {
+ case DRIVING_STYLE_NORMAL:
+ //TODO
+ break;
+ case DRIVING_STYLE_CAUTIOUS:
+ //TODO
+ break;
+ case DRIVING_STYLE_AGGRESSIVE:
+ //TODO
+ break;
}*/
- //TODO: url encode (curl_escape) the json part of the request
+ //Stringify JSON
+ rapidjson::StringBuffer buffer;
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+ document.Accept(writer);
+ const char* json = buffer.GetString();
- add_handle(url, REQ_TYPE_ROUTE, user_data);
+ //we think that this is already being encoded somewhere else
+ //std::string encoded_json = url_encode(json);
+ char routeRequest[1024];
+ if (maps_key != NULL)
+ snprintf(routeRequest, sizeof(routeRequest), ROUTE_URL, maps_key, json);
+ else
+ snprintf(routeRequest, sizeof(routeRequest), ROUTE_URL, "null", json);
+
+ add_handle(routeRequest, REQ_TYPE_ROUTE, user_data);
return 0;
}
+#ifdef __cplusplus
+}
+#endif