Line data Source code
1 : // Copyright Kevlin Henney, 2000-2005.
2 : // Copyright Alexander Nasonov, 2006-2010.
3 : // Copyright Antony Polukhin, 2011-2019.
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See
6 : // accompanying file LICENSE_1_0.txt or copy at
7 : // http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : // what: lexical_cast custom keyword cast
10 : // who: contributed by Kevlin Henney,
11 : // enhanced with contributions from Terje Slettebo,
12 : // with additional fixes and suggestions from Gennaro Prota,
13 : // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
14 : // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
15 : // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
16 : // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2014, Nowember 2016
17 :
18 : #ifndef BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
19 : #define BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_STREAMS_HPP
20 :
21 : #include <boost/config.hpp>
22 : #ifdef BOOST_HAS_PRAGMA_ONCE
23 : # pragma once
24 : #endif
25 :
26 :
27 : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
28 : #define BOOST_LCAST_NO_WCHAR_T
29 : #endif
30 :
31 : #include <cstddef>
32 : #include <string>
33 : #include <cstring>
34 : #include <cstdio>
35 : #include <boost/limits.hpp>
36 : #include <boost/type_traits/conditional.hpp>
37 : #include <boost/type_traits/is_pointer.hpp>
38 : #include <boost/static_assert.hpp>
39 : #include <boost/detail/workaround.hpp>
40 :
41 :
42 : #ifndef BOOST_NO_STD_LOCALE
43 : # include <locale>
44 : #else
45 : # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
46 : // Getting error at this point means, that your STL library is old/lame/misconfigured.
47 : // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
48 : // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
49 : // separators.
50 : # error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
51 : # error "boost::lexical_cast to use only 'C' locale during conversions."
52 : # endif
53 : #endif
54 :
55 : #ifdef BOOST_NO_STRINGSTREAM
56 : #include <strstream>
57 : #else
58 : #include <sstream>
59 : #endif
60 :
61 : #include <boost/lexical_cast/detail/lcast_char_constants.hpp>
62 : #include <boost/lexical_cast/detail/lcast_unsigned_converters.hpp>
63 : #include <boost/lexical_cast/detail/inf_nan.hpp>
64 :
65 : #include <istream>
66 :
67 : #ifndef BOOST_NO_CXX11_HDR_ARRAY
68 : #include <array>
69 : #endif
70 :
71 : #include <boost/array.hpp>
72 : #include <boost/type_traits/make_unsigned.hpp>
73 : #include <boost/type_traits/is_integral.hpp>
74 : #include <boost/type_traits/is_float.hpp>
75 : #include <boost/range/iterator_range_core.hpp>
76 : #include <boost/container/container_fwd.hpp>
77 : #include <boost/integer.hpp>
78 : #include <boost/detail/basic_pointerbuf.hpp>
79 : #include <boost/noncopyable.hpp>
80 : #ifndef BOOST_NO_CWCHAR
81 : # include <cwchar>
82 : #endif
83 :
84 : namespace boost {
85 :
86 : namespace detail // basic_unlockedbuf
87 : {
88 : // acts as a stream buffer which wraps around a pair of pointers
89 : // and gives acces to internals
90 : template <class BufferType, class CharT>
91 0 : class basic_unlockedbuf : public basic_pointerbuf<CharT, BufferType> {
92 : public:
93 : typedef basic_pointerbuf<CharT, BufferType> base_type;
94 : typedef BOOST_DEDUCED_TYPENAME base_type::streamsize streamsize;
95 :
96 : #ifndef BOOST_NO_USING_TEMPLATE
97 : using base_type::pptr;
98 : using base_type::pbase;
99 : using base_type::setbuf;
100 : #else
101 : charT* pptr() const { return base_type::pptr(); }
102 : charT* pbase() const { return base_type::pbase(); }
103 : BufferType* setbuf(char_type* s, streamsize n) { return base_type::setbuf(s, n); }
104 : #endif
105 : };
106 : }
107 :
108 : namespace detail
109 : {
110 : struct do_not_construct_out_buffer_t{};
111 : struct do_not_construct_out_stream_t{
112 1782 : do_not_construct_out_stream_t(do_not_construct_out_buffer_t*){}
113 : };
114 :
115 : template <class CharT, class Traits>
116 : struct out_stream_helper_trait {
117 : #if defined(BOOST_NO_STRINGSTREAM)
118 : typedef std::ostream out_stream_t;
119 : typedef basic_unlockedbuf<std::strstreambuf, char> stringbuffer_t;
120 : #elif defined(BOOST_NO_STD_LOCALE)
121 : typedef std::ostream out_stream_t;
122 : typedef basic_unlockedbuf<std::stringbuf, char> stringbuffer_t;
123 : typedef basic_unlockedbuf<std::streambuf, char> buffer_t;
124 : #else
125 : typedef std::basic_ostream<CharT, Traits> out_stream_t;
126 : typedef basic_unlockedbuf<std::basic_stringbuf<CharT, Traits>, CharT> stringbuffer_t;
127 : typedef basic_unlockedbuf<std::basic_streambuf<CharT, Traits>, CharT> buffer_t;
128 : #endif
129 : };
130 : }
131 :
132 : namespace detail // optimized stream wrappers
133 : {
134 : template< class CharT // a result of widest_char transformation
135 : , class Traits
136 : , bool RequiresStringbuffer
137 : , std::size_t CharacterBufferSize
138 : >
139 0 : class lexical_istream_limited_src: boost::noncopyable {
140 : typedef BOOST_DEDUCED_TYPENAME boost::conditional<
141 : RequiresStringbuffer,
142 : BOOST_DEDUCED_TYPENAME out_stream_helper_trait<CharT, Traits>::out_stream_t,
143 : do_not_construct_out_stream_t
144 : >::type deduced_out_stream_t;
145 :
146 : typedef BOOST_DEDUCED_TYPENAME boost::conditional<
147 : RequiresStringbuffer,
148 : BOOST_DEDUCED_TYPENAME out_stream_helper_trait<CharT, Traits>::stringbuffer_t,
149 : do_not_construct_out_buffer_t
150 : >::type deduced_out_buffer_t;
151 :
152 : deduced_out_buffer_t out_buffer;
153 : deduced_out_stream_t out_stream;
154 : CharT buffer[CharacterBufferSize];
155 :
156 : // After the `operator <<` finishes, `[start, finish)` is
157 : // the range to output by `operator >>`
158 : const CharT* start;
159 : const CharT* finish;
160 :
161 : public:
162 1782 : lexical_istream_limited_src() BOOST_NOEXCEPT
163 : : out_buffer()
164 : , out_stream(&out_buffer)
165 0 : , start(buffer)
166 1782 : , finish(buffer + CharacterBufferSize)
167 0 : {}
168 :
169 1782 : const CharT* cbegin() const BOOST_NOEXCEPT {
170 : return start;
171 : }
172 :
173 1782 : const CharT* cend() const BOOST_NOEXCEPT {
174 : return finish;
175 : }
176 :
177 : private:
178 : /************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
179 : bool shl_char(CharT ch) BOOST_NOEXCEPT {
180 : Traits::assign(buffer[0], ch);
181 : finish = start + 1;
182 : return true;
183 : }
184 :
185 : #ifndef BOOST_LCAST_NO_WCHAR_T
186 : template <class T>
187 : bool shl_char(T ch) {
188 : BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
189 : "boost::lexical_cast does not support narrowing of char types."
190 : "Use boost::locale instead" );
191 : #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
192 : std::locale loc;
193 : CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
194 : #else
195 : CharT const w = static_cast<CharT>(ch);
196 : #endif
197 : Traits::assign(buffer[0], w);
198 : finish = start + 1;
199 : return true;
200 : }
201 : #endif
202 :
203 : bool shl_char_array(CharT const* str_value) BOOST_NOEXCEPT {
204 : start = str_value;
205 : finish = start + Traits::length(str_value);
206 : return true;
207 : }
208 :
209 : template <class T>
210 : bool shl_char_array(T const* str_value) {
211 : BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
212 : "boost::lexical_cast does not support narrowing of char types."
213 : "Use boost::locale instead" );
214 : return shl_input_streamable(str_value);
215 : }
216 :
217 : bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT {
218 : start = str;
219 : finish = std::find(start, start + max_size, Traits::to_char_type(0));
220 : return true;
221 : }
222 :
223 : template<typename InputStreamable>
224 0 : bool shl_input_streamable(InputStreamable& input) {
225 : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
226 : // If you have compilation error at this point, than your STL library
227 : // does not support such conversions. Try updating it.
228 : BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value));
229 : #endif
230 :
231 : #ifndef BOOST_NO_EXCEPTIONS
232 0 : out_stream.exceptions(std::ios::badbit);
233 : try {
234 : #endif
235 0 : bool const result = !(out_stream << input).fail();
236 0 : const deduced_out_buffer_t* const p = static_cast<deduced_out_buffer_t*>(
237 : out_stream.rdbuf()
238 : );
239 0 : start = p->pbase();
240 0 : finish = p->pptr();
241 0 : return result;
242 : #ifndef BOOST_NO_EXCEPTIONS
243 0 : } catch (const ::std::ios_base::failure& /*f*/) {
244 : return false;
245 : }
246 : #endif
247 : }
248 :
249 : template <class T>
250 361 : inline bool shl_unsigned(const T n) {
251 361 : CharT* tmp_finish = buffer + CharacterBufferSize;
252 361 : start = lcast_put_unsigned<Traits, T, CharT>(n, tmp_finish).convert();
253 361 : finish = tmp_finish;
254 : return true;
255 : }
256 :
257 : template <class T>
258 894123 : inline bool shl_signed(const T n) {
259 894123 : CharT* tmp_finish = buffer + CharacterBufferSize;
260 : typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type utype;
261 894123 : CharT* tmp_start = lcast_put_unsigned<Traits, utype, CharT>(lcast_to_unsigned(n), tmp_finish).convert();
262 894123 : if (n < 0) {
263 39614 : --tmp_start;
264 39614 : CharT const minus = lcast_char_constants<CharT>::minus;
265 39614 : Traits::assign(*tmp_start, minus);
266 : }
267 894123 : start = tmp_start;
268 894123 : finish = tmp_finish;
269 894123 : return true;
270 : }
271 :
272 : template <class T, class SomeCharT>
273 : bool shl_real_type(const T& val, SomeCharT* /*begin*/) {
274 : lcast_set_precision(out_stream, &val);
275 : return shl_input_streamable(val);
276 : }
277 :
278 : bool shl_real_type(float val, char* begin) {
279 : using namespace std;
280 : const double val_as_double = val;
281 : finish = start +
282 : #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
283 : sprintf_s(begin, CharacterBufferSize,
284 : #else
285 : sprintf(begin,
286 : #endif
287 : "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double);
288 : return finish > start;
289 : }
290 :
291 0 : bool shl_real_type(double val, char* begin) {
292 : using namespace std;
293 0 : finish = start +
294 : #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
295 : sprintf_s(begin, CharacterBufferSize,
296 : #else
297 0 : sprintf(begin,
298 : #endif
299 0 : "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val);
300 0 : return finish > start;
301 : }
302 :
303 : #ifndef __MINGW32__
304 : bool shl_real_type(long double val, char* begin) {
305 : using namespace std;
306 : finish = start +
307 : #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
308 : sprintf_s(begin, CharacterBufferSize,
309 : #else
310 : sprintf(begin,
311 : #endif
312 : "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val );
313 : return finish > start;
314 : }
315 : #endif
316 :
317 :
318 : #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
319 : bool shl_real_type(float val, wchar_t* begin) {
320 : using namespace std;
321 : const double val_as_double = val;
322 : finish = start + swprintf(begin, CharacterBufferSize,
323 : L"%.*g",
324 : static_cast<int>(boost::detail::lcast_get_precision<float >()),
325 : val_as_double );
326 : return finish > start;
327 : }
328 :
329 : bool shl_real_type(double val, wchar_t* begin) {
330 : using namespace std;
331 : finish = start + swprintf(begin, CharacterBufferSize,
332 : L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
333 : return finish > start;
334 : }
335 :
336 : bool shl_real_type(long double val, wchar_t* begin) {
337 : using namespace std;
338 : finish = start + swprintf(begin, CharacterBufferSize,
339 : L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
340 : return finish > start;
341 : }
342 : #endif
343 : template <class T>
344 0 : bool shl_real(T val) {
345 0 : CharT* tmp_finish = buffer + CharacterBufferSize;
346 0 : if (put_inf_nan(buffer, tmp_finish, val)) {
347 0 : finish = tmp_finish;
348 0 : return true;
349 : }
350 :
351 0 : return shl_real_type(val, static_cast<CharT*>(buffer));
352 : }
353 :
354 : /************************************ OPERATORS << ( ... ) ********************************/
355 : public:
356 : template<class Alloc>
357 0 : bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT {
358 0 : start = str.data();
359 0 : finish = start + str.length();
360 : return true;
361 : }
362 :
363 : template<class Alloc>
364 : bool operator<<(boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT {
365 : start = str.data();
366 : finish = start + str.length();
367 : return true;
368 : }
369 :
370 1421 : bool operator<<(bool value) BOOST_NOEXCEPT {
371 1421 : CharT const czero = lcast_char_constants<CharT>::zero;
372 1421 : Traits::assign(buffer[0], Traits::to_char_type(czero + value));
373 1421 : finish = start + 1;
374 : return true;
375 : }
376 :
377 : template <class C>
378 : BOOST_DEDUCED_TYPENAME boost::disable_if<boost::is_const<C>, bool>::type
379 : operator<<(const iterator_range<C*>& rng) BOOST_NOEXCEPT {
380 : return (*this) << iterator_range<const C*>(rng.begin(), rng.end());
381 : }
382 :
383 : bool operator<<(const iterator_range<const CharT*>& rng) BOOST_NOEXCEPT {
384 : start = rng.begin();
385 : finish = rng.end();
386 : return true;
387 : }
388 :
389 : bool operator<<(const iterator_range<const signed char*>& rng) BOOST_NOEXCEPT {
390 : return (*this) << iterator_range<const char*>(
391 : reinterpret_cast<const char*>(rng.begin()),
392 : reinterpret_cast<const char*>(rng.end())
393 : );
394 : }
395 :
396 : bool operator<<(const iterator_range<const unsigned char*>& rng) BOOST_NOEXCEPT {
397 : return (*this) << iterator_range<const char*>(
398 : reinterpret_cast<const char*>(rng.begin()),
399 : reinterpret_cast<const char*>(rng.end())
400 : );
401 : }
402 :
403 : bool operator<<(char ch) { return shl_char(ch); }
404 : bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); }
405 : bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); }
406 : #if !defined(BOOST_LCAST_NO_WCHAR_T)
407 : bool operator<<(wchar_t const* str) { return shl_char_array(str); }
408 : bool operator<<(wchar_t * str) { return shl_char_array(str); }
409 : #ifndef BOOST_NO_INTRINSIC_WCHAR_T
410 : bool operator<<(wchar_t ch) { return shl_char(ch); }
411 : #endif
412 : #endif
413 : #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
414 : bool operator<<(char16_t ch) { return shl_char(ch); }
415 : bool operator<<(char16_t * str) { return shl_char_array(str); }
416 : bool operator<<(char16_t const * str) { return shl_char_array(str); }
417 : #endif
418 : #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
419 : bool operator<<(char32_t ch) { return shl_char(ch); }
420 : bool operator<<(char32_t * str) { return shl_char_array(str); }
421 : bool operator<<(char32_t const * str) { return shl_char_array(str); }
422 : #endif
423 : bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
424 : bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
425 : bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
426 : bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
427 : bool operator<<(char const* str_value) { return shl_char_array(str_value); }
428 : bool operator<<(char* str_value) { return shl_char_array(str_value); }
429 : bool operator<<(short n) { return shl_signed(n); }
430 : bool operator<<(int n) { return shl_signed(n); }
431 : bool operator<<(long n) { return shl_signed(n); }
432 : bool operator<<(unsigned short n) { return shl_unsigned(n); }
433 356 : bool operator<<(unsigned int n) { return shl_unsigned(n); }
434 5 : bool operator<<(unsigned long n) { return shl_unsigned(n); }
435 :
436 : #if defined(BOOST_HAS_LONG_LONG)
437 0 : bool operator<<(boost::ulong_long_type n) { return shl_unsigned(n); }
438 : bool operator<<(boost::long_long_type n) { return shl_signed(n); }
439 : #elif defined(BOOST_HAS_MS_INT64)
440 : bool operator<<(unsigned __int64 n) { return shl_unsigned(n); }
441 : bool operator<<( __int64 n) { return shl_signed(n); }
442 : #endif
443 :
444 : #ifdef BOOST_HAS_INT128
445 : bool operator<<(const boost::uint128_type& n) { return shl_unsigned(n); }
446 : bool operator<<(const boost::int128_type& n) { return shl_signed(n); }
447 : #endif
448 : bool operator<<(float val) { return shl_real(val); }
449 0 : bool operator<<(double val) { return shl_real(val); }
450 : bool operator<<(long double val) {
451 : #ifndef __MINGW32__
452 : return shl_real(val);
453 : #else
454 : return shl_real(static_cast<double>(val));
455 : #endif
456 : }
457 :
458 : // Adding constness to characters. Constness does not change layout
459 : template <class C, std::size_t N>
460 : BOOST_DEDUCED_TYPENAME boost::disable_if<boost::is_const<C>, bool>::type
461 : operator<<(boost::array<C, N> const& input) BOOST_NOEXCEPT {
462 : BOOST_STATIC_ASSERT_MSG(
463 : (sizeof(boost::array<const C, N>) == sizeof(boost::array<C, N>)),
464 : "boost::array<C, N> and boost::array<const C, N> must have exactly the same layout."
465 : );
466 : return ((*this) << reinterpret_cast<boost::array<const C, N> const& >(input));
467 : }
468 :
469 : template <std::size_t N>
470 : bool operator<<(boost::array<const CharT, N> const& input) BOOST_NOEXCEPT {
471 : return shl_char_array_limited(input.data(), N);
472 : }
473 :
474 : template <std::size_t N>
475 : bool operator<<(boost::array<const unsigned char, N> const& input) BOOST_NOEXCEPT {
476 : return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input));
477 : }
478 :
479 : template <std::size_t N>
480 : bool operator<<(boost::array<const signed char, N> const& input) BOOST_NOEXCEPT {
481 : return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input));
482 : }
483 :
484 : #ifndef BOOST_NO_CXX11_HDR_ARRAY
485 : // Making a Boost.Array from std::array
486 : template <class C, std::size_t N>
487 : bool operator<<(std::array<C, N> const& input) BOOST_NOEXCEPT {
488 : BOOST_STATIC_ASSERT_MSG(
489 : (sizeof(std::array<C, N>) == sizeof(boost::array<C, N>)),
490 : "std::array and boost::array must have exactly the same layout. "
491 : "Bug in implementation of std::array or boost::array."
492 : );
493 : return ((*this) << reinterpret_cast<boost::array<C, N> const& >(input));
494 : }
495 : #endif
496 : template <class InStreamable>
497 0 : bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
498 : };
499 :
500 :
501 : template <class CharT, class Traits>
502 : class lexical_ostream_limited_src: boost::noncopyable {
503 : //`[start, finish)` is the range to output by `operator >>`
504 : const CharT* start;
505 : const CharT* const finish;
506 :
507 : public:
508 1782 : lexical_ostream_limited_src(const CharT* begin, const CharT* end) BOOST_NOEXCEPT
509 : : start(begin)
510 1782 : , finish(end)
511 : {}
512 :
513 : /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
514 : private:
515 : template <typename Type>
516 0 : bool shr_unsigned(Type& output) {
517 0 : if (start == finish) return false;
518 0 : CharT const minus = lcast_char_constants<CharT>::minus;
519 0 : CharT const plus = lcast_char_constants<CharT>::plus;
520 0 : bool const has_minus = Traits::eq(minus, *start);
521 :
522 : /* We won`t use `start' any more, so no need in decrementing it after */
523 0 : if (has_minus || Traits::eq(plus, *start)) {
524 0 : ++start;
525 : }
526 :
527 0 : bool const succeed = lcast_ret_unsigned<Traits, Type, CharT>(output, start, finish).convert();
528 :
529 0 : if (has_minus) {
530 0 : output = static_cast<Type>(0u - output);
531 : }
532 :
533 : return succeed;
534 : }
535 :
536 : template <typename Type>
537 : bool shr_signed(Type& output) {
538 : if (start == finish) return false;
539 : CharT const minus = lcast_char_constants<CharT>::minus;
540 : CharT const plus = lcast_char_constants<CharT>::plus;
541 : typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
542 : utype out_tmp = 0;
543 : bool const has_minus = Traits::eq(minus, *start);
544 :
545 : /* We won`t use `start' any more, so no need in decrementing it after */
546 : if (has_minus || Traits::eq(plus, *start)) {
547 : ++start;
548 : }
549 :
550 : bool succeed = lcast_ret_unsigned<Traits, utype, CharT>(out_tmp, start, finish).convert();
551 : if (has_minus) {
552 : utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
553 : succeed = succeed && out_tmp<=comp_val;
554 : output = static_cast<Type>(0u - out_tmp);
555 : } else {
556 : utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
557 : succeed = succeed && out_tmp<=comp_val;
558 : output = static_cast<Type>(out_tmp);
559 : }
560 : return succeed;
561 : }
562 :
563 : template<typename InputStreamable>
564 : bool shr_using_base_class(InputStreamable& output)
565 : {
566 : BOOST_STATIC_ASSERT_MSG(
567 : (!boost::is_pointer<InputStreamable>::value),
568 : "boost::lexical_cast can not convert to pointers"
569 : );
570 :
571 : #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
572 : BOOST_STATIC_ASSERT_MSG((boost::is_same<char, CharT>::value),
573 : "boost::lexical_cast can not convert, because your STL library does not "
574 : "support such conversions. Try updating it."
575 : );
576 : #endif
577 :
578 : #if defined(BOOST_NO_STRINGSTREAM)
579 : std::istrstream stream(start, static_cast<std::istrstream::streamsize>(finish - start));
580 : #else
581 : typedef BOOST_DEDUCED_TYPENAME out_stream_helper_trait<CharT, Traits>::buffer_t buffer_t;
582 : buffer_t buf;
583 : // Usually `istream` and `basic_istream` do not modify
584 : // content of buffer; `buffer_t` assures that this is true
585 : buf.setbuf(const_cast<CharT*>(start), static_cast<typename buffer_t::streamsize>(finish - start));
586 : #if defined(BOOST_NO_STD_LOCALE)
587 : std::istream stream(&buf);
588 : #else
589 : std::basic_istream<CharT, Traits> stream(&buf);
590 : #endif // BOOST_NO_STD_LOCALE
591 : #endif // BOOST_NO_STRINGSTREAM
592 :
593 : #ifndef BOOST_NO_EXCEPTIONS
594 : stream.exceptions(std::ios::badbit);
595 : try {
596 : #endif
597 : stream.unsetf(std::ios::skipws);
598 : lcast_set_precision(stream, static_cast<InputStreamable*>(0));
599 :
600 : return (stream >> output)
601 : && (stream.get() == Traits::eof());
602 :
603 : #ifndef BOOST_NO_EXCEPTIONS
604 : } catch (const ::std::ios_base::failure& /*f*/) {
605 : return false;
606 : }
607 : #endif
608 : }
609 :
610 : template<class T>
611 : inline bool shr_xchar(T& output) BOOST_NOEXCEPT {
612 : BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
613 : "boost::lexical_cast does not support narrowing of character types."
614 : "Use boost::locale instead" );
615 : bool const ok = (finish - start == 1);
616 : if (ok) {
617 : CharT out;
618 : Traits::assign(out, *start);
619 : output = static_cast<T>(out);
620 : }
621 : return ok;
622 : }
623 :
624 : template <std::size_t N, class ArrayT>
625 : bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT {
626 : using namespace std;
627 : const std::size_t size = static_cast<std::size_t>(finish - start);
628 : if (size > N - 1) { // `-1` because we need to store \0 at the end
629 : return false;
630 : }
631 :
632 : memcpy(&output[0], start, size * sizeof(CharT));
633 : output[size] = Traits::to_char_type(0);
634 : return true;
635 : }
636 :
637 : /************************************ OPERATORS >> ( ... ) ********************************/
638 : public:
639 : bool operator>>(unsigned short& output) { return shr_unsigned(output); }
640 0 : bool operator>>(unsigned int& output) { return shr_unsigned(output); }
641 0 : bool operator>>(unsigned long int& output) { return shr_unsigned(output); }
642 : bool operator>>(short& output) { return shr_signed(output); }
643 : bool operator>>(int& output) { return shr_signed(output); }
644 : bool operator>>(long int& output) { return shr_signed(output); }
645 : #if defined(BOOST_HAS_LONG_LONG)
646 : bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); }
647 : bool operator>>(boost::long_long_type& output) { return shr_signed(output); }
648 : #elif defined(BOOST_HAS_MS_INT64)
649 : bool operator>>(unsigned __int64& output) { return shr_unsigned(output); }
650 : bool operator>>(__int64& output) { return shr_signed(output); }
651 : #endif
652 :
653 : #ifdef BOOST_HAS_INT128
654 : bool operator>>(boost::uint128_type& output) { return shr_unsigned(output); }
655 : bool operator>>(boost::int128_type& output) { return shr_signed(output); }
656 : #endif
657 :
658 : bool operator>>(char& output) { return shr_xchar(output); }
659 : bool operator>>(unsigned char& output) { return shr_xchar(output); }
660 : bool operator>>(signed char& output) { return shr_xchar(output); }
661 : #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
662 : bool operator>>(wchar_t& output) { return shr_xchar(output); }
663 : #endif
664 : #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
665 : bool operator>>(char16_t& output) { return shr_xchar(output); }
666 : #endif
667 : #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
668 : bool operator>>(char32_t& output) { return shr_xchar(output); }
669 : #endif
670 : template<class Alloc>
671 1782 : bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) {
672 1782 : str.assign(start, finish); return true;
673 : }
674 :
675 : template<class Alloc>
676 : bool operator>>(boost::container::basic_string<CharT,Traits,Alloc>& str) {
677 : str.assign(start, finish); return true;
678 : }
679 :
680 : template <std::size_t N>
681 : bool operator>>(boost::array<CharT, N>& output) BOOST_NOEXCEPT {
682 : return shr_std_array<N>(output);
683 : }
684 :
685 : template <std::size_t N>
686 : bool operator>>(boost::array<unsigned char, N>& output) BOOST_NOEXCEPT {
687 : return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
688 : }
689 :
690 : template <std::size_t N>
691 : bool operator>>(boost::array<signed char, N>& output) BOOST_NOEXCEPT {
692 : return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
693 : }
694 :
695 : #ifndef BOOST_NO_CXX11_HDR_ARRAY
696 : template <class C, std::size_t N>
697 : bool operator>>(std::array<C, N>& output) BOOST_NOEXCEPT {
698 : BOOST_STATIC_ASSERT_MSG(
699 : (sizeof(std::array<C, N>) == sizeof(boost::array<C, N>)),
700 : "std::array<C, N> and boost::array<C, N> must have exactly the same layout."
701 : );
702 : return ((*this) >> reinterpret_cast<boost::array<C, N>& >(output));
703 : }
704 : #endif
705 :
706 : bool operator>>(bool& output) BOOST_NOEXCEPT {
707 : output = false; // Suppress warning about uninitalized variable
708 :
709 : if (start == finish) return false;
710 : CharT const zero = lcast_char_constants<CharT>::zero;
711 : CharT const plus = lcast_char_constants<CharT>::plus;
712 : CharT const minus = lcast_char_constants<CharT>::minus;
713 :
714 : const CharT* const dec_finish = finish - 1;
715 : output = Traits::eq(*dec_finish, zero + 1);
716 : if (!output && !Traits::eq(*dec_finish, zero)) {
717 : return false; // Does not ends on '0' or '1'
718 : }
719 :
720 : if (start == dec_finish) return true;
721 :
722 : // We may have sign at the beginning
723 : if (Traits::eq(plus, *start) || (Traits::eq(minus, *start) && !output)) {
724 : ++ start;
725 : }
726 :
727 : // Skipping zeros
728 : while (start != dec_finish) {
729 : if (!Traits::eq(zero, *start)) {
730 : return false; // Not a zero => error
731 : }
732 :
733 : ++ start;
734 : }
735 :
736 : return true;
737 : }
738 :
739 : private:
740 : // Not optimised converter
741 : template <class T>
742 : bool float_types_converter_internal(T& output) {
743 : if (parse_inf_nan(start, finish, output)) return true;
744 : bool const return_value = shr_using_base_class(output);
745 :
746 : /* Some compilers and libraries successfully
747 : * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
748 : * We are trying to provide a unified behaviour,
749 : * so we just forbid such conversions (as some
750 : * of the most popular compilers/libraries do)
751 : * */
752 : CharT const minus = lcast_char_constants<CharT>::minus;
753 : CharT const plus = lcast_char_constants<CharT>::plus;
754 : CharT const capital_e = lcast_char_constants<CharT>::capital_e;
755 : CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
756 : if ( return_value &&
757 : (
758 : Traits::eq(*(finish-1), lowercase_e) // 1.0e
759 : || Traits::eq(*(finish-1), capital_e) // 1.0E
760 : || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E-
761 : || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+
762 : )
763 : ) return false;
764 :
765 : return return_value;
766 : }
767 :
768 : public:
769 : bool operator>>(float& output) { return float_types_converter_internal(output); }
770 : bool operator>>(double& output) { return float_types_converter_internal(output); }
771 : bool operator>>(long double& output) { return float_types_converter_internal(output); }
772 :
773 : // Generic istream-based algorithm.
774 : // lcast_streambuf_for_target<InputStreamable>::value is true.
775 : template <typename InputStreamable>
776 : bool operator>>(InputStreamable& output) {
777 : return shr_using_base_class(output);
778 : }
779 : };
780 : }
781 : } // namespace boost
782 :
783 : #undef BOOST_LCAST_NO_WCHAR_T
784 :
785 : #endif // BOOST_LEXICAL_CAST_DETAIL_CONVERTER_LEXICAL_HPP
786 :
|