Chris@102
|
1 // Copyright Kevlin Henney, 2000-2005.
|
Chris@102
|
2 // Copyright Alexander Nasonov, 2006-2010.
|
Chris@102
|
3 // Copyright Antony Polukhin, 2011-2014.
|
Chris@102
|
4 //
|
Chris@102
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@102
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@102
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@102
|
8 //
|
Chris@102
|
9 // what: lexical_cast custom keyword cast
|
Chris@102
|
10 // who: contributed by Kevlin Henney,
|
Chris@102
|
11 // enhanced with contributions from Terje Slettebo,
|
Chris@102
|
12 // with additional fixes and suggestions from Gennaro Prota,
|
Chris@102
|
13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
|
Chris@102
|
14 // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
|
Chris@102
|
15 // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
|
Chris@102
|
16 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014
|
Chris@102
|
17
|
Chris@102
|
18 #ifndef BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
|
Chris@102
|
19 #define BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
|
Chris@102
|
20
|
Chris@102
|
21 #include <boost/config.hpp>
|
Chris@102
|
22 #ifdef BOOST_HAS_PRAGMA_ONCE
|
Chris@102
|
23 # pragma once
|
Chris@102
|
24 #endif
|
Chris@102
|
25
|
Chris@102
|
26 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
|
Chris@102
|
27 #define BOOST_LCAST_NO_WCHAR_T
|
Chris@102
|
28 #endif
|
Chris@102
|
29
|
Chris@102
|
30 #include <cstddef>
|
Chris@102
|
31 #include <cstring>
|
Chris@102
|
32 #include <boost/limits.hpp>
|
Chris@102
|
33 #include <boost/detail/workaround.hpp>
|
Chris@102
|
34 #include <boost/math/special_functions/sign.hpp>
|
Chris@102
|
35 #include <boost/math/special_functions/fpclassify.hpp>
|
Chris@102
|
36
|
Chris@102
|
37 #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
|
Chris@102
|
38
|
Chris@102
|
39 namespace boost {
|
Chris@102
|
40 namespace detail
|
Chris@102
|
41 {
|
Chris@102
|
42 template <class CharT>
|
Chris@102
|
43 bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT {
|
Chris@102
|
44 for( unsigned int i=0; i < len; ++i ) {
|
Chris@102
|
45 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
|
Chris@102
|
46 }
|
Chris@102
|
47
|
Chris@102
|
48 return true;
|
Chris@102
|
49 }
|
Chris@102
|
50
|
Chris@102
|
51 /* Returns true and sets the correct value if found NaN or Inf. */
|
Chris@102
|
52 template <class CharT, class T>
|
Chris@102
|
53 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
|
Chris@102
|
54 , const CharT* lc_NAN, const CharT* lc_nan
|
Chris@102
|
55 , const CharT* lc_INFINITY, const CharT* lc_infinity
|
Chris@102
|
56 , const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT
|
Chris@102
|
57 {
|
Chris@102
|
58 using namespace std;
|
Chris@102
|
59 if (begin == end) return false;
|
Chris@102
|
60 const CharT minus = lcast_char_constants<CharT>::minus;
|
Chris@102
|
61 const CharT plus = lcast_char_constants<CharT>::plus;
|
Chris@102
|
62 const int inifinity_size = 8; // == sizeof("infinity") - 1
|
Chris@102
|
63
|
Chris@102
|
64 /* Parsing +/- */
|
Chris@102
|
65 bool const has_minus = (*begin == minus);
|
Chris@102
|
66 if (has_minus || *begin == plus) {
|
Chris@102
|
67 ++ begin;
|
Chris@102
|
68 }
|
Chris@102
|
69
|
Chris@102
|
70 if (end - begin < 3) return false;
|
Chris@102
|
71 if (lc_iequal(begin, lc_nan, lc_NAN, 3)) {
|
Chris@102
|
72 begin += 3;
|
Chris@102
|
73 if (end != begin) {
|
Chris@102
|
74 /* It is 'nan(...)' or some bad input*/
|
Chris@102
|
75
|
Chris@102
|
76 if (end - begin < 2) return false; // bad input
|
Chris@102
|
77 -- end;
|
Chris@102
|
78 if (*begin != opening_brace || *end != closing_brace) return false; // bad input
|
Chris@102
|
79 }
|
Chris@102
|
80
|
Chris@102
|
81 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
|
Chris@102
|
82 else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
|
Chris@102
|
83 return true;
|
Chris@102
|
84 } else if (
|
Chris@102
|
85 ( /* 'INF' or 'inf' */
|
Chris@102
|
86 end - begin == 3 // 3 == sizeof('inf') - 1
|
Chris@102
|
87 && lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
|
Chris@102
|
88 )
|
Chris@102
|
89 ||
|
Chris@102
|
90 ( /* 'INFINITY' or 'infinity' */
|
Chris@102
|
91 end - begin == inifinity_size
|
Chris@102
|
92 && lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size)
|
Chris@102
|
93 )
|
Chris@102
|
94 )
|
Chris@102
|
95 {
|
Chris@102
|
96 if( !has_minus ) value = std::numeric_limits<T>::infinity();
|
Chris@102
|
97 else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
|
Chris@102
|
98 return true;
|
Chris@102
|
99 }
|
Chris@102
|
100
|
Chris@102
|
101 return false;
|
Chris@102
|
102 }
|
Chris@102
|
103
|
Chris@102
|
104 template <class CharT, class T>
|
Chris@102
|
105 bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
|
Chris@102
|
106 , const CharT* lc_nan
|
Chris@102
|
107 , const CharT* lc_infinity) BOOST_NOEXCEPT
|
Chris@102
|
108 {
|
Chris@102
|
109 using namespace std;
|
Chris@102
|
110 const CharT minus = lcast_char_constants<CharT>::minus;
|
Chris@102
|
111 if ((boost::math::isnan)(value)) {
|
Chris@102
|
112 if ((boost::math::signbit)(value)) {
|
Chris@102
|
113 *begin = minus;
|
Chris@102
|
114 ++ begin;
|
Chris@102
|
115 }
|
Chris@102
|
116
|
Chris@102
|
117 memcpy(begin, lc_nan, 3 * sizeof(CharT));
|
Chris@102
|
118 end = begin + 3;
|
Chris@102
|
119 return true;
|
Chris@102
|
120 } else if ((boost::math::isinf)(value)) {
|
Chris@102
|
121 if ((boost::math::signbit)(value)) {
|
Chris@102
|
122 *begin = minus;
|
Chris@102
|
123 ++ begin;
|
Chris@102
|
124 }
|
Chris@102
|
125
|
Chris@102
|
126 memcpy(begin, lc_infinity, 3 * sizeof(CharT));
|
Chris@102
|
127 end = begin + 3;
|
Chris@102
|
128 return true;
|
Chris@102
|
129 }
|
Chris@102
|
130
|
Chris@102
|
131 return false;
|
Chris@102
|
132 }
|
Chris@102
|
133
|
Chris@102
|
134
|
Chris@102
|
135 #ifndef BOOST_LCAST_NO_WCHAR_T
|
Chris@102
|
136 template <class T>
|
Chris@102
|
137 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT {
|
Chris@102
|
138 return parse_inf_nan_impl(begin, end, value
|
Chris@102
|
139 , L"NAN", L"nan"
|
Chris@102
|
140 , L"INFINITY", L"infinity"
|
Chris@102
|
141 , L'(', L')');
|
Chris@102
|
142 }
|
Chris@102
|
143
|
Chris@102
|
144 template <class T>
|
Chris@102
|
145 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT {
|
Chris@102
|
146 return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
|
Chris@102
|
147 }
|
Chris@102
|
148
|
Chris@102
|
149 #endif
|
Chris@102
|
150 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
|
Chris@102
|
151 template <class T>
|
Chris@102
|
152 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT {
|
Chris@102
|
153 return parse_inf_nan_impl(begin, end, value
|
Chris@102
|
154 , u"NAN", u"nan"
|
Chris@102
|
155 , u"INFINITY", u"infinity"
|
Chris@102
|
156 , u'(', u')');
|
Chris@102
|
157 }
|
Chris@102
|
158
|
Chris@102
|
159 template <class T>
|
Chris@102
|
160 bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT {
|
Chris@102
|
161 return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
|
Chris@102
|
162 }
|
Chris@102
|
163 #endif
|
Chris@102
|
164 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
|
Chris@102
|
165 template <class T>
|
Chris@102
|
166 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT {
|
Chris@102
|
167 return parse_inf_nan_impl(begin, end, value
|
Chris@102
|
168 , U"NAN", U"nan"
|
Chris@102
|
169 , U"INFINITY", U"infinity"
|
Chris@102
|
170 , U'(', U')');
|
Chris@102
|
171 }
|
Chris@102
|
172
|
Chris@102
|
173 template <class T>
|
Chris@102
|
174 bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT {
|
Chris@102
|
175 return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
|
Chris@102
|
176 }
|
Chris@102
|
177 #endif
|
Chris@102
|
178
|
Chris@102
|
179 template <class CharT, class T>
|
Chris@102
|
180 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT {
|
Chris@102
|
181 return parse_inf_nan_impl(begin, end, value
|
Chris@102
|
182 , "NAN", "nan"
|
Chris@102
|
183 , "INFINITY", "infinity"
|
Chris@102
|
184 , '(', ')');
|
Chris@102
|
185 }
|
Chris@102
|
186
|
Chris@102
|
187 template <class CharT, class T>
|
Chris@102
|
188 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT {
|
Chris@102
|
189 return put_inf_nan_impl(begin, end, value, "nan", "infinity");
|
Chris@102
|
190 }
|
Chris@102
|
191 }
|
Chris@102
|
192 } // namespace boost
|
Chris@102
|
193
|
Chris@102
|
194 #undef BOOST_LCAST_NO_WCHAR_T
|
Chris@102
|
195
|
Chris@102
|
196 #endif // BOOST_LEXICAL_CAST_DETAIL_INF_NAN_HPP
|
Chris@102
|
197
|