File indexing completed on 2025-01-18 09:39:13
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
0019 #define BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
0020
0021 #include <boost/config.hpp>
0022 #ifdef BOOST_HAS_PRAGMA_ONCE
0023 # pragma once
0024 #endif
0025
0026 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
0027 #define BOOST_LCAST_NO_WCHAR_T
0028 #endif
0029
0030 #include <boost/limits.hpp>
0031 #include <boost/detail/workaround.hpp>
0032 #include <boost/core/cmath.hpp>
0033 #include <cstddef>
0034 #include <cstring>
0035
0036 #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
0037
0038 namespace boost {
0039 namespace detail
0040 {
0041 template <class CharT>
0042 bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) noexcept {
0043 for( unsigned int i=0; i < len; ++i ) {
0044 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
0045 }
0046
0047 return true;
0048 }
0049
0050
0051 template <class CharT, class T>
0052 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
0053 , const CharT* lc_NAN, const CharT* lc_nan
0054 , const CharT* lc_INFINITY, const CharT* lc_infinity
0055 , const CharT opening_brace, const CharT closing_brace) noexcept
0056 {
0057 if (begin == end) return false;
0058 const CharT minus = lcast_char_constants<CharT>::minus;
0059 const CharT plus = lcast_char_constants<CharT>::plus;
0060 const int inifinity_size = 8;
0061
0062
0063 bool const has_minus = (*begin == minus);
0064 if (has_minus || *begin == plus) {
0065 ++ begin;
0066 }
0067
0068 if (end - begin < 3) return false;
0069 if (lc_iequal(begin, lc_nan, lc_NAN, 3)) {
0070 begin += 3;
0071 if (end != begin) {
0072
0073
0074 if (end - begin < 2) return false;
0075 -- end;
0076 if (*begin != opening_brace || *end != closing_brace) return false;
0077 }
0078
0079 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
0080 else value = boost::core::copysign(std::numeric_limits<T>::quiet_NaN(), static_cast<T>(-1));
0081 return true;
0082 } else if (
0083 (
0084 end - begin == 3
0085 && lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
0086 )
0087 ||
0088 (
0089 end - begin == inifinity_size
0090 && lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size)
0091 )
0092 )
0093 {
0094 if( !has_minus ) value = std::numeric_limits<T>::infinity();
0095 else value = -std::numeric_limits<T>::infinity();
0096 return true;
0097 }
0098
0099 return false;
0100 }
0101
0102 template <class CharT, class T>
0103 bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
0104 , const CharT* lc_nan
0105 , const CharT* lc_infinity) noexcept
0106 {
0107 const CharT minus = lcast_char_constants<CharT>::minus;
0108 if (boost::core::isnan(value)) {
0109 if (boost::core::signbit(value)) {
0110 *begin = minus;
0111 ++ begin;
0112 }
0113
0114 std::memcpy(begin, lc_nan, 3 * sizeof(CharT));
0115 end = begin + 3;
0116 return true;
0117 } else if (boost::core::isinf(value)) {
0118 if (boost::core::signbit(value)) {
0119 *begin = minus;
0120 ++ begin;
0121 }
0122
0123 std::memcpy(begin, lc_infinity, 3 * sizeof(CharT));
0124 end = begin + 3;
0125 return true;
0126 }
0127
0128 return false;
0129 }
0130
0131
0132 #ifndef BOOST_LCAST_NO_WCHAR_T
0133 template <class T>
0134 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) noexcept {
0135 return parse_inf_nan_impl(begin, end, value
0136 , L"NAN", L"nan"
0137 , L"INFINITY", L"infinity"
0138 , L'(', L')');
0139 }
0140
0141 template <class T>
0142 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) noexcept {
0143 return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
0144 }
0145
0146 #endif
0147 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0148 template <class T>
0149 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) noexcept {
0150 return parse_inf_nan_impl(begin, end, value
0151 , u"NAN", u"nan"
0152 , u"INFINITY", u"infinity"
0153 , u'(', u')');
0154 }
0155
0156 template <class T>
0157 bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) noexcept {
0158 return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
0159 }
0160 #endif
0161 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0162 template <class T>
0163 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) noexcept {
0164 return parse_inf_nan_impl(begin, end, value
0165 , U"NAN", U"nan"
0166 , U"INFINITY", U"infinity"
0167 , U'(', U')');
0168 }
0169
0170 template <class T>
0171 bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) noexcept {
0172 return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
0173 }
0174 #endif
0175
0176 template <class CharT, class T>
0177 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) noexcept {
0178 return parse_inf_nan_impl(begin, end, value
0179 , "NAN", "nan"
0180 , "INFINITY", "infinity"
0181 , '(', ')');
0182 }
0183
0184 template <class CharT, class T>
0185 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) noexcept {
0186 return put_inf_nan_impl(begin, end, value, "nan", "infinity");
0187 }
0188 }
0189 }
0190
0191 #undef BOOST_LCAST_NO_WCHAR_T
0192
0193 #endif
0194