Merge pull request #1697 from mapnik/faster_to_string
default to fast, simple, and correct (per ostringstream) to_string conversions
This commit is contained in:
commit
27554cbef8
2 changed files with 233 additions and 55 deletions
|
@ -24,7 +24,8 @@
|
|||
#include <mapnik/util/conversions.hpp>
|
||||
#include <mapnik/value_types.hpp>
|
||||
|
||||
// boost
|
||||
#include <cstring>
|
||||
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
|
||||
#define BOOST_SPIRIT_AUTO(domain_, name, expr) \
|
||||
|
@ -34,20 +35,18 @@
|
|||
boost::spirit::domain_::domain, name##_expr_type); \
|
||||
BOOST_AUTO(name, boost::proto::deep_copy(expr)); \
|
||||
|
||||
#include <cmath> // log10
|
||||
//#define MAPNIK_KARMA_TO_STRING
|
||||
|
||||
// boost
|
||||
#ifdef MAPNIK_KARMA_TO_STRING
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11
|
||||
|
||||
#if BOOST_VERSION >= 104500
|
||||
#include <boost/config/warning_disable.hpp>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#else
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#if BOOST_VERSION < 104500
|
||||
#error you must have >= boost 104500 to use karma for string output
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <boost/spirit/include/karma.hpp>
|
||||
#include <cmath> // log10
|
||||
#include <boost/math/special_functions/trunc.hpp> // trunc to avoid needing C++11
|
||||
#endif
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
@ -62,8 +61,6 @@ BOOST_SPIRIT_AUTO(qi, LONGLONG, qi::long_long)
|
|||
BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_)
|
||||
BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_)
|
||||
|
||||
|
||||
|
||||
struct bool_symbols : qi::symbols<char,bool>
|
||||
{
|
||||
bool_symbols()
|
||||
|
@ -163,7 +160,7 @@ bool string2float(const char * value, float & result)
|
|||
return r && (iter == end);
|
||||
}
|
||||
|
||||
#if BOOST_VERSION >= 104500
|
||||
#ifdef MAPNIK_KARMA_TO_STRING
|
||||
|
||||
bool to_string(std::string & str, int value)
|
||||
{
|
||||
|
@ -286,48 +283,89 @@ bool to_string(std::string & str, double value)
|
|||
|
||||
#else
|
||||
|
||||
template <typename T>
|
||||
bool to_string_lexical(std::string & str, T value)
|
||||
bool to_string(std::string & s, int val)
|
||||
{
|
||||
try
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
str = boost::lexical_cast<T>(value);
|
||||
return true;
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%d", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool to_string(std::string & str, int value)
|
||||
{
|
||||
return to_string_lexical(str, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef BIGINT
|
||||
bool to_string(std::string & str, mapnik::value_integer value)
|
||||
bool to_string(std::string & s, mapnik::value_integer val)
|
||||
{
|
||||
return to_string_lexical(str, value);
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%lld", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool to_string(std::string & str, unsigned value)
|
||||
{
|
||||
return to_string_lexical(str, value);
|
||||
}
|
||||
|
||||
bool to_string(std::string & str, bool value)
|
||||
{
|
||||
return to_string_lexical(str, value);
|
||||
}
|
||||
|
||||
bool to_string(std::string & str, double value)
|
||||
{
|
||||
return to_string_lexical(str, value);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool to_string(std::string & s, unsigned val)
|
||||
{
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%u", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool to_string(std::string & s, bool val)
|
||||
{
|
||||
if (val) s = "true";
|
||||
else s = "false";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool to_string(std::string & s, double val)
|
||||
{
|
||||
double abs_n = std::fabs(val);
|
||||
std::string format;
|
||||
if (abs_n >= 1e16 || abs_n < 1e-4)
|
||||
{
|
||||
format = "%e";
|
||||
}
|
||||
else
|
||||
{
|
||||
format = "%g";
|
||||
}
|
||||
s.resize(s.capacity());
|
||||
while (true)
|
||||
{
|
||||
size_t n2 = static_cast<size_t>(snprintf(&s[0], s.size()+1, "%g", val));
|
||||
if (n2 <= s.size())
|
||||
{
|
||||
s.resize(n2);
|
||||
break;
|
||||
}
|
||||
s.resize(n2);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // end namespace util
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <boost/version.hpp>
|
||||
#include <mapnik/value_types.hpp>
|
||||
#include <mapnik/util/conversions.hpp>
|
||||
#include <boost/detail/lightweight_test.hpp>
|
||||
#include <iostream>
|
||||
|
@ -69,16 +70,104 @@ int main( int, char*[] )
|
|||
BOOST_TEST_EQ( out, "0.000123457" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1000000000000000));
|
||||
BOOST_TEST_EQ( out, "1000000000000000" );
|
||||
to_string(out, double(0.0001));
|
||||
BOOST_TEST_EQ( out, "0.0001" );
|
||||
out.clear();
|
||||
|
||||
|
||||
to_string(out, double(0.00001));
|
||||
BOOST_TEST_EQ( out, "1e-05" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.000001));
|
||||
BOOST_TEST_EQ( out, "1e-06" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.0000001));
|
||||
BOOST_TEST_EQ( out, "1e-07" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.00000001));
|
||||
BOOST_TEST_EQ( out, "1e-08" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.000000001));
|
||||
BOOST_TEST_EQ( out, "1e-09" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.0000000001));
|
||||
BOOST_TEST_EQ( out, "1e-10" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.00000000001));
|
||||
BOOST_TEST_EQ( out, "1e-11" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.000000000001));
|
||||
BOOST_TEST_EQ( out, "1e-12" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.0000000000001));
|
||||
BOOST_TEST_EQ( out, "1e-13" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.00000000000001));
|
||||
BOOST_TEST_EQ( out, "1e-14" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(0.000000000000001));
|
||||
BOOST_TEST_EQ( out, "1e-15" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(100000));
|
||||
BOOST_TEST_EQ( out, "100000" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1000000));
|
||||
BOOST_TEST_EQ( out, "1e+06" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(10000000));
|
||||
BOOST_TEST_EQ( out, "1e+07" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(100000000));
|
||||
BOOST_TEST_EQ( out, "1e+08" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1000000000));
|
||||
BOOST_TEST_EQ( out, "1e+09" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(10000000000));
|
||||
BOOST_TEST_EQ( out, "1e+10" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(100000000000));
|
||||
BOOST_TEST_EQ( out, "1e+11" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1000000000000));
|
||||
BOOST_TEST_EQ( out, "1e+12" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(10000000000000));
|
||||
BOOST_TEST_EQ( out, "1e+13" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(100000000000000));
|
||||
BOOST_TEST_EQ( out, "1e+14" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1000000000000005));
|
||||
BOOST_TEST_EQ( out, "1e+15" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(-1000000000000000));
|
||||
BOOST_TEST_EQ( out, "-1000000000000000" );
|
||||
BOOST_TEST_EQ( out, "-1e+15" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(100000000000000.1));
|
||||
BOOST_TEST_EQ( out, "100000000000000.1" );
|
||||
BOOST_TEST_EQ( out, "1e+14" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1.00001));
|
||||
|
@ -86,7 +175,11 @@ int main( int, char*[] )
|
|||
out.clear();
|
||||
|
||||
to_string(out, double(1234000000000000));
|
||||
BOOST_TEST_EQ( out, "1234000000000000" );
|
||||
BOOST_TEST_EQ( out, "1.234e+15" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1e+16));
|
||||
BOOST_TEST_EQ( out, "1e+16" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, double(1.234e+16));
|
||||
|
@ -96,12 +189,59 @@ int main( int, char*[] )
|
|||
to_string(out, double(-1.234e+16));
|
||||
BOOST_TEST_EQ( out, "-1.234e+16" );
|
||||
out.clear();
|
||||
// https://github.com/mapbox/tilemill/issues/1456
|
||||
to_string(out, double(8.3));
|
||||
BOOST_TEST_EQ( out, "8.3" );
|
||||
out.clear();
|
||||
|
||||
// Test int
|
||||
|
||||
to_string(out, int(2));
|
||||
// int
|
||||
to_string(out, int(2));
|
||||
BOOST_TEST_EQ( out, "2" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, int(0));
|
||||
BOOST_TEST_EQ( out, "0" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, int(-2));
|
||||
BOOST_TEST_EQ( out, "-2" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, int(2147483647));
|
||||
BOOST_TEST_EQ( out, "2147483647" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, int(-2147483648));
|
||||
BOOST_TEST_EQ( out, "-2147483648" );
|
||||
out.clear();
|
||||
|
||||
// unsigned
|
||||
to_string(out, unsigned(4294967295));
|
||||
BOOST_TEST_EQ( out, "4294967295" );
|
||||
out.clear();
|
||||
|
||||
#ifdef BIGINT
|
||||
// long long
|
||||
to_string(out,mapnik::value_integer(-0));
|
||||
BOOST_TEST_EQ( out, "0" );
|
||||
out.clear();
|
||||
|
||||
to_string(out,mapnik::value_integer(-2));
|
||||
BOOST_TEST_EQ( out, "-2" );
|
||||
out.clear();
|
||||
|
||||
to_string(out,mapnik::value_integer(9223372036854775807));
|
||||
BOOST_TEST_EQ( out, "9223372036854775807" );
|
||||
out.clear();
|
||||
#endif
|
||||
// bool
|
||||
to_string(out, true);
|
||||
BOOST_TEST_EQ( out, "true" );
|
||||
out.clear();
|
||||
|
||||
to_string(out, false);
|
||||
BOOST_TEST_EQ( out, "false" );
|
||||
out.clear();
|
||||
}
|
||||
catch (std::exception const & ex)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue