From 907bced466c73679076b0b836f5f7339833179c4 Mon Sep 17 00:00:00 2001 From: bolero-MURAKAMI Date: Mon, 16 Apr 2012 11:21:40 +0900 Subject: [PATCH] add atof, strtof, strtod, strtold --- sprout/cstdlib/atof.hpp | 17 +++ sprout/cstdlib/conversion.hpp | 5 + sprout/cstdlib/str_to_float.hpp | 255 ++++++++++++++++++++++++++++++++ sprout/cstdlib/str_to_int.hpp | 1 + sprout/cstdlib/strtod.hpp | 26 ++++ sprout/cstdlib/strtof.hpp | 26 ++++ sprout/cstdlib/strtold.hpp | 26 ++++ 7 files changed, 356 insertions(+) create mode 100644 sprout/cstdlib/atof.hpp create mode 100644 sprout/cstdlib/str_to_float.hpp create mode 100644 sprout/cstdlib/strtod.hpp create mode 100644 sprout/cstdlib/strtof.hpp create mode 100644 sprout/cstdlib/strtold.hpp diff --git a/sprout/cstdlib/atof.hpp b/sprout/cstdlib/atof.hpp new file mode 100644 index 00000000..a2e7b9fa --- /dev/null +++ b/sprout/cstdlib/atof.hpp @@ -0,0 +1,17 @@ +#ifndef SPROUT_CSTDLIB_ATOF_HPP +#define SPROUT_CSTDLIB_ATOF_HPP + +#include +#include + +namespace sprout { + // + // atof + // + template + inline SPROUT_CONSTEXPR double atof(Char const* str){ + return sprout::str_to_float(str); + } +} // namespace sprout + +#endif // #ifndef SPROUT_CSTDLIB_ATOF_HPP diff --git a/sprout/cstdlib/conversion.hpp b/sprout/cstdlib/conversion.hpp index acde2a35..f1c3bc5d 100644 --- a/sprout/cstdlib/conversion.hpp +++ b/sprout/cstdlib/conversion.hpp @@ -4,12 +4,17 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include +#include +#include +#include #endif // #ifndef SPROUT_CSTDLIB_CONVERSION_HPP diff --git a/sprout/cstdlib/str_to_float.hpp b/sprout/cstdlib/str_to_float.hpp new file mode 100644 index 00000000..6a554fb6 --- /dev/null +++ b/sprout/cstdlib/str_to_float.hpp @@ -0,0 +1,255 @@ +#ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP +#define SPROUT_CSTDLIB_STR_TO_FLOAT_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sprout { + namespace detail { + template + inline SPROUT_CONSTEXPR FloatType str_to_float_impl_scale( + CStrIterator 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) + ) + { + typedef typename std::iterator_traits::value_type char_type; + 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( + CStrIterator 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; + return exponent >= std::numeric_limits::min_exponent + && exponent <= std::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( + CStrIterator 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; + 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 - static_cast('0')) + ) + : sprout::detail::str_to_float_impl_exponent_2( + str, + negative, + number, + num_digits, + num_decimals, + negative ? exponent + n : exponent - n, + n + ) + ; + } + template + inline SPROUT_CONSTEXPR FloatType str_to_float_impl_exponent( + CStrIterator 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 == static_cast('e') || *str == static_cast('E')) + ? *sprout::next(str) == static_cast('-') + ? 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( + CStrIterator 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 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( + CStrIterator 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 sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl_decimal( + sprout::next(str), + negative, + number * 10 + (*str - static_cast('0')), + 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( + CStrIterator str, + bool negative, + FloatType number = FloatType(), + std::size_t num_digits = 0 + ) + { + typedef typename std::iterator_traits::value_type char_type; + return sprout::ascii::isdigit(*str) ? sprout::detail::str_to_float_impl( + sprout::next(str), + negative, + number * 10 + (*str - static_cast('0')), + num_digits + 1 + ) + : *str == static_cast('.') ? 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(CStrIterator str) { + return sprout::ascii::isspace(*str) + ? sprout::detail::str_to_float(sprout::next(str)) + : *str == static_cast::value_type>('-') + ? sprout::detail::str_to_float_impl(sprout::next(str), true) + : *str == static_cast::value_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(CStrIterator str, CharPtr* endptr) { + return !endptr ? sprout::detail::str_to_float(str) + : std::strtod(str, endptr) + ; + } + } // namespace detail + + // + // str_to_float + // + template + inline SPROUT_CONSTEXPR FloatType str_to_float(Char const* str, Char** endptr) { + return sprout::detail::str_to_float(str, endptr); + } + template + inline SPROUT_CONSTEXPR FloatType str_to_float(Char const* str, std::nullptr_t endptr) { + return sprout::detail::str_to_float(str); + } + template + inline SPROUT_CONSTEXPR FloatType str_to_float(Char const* str) { + return sprout::detail::str_to_float(str); + } +} // namespace sprout + +#endif // #ifndef SPROUT_CSTDLIB_STR_TO_FLOAT_HPP diff --git a/sprout/cstdlib/str_to_int.hpp b/sprout/cstdlib/str_to_int.hpp index 784be7c0..5bf05d02 100644 --- a/sprout/cstdlib/str_to_int.hpp +++ b/sprout/cstdlib/str_to_int.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/sprout/cstdlib/strtod.hpp b/sprout/cstdlib/strtod.hpp new file mode 100644 index 00000000..23926cc1 --- /dev/null +++ b/sprout/cstdlib/strtod.hpp @@ -0,0 +1,26 @@ +#ifndef SPROUT_CSTDLIB_STRTOD_HPP +#define SPROUT_CSTDLIB_STRTOD_HPP + +#include +#include +#include + +namespace sprout { + // + // strtod + // + template + inline SPROUT_CONSTEXPR double strtod(Char const* str, Char** endptr){ + return sprout::str_to_float(str, endptr); + } + template + inline SPROUT_CONSTEXPR double strtod(Char const* str, std::nullptr_t endptr){ + return sprout::str_to_float(str); + } + template + inline SPROUT_CONSTEXPR double strtod(Char const* str){ + return sprout::str_to_float(str); + } +} // namespace sprout + +#endif // #ifndef SPROUT_CSTDLIB_STRTOD_HPP diff --git a/sprout/cstdlib/strtof.hpp b/sprout/cstdlib/strtof.hpp new file mode 100644 index 00000000..257e059a --- /dev/null +++ b/sprout/cstdlib/strtof.hpp @@ -0,0 +1,26 @@ +#ifndef SPROUT_CSTDLIB_STRTOF_HPP +#define SPROUT_CSTDLIB_STRTOF_HPP + +#include +#include +#include + +namespace sprout { + // + // strtof + // + template + inline SPROUT_CONSTEXPR float strtof(Char const* str, Char** endptr){ + return sprout::str_to_float(str, endptr); + } + template + inline SPROUT_CONSTEXPR float strtof(Char const* str, std::nullptr_t endptr){ + return sprout::str_to_float(str); + } + template + inline SPROUT_CONSTEXPR float strtof(Char const* str){ + return sprout::str_to_float(str); + } +} // namespace sprout + +#endif // #ifndef SPROUT_CSTDLIB_STRTOF_HPP diff --git a/sprout/cstdlib/strtold.hpp b/sprout/cstdlib/strtold.hpp new file mode 100644 index 00000000..809ed27a --- /dev/null +++ b/sprout/cstdlib/strtold.hpp @@ -0,0 +1,26 @@ +#ifndef SPROUT_CSTDLIB_STRTOLD_HPP +#define SPROUT_CSTDLIB_STRTOLD_HPP + +#include +#include +#include + +namespace sprout { + // + // strtold + // + template + inline SPROUT_CONSTEXPR long double strtold(Char const* str, Char** endptr){ + return sprout::str_to_float(str, endptr); + } + template + inline SPROUT_CONSTEXPR long double strtold(Char const* str, std::nullptr_t endptr){ + return sprout::str_to_float(str); + } + template + inline SPROUT_CONSTEXPR long double strtold(Char const* str){ + return sprout::str_to_float(str); + } +} // namespace sprout + +#endif // #ifndef SPROUT_CSTDLIB_STRTOLD_HPP