move type conversions code fully to cpp file to reduce compile times across code base

This commit is contained in:
Dane Springmeyer 2013-01-04 09:27:39 -08:00
parent a01a998aff
commit 3304841009
2 changed files with 197 additions and 139 deletions

View File

@ -25,33 +25,20 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/value_types.hpp>
// stl
#include <string>
#include <cmath> // log10
// boost
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/karma.hpp>
// boost
#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>
#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 <typename T>
bool to_string(std::string & str, T value)
{
namespace karma = boost::spirit::karma;
std::back_insert_iterator<std::string> sink(str);
return karma::generate(sink, value);
}
template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> 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<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n))));
}
template <typename OutputIterator>
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 <typename OutputIterator>
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<T>::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 <typename CharEncoding, typename Tag, typename OutputIterator>
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<CharEncoding, Tag>::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<CharEncoding, Tag>::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, double_policy<double> > double_type;
std::back_insert_iterator<std::string> sink(str);
return karma::generate(sink, double_type(), value);
}
#else
template <typename T>
bool to_string(std::string & str, T value)
{
try
{
str = boost::lexical_cast<T>(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);
}}

View File

@ -22,6 +22,7 @@
// mapnik
#include <mapnik/util/conversions.hpp>
#include <mapnik/value.hpp>
// boost
#include <boost/spirit/include/qi.hpp>
@ -33,13 +34,29 @@
boost::spirit::domain_::domain, name##_expr_type); \
BOOST_AUTO(name, boost::proto::deep_copy(expr)); \
#include <cmath> // log10
namespace mapnik { namespace util {
// boost
#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>
#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<std::string> sink(str);
return karma::generate(sink, value);
}
bool to_string(std::string & str, unsigned value)
{
namespace karma = boost::spirit::karma;
std::back_insert_iterator<std::string> sink(str);
return karma::generate(sink, value);
}
bool to_string(std::string & str, bool value)
{
namespace karma = boost::spirit::karma;
std::back_insert_iterator<std::string> 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<std::string> sink(str);
return karma::generate(sink, value);
}
namespace detail {
template <typename T>
struct double_policy : boost::spirit::karma::real_policies<T>
{
typedef boost::spirit::karma::real_policies<T> 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<unsigned>(15 - boost::math::trunc(log10(traits::get_absolute_value(n))));
}
template <typename OutputIterator>
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 <typename OutputIterator>
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<T>::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 <typename CharEncoding, typename Tag, typename OutputIterator>
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<CharEncoding, Tag>::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<CharEncoding, Tag>::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, detail::double_policy<double> > double_type;
std::back_insert_iterator<std::string> sink(str);
return karma::generate(sink, double_type(), value);
}
#else
template <typename T>
bool to_string_lexical(std::string & str, T value)
{
try
{
str = boost::lexical_cast<T>(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
}