diff --git a/include/mbgl/util/string.hpp b/include/mbgl/util/string.hpp index c44a84a53a9..418e1872f3a 100644 --- a/include/mbgl/util/string.hpp +++ b/include/mbgl/util/string.hpp @@ -1,27 +1,14 @@ #pragma once #include -#include #include -#include +#include // Polyfill needed by Qt when building for Android with GCC #if defined(__ANDROID__) && defined(__GLIBCXX__) -// TODO: remove use std::to_string to avoid using -#include - namespace std { -template -std::string to_string(T value) -{ - std::ostringstream oss; - oss << value; - - return oss.str(); -} - inline int stoi(const std::string &str) { return atoi(str.c_str()); @@ -38,44 +25,70 @@ inline float stof(const std::string &str) { namespace mbgl { namespace util { -template -inline std::string toString(T t) { - return std::to_string(t); +std::string toString(int64_t); +std::string toString(uint64_t); +std::string toString(int32_t); +std::string toString(uint32_t); +std::string toString(double, bool decimal = false); + +inline std::string toString(int16_t t) { + return toString(static_cast(t)); } -inline std::string toString(int8_t num) { - return std::to_string(int(num)); +inline std::string toString(uint16_t t) { + return toString(static_cast(t)); } -inline std::string toString(uint8_t num) { - return std::to_string(unsigned(num)); +inline std::string toString(int8_t t) { + return toString(static_cast(t)); } -std::string toString(float, bool decimal = false); -std::string toString(double, bool decimal = false); -std::string toString(long double, bool decimal = false); +inline std::string toString(uint8_t t) { + return toString(static_cast(t)); +} -std::string toHex(size_t); +template ::value>> +inline std::string toString(unsigned long t) { + return toString(static_cast(t)); +} -inline std::string toString(std::exception_ptr error) { - assert(error); +template ::value>> +inline std::string toString(unsigned long long t) { + return toString(static_cast(t)); +} - if (!error) { - return "(null)"; - } +inline std::string toString(float t, bool decimal = false) { + return toString(static_cast(t), decimal); +} - try { - std::rethrow_exception(error); - } catch (const std::exception& ex) { - return ex.what(); - } catch (...) { - return "Unknown exception type"; - } +inline std::string toString(long double t, bool decimal = false) { + return toString(static_cast(t), decimal); } +std::string toString(std::exception_ptr); + +template +std::string toString(T) = delete; + +std::string toHex(size_t); + inline float stof(const std::string& str) { return std::stof(str); } } // namespace util } // namespace mbgl + +// Android's libstdc++ doesn't have std::to_string() +#if defined(__ANDROID__) && defined(__GLIBCXX__) + +namespace std { + +template +inline std::string to_string(T value) { + return mbgl::util::toString(value); +} + +} // namespace std + +#endif diff --git a/platform/android/src/geojson/feature.cpp b/platform/android/src/geojson/feature.cpp index f0ed097842a..767b145a898 100644 --- a/platform/android/src/geojson/feature.cpp +++ b/platform/android/src/geojson/feature.cpp @@ -33,7 +33,7 @@ class FeatureIdVisitor { public: template std::string operator()(const T& i) const { - return std::to_string(i); + return util::toString(i); } std::string operator()(const std::string& i) const { diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp index e1b3493f0fe..bb6fc90e45b 100644 --- a/platform/android/src/http_file_source.cpp +++ b/platform/android/src/http_file_source.cpp @@ -151,9 +151,9 @@ void HTTPRequest::onResponse(jni::JNIEnv& env, int code, } response.error = std::make_unique(Error::Reason::RateLimit, "HTTP status code 429", http::parseRetryHeaders(retryAfter, xRateLimitReset)); } else if (code >= 500 && code < 600) { - response.error = std::make_unique(Error::Reason::Server, std::string{ "HTTP status code " } + std::to_string(code)); + response.error = std::make_unique(Error::Reason::Server, std::string{ "HTTP status code " } + util::toString(code)); } else { - response.error = std::make_unique(Error::Reason::Other, std::string{ "HTTP status code " } + std::to_string(code)); + response.error = std::make_unique(Error::Reason::Other, std::string{ "HTTP status code " } + util::toString(code)); } async.send(); diff --git a/src/mbgl/util/string.cpp b/src/mbgl/util/string.cpp index 06ccb569688..2f737e74360 100644 --- a/src/mbgl/util/string.cpp +++ b/src/mbgl/util/string.cpp @@ -1,19 +1,67 @@ #include -#include + +#include +#include + +#include namespace mbgl { namespace util { -std::string toString(float num, bool decimal) { - return dtoa(num, decimal); +std::string toString(int32_t t) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.Int(t); + return s.GetString(); +} + +std::string toString(uint32_t t) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.Uint(t); + return s.GetString(); } -std::string toString(double num, bool decimal) { - return dtoa(num, decimal); +std::string toString(int64_t t) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.Int64(t); + return s.GetString(); } -std::string toString(long double num, bool decimal) { - return dtoa(num, decimal); +std::string toString(uint64_t t) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.Uint64(t); + return s.GetString(); +} + +std::string toString(double t, bool decimal) { + rapidjson::StringBuffer s; + rapidjson::Writer writer(s); + writer.Double(t); + std::string data = s.GetString(); + if (!decimal && data.length() >= 3 && data[data.length() - 1] == '0' && data[data.length() - 2] == '.') { + // Remove trailing ".0" for integers + data.resize(data.length() - 2); + } + return data; +} + +std::string toString(std::exception_ptr error) { + assert(error); + + if (!error) { + return "(null)"; + } + + try { + std::rethrow_exception(error); + } catch (const std::exception& ex) { + return ex.what(); + } catch (...) { + return "Unknown exception type"; + } } namespace {