annotate DEPENDENCIES/generic/include/boost/lexical_cast/detail/converter_lexical_streams.hpp @ 133:4acb5d8d80b6 tip

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