Sprout/sprout/cstdlib/str_to_float.hpp

295 lines
9.1 KiB
C++
Raw Normal View History

2013-08-08 09:54:33 +00:00
/*=============================================================================
2016-02-25 09:48:28 +00:00
Copyright (c) 2011-2016 Bolero MURAKAMI
2013-08-08 09:54:33 +00:00
https://github.com/bolero-MURAKAMI/Sprout
Distributed under 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)
=============================================================================*/
2012-04-16 02:21:40 +00:00
#ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP
#define SPROUT_CSTDLIB_STR_TO_FLOAT_HPP
#include <cstdlib>
#include <cmath>
2012-04-16 03:00:20 +00:00
#include <type_traits>
2012-04-16 02:21:40 +00:00
#include <sprout/config.hpp>
#include <sprout/workaround/std/cstddef.hpp>
2013-08-06 15:15:09 +00:00
#include <sprout/limits.hpp>
2012-04-16 02:21:40 +00:00
#include <sprout/iterator/operation.hpp>
#include <sprout/ctype/ascii.hpp>
2014-10-27 01:16:49 +00:00
#include <sprout/detail/char_literal.hpp>
#include <sprout/detail/char_type_of_consecutive.hpp>
2012-04-16 02:21:40 +00:00
namespace sprout {
namespace detail {
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_scale(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
long exponent = 0,
long n = 0,
FloatType p10 = FloatType(10)
)
{
return n ? sprout::detail::str_to_float_impl_scale<FloatType>(
str,
negative,
n & 1 ? (exponent < 0 ? number / p10 : number * p10) : number,
num_digits,
num_decimals,
exponent,
n >> 1,
p10 * p10
)
: number
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_exponent_2(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
2013-07-22 13:00:09 +00:00
long exponent = 0
2012-04-16 02:21:40 +00:00
)
{
2013-08-06 15:15:09 +00:00
return exponent >= sprout::numeric_limits<FloatType>::min_exponent
&& exponent <= sprout::numeric_limits<FloatType>::max_exponent
2012-04-16 02:21:40 +00:00
? sprout::detail::str_to_float_impl_scale<FloatType>(
str,
negative,
number,
num_digits,
num_decimals,
exponent,
exponent < 0 ? -exponent : exponent
)
: HUGE_VAL
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_exponent_1(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
long exponent = 0,
long n = 0
)
{
typedef typename std::iterator_traits<NullTerminatedIterator>::value_type char_type;
2014-10-27 01:16:49 +00:00
SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits<char_type>::value);
2012-04-16 02:21:40 +00:00
return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl_exponent_1<FloatType>(
sprout::next(str),
negative,
number,
num_digits,
num_decimals,
exponent,
2014-10-27 01:16:49 +00:00
n * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type))
2012-04-16 02:21:40 +00:00
)
: sprout::detail::str_to_float_impl_exponent_2<FloatType>(
str,
negative,
number,
num_digits,
num_decimals,
2013-07-22 13:00:09 +00:00
negative ? exponent + n : exponent - n
2012-04-16 02:21:40 +00:00
)
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_exponent(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
long exponent = 0
)
{
typedef typename std::iterator_traits<NullTerminatedIterator>::value_type char_type;
2014-10-27 01:16:49 +00:00
return (*str == SPROUT_CHAR_LITERAL('e', char_type) || *str == SPROUT_CHAR_LITERAL('E', char_type))
? *sprout::next(str) == SPROUT_CHAR_LITERAL('-', char_type)
2012-04-16 02:21:40 +00:00
? sprout::detail::str_to_float_impl_exponent_1<FloatType>(
sprout::next(str, 2),
true,
number,
num_digits,
num_decimals,
exponent
)
: sprout::detail::str_to_float_impl_exponent_1<FloatType>(
sprout::next(str, 2),
false,
number,
num_digits,
num_decimals,
exponent
)
: sprout::detail::str_to_float_impl_exponent_2<FloatType>(
str,
negative,
number,
num_digits,
num_decimals,
exponent
)
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_decimal_1(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
long exponent = 0
)
{
return num_digits == 0 ? FloatType()
: sprout::detail::str_to_float_impl_exponent<FloatType>(
str,
negative,
negative ? -number : number,
num_digits,
num_decimals,
exponent
)
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl_decimal(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0,
std::size_t num_decimals = 0,
long exponent = 0
)
{
typedef typename std::iterator_traits<NullTerminatedIterator>::value_type char_type;
2014-10-27 01:16:49 +00:00
SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits<char_type>::value);
2012-04-16 02:21:40 +00:00
return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl_decimal<FloatType>(
sprout::next(str),
negative,
2014-10-27 01:16:49 +00:00
number * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type)),
2012-04-16 02:21:40 +00:00
num_digits + 1,
num_decimals + 1,
exponent
)
: sprout::detail::str_to_float_impl_decimal_1<FloatType>(
str,
negative,
number,
num_digits,
num_decimals,
exponent - num_decimals
)
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float_impl(
NullTerminatedIterator str,
2012-04-16 02:21:40 +00:00
bool negative,
FloatType number = FloatType(),
std::size_t num_digits = 0
)
{
typedef typename std::iterator_traits<NullTerminatedIterator>::value_type char_type;
2014-10-27 01:16:49 +00:00
SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits<char_type>::value);
2012-04-16 02:21:40 +00:00
return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl<FloatType>(
sprout::next(str),
negative,
2014-10-27 01:16:49 +00:00
number * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type)),
2012-04-16 02:21:40 +00:00
num_digits + 1
)
2014-10-27 01:16:49 +00:00
: *str == SPROUT_CHAR_LITERAL('.', char_type) ? sprout::detail::str_to_float_impl_decimal<FloatType>(
2012-04-16 02:21:40 +00:00
sprout::next(str),
negative,
number,
num_digits
)
: sprout::detail::str_to_float_impl_decimal_1<FloatType>(
str,
negative,
number,
num_digits
)
;
}
template<typename FloatType, typename NullTerminatedIterator>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float(NullTerminatedIterator str) {
2014-10-27 01:16:49 +00:00
typedef typename std::iterator_traits<NullTerminatedIterator>::value_type char_type;
2012-04-16 02:21:40 +00:00
return sprout::ascii::isspace(*str)
? sprout::detail::str_to_float<FloatType>(sprout::next(str))
2014-10-27 01:16:49 +00:00
: *str == SPROUT_CHAR_LITERAL('-', char_type)
2012-04-16 02:21:40 +00:00
? sprout::detail::str_to_float_impl<FloatType>(sprout::next(str), true)
2014-10-27 01:16:49 +00:00
: *str == SPROUT_CHAR_LITERAL('+', char_type)
2012-04-16 02:21:40 +00:00
? sprout::detail::str_to_float_impl<FloatType>(sprout::next(str), false)
: sprout::detail::str_to_float_impl<FloatType>(str, false)
;
}
template<typename FloatType, typename NullTerminatedIterator, typename CharPtr>
2012-10-05 15:58:56 +00:00
inline SPROUT_CONSTEXPR FloatType
str_to_float(NullTerminatedIterator str, CharPtr* endptr) {
2012-04-16 02:21:40 +00:00
return !endptr ? sprout::detail::str_to_float<FloatType>(str)
2014-03-01 01:35:24 +00:00
#if defined(__MINGW32__)
: std::is_same<typename std::remove_cv<FloatType>::type, float>::value ? ::strtof(&*str, endptr)
: std::is_same<typename std::remove_cv<FloatType>::type, double>::value ? std::strtod(&*str, endptr)
: ::strtold(&*str, endptr)
#else
: std::is_same<typename std::remove_cv<FloatType>::type, float>::value ? std::strtof(&*str, endptr)
: std::is_same<typename std::remove_cv<FloatType>::type, double>::value ? std::strtod(&*str, endptr)
: std::strtold(&*str, endptr)
#endif
2012-04-16 02:21:40 +00:00
;
}
} // namespace detail
//
// str_to_float
//
2012-12-17 11:10:17 +00:00
template<typename FloatType, typename Char>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_floating_point<FloatType>::value,
FloatType
>::type
2012-10-05 15:58:56 +00:00
str_to_float(Char const* str, Char** endptr) {
2012-04-16 02:21:40 +00:00
return sprout::detail::str_to_float<FloatType>(str, endptr);
}
2012-12-17 11:10:17 +00:00
template<typename FloatType, typename Char>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_floating_point<FloatType>::value,
FloatType
>::type
2013-07-22 13:00:09 +00:00
str_to_float(Char const* str, std::nullptr_t) {
2012-04-16 02:21:40 +00:00
return sprout::detail::str_to_float<FloatType>(str);
}
2012-12-17 11:10:17 +00:00
template<typename FloatType, typename Char>
inline SPROUT_CONSTEXPR typename std::enable_if<
std::is_floating_point<FloatType>::value,
FloatType
>::type
2012-10-05 15:58:56 +00:00
str_to_float(Char const* str) {
2012-04-16 02:21:40 +00:00
return sprout::detail::str_to_float<FloatType>(str);
}
} // namespace sprout
#endif // #ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP