From 6859b53155c10f2e1c993117d57abf2bcbec90ec Mon Sep 17 00:00:00 2001 From: Dennis Luxen Date: Mon, 24 Nov 2014 15:15:57 +0100 Subject: [PATCH] use JSON container to hold all intermediate results: - no hand-rolled GPX generation anymore - render gpx thru a JSONContainer visitor pattern - precursor to expose JSON containter as result from OSRM lib interface, cf. #1261 --- Descriptors/GPXDescriptor.h | 53 ++++++-------- Util/xml_renderer.hpp | 140 ++++++++++++++++++++++++++++++++++++ 2 files changed, 162 insertions(+), 31 deletions(-) create mode 100644 Util/xml_renderer.hpp diff --git a/Descriptors/GPXDescriptor.h b/Descriptors/GPXDescriptor.h index 6f76b3bc8..341fb3899 100644 --- a/Descriptors/GPXDescriptor.h +++ b/Descriptors/GPXDescriptor.h @@ -29,31 +29,36 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define GPX_DESCRIPTOR_H #include "BaseDescriptor.h" +#include "../DataStructures/JSONContainer.h" +#include "../Util/xml_renderer.hpp" + +#include template class GPXDescriptor final : public BaseDescriptor { private: DescriptorConfig config; - FixedPointCoordinate current; DataFacadeT *facade; - void AddRoutePoint(const FixedPointCoordinate &coordinate, std::vector &output) + void AddRoutePoint(const FixedPointCoordinate &coordinate, JSON::Array &json_result) { - const std::string route_point_head = ""; + JSON::Object json_lat; + JSON::Object json_lon; + JSON::Array json_row; std::string tmp; FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp); - output.insert(output.end(), route_point_head.begin(), route_point_head.end()); - output.insert(output.end(), tmp.begin(), tmp.end()); - output.push_back('\"'); + json_lat.values["_lat"] = tmp; FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp); - output.insert(output.end(), route_point_middle.begin(), route_point_middle.end()); - output.insert(output.end(), tmp.begin(), tmp.end()); - output.insert(output.end(), route_point_tail.begin(), route_point_tail.end()); + json_lon.values["_lon"] = tmp; + + json_row.values.push_back(json_lat); + json_row.values.push_back(json_lon); + JSON::Object entry; + entry.values["rtept"] = json_row; + json_result.values.push_back(entry); } public: @@ -61,26 +66,13 @@ template class GPXDescriptor final : public BaseDescriptor" - "" - "Data (c)" - " OpenStreetMap contributors (ODbL)" - "" - ""); - reply.content.insert(reply.content.end(), header.begin(), header.end()); - const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) && - (!raw_route.unpacked_path_segments.front().empty()); - if (found_route) + JSON::Array json_result; + if (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) { AddRoutePoint(raw_route.segment_end_coordinates.front().source_phantom.location, - reply.content); + json_result); for (const std::vector &path_data_vector : raw_route.unpacked_path_segments) { @@ -88,14 +80,13 @@ template class GPXDescriptor final : public BaseDescriptorGetCoordinateOfNode(path_data.node); - AddRoutePoint(current_coordinate, reply.content); + AddRoutePoint(current_coordinate, json_result); } } AddRoutePoint(raw_route.segment_end_coordinates.back().target_phantom.location, - reply.content); + json_result); } - std::string footer(""); - reply.content.insert(reply.content.end(), footer.begin(), footer.end()); + JSON::gpx_render(reply.content, json_result); } }; #endif // GPX_DESCRIPTOR_H diff --git a/Util/xml_renderer.hpp b/Util/xml_renderer.hpp new file mode 100644 index 000000000..6308a46a1 --- /dev/null +++ b/Util/xml_renderer.hpp @@ -0,0 +1,140 @@ +/* + +Copyright (c) 2013, Project OSRM, Dennis Luxen, others +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef XML_RENDERER_HPP +#define XML_RENDERER_HPP + +#include "../DataStructures/JSONContainer.h" +#include "cast.hpp" + +namespace JSON { + +struct XMLToArrayRenderer : mapbox::util::static_visitor<> +{ + explicit XMLToArrayRenderer(std::vector &_out) : out(_out) {} + + void operator()(const String &string) const + { + out.push_back('\"'); + out.insert(out.end(), string.value.begin(), string.value.end()); + out.push_back('\"'); + } + + void operator()(const Number &number) const + { + const std::string number_string = cast::double_fixed_to_string(number.value); + out.insert(out.end(), number_string.begin(), number_string.end()); + } + + void operator()(const Object &object) const + { + auto iterator = object.values.begin(); + while (iterator != object.values.end()) + { + if (iterator->first.at(0) != '_') + { + out.push_back('<'); + out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end()); + } + else + { + out.push_back(' '); + out.insert(out.end(), ++(*iterator).first.begin(), (*iterator).first.end()); + out.push_back('='); + + } + mapbox::util::apply_visitor(XMLToArrayRenderer(out), (*iterator).second); + if (iterator->first.at(0) != '_') + { + out.push_back('/'); + out.push_back('>'); + } + ++iterator; + } + } + + void operator()(const Array &array) const + { + std::vector::const_iterator iterator; + iterator = array.values.begin(); + while (iterator != array.values.end()) + { + mapbox::util::apply_visitor(XMLToArrayRenderer(out), *iterator); + ++iterator; + } + } + + void operator()(const True &) const + { + const std::string temp("true"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const False &) const + { + const std::string temp("false"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + void operator()(const Null &) const + { + const std::string temp("null"); + out.insert(out.end(), temp.begin(), temp.end()); + } + + private: + std::vector &out; +}; + +template +inline void xml_render(std::vector &out, const JSONObject &object) +{ + Value value = object; + mapbox::util::apply_visitor(XMLToArrayRenderer(out), value); +} + +template +inline void gpx_render(std::vector &out, const JSONObject &object) +{ + // add header + + const std::string header {"Data (c) OpenStreetMap contributors (ODbL)"}; + out.insert(out.end(), header.begin(), header.end()); + + xml_render(out, object); + + const std::string footer {""}; + out.insert(out.end(), footer.begin(), footer.end()); +} +} // namespace JSON + +#endif // XML_RENDERER_HPP