Remove hand written conversion code and replace with stdlib features.
With C++11 the stdlib gains: - `std::stoi` function family to convert from `std::string` to integral type - `std::to_string` to convert from number types to `std::string` The only reason for hand-writing the conversion code therefore is performance. I benchmarked an `osrm-extract` with the hand-written code against one with the stdlib conversion features and could not find any significant difference (we switch back and forth between C++ and Lua, shaving off a few us in conversion doesn't gain us much). Formatting arithmetic types in the default format with given precision requires streams, but is doable in a few lines of idiomatic stdlib code. For this, there is now the following function template available: template <Arithmetic T, int Precision = 6> inline std::string to_string_with_precision(const T); that requires integral or floating point types and returns a formatted string in the defaukt format with the given precision applied. In addition this completely rips out Boost.Spirit from the `casts.hpp` header, resulting in faster compile times. Boom! References: - http://en.cppreference.com/w/cpp/string/basic_string/stol - http://en.cppreference.com/w/cpp/string/basic_string/to_string - http://www.kumobius.com/2013/08/c-string-to-int/
This commit is contained in:
parent
31cf8a8813
commit
f9f0ffb64d
@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "../data_structures/segment_information.hpp"
|
#include "../data_structures/segment_information.hpp"
|
||||||
#include "../data_structures/turn_instructions.hpp"
|
#include "../data_structures/turn_instructions.hpp"
|
||||||
#include "../util/bearing.hpp"
|
#include "../util/bearing.hpp"
|
||||||
|
#include "../util/cast.hpp"
|
||||||
#include "../util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "../util/json_renderer.hpp"
|
#include "../util/json_renderer.hpp"
|
||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
@ -44,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <osrm/json_container.hpp>
|
#include <osrm/json_container.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<DataFacadeT>
|
||||||
{
|
{
|
||||||
@ -327,18 +329,18 @@ template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<
|
|||||||
std::string current_turn_instruction;
|
std::string current_turn_instruction;
|
||||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||||
{
|
{
|
||||||
temp_instruction = cast::integral_to_string(
|
temp_instruction = std::to_string(
|
||||||
cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
cast::enum_to_underlying(TurnInstruction::EnterRoundAbout));
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
current_turn_instruction += "-";
|
current_turn_instruction += "-";
|
||||||
temp_instruction = cast::integral_to_string(round_about.leave_at_exit + 1);
|
temp_instruction = std::to_string(round_about.leave_at_exit + 1);
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
round_about.leave_at_exit = 0;
|
round_about.leave_at_exit = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp_instruction =
|
temp_instruction =
|
||||||
cast::integral_to_string(cast::enum_to_underlying(current_instruction));
|
std::to_string(cast::enum_to_underlying(current_instruction));
|
||||||
current_turn_instruction += temp_instruction;
|
current_turn_instruction += temp_instruction;
|
||||||
}
|
}
|
||||||
json_instruction_row.values.push_back(current_turn_instruction);
|
json_instruction_row.values.push_back(current_turn_instruction);
|
||||||
@ -348,7 +350,7 @@ template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<
|
|||||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||||
json_instruction_row.values.push_back(std::round(segment.duration / 10.));
|
json_instruction_row.values.push_back(std::round(segment.duration / 10.));
|
||||||
json_instruction_row.values.push_back(
|
json_instruction_row.values.push_back(
|
||||||
cast::integral_to_string(static_cast<unsigned>(segment.length)) + "m");
|
std::to_string(static_cast<unsigned>(segment.length)) + "m");
|
||||||
const double bearing_value = (segment.bearing / 10.);
|
const double bearing_value = (segment.bearing / 10.);
|
||||||
json_instruction_row.values.push_back(bearing::get(bearing_value));
|
json_instruction_row.values.push_back(bearing::get(bearing_value));
|
||||||
json_instruction_row.values.push_back(
|
json_instruction_row.values.push_back(
|
||||||
@ -372,8 +374,8 @@ template <class DataFacadeT> class JSONDescriptor final : public BaseDescriptor<
|
|||||||
}
|
}
|
||||||
|
|
||||||
osrm::json::Array json_last_instruction_row;
|
osrm::json::Array json_last_instruction_row;
|
||||||
temp_instruction = cast::integral_to_string(
|
temp_instruction =
|
||||||
cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
std::to_string(cast::enum_to_underlying(TurnInstruction::ReachedYourDestination));
|
||||||
json_last_instruction_row.values.push_back(temp_instruction);
|
json_last_instruction_row.values.push_back(temp_instruction);
|
||||||
json_last_instruction_row.values.push_back("");
|
json_last_instruction_row.values.push_back("");
|
||||||
json_last_instruction_row.values.push_back(0);
|
json_last_instruction_row.values.push_back(0);
|
||||||
|
@ -37,6 +37,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <boost/regex.hpp>
|
#include <boost/regex.hpp>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
bool simple_duration_is_valid(const std::string &s)
|
bool simple_duration_is_valid(const std::string &s)
|
||||||
{
|
{
|
||||||
@ -89,18 +90,18 @@ unsigned parseDuration(const std::string &s)
|
|||||||
{
|
{
|
||||||
if (1 == result.size())
|
if (1 == result.size())
|
||||||
{
|
{
|
||||||
minutes = cast::string_to_int(result[0]);
|
minutes = std::stoul(result[0]);
|
||||||
}
|
}
|
||||||
if (2 == result.size())
|
if (2 == result.size())
|
||||||
{
|
{
|
||||||
minutes = cast::string_to_int(result[1]);
|
minutes = std::stoul(result[1]);
|
||||||
hours = cast::string_to_int(result[0]);
|
hours = std::stoul(result[0]);
|
||||||
}
|
}
|
||||||
if (3 == result.size())
|
if (3 == result.size())
|
||||||
{
|
{
|
||||||
seconds = cast::string_to_int(result[2]);
|
seconds = std::stoul(result[2]);
|
||||||
minutes = cast::string_to_int(result[1]);
|
minutes = std::stoul(result[1]);
|
||||||
hours = cast::string_to_int(result[0]);
|
hours = std::stoul(result[0]);
|
||||||
}
|
}
|
||||||
return (3600 * hours + 60 * minutes + seconds);
|
return (3600 * hours + 60 * minutes + seconds);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "plugin_base.hpp"
|
#include "plugin_base.hpp"
|
||||||
|
|
||||||
#include "../util/cast.hpp"
|
|
||||||
#include "../util/json_renderer.hpp"
|
#include "../util/json_renderer.hpp"
|
||||||
|
|
||||||
#include <osrm/json_container.hpp>
|
#include <osrm/json_container.hpp>
|
||||||
@ -53,10 +52,10 @@ class HelloWorldPlugin final : public BasePlugin
|
|||||||
std::string temp_string;
|
std::string temp_string;
|
||||||
json_result.values["title"] = "Hello World";
|
json_result.values["title"] = "Hello World";
|
||||||
|
|
||||||
temp_string = cast::integral_to_string(routeParameters.zoom_level);
|
temp_string = std::to_string(routeParameters.zoom_level);
|
||||||
json_result.values["zoom_level"] = temp_string;
|
json_result.values["zoom_level"] = temp_string;
|
||||||
|
|
||||||
temp_string = cast::integral_to_string(routeParameters.check_sum);
|
temp_string = std::to_string(routeParameters.check_sum);
|
||||||
json_result.values["check_sum"] = temp_string;
|
json_result.values["check_sum"] = temp_string;
|
||||||
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
||||||
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
||||||
@ -68,7 +67,7 @@ class HelloWorldPlugin final : public BasePlugin
|
|||||||
(!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
(!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
||||||
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
||||||
|
|
||||||
temp_string = cast::integral_to_string(routeParameters.coordinates.size());
|
temp_string = std::to_string(routeParameters.coordinates.size());
|
||||||
json_result.values["location_count"] = temp_string;
|
json_result.values["location_count"] = temp_string;
|
||||||
|
|
||||||
osrm::json::Array json_locations;
|
osrm::json::Array json_locations;
|
||||||
@ -82,7 +81,7 @@ class HelloWorldPlugin final : public BasePlugin
|
|||||||
static_cast<double>(coordinate.lat / COORDINATE_PRECISION));
|
static_cast<double>(coordinate.lat / COORDINATE_PRECISION));
|
||||||
json_coordinates.values.push_back(
|
json_coordinates.values.push_back(
|
||||||
static_cast<double>(coordinate.lon / COORDINATE_PRECISION));
|
static_cast<double>(coordinate.lon / COORDINATE_PRECISION));
|
||||||
json_location.values[cast::integral_to_string(counter)] = json_coordinates;
|
json_location.values[std::to_string(counter)] = json_coordinates;
|
||||||
json_locations.values.push_back(json_location);
|
json_locations.values.push_back(json_location);
|
||||||
++counter;
|
++counter;
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include "reply.hpp"
|
#include "reply.hpp"
|
||||||
|
|
||||||
#include "../../util/cast.hpp"
|
#include <string>
|
||||||
|
|
||||||
namespace http
|
namespace http
|
||||||
{
|
{
|
||||||
@ -48,7 +48,7 @@ void reply::set_size(const std::size_t size)
|
|||||||
{
|
{
|
||||||
if ("Content-Length" == h.name)
|
if ("Content-Length" == h.name)
|
||||||
{
|
{
|
||||||
h.value = cast::integral_to_string(size);
|
h.value = std::to_string(size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ reply reply::stock_reply(const reply::status_type status)
|
|||||||
const std::string status_string = reply.status_to_string(status);
|
const std::string status_string = reply.status_to_string(status);
|
||||||
reply.content.insert(reply.content.end(), status_string.begin(), status_string.end());
|
reply.content.insert(reply.content.end(), status_string.begin(), status_string.end());
|
||||||
reply.headers.emplace_back("Access-Control-Allow-Origin", "*");
|
reply.headers.emplace_back("Access-Control-Allow-Origin", "*");
|
||||||
reply.headers.emplace_back("Content-Length", cast::integral_to_string(reply.content.size()));
|
reply.headers.emplace_back("Content-Length", std::to_string(reply.content.size()));
|
||||||
reply.headers.emplace_back("Content-Type", "text/html");
|
reply.headers.emplace_back("Content-Type", "text/html");
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
RequestHandler::RequestHandler() : routing_machine(nullptr) {}
|
RequestHandler::RequestHandler() : routing_machine(nullptr) {}
|
||||||
|
|
||||||
@ -102,7 +103,7 @@ void RequestHandler::handle_request(const http::request ¤t_request,
|
|||||||
|
|
||||||
json_result.values["status"] = 400;
|
json_result.values["status"] = 400;
|
||||||
std::string message = "Query string malformed close to position ";
|
std::string message = "Query string malformed close to position ";
|
||||||
message += cast::integral_to_string(position);
|
message += std::to_string(position);
|
||||||
json_result.values["status_message"] = message;
|
json_result.values["status_message"] = message;
|
||||||
osrm::json::render(current_reply.content, json_result);
|
osrm::json::render(current_reply.content, json_result);
|
||||||
return;
|
return;
|
||||||
@ -135,7 +136,7 @@ void RequestHandler::handle_request(const http::request ¤t_request,
|
|||||||
|
|
||||||
// set headers
|
// set headers
|
||||||
current_reply.headers.emplace_back("Content-Length",
|
current_reply.headers.emplace_back("Content-Length",
|
||||||
cast::integral_to_string(current_reply.content.size()));
|
std::to_string(current_reply.content.size()));
|
||||||
if ("gpx" == route_parameters.output_format)
|
if ("gpx" == route_parameters.output_format)
|
||||||
{ // gpx file
|
{ // gpx file
|
||||||
osrm::json::gpx_render(current_reply.content, json_result.values["route"]);
|
osrm::json::gpx_render(current_reply.content, json_result.values["route"]);
|
||||||
|
@ -31,7 +31,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "connection.hpp"
|
#include "connection.hpp"
|
||||||
#include "request_handler.hpp"
|
#include "request_handler.hpp"
|
||||||
|
|
||||||
#include "../util/cast.hpp"
|
|
||||||
#include "../util/integer_range.hpp"
|
#include "../util/integer_range.hpp"
|
||||||
#include "../util/simple_logger.hpp"
|
#include "../util/simple_logger.hpp"
|
||||||
|
|
||||||
@ -44,6 +43,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class Server
|
class Server
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ class Server
|
|||||||
: thread_pool_size(thread_pool_size), acceptor(io_service),
|
: thread_pool_size(thread_pool_size), acceptor(io_service),
|
||||||
new_connection(std::make_shared<http::Connection>(io_service, request_handler))
|
new_connection(std::make_shared<http::Connection>(io_service, request_handler))
|
||||||
{
|
{
|
||||||
const std::string port_string = cast::integral_to_string(port);
|
const auto port_string = std::to_string(port);
|
||||||
|
|
||||||
boost::asio::ip::tcp::resolver resolver(io_service);
|
boost::asio::ip::tcp::resolver resolver(io_service);
|
||||||
boost::asio::ip::tcp::resolver::query query(address, port_string);
|
boost::asio::ip::tcp::resolver::query query(address, port_string);
|
||||||
|
164
util/cast.hpp
164
util/cast.hpp
@ -28,158 +28,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef CAST_HPP
|
#ifndef CAST_HPP
|
||||||
#define CAST_HPP
|
#define CAST_HPP
|
||||||
|
|
||||||
#include <boost/spirit/include/karma.hpp>
|
|
||||||
#include <boost/spirit/include/qi.hpp>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
struct cast
|
namespace cast
|
||||||
{
|
{
|
||||||
// convert scoped enums to integers
|
template <typename Enumeration>
|
||||||
template <typename Enumeration>
|
inline auto enum_to_underlying(Enumeration const value) ->
|
||||||
static auto enum_to_underlying(Enumeration const value) ->
|
typename std::underlying_type<Enumeration>::type
|
||||||
typename std::underlying_type<Enumeration>::type
|
{
|
||||||
{
|
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
|
||||||
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Number>
|
template <typename T, int Precision = 6> inline std::string to_string_with_precision(const T x)
|
||||||
static typename std::enable_if<std::is_integral<Number>::value, std::string>::type
|
{
|
||||||
integral_to_string(const Number value)
|
static_assert(std::is_arithmetic<T>::value, "integral or floating point type required");
|
||||||
{
|
|
||||||
std::string output;
|
|
||||||
std::back_insert_iterator<std::string> sink(output);
|
|
||||||
|
|
||||||
if (8 == sizeof(Number))
|
std::ostringstream out;
|
||||||
{
|
out << std::setprecision(Precision) << x;
|
||||||
boost::spirit::karma::generate(sink, boost::spirit::karma::long_long, value);
|
return out.str();
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
|
||||||
if (std::is_signed<Number>::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) noexcept
|
|
||||||
{
|
|
||||||
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 <typename T> struct scientific_policy : boost::spirit::karma::real_policies<T>
|
|
||||||
{
|
|
||||||
// we want the numbers always to be in fixed format
|
|
||||||
static int floatfield(T) { return boost::spirit::karma::real_policies<T>::fmtflags::fixed; }
|
|
||||||
static unsigned int precision(T) { return 6; }
|
|
||||||
};
|
|
||||||
using science_type = boost::spirit::karma::real_generator<double, scientific_policy<double>>;
|
|
||||||
|
|
||||||
static std::string double_fixed_to_string(const double value)
|
|
||||||
{
|
|
||||||
std::string output;
|
|
||||||
std::back_insert_iterator<std::string> 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<std::string> 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
|
#endif // CAST_HPP
|
||||||
|
@ -111,7 +111,7 @@ struct ArrayRenderer : mapbox::util::static_visitor<>
|
|||||||
|
|
||||||
void operator()(const Number &number) const
|
void operator()(const Number &number) const
|
||||||
{
|
{
|
||||||
const std::string number_string = cast::double_fixed_to_string(number.value);
|
const std::string number_string = cast::to_string_with_precision(number.value);
|
||||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ struct XMLToArrayRenderer : mapbox::util::static_visitor<>
|
|||||||
|
|
||||||
void operator()(const Number &number) const
|
void operator()(const Number &number) const
|
||||||
{
|
{
|
||||||
const std::string number_string = cast::double_fixed_to_string(number.value);
|
const std::string number_string = cast::to_string_with_precision(number.value);
|
||||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user