diff --git a/DataStructures/JSONContainer.h b/DataStructures/JSONContainer.h index 257ec938a..350441d12 100644 --- a/DataStructures/JSONContainer.h +++ b/DataStructures/JSONContainer.h @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define JSON_CONTAINER_H #include "../ThirdParty/variant/variant.hpp" -#include "../Util/StringUtil.h" +#include "../Util/cast.hpp" #include #include @@ -157,7 +157,7 @@ struct ArrayRenderer : mapbox::util::static_visitor<> void operator()(const Number &number) const { - const std::string number_string = FixedDoubleToString(number.value); + const std::string number_string = cast::double_fixed_to_string(number.value); out.insert(out.end(), number_string.begin(), number_string.end()); } diff --git a/Descriptors/JSONDescriptor.h b/Descriptors/JSONDescriptor.h index c70b0eb5d..965495246 100644 --- a/Descriptors/JSONDescriptor.h +++ b/Descriptors/JSONDescriptor.h @@ -330,16 +330,16 @@ template class JSONDescriptor : public BaseDescriptor class JSONDescriptor : public BaseDescriptor(segment.length)) + "m"); + cast::integral_to_string(static_cast(segment.length)) + "m"); const double bearing_value = (segment.bearing / 10.); json_instruction_row.values.push_back(Azimuth::Get(bearing_value)); json_instruction_row.values.push_back( @@ -375,7 +375,7 @@ template class JSONDescriptor : public BaseDescriptor #include +#include #include #include @@ -68,18 +69,18 @@ inline unsigned parseDuration(const std::string &s) { if (1 == result.size()) { - minutes = StringToUint(result[0]); + minutes = cast::string_to_int(result[0]); } if (2 == result.size()) { - minutes = StringToUint(result[1]); - hours = StringToUint(result[0]); + minutes = cast::string_to_int(result[1]); + hours = cast::string_to_int(result[0]); } if (3 == result.size()) { - seconds = StringToUint(result[2]); - minutes = StringToUint(result[1]); - hours = StringToUint(result[0]); + seconds = cast::string_to_int(result[2]); + minutes = cast::string_to_int(result[1]); + hours = cast::string_to_int(result[0]); } return 10 * (3600 * hours + 60 * minutes + seconds); } diff --git a/Extractor/XMLParser.cpp b/Extractor/XMLParser.cpp index 273ed6693..c2ed489ef 100644 --- a/Extractor/XMLParser.cpp +++ b/Extractor/XMLParser.cpp @@ -34,6 +34,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../DataStructures/ImportNode.h" #include "../DataStructures/InputReaderFactory.h" #include "../DataStructures/Restriction.h" +#include "../Util/cast.hpp" #include "../Util/SimpleLogger.h" #include "../Util/StringUtil.h" #include "../typedefs.h" @@ -168,17 +169,17 @@ InputRestrictionContainer XMLParser::ReadXMLRestriction() if (xmlStrEqual(role, (const xmlChar *)"to") && xmlStrEqual(type, (const xmlChar *)"way")) { - restriction.toWay = StringToUint((const char *)ref); + restriction.toWay = cast::string_to_uint((const char *)ref); } if (xmlStrEqual(role, (const xmlChar *)"from") && xmlStrEqual(type, (const xmlChar *)"way")) { - restriction.fromWay = StringToUint((const char *)ref); + restriction.fromWay = cast::string_to_uint((const char *)ref); } if (xmlStrEqual(role, (const xmlChar *)"via") && xmlStrEqual(type, (const xmlChar *)"node")) { - restriction.restriction.viaNode = StringToUint((const char *)ref); + restriction.restriction.viaNode = cast::string_to_uint((const char *)ref); } if (nullptr != type) @@ -231,7 +232,7 @@ ExtractionWay XMLParser::ReadXMLWay() xmlStrEqual(child_name, (const xmlChar *)"way") == 1) { xmlChar *way_id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id"); - way.id = StringToUint((char *)way_id); + way.id = cast::string_to_uint((char *)way_id); xmlFree(way_id); xmlFree(child_name); break; @@ -265,7 +266,7 @@ ExtractionWay XMLParser::ReadXMLWay() xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref"); if (ref != nullptr) { - way.path.push_back(StringToUint((const char *)ref)); + way.path.push_back(cast::string_to_uint((const char *)ref)); xmlFree(ref); } } @@ -281,19 +282,19 @@ ImportNode XMLParser::ReadXMLNode() xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat"); if (attribute != nullptr) { - node.lat = static_cast(COORDINATE_PRECISION * StringToDouble((const char *)attribute)); + node.lat = static_cast(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute)); xmlFree(attribute); } attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon"); if (attribute != nullptr) { - node.lon = static_cast(COORDINATE_PRECISION * StringToDouble((const char *)attribute)); + node.lon = static_cast(COORDINATE_PRECISION * cast::string_to_double((const char *)attribute)); xmlFree(attribute); } attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id"); if (attribute != nullptr) { - node.node_id = StringToUint((const char *)attribute); + node.node_id = cast::string_to_uint((const char *)attribute); xmlFree(attribute); } diff --git a/Plugins/HelloWorldPlugin.h b/Plugins/HelloWorldPlugin.h index 422e7901f..cd73e43b8 100644 --- a/Plugins/HelloWorldPlugin.h +++ b/Plugins/HelloWorldPlugin.h @@ -30,7 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "BasePlugin.h" #include "../DataStructures/JSONContainer.h" -#include "../Util/StringUtil.h" +#include "../Util/cast.hpp" #include @@ -52,10 +52,10 @@ class HelloWorldPlugin : public BasePlugin std::string temp_string; json_result.values["title"] = "Hello World"; - temp_string = IntegralToString(routeParameters.zoom_level); + temp_string = cast::integral_to_string(routeParameters.zoom_level); json_result.values["zoom_level"] = temp_string; - temp_string = IntegralToString(routeParameters.check_sum); + temp_string = cast::integral_to_string(routeParameters.check_sum); json_result.values["check_sum"] = temp_string; json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no"); json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no"); @@ -67,7 +67,7 @@ class HelloWorldPlugin : public BasePlugin (!routeParameters.jsonp_parameter.empty() ? "yes" : "no"); json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no"); - temp_string = IntegralToString(routeParameters.coordinates.size()); + temp_string = cast::integral_to_string(routeParameters.coordinates.size()); json_result.values["location_count"] = temp_string; JSON::Array json_locations; @@ -79,7 +79,7 @@ class HelloWorldPlugin : public BasePlugin json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION); json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION); - json_location.values[IntegralToString(counter)] = json_coordinates; + json_location.values[cast::integral_to_string(counter)] = json_coordinates; json_locations.values.push_back(json_location); ++counter; } diff --git a/Server/Http/Reply.cpp b/Server/Http/Reply.cpp index b95a15459..e2cf0aecf 100644 --- a/Server/Http/Reply.cpp +++ b/Server/Http/Reply.cpp @@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include "../../Util/StringUtil.h" +#include "../../Util/cast.hpp" namespace http { @@ -38,7 +38,7 @@ void Reply::SetSize(const unsigned size) { if ("Content-Length" == h.name) { - h.value = IntegralToString(size); + h.value = cast::integral_to_string(size); } } } @@ -87,7 +87,7 @@ Reply Reply::StockReply(Reply::status_type status) const std::string status_string = reply.ToString(status); reply.content.insert(reply.content.end(), status_string.begin(), status_string.end()); reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); - reply.headers.emplace_back("Content-Length", IntegralToString(reply.content.size())); + reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); reply.headers.emplace_back("Content-Type", "text/html"); return reply; } diff --git a/Server/RequestHandler.cpp b/Server/RequestHandler.cpp index 53cfbbd4e..06106de74 100644 --- a/Server/RequestHandler.cpp +++ b/Server/RequestHandler.cpp @@ -88,11 +88,11 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply { reply = http::Reply::StockReply(http::Reply::badRequest); reply.content.clear(); - const unsigned position = static_cast(std::distance(request.begin(), iter)); + const auto position = std::distance(request.begin(), iter); JSON::Object json_result; json_result.values["status"] = 400; std::string message = "Query string malformed close to position "; - message += IntegralToString(position); + message += cast::integral_to_string(position); json_result.values["status_message"] = message; JSON::render(reply.content, json_result); return; @@ -113,7 +113,7 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply } // set headers - reply.headers.emplace_back("Content-Length", IntegralToString(reply.content.size())); + reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size())); if ("gpx" == route_parameters.output_format) { // gpx file reply.headers.emplace_back("Content-Type", "application/gpx+xml; charset=UTF-8"); diff --git a/Server/Server.h b/Server/Server.h index 8756cfcbe..6bc863ada 100644 --- a/Server/Server.h +++ b/Server/Server.h @@ -31,9 +31,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Connection.h" #include "RequestHandler.h" +#include "../Util/cast.hpp" #include "../Util/make_unique.hpp" #include "../Util/SimpleLogger.h" -#include "../Util/StringUtil.h" #include #include @@ -60,9 +60,9 @@ class Server explicit Server(const std::string &address, const int port, const unsigned thread_pool_size) : thread_pool_size(thread_pool_size), acceptor(io_service), - new_connection(new http::Connection(io_service, request_handler)), request_handler() + new_connection(std::make_shared(io_service, request_handler)), request_handler() { - const std::string port_string = IntegralToString(port); + const std::string port_string = cast::integral_to_string(port); boost::asio::ip::tcp::resolver resolver(io_service); boost::asio::ip::tcp::resolver::query query(address, port_string); @@ -86,9 +86,9 @@ class Server boost::bind(&boost::asio::io_service::run, &io_service)); threads.push_back(thread); } - for (unsigned i = 0; i < threads.size(); ++i) + for (auto thread : threads) { - threads[i]->join(); + thread->join(); } } @@ -102,7 +102,7 @@ class Server if (!e) { new_connection->start(); - new_connection.reset(new http::Connection(io_service, request_handler)); + new_connection = std::make_shared(io_service, request_handler); acceptor.async_accept( new_connection->socket(), boost::bind(&Server::HandleAccept, this, boost::asio::placeholders::error)); diff --git a/Util/cast.hpp b/Util/cast.hpp new file mode 100644 index 000000000..7807eda9a --- /dev/null +++ b/Util/cast.hpp @@ -0,0 +1,188 @@ +/* + +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 CAST_HPP +#define CAST_HPP + +#include +#include + +#include +#include + +struct cast +{ + // convert scoped enums to integers + template + static auto enum_to_underlying(Enumeration const value) -> typename std::underlying_type::type + { + return static_cast::type>(value); + } + + template + static typename std::enable_if::value, std::string>::type + integral_to_string(const Number value) + { + std::string output; + std::back_insert_iterator sink(output); + + if (8 == sizeof(Number)) + { + boost::spirit::karma::generate(sink, boost::spirit::karma::long_long, value); + } + else + { + if (std::is_signed::value) + { + boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value); + } + else + { + boost::spirit::karma::generate(sink, boost::spirit::karma::uint_, value); + } + } + return output; + } + + static int string_to_int(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && std::isspace(*first_digit)) + { + ++first_digit; + } + int value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::int_, value); + return value; + } + + static unsigned string_to_uint(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && (std::isspace(*first_digit) || '-' == *first_digit)) + { + ++first_digit; + } + unsigned value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::uint_, value); + return value; + } + + static uint64_t string_to_uint64(const std::string &input) + { + auto first_digit = input.begin(); + // Delete any trailing white-spaces + while (first_digit != input.end() && std::isspace(*first_digit)) + { + ++first_digit; + } + uint64_t value = 0; + boost::spirit::qi::parse(first_digit, input.end(), boost::spirit::long_long, value); + return value; + } + + // source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/ + static double string_to_double(const char *p) + { + double r = 0.0; + bool neg = false; + if (*p == '-') + { + neg = true; + ++p; + } + while (*p >= '0' && *p <= '9') + { + r = (r * 10.0) + (*p - '0'); + ++p; + } + if (*p == '.') + { + double f = 0.0; + int n = 0; + ++p; + while (*p >= '0' && *p <= '9') + { + f = (f * 10.0) + (*p - '0'); + ++p; + ++n; + } + r += f / std::pow(10.0, n); + } + if (neg) + { + r = -r; + } + return r; + } + + template struct scientific_policy : boost::spirit::karma::real_policies + { + // we want the numbers always to be in fixed format + static int floatfield(T n) + { + return boost::spirit::karma::real_policies::fmtflags::fixed; + } + static unsigned int precision(T) { return 6; } + }; + typedef boost::spirit::karma::real_generator> science_type; + + static std::string double_fixed_to_string(const double value) + { + std::string output; + std::back_insert_iterator sink(output); + boost::spirit::karma::generate(sink, science_type(), value); + if (output.size() >= 2 && output[output.size() - 2] == '.' && + output[output.size() - 1] == '0') + { + output.resize(output.size() - 2); + } + return output; + } + + static std::string double_to_string(const double value) + { + std::string output; + std::back_insert_iterator sink(output); + boost::spirit::karma::generate(sink, value); + return output; + } + + static void double_with_two_digits_to_string(const double value, + std::string &output) + { + // The largest 32-bit integer is 4294967295, that is 10 chars + // On the safe side, add 1 for sign, and 1 for trailing zero + char buffer[12]; + sprintf(buffer, "%g", value); + output = buffer; + } +}; + +#endif // CAST_HPP