diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index da7e69198..7b689bd59 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -25,33 +25,20 @@ // mapnik #include +#include // stl #include -#include // log10 - -// boost -#include -#include - -// boost -#include -#include // trunc to avoid needing C++11 - -#if BOOST_VERSION >= 104500 -#include -#include -#else -#include -#endif namespace mapnik { namespace util { MAPNIK_DECL bool string2int(const char * value, int & result); MAPNIK_DECL bool string2int(std::string const& value, int & result); -MAPNIK_DECL bool string2longlong(const char * value, boost::long_long_type & result); -MAPNIK_DECL bool string2longlong(std::string const& value, boost::long_long_type & result); +#ifdef BIGINT +MAPNIK_DECL bool string2int(const char * value, mapnik::value_integer & result); +MAPNIK_DECL bool string2int(std::string const& value, mapnik::value_integer & result); +#endif MAPNIK_DECL bool string2double(std::string const& value, double & result); MAPNIK_DECL bool string2double(const char * value, double & result); @@ -59,124 +46,11 @@ MAPNIK_DECL bool string2double(const char * value, double & result); MAPNIK_DECL bool string2float(std::string const& value, float & result); MAPNIK_DECL bool string2float(const char * value, float & result); -#if BOOST_VERSION >= 104500 -// generic -template -bool to_string(std::string & str, T value) -{ - namespace karma = boost::spirit::karma; - std::back_insert_iterator sink(str); - return karma::generate(sink, value); -} - -template -struct double_policy : boost::spirit::karma::real_policies -{ - typedef boost::spirit::karma::real_policies base_type; - - static int floatfield(T n) { - using namespace boost::spirit; // for traits - - if (traits::test_zero(n)) - return base_type::fmtflags::fixed; - - T abs_n = traits::get_absolute_value(n); - return (abs_n >= 1e16 || abs_n < 1e-4) - ? base_type::fmtflags::scientific : base_type::fmtflags::fixed; - } - - static unsigned precision(T n) { - if ( n == 0.0 ) return 0; - using namespace boost::spirit; // for traits - return static_cast(15 - boost::math::trunc(log10(traits::get_absolute_value(n)))); - } - - template - static bool dot(OutputIterator& sink, T n, unsigned precision) { - if (n == 0.0) return true; // avoid trailing zeroes - return base_type::dot(sink, n, precision); - } - - template - static bool fraction_part (OutputIterator& sink, T n - , unsigned precision_, unsigned precision) - { - // NOTE: copied from karma only to avoid trailing zeroes - // (maybe a bug ?) - - // allow for ADL to find the correct overload for floor and log10 - using namespace std; - - using namespace boost::spirit; // for traits - using namespace boost::spirit::karma; // for char_inserter - using namespace boost; // for remove_const - - if ( traits::test_zero(n) ) return true; // this part added to karma - - // The following is equivalent to: - // generate(sink, right_align(precision, '0')[ulong], n); - // but it's spelled out to avoid inter-modular dependencies. - - typename remove_const::type digits = - (traits::test_zero(n) ? 0 : floor(log10(n))) + 1; - bool r = true; - for (/**/; r && digits < precision_; digits = digits + 1) - r = char_inserter<>::call(sink, '0'); - if (precision && r) - r = int_inserter<10>::call(sink, n); - return r; - } - - template - static bool exponent (OutputIterator& sink, long n) - { - // NOTE: copied from karma to force sign in exponent - const bool force_sign = true; - - using namespace boost::spirit; // for traits - using namespace boost::spirit::karma; // for char_inserter, sign_inserter - - long abs_n = traits::get_absolute_value(n); - bool r = char_inserter::call(sink, 'e') && - sign_inserter::call(sink, traits::test_zero(n) - , traits::test_negative(n), force_sign); - - // the C99 Standard requires at least two digits in the exponent - if (r && abs_n < 10) - r = char_inserter::call(sink, '0'); - return r && int_inserter<10>::call(sink, abs_n); - } - -}; - - -// specialisation for double -template <> -inline bool to_string(std::string & str, double value) -{ - namespace karma = boost::spirit::karma; - typedef karma::real_generator > double_type; - std::back_insert_iterator sink(str); - return karma::generate(sink, double_type(), value); -} - -#else - -template -bool to_string(std::string & str, T value) -{ - try - { - str = boost::lexical_cast(value); - return true; - } - catch (std::exception const& ex) - { - return false; - } -} - -#endif +MAPNIK_DECL bool to_string(std::string & str, int value); +MAPNIK_DECL bool to_string(std::string & str, unsigned value); +MAPNIK_DECL bool to_string(std::string & str, bool value); +MAPNIK_DECL bool to_string(std::string & str, double value); +MAPNIK_DECL bool to_string(std::string & str, mapnik::value_integer value); }} diff --git a/src/conversions.cpp b/src/conversions.cpp index 549aad498..3887b32ae 100644 --- a/src/conversions.cpp +++ b/src/conversions.cpp @@ -22,6 +22,7 @@ // mapnik #include +#include // boost #include @@ -33,13 +34,29 @@ boost::spirit::domain_::domain, name##_expr_type); \ BOOST_AUTO(name, boost::proto::deep_copy(expr)); \ +#include // log10 -namespace mapnik { namespace util { +// boost +#include +#include // trunc to avoid needing C++11 + +#if BOOST_VERSION >= 104500 +#include +#include +#else +#include +#endif + +namespace mapnik { + +namespace util { using namespace boost::spirit; BOOST_SPIRIT_AUTO(qi, INTEGER, qi::int_) +#ifdef BIGINT BOOST_SPIRIT_AUTO(qi, LONGLONG, qi::long_long) +#endif BOOST_SPIRIT_AUTO(qi, FLOAT, qi::float_) BOOST_SPIRIT_AUTO(qi, DOUBLE, qi::double_) @@ -64,7 +81,8 @@ bool string2int(std::string const& value, int & result) return r && (str_beg == str_end); } -bool string2longlong(const char * value, boost::long_long_type & result) +#ifdef BIGINT +bool string2int(const char * value, mapnik::value_integer & result) { size_t length = strlen(value); if (length < 1 || value == NULL) @@ -75,7 +93,7 @@ bool string2longlong(const char * value, boost::long_long_type & result) return r && (iter == end); } -bool string2longlong(std::string const& value, boost::long_long_type & result) +bool string2int(std::string const& value, mapnik::value_integer & result) { if (value.empty()) return false; @@ -84,6 +102,7 @@ bool string2longlong(std::string const& value, boost::long_long_type & result) bool r = qi::phrase_parse(str_beg,str_end,LONGLONG,ascii::space,result); return r && (str_beg == str_end); } +#endif bool string2double(std::string const& value, double & result) { @@ -127,5 +146,170 @@ bool string2float(const char * value, float & result) return r && (iter == end); } + +#if BOOST_VERSION >= 104500 + +bool to_string(std::string & str, int value) +{ + namespace karma = boost::spirit::karma; + std::back_insert_iterator sink(str); + return karma::generate(sink, value); } + +bool to_string(std::string & str, unsigned value) +{ + namespace karma = boost::spirit::karma; + std::back_insert_iterator sink(str); + return karma::generate(sink, value); +} + +bool to_string(std::string & str, bool value) +{ + namespace karma = boost::spirit::karma; + std::back_insert_iterator sink(str); + return karma::generate(sink, value); +} + +bool to_string(std::string & str, boost::long_long_type value) +{ + namespace karma = boost::spirit::karma; + std::back_insert_iterator sink(str); + return karma::generate(sink, value); +} + +namespace detail { + template + struct double_policy : boost::spirit::karma::real_policies + { + typedef boost::spirit::karma::real_policies base_type; + + static int floatfield(T n) { + using namespace boost::spirit; // for traits + + if (traits::test_zero(n)) + return base_type::fmtflags::fixed; + + T abs_n = traits::get_absolute_value(n); + return (abs_n >= 1e16 || abs_n < 1e-4) + ? base_type::fmtflags::scientific : base_type::fmtflags::fixed; + } + + static unsigned precision(T n) { + if ( n == 0.0 ) return 0; + using namespace boost::spirit; // for traits + return static_cast(15 - boost::math::trunc(log10(traits::get_absolute_value(n)))); + } + + template + static bool dot(OutputIterator& sink, T n, unsigned precision) { + if (n == 0.0) return true; // avoid trailing zeroes + return base_type::dot(sink, n, precision); + } + + template + static bool fraction_part (OutputIterator& sink, T n + , unsigned precision_, unsigned precision) + { + // NOTE: copied from karma only to avoid trailing zeroes + // (maybe a bug ?) + + // allow for ADL to find the correct overload for floor and log10 + using namespace std; + + using namespace boost::spirit; // for traits + using namespace boost::spirit::karma; // for char_inserter + using namespace boost; // for remove_const + + if ( traits::test_zero(n) ) return true; // this part added to karma + + // The following is equivalent to: + // generate(sink, right_align(precision, '0')[ulong], n); + // but it's spelled out to avoid inter-modular dependencies. + + typename remove_const::type digits = + (traits::test_zero(n) ? 0 : floor(log10(n))) + 1; + bool r = true; + for (/**/; r && digits < precision_; digits = digits + 1) + r = char_inserter<>::call(sink, '0'); + if (precision && r) + r = int_inserter<10>::call(sink, n); + return r; + } + + template + static bool exponent (OutputIterator& sink, long n) + { + // NOTE: copied from karma to force sign in exponent + const bool force_sign = true; + + using namespace boost::spirit; // for traits + using namespace boost::spirit::karma; // for char_inserter, sign_inserter + + unsigned long abs_n = traits::get_absolute_value(n); + bool r = char_inserter::call(sink, 'e') && + sign_inserter::call(sink, traits::test_zero(n) + , traits::test_negative(n), force_sign); + + // the C99 Standard requires at least two digits in the exponent + if (r && abs_n < 10) + r = char_inserter::call(sink, '0'); + return r && int_inserter<10>::call(sink, abs_n); + } + + }; +} + +bool to_string(std::string & str, double value) +{ + namespace karma = boost::spirit::karma; + typedef karma::real_generator > double_type; + std::back_insert_iterator sink(str); + return karma::generate(sink, double_type(), value); +} + +#else + +template +bool to_string_lexical(std::string & str, T value) +{ + try + { + str = boost::lexical_cast(value); + return true; + } + catch (std::exception const& ex) + { + return false; + } +} + +bool to_string(std::string & str, int value) +{ + return to_string_lexical(str, value); +} + +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); +} + +bool to_string(std::string & str, boost::long_long_type value) +{ + return to_string_lexical(str, value); +} + +#endif + +} // end namespace util + }