[srs] Implement str_cast and use it instead of lexical_cast.

This commit is contained in:
Adam Wulkiewicz
2018-04-18 00:33:47 +02:00
parent 8feb7ca7ba
commit ae75d05c2c
4 changed files with 170 additions and 23 deletions

View File

@@ -41,18 +41,12 @@
#include <string>
#include <boost/algorithm/string.hpp>
#include <boost/config.hpp>
#include <boost/static_assert.hpp>
#if !defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
#include <boost/lexical_cast.hpp>
#endif // !defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
#include <boost/algorithm/string.hpp>
#include <boost/config.hpp>
#include <boost/geometry/core/cs.hpp>
#include <boost/geometry/srs/projections/str_cast.hpp>
#include <boost/geometry/util/math.hpp>
namespace boost { namespace geometry { namespace projections
@@ -145,11 +139,7 @@ struct dms_parser
template <size_t I>
static inline void assign_dms(dms_value& dms, std::string& value, bool& has_value)
{
#if !defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
dms.dms[I] = boost::lexical_cast<T>(value.c_str());
#else // !defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
dms.dms[I] = std::atof(value.c_str());
#endif // !defined(BOOST_GEOMETRY_NO_LEXICAL_CAST)
dms.dms[I] = geometry::str_cast<T>(value);
dms.has_dms[I] = true;
has_value = false;
value.clear();

View File

@@ -44,7 +44,6 @@
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range.hpp>
#include <boost/type_traits/is_same.hpp>
@@ -157,12 +156,12 @@ inline void pj_init_units(std::vector<pvalue<T> > const& params,
std::size_t const pos = s.find('/');
if (pos == std::string::npos)
{
to_meter = lexical_cast<T>(s);
to_meter = geometry::str_cast<T>(s);
}
else
{
T const numerator = lexical_cast<T>(s.substr(0, pos));
T const denominator = lexical_cast<T>(s.substr(pos + 1));
T const numerator = geometry::str_cast<T>(s.substr(0, pos));
T const denominator = geometry::str_cast<T>(s.substr(pos + 1));
if (numerator == 0.0 || denominator == 0.0)
{
BOOST_THROW_EXCEPTION( projection_exception(error_unit_factor_less_than_0) );
@@ -316,8 +315,8 @@ inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool
dms_parser<T, true> parser;
// TODO: Handle case when lexical_cast is not used consistently.
// This should probably be done in dms_parser.
// TODO: Is this try-catch needed?
// In other cases the bad_str_cast exception is simply thrown
BOOST_TRY
{
if (value.empty()) {
@@ -326,7 +325,7 @@ inline parameters<T> pj_init(BGParams const& bg_params, R const& arguments, bool
pin.from_greenwich = parser.apply(value).angle();
}
}
BOOST_CATCH(boost::bad_lexical_cast const&)
BOOST_CATCH(geometry::bad_str_cast const&)
{
BOOST_THROW_EXCEPTION( projection_exception(error_unknown_prime_meridian) );
}

View File

@@ -122,7 +122,7 @@ inline bool pj_param_i(std::vector<pvalue<T> > const& pl, std::string const& nam
typename std::vector<pvalue<T> >::const_iterator it = pj_param_find(pl, name);
if (it != pl.end())
{
par = atoi(it->s.c_str());
par = geometry::str_cast<int>(it->s);
return true;
}
return false;
@@ -135,7 +135,7 @@ inline bool pj_param_f(std::vector<pvalue<T> > const& pl, std::string const& nam
typename std::vector<pvalue<T> >::const_iterator it = pj_param_find(pl, name);
if (it != pl.end())
{
par = atof(it->s.c_str());
par = geometry::str_cast<T>(it->s);
return true;
}
return false;

View File

@@ -0,0 +1,158 @@
// Boost.Geometry
// Copyright (c) 2018, Oracle and/or its affiliates.
// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_GEOMETRY_SRS_PROJECTIONS_STR_CAST_HPP
#define BOOST_GEOMETRY_SRS_PROJECTIONS_STR_CAST_HPP
#include <boost/config.hpp>
#include <boost/geometry/core/exception.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_signed.hpp>
#include <cstdlib>
#include <string>
namespace boost { namespace geometry
{
class bad_str_cast : public geometry::exception
{
virtual char const* what() const throw()
{
return "Unable to convert from string.";
}
};
#ifndef DOXYGEN_NO_DETAIL
namespace detail
{
template
<
typename T,
bool IsIntegral = boost::is_integral<T>::value,
bool IsSigned = boost::is_signed<T>::value
>
struct str_cast_traits_strtox
{
static inline T apply(const char *str, char **str_end)
{
return strtod(str, str_end);
}
};
template <typename T>
struct str_cast_traits_strtox<T, true, true>
{
static inline T apply(const char *str, char **str_end)
{
return strtol(str, str_end, 0);
}
};
template <typename T>
struct str_cast_traits_strtox<T, true, false>
{
static inline T apply(const char *str, char **str_end)
{
return strtoul(str, str_end, 0);
}
};
template <typename T>
struct str_cast_traits_strtox<T, false, false>
{
static inline T apply(const char *str, char **str_end)
{
return strtod(str, str_end);
}
};
// Assuming a compiler supporting r-value references
// supports long long and strtoll, strtoull, strtof, strtold
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
template <>
struct str_cast_traits_strtox<long long, true, true>
{
static inline long long apply(const char *str, char **str_end)
{
return strtoll(str, str_end, 0);
}
};
template <>
struct str_cast_traits_strtox<unsigned long long, true, false>
{
static inline unsigned long long apply(const char *str, char **str_end)
{
return strtoull(str, str_end, 0);
}
};
template <>
struct str_cast_traits_strtox<float, false, false>
{
static inline float apply(const char *str, char **str_end)
{
return strtof(str, str_end);
}
};
template <>
struct str_cast_traits_strtox<long double, false, false>
{
static inline long double apply(const char *str, char **str_end)
{
return strtold(str, str_end);
}
};
#endif // C++11 strtox supported
template <typename T>
struct str_cast_traits_generic
{
static inline T apply(const char *str)
{
char * str_end = (char*)(void*)str;
T res = str_cast_traits_strtox
<
typename boost::remove_cv<T>::type
>::apply(str, &str_end);
if (str_end == str)
{
BOOST_THROW_EXCEPTION( bad_str_cast() );
}
return res;
}
};
} // namespace detail
#endif // DOXYGEN_NO_DETAIL
template <typename T>
struct str_cast_traits
{
template <typename String>
static inline T apply(String const& str)
{
return detail::str_cast_traits_generic<T>::apply(str.c_str());
}
};
template <typename T, typename String>
inline T str_cast(String const& str)
{
return str_cast_traits<T>::apply(str);
}
}} // namespace boost::geometry
#endif // BOOST_GEOMETRY_SRS_PROJECTIONS_STR_CAST_HPP