Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 08:16:16

0001 // Copyright Kevlin Henney, 2000-2005.
0002 // Copyright Alexander Nasonov, 2006-2010.
0003 // Copyright Antony Polukhin, 2011-2024.
0004 //
0005 // Distributed under the Boost Software License, Version 1.0. (See
0006 // accompanying file LICENSE_1_0.txt or copy at
0007 // http://www.boost.org/LICENSE_1_0.txt)
0008 //
0009 // what:  lexical_cast custom keyword cast
0010 // who:   contributed by Kevlin Henney,
0011 //        enhanced with contributions from Terje Slettebo,
0012 //        with additional fixes and suggestions from Gennaro Prota,
0013 //        Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
0014 //        Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
0015 //        Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
0016 // when:  November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
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         /* Returns true and sets the correct value if found NaN or Inf. */
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; // == sizeof("infinity") - 1
0061 
0062             /* Parsing +/- */
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                     /* It is 'nan(...)' or some bad input*/
0073 
0074                     if (end - begin < 2) return false; // bad input
0075                     -- end;
0076                     if (*begin != opening_brace || *end != closing_brace) return false; // bad input
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                 ( /* 'INF' or 'inf' */
0084                   end - begin == 3      // 3 == sizeof('inf') - 1
0085                   && lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
0086                 )
0087                 ||
0088                 ( /* 'INFINITY' or 'infinity' */
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         const CharT* get_inf_nan_impl(T value
0104                          , const CharT* lc_nan
0105                          , const CharT* lc_minus_nan
0106                          , const CharT* lc_infinity
0107                          , const CharT* lc_minus_infinity) noexcept
0108         {
0109             if (boost::core::isnan(value)) {
0110                 if (boost::core::signbit(value)) {
0111                     return lc_minus_nan;
0112                 }
0113                 return lc_nan;
0114             } else if (boost::core::isinf(value)) {
0115                 if (boost::core::signbit(value)) {
0116                     return lc_minus_infinity;
0117                 }
0118                 return lc_infinity;
0119             }
0120 
0121             return nullptr;
0122         }
0123 
0124 
0125 #ifndef BOOST_LCAST_NO_WCHAR_T
0126         template <class T>
0127         bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) noexcept {
0128             return parse_inf_nan_impl(begin, end, value
0129                                , L"NAN", L"nan"
0130                                , L"INFINITY", L"infinity"
0131                                , L'(', L')');
0132         }
0133 
0134         template <class T>
0135         const wchar_t* get_inf_nan(T value, wchar_t) noexcept {
0136             return detail::get_inf_nan_impl(value, L"nan", L"-nan", L"inf", L"-inf");
0137         }
0138 
0139 #endif
0140 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0141         template <class T>
0142         bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) noexcept {
0143             return parse_inf_nan_impl(begin, end, value
0144                                , u"NAN", u"nan"
0145                                , u"INFINITY", u"infinity"
0146                                , u'(', u')');
0147         }
0148 
0149         template <class T>
0150         const char16_t* get_inf_nan(T value, char16_t) noexcept {
0151             return detail::get_inf_nan_impl(value, u"nan", u"-nan", u"inf", u"-inf");
0152         }
0153 #endif
0154 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
0155         template <class T>
0156         bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) noexcept {
0157             return parse_inf_nan_impl(begin, end, value
0158                                , U"NAN", U"nan"
0159                                , U"INFINITY", U"infinity"
0160                                , U'(', U')');
0161         }
0162 
0163         template <class T>
0164         const char32_t* get_inf_nan(T value, char32_t) noexcept {
0165             return detail::get_inf_nan_impl(value, U"nan", U"-nan", U"inf", U"-inf");
0166         }
0167 #endif
0168 
0169         template <class CharT, class T>
0170         bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) noexcept {
0171             return parse_inf_nan_impl(begin, end, value
0172                                , "NAN", "nan"
0173                                , "INFINITY", "infinity"
0174                                , '(', ')');
0175         }
0176 
0177         template <class T>
0178         const char* get_inf_nan(T value, char) noexcept {
0179             return detail::get_inf_nan_impl(value, "nan", "-nan", "inf", "-inf");
0180         }
0181     }
0182 } // namespace boost
0183 
0184 #undef BOOST_LCAST_NO_WCHAR_T
0185 
0186 #endif // BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
0187