/*============================================================================= Copyright (c) 2011-2016 Bolero MURAKAMI 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) =============================================================================*/ #ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP #define SPROUT_CSTDLIB_STR_TO_FLOAT_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { namespace detail { template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_scale( NullTerminatedIterator const& str, 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( str, negative, n & 1 ? (exponent < 0 ? number / p10 : number * p10) : number, num_digits, num_decimals, exponent, n >> 1, p10 * p10 ) : number ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_exponent_2( NullTerminatedIterator const& str, bool negative, FloatType number = FloatType(), std::size_t num_digits = 0, std::size_t num_decimals = 0, long exponent = 0 ) { return exponent >= sprout::numeric_limits::min_exponent && exponent <= sprout::numeric_limits::max_exponent ? sprout::detail::str_to_float_impl_scale( str, negative, number, num_digits, num_decimals, exponent, exponent < 0 ? -exponent : exponent ) : HUGE_VAL ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_exponent_1( NullTerminatedIterator const& str, 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::value_type char_type; SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits::value); return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl_exponent_1( sprout::next(str), negative, number, num_digits, num_decimals, exponent, n * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type)) ) : sprout::detail::str_to_float_impl_exponent_2( str, negative, number, num_digits, num_decimals, negative ? exponent + n : exponent - n ) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_exponent( NullTerminatedIterator const& str, 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::value_type char_type; return (*str == SPROUT_CHAR_LITERAL('e', char_type) || *str == SPROUT_CHAR_LITERAL('E', char_type)) ? *sprout::next(str) == SPROUT_CHAR_LITERAL('-', char_type) ? sprout::detail::str_to_float_impl_exponent_1( sprout::next(str, 2), true, number, num_digits, num_decimals, exponent ) : sprout::detail::str_to_float_impl_exponent_1( sprout::next(str, 2), false, number, num_digits, num_decimals, exponent ) : sprout::detail::str_to_float_impl_exponent_2( str, negative, number, num_digits, num_decimals, exponent ) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_decimal_1( NullTerminatedIterator const& str, 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( str, negative, negative ? -number : number, num_digits, num_decimals, exponent ) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl_decimal( NullTerminatedIterator const& str, 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::value_type char_type; SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits::value); return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl_decimal( sprout::next(str), negative, number * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type)), num_digits + 1, num_decimals + 1, exponent ) : sprout::detail::str_to_float_impl_decimal_1( str, negative, number, num_digits, num_decimals, exponent - num_decimals ) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float_impl( NullTerminatedIterator const& str, bool negative, FloatType number = FloatType(), std::size_t num_digits = 0 ) { typedef typename std::iterator_traits::value_type char_type; SPROUT_STATIC_ASSERT(sprout::detail::is_char_type_of_consecutive_digits::value); return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl( sprout::next(str), negative, number * 10 + (*str - SPROUT_CHAR_LITERAL('0', char_type)), num_digits + 1 ) : *str == SPROUT_CHAR_LITERAL('.', char_type) ? sprout::detail::str_to_float_impl_decimal( sprout::next(str), negative, number, num_digits ) : sprout::detail::str_to_float_impl_decimal_1( str, negative, number, num_digits ) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float(NullTerminatedIterator const& str) { typedef typename std::iterator_traits::value_type char_type; return sprout::ascii::isspace(*str) ? sprout::detail::str_to_float(sprout::next(str)) : *str == SPROUT_CHAR_LITERAL('-', char_type) ? sprout::detail::str_to_float_impl(sprout::next(str), true) : *str == SPROUT_CHAR_LITERAL('+', char_type) ? sprout::detail::str_to_float_impl(sprout::next(str), false) : sprout::detail::str_to_float_impl(str, false) ; } template inline SPROUT_CONSTEXPR FloatType str_to_float(NullTerminatedIterator const& str, CharPtr* endptr) { return !endptr ? sprout::detail::str_to_float(str) #if defined(__MINGW32__) : std::is_same::type, float>::value ? ::strtof(&*str, endptr) : std::is_same::type, double>::value ? std::strtod(&*str, endptr) : ::strtold(&*str, endptr) #else : std::is_same::type, float>::value ? std::strtof(&*str, endptr) : std::is_same::type, double>::value ? std::strtod(&*str, endptr) : std::strtold(&*str, endptr) #endif ; } } // namespace detail // // str_to_float // template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_floating_point::value, FloatType >::type str_to_float(Char const* str, Char** endptr) { return sprout::detail::str_to_float(str, endptr); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_floating_point::value, FloatType >::type str_to_float(Char const* str, std::nullptr_t) { return sprout::detail::str_to_float(str); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_floating_point::value, FloatType >::type str_to_float(Char const* str) { return sprout::detail::str_to_float(str); } } // namespace sprout #endif // #ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP