annotate DEPENDENCIES/generic/include/boost/lexical_cast.hpp @ 16:2665513ce2d3

Add boost headers
author Chris Cannam
date Tue, 05 Aug 2014 11:11:38 +0100
parents
children c530137014c0
rev   line source
Chris@16 1 #ifndef BOOST_LEXICAL_CAST_INCLUDED
Chris@16 2 #define BOOST_LEXICAL_CAST_INCLUDED
Chris@16 3
Chris@16 4 // MS compatible compilers support #pragma once
Chris@16 5
Chris@16 6 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
Chris@16 7 # pragma once
Chris@16 8 #endif
Chris@16 9
Chris@16 10 // Boost lexical_cast.hpp header -------------------------------------------//
Chris@16 11 //
Chris@16 12 // See http://www.boost.org/libs/conversion for documentation.
Chris@16 13 // See end of this header for rights and permissions.
Chris@16 14 //
Chris@16 15 // what: lexical_cast custom keyword cast
Chris@16 16 // who: contributed by Kevlin Henney,
Chris@16 17 // enhanced with contributions from Terje Slettebo,
Chris@16 18 // with additional fixes and suggestions from Gennaro Prota,
Chris@16 19 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
Chris@16 20 // Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
Chris@16 21 // Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
Chris@16 22 // when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2013
Chris@16 23
Chris@16 24 #include <boost/config.hpp>
Chris@16 25 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
Chris@16 26 #define BOOST_LCAST_NO_WCHAR_T
Chris@16 27 #endif
Chris@16 28
Chris@16 29 #include <climits>
Chris@16 30 #include <cstddef>
Chris@16 31 #include <string>
Chris@16 32 #include <cstring>
Chris@16 33 #include <cstdio>
Chris@16 34 #include <typeinfo>
Chris@16 35 #include <exception>
Chris@16 36 #include <boost/limits.hpp>
Chris@16 37 #include <boost/mpl/if.hpp>
Chris@16 38 #include <boost/throw_exception.hpp>
Chris@16 39 #include <boost/type_traits/ice.hpp>
Chris@16 40 #include <boost/type_traits/is_pointer.hpp>
Chris@16 41 #include <boost/static_assert.hpp>
Chris@16 42 #include <boost/detail/lcast_precision.hpp>
Chris@16 43 #include <boost/detail/workaround.hpp>
Chris@16 44
Chris@16 45
Chris@16 46 #ifndef BOOST_NO_STD_LOCALE
Chris@16 47 # include <locale>
Chris@16 48 #else
Chris@16 49 # ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 50 // Getting error at this point means, that your STL library is old/lame/misconfigured.
Chris@16 51 // If nothing can be done with STL library, define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
Chris@16 52 // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
Chris@16 53 // separators.
Chris@16 54 # error "Unable to use <locale> header. Define BOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
Chris@16 55 # error "boost::lexical_cast to use only 'C' locale during conversions."
Chris@16 56 # endif
Chris@16 57 #endif
Chris@16 58
Chris@16 59 #ifdef BOOST_NO_STRINGSTREAM
Chris@16 60 #include <strstream>
Chris@16 61 #else
Chris@16 62 #include <sstream>
Chris@16 63 #endif
Chris@16 64
Chris@16 65 #ifdef BOOST_NO_TYPEID
Chris@16 66 #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
Chris@16 67 #else
Chris@16 68 #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
Chris@16 69 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
Chris@16 70 #endif
Chris@16 71
Chris@16 72 namespace boost
Chris@16 73 {
Chris@16 74 // exception used to indicate runtime lexical_cast failure
Chris@16 75 class BOOST_SYMBOL_VISIBLE bad_lexical_cast :
Chris@16 76 // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
Chris@16 77 #if defined(BOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
Chris@16 78 public std::exception
Chris@16 79 #else
Chris@16 80 public std::bad_cast
Chris@16 81 #endif
Chris@16 82
Chris@16 83 #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
Chris@16 84 // under bcc32 5.5.1 bad_cast doesn't derive from exception
Chris@16 85 , public std::exception
Chris@16 86 #endif
Chris@16 87
Chris@16 88 {
Chris@16 89 public:
Chris@16 90 bad_lexical_cast() BOOST_NOEXCEPT :
Chris@16 91 #ifndef BOOST_NO_TYPEID
Chris@16 92 source(&typeid(void)), target(&typeid(void))
Chris@16 93 #else
Chris@16 94 source(0), target(0) // this breaks getters
Chris@16 95 #endif
Chris@16 96 {
Chris@16 97 }
Chris@16 98
Chris@16 99 bad_lexical_cast(
Chris@16 100 const std::type_info &source_type_arg,
Chris@16 101 const std::type_info &target_type_arg) BOOST_NOEXCEPT :
Chris@16 102 source(&source_type_arg), target(&target_type_arg)
Chris@16 103 {
Chris@16 104 }
Chris@16 105
Chris@16 106 const std::type_info &source_type() const
Chris@16 107 {
Chris@16 108 return *source;
Chris@16 109 }
Chris@16 110 const std::type_info &target_type() const
Chris@16 111 {
Chris@16 112 return *target;
Chris@16 113 }
Chris@16 114
Chris@16 115 #ifndef BOOST_NO_CXX11_NOEXCEPT
Chris@16 116 virtual const char *what() const noexcept
Chris@16 117 #else
Chris@16 118 virtual const char *what() const throw()
Chris@16 119 #endif
Chris@16 120 {
Chris@16 121 return "bad lexical cast: "
Chris@16 122 "source type value could not be interpreted as target";
Chris@16 123 }
Chris@16 124
Chris@16 125 #ifndef BOOST_NO_CXX11_NOEXCEPT
Chris@16 126 virtual ~bad_lexical_cast() BOOST_NOEXCEPT
Chris@16 127 #else
Chris@16 128 virtual ~bad_lexical_cast() throw()
Chris@16 129 #endif
Chris@16 130 {}
Chris@16 131 private:
Chris@16 132 const std::type_info *source;
Chris@16 133 const std::type_info *target;
Chris@16 134 };
Chris@16 135
Chris@16 136 namespace detail // widest_char
Chris@16 137 {
Chris@16 138 template <typename TargetChar, typename SourceChar>
Chris@16 139 struct widest_char
Chris@16 140 {
Chris@16 141 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 142 (sizeof(TargetChar) > sizeof(SourceChar))
Chris@16 143 , TargetChar
Chris@16 144 , SourceChar >::type type;
Chris@16 145 };
Chris@16 146 }
Chris@16 147 } // namespace boost
Chris@16 148
Chris@16 149 #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__)
Chris@16 150
Chris@16 151 #include <cmath>
Chris@16 152 #include <istream>
Chris@16 153
Chris@16 154 #ifndef BOOST_NO_CXX11_HDR_ARRAY
Chris@16 155 #include <array>
Chris@16 156 #endif
Chris@16 157
Chris@16 158 #include <boost/array.hpp>
Chris@16 159 #include <boost/numeric/conversion/cast.hpp>
Chris@16 160 #include <boost/type_traits/make_unsigned.hpp>
Chris@16 161 #include <boost/type_traits/is_signed.hpp>
Chris@16 162 #include <boost/type_traits/is_integral.hpp>
Chris@16 163 #include <boost/type_traits/is_arithmetic.hpp>
Chris@16 164 #include <boost/type_traits/remove_pointer.hpp>
Chris@16 165 #include <boost/type_traits/has_left_shift.hpp>
Chris@16 166 #include <boost/type_traits/has_right_shift.hpp>
Chris@16 167 #include <boost/math/special_functions/sign.hpp>
Chris@16 168 #include <boost/math/special_functions/fpclassify.hpp>
Chris@16 169 #include <boost/range/iterator_range_core.hpp>
Chris@16 170 #include <boost/container/container_fwd.hpp>
Chris@16 171 #include <boost/integer.hpp>
Chris@16 172 #ifndef BOOST_NO_CWCHAR
Chris@16 173 # include <cwchar>
Chris@16 174 #endif
Chris@16 175
Chris@16 176 namespace boost {
Chris@16 177
Chris@16 178 namespace detail // is_char_or_wchar<...>
Chris@16 179 {
Chris@16 180 // returns true, if T is one of the character types
Chris@16 181 template < typename T >
Chris@16 182 struct is_char_or_wchar
Chris@16 183 {
Chris@16 184 typedef boost::type_traits::ice_or<
Chris@16 185 boost::is_same< T, char >::value,
Chris@16 186 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 187 boost::is_same< T, wchar_t >::value,
Chris@16 188 #endif
Chris@16 189 #ifndef BOOST_NO_CXX11_CHAR16_T
Chris@16 190 boost::is_same< T, char16_t >::value,
Chris@16 191 #endif
Chris@16 192 #ifndef BOOST_NO_CXX11_CHAR32_T
Chris@16 193 boost::is_same< T, char32_t >::value,
Chris@16 194 #endif
Chris@16 195 boost::is_same< T, unsigned char >::value,
Chris@16 196 boost::is_same< T, signed char >::value
Chris@16 197 > result_type;
Chris@16 198
Chris@16 199 BOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
Chris@16 200 };
Chris@16 201 }
Chris@16 202
Chris@16 203 namespace detail // normalize_single_byte_char<Char>
Chris@16 204 {
Chris@16 205 // Converts signed/unsigned char to char
Chris@16 206 template < class Char >
Chris@16 207 struct normalize_single_byte_char
Chris@16 208 {
Chris@16 209 typedef Char type;
Chris@16 210 };
Chris@16 211
Chris@16 212 template <>
Chris@16 213 struct normalize_single_byte_char< signed char >
Chris@16 214 {
Chris@16 215 typedef char type;
Chris@16 216 };
Chris@16 217
Chris@16 218 template <>
Chris@16 219 struct normalize_single_byte_char< unsigned char >
Chris@16 220 {
Chris@16 221 typedef char type;
Chris@16 222 };
Chris@16 223 }
Chris@16 224
Chris@16 225 namespace detail // deduce_character_type_later<T>
Chris@16 226 {
Chris@16 227 // Helper type, meaning that stram character for T must be deduced
Chris@16 228 // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
Chris@16 229 template < class T > struct deduce_character_type_later {};
Chris@16 230 }
Chris@16 231
Chris@16 232 namespace detail // stream_char_common<T>
Chris@16 233 {
Chris@16 234 // Selectors to choose stream character type (common for Source and Target)
Chris@16 235 // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
Chris@16 236 // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
Chris@16 237 template < typename Type >
Chris@16 238 struct stream_char_common: public boost::mpl::if_c<
Chris@16 239 boost::detail::is_char_or_wchar< Type >::value,
Chris@16 240 Type,
Chris@16 241 boost::detail::deduce_character_type_later< Type >
Chris@16 242 > {};
Chris@16 243
Chris@16 244 template < typename Char >
Chris@16 245 struct stream_char_common< Char* >: public boost::mpl::if_c<
Chris@16 246 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 247 Char,
Chris@16 248 boost::detail::deduce_character_type_later< Char* >
Chris@16 249 > {};
Chris@16 250
Chris@16 251 template < typename Char >
Chris@16 252 struct stream_char_common< const Char* >: public boost::mpl::if_c<
Chris@16 253 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 254 Char,
Chris@16 255 boost::detail::deduce_character_type_later< const Char* >
Chris@16 256 > {};
Chris@16 257
Chris@16 258 template < typename Char >
Chris@16 259 struct stream_char_common< boost::iterator_range< Char* > >: public boost::mpl::if_c<
Chris@16 260 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 261 Char,
Chris@16 262 boost::detail::deduce_character_type_later< boost::iterator_range< Char* > >
Chris@16 263 > {};
Chris@16 264
Chris@16 265 template < typename Char >
Chris@16 266 struct stream_char_common< boost::iterator_range< const Char* > >: public boost::mpl::if_c<
Chris@16 267 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 268 Char,
Chris@16 269 boost::detail::deduce_character_type_later< boost::iterator_range< const Char* > >
Chris@16 270 > {};
Chris@16 271
Chris@16 272 template < class Char, class Traits, class Alloc >
Chris@16 273 struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
Chris@16 274 {
Chris@16 275 typedef Char type;
Chris@16 276 };
Chris@16 277
Chris@16 278 template < class Char, class Traits, class Alloc >
Chris@16 279 struct stream_char_common< boost::container::basic_string< Char, Traits, Alloc > >
Chris@16 280 {
Chris@16 281 typedef Char type;
Chris@16 282 };
Chris@16 283
Chris@16 284 template < typename Char, std::size_t N >
Chris@16 285 struct stream_char_common< boost::array< Char, N > >: public boost::mpl::if_c<
Chris@16 286 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 287 Char,
Chris@16 288 boost::detail::deduce_character_type_later< boost::array< Char, N > >
Chris@16 289 > {};
Chris@16 290
Chris@16 291 template < typename Char, std::size_t N >
Chris@16 292 struct stream_char_common< boost::array< const Char, N > >: public boost::mpl::if_c<
Chris@16 293 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 294 Char,
Chris@16 295 boost::detail::deduce_character_type_later< boost::array< const Char, N > >
Chris@16 296 > {};
Chris@16 297
Chris@16 298 #ifndef BOOST_NO_CXX11_HDR_ARRAY
Chris@16 299 template < typename Char, std::size_t N >
Chris@16 300 struct stream_char_common< std::array<Char, N > >: public boost::mpl::if_c<
Chris@16 301 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 302 Char,
Chris@16 303 boost::detail::deduce_character_type_later< std::array< Char, N > >
Chris@16 304 > {};
Chris@16 305
Chris@16 306 template < typename Char, std::size_t N >
Chris@16 307 struct stream_char_common< std::array< const Char, N > >: public boost::mpl::if_c<
Chris@16 308 boost::detail::is_char_or_wchar< Char >::value,
Chris@16 309 Char,
Chris@16 310 boost::detail::deduce_character_type_later< std::array< const Char, N > >
Chris@16 311 > {};
Chris@16 312 #endif
Chris@16 313
Chris@16 314 #ifdef BOOST_HAS_INT128
Chris@16 315 template <> struct stream_char_common< boost::int128_type >: public boost::mpl::identity< char > {};
Chris@16 316 template <> struct stream_char_common< boost::uint128_type >: public boost::mpl::identity< char > {};
Chris@16 317 #endif
Chris@16 318
Chris@16 319 #if !defined(BOOST_LCAST_NO_WCHAR_T) && defined(BOOST_NO_INTRINSIC_WCHAR_T)
Chris@16 320 template <>
Chris@16 321 struct stream_char_common< wchar_t >
Chris@16 322 {
Chris@16 323 typedef char type;
Chris@16 324 };
Chris@16 325 #endif
Chris@16 326 }
Chris@16 327
Chris@16 328 namespace detail // deduce_source_char_impl<T>
Chris@16 329 {
Chris@16 330 // If type T is `deduce_character_type_later` type, then tries to deduce
Chris@16 331 // character type using boost::has_left_shift<T> metafunction.
Chris@16 332 // Otherwise supplied type T is a character type, that must be normalized
Chris@16 333 // using normalize_single_byte_char<Char>.
Chris@16 334 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
Chris@16 335 template < class Char >
Chris@16 336 struct deduce_source_char_impl
Chris@16 337 {
Chris@16 338 typedef BOOST_DEDUCED_TYPENAME boost::detail::normalize_single_byte_char< Char >::type type;
Chris@16 339 };
Chris@16 340
Chris@16 341 template < class T >
Chris@16 342 struct deduce_source_char_impl< deduce_character_type_later< T > >
Chris@16 343 {
Chris@16 344 typedef boost::has_left_shift< std::basic_ostream< char >, T > result_t;
Chris@16 345
Chris@16 346 #if defined(BOOST_LCAST_NO_WCHAR_T)
Chris@16 347 BOOST_STATIC_ASSERT_MSG((result_t::value),
Chris@16 348 "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation");
Chris@16 349 typedef char type;
Chris@16 350 #else
Chris@16 351 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 352 result_t::value, char, wchar_t
Chris@16 353 >::type type;
Chris@16 354
Chris@16 355 BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_left_shift< std::basic_ostream< type >, T >::value),
Chris@16 356 "Source type is neither std::ostream`able nor std::wostream`able");
Chris@16 357 #endif
Chris@16 358 };
Chris@16 359 }
Chris@16 360
Chris@16 361 namespace detail // deduce_target_char_impl<T>
Chris@16 362 {
Chris@16 363 // If type T is `deduce_character_type_later` type, then tries to deduce
Chris@16 364 // character type using boost::has_right_shift<T> metafunction.
Chris@16 365 // Otherwise supplied type T is a character type, that must be normalized
Chris@16 366 // using normalize_single_byte_char<Char>.
Chris@16 367 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
Chris@16 368 template < class Char >
Chris@16 369 struct deduce_target_char_impl
Chris@16 370 {
Chris@16 371 typedef BOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type;
Chris@16 372 };
Chris@16 373
Chris@16 374 template < class T >
Chris@16 375 struct deduce_target_char_impl< deduce_character_type_later<T> >
Chris@16 376 {
Chris@16 377 typedef boost::has_right_shift<std::basic_istream<char>, T > result_t;
Chris@16 378
Chris@16 379 #if defined(BOOST_LCAST_NO_WCHAR_T)
Chris@16 380 BOOST_STATIC_ASSERT_MSG((result_t::value),
Chris@16 381 "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation");
Chris@16 382 typedef char type;
Chris@16 383 #else
Chris@16 384 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 385 result_t::value, char, wchar_t
Chris@16 386 >::type type;
Chris@16 387
Chris@16 388 BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
Chris@16 389 "Target type is neither std::istream`able nor std::wistream`able");
Chris@16 390 #endif
Chris@16 391 };
Chris@16 392 }
Chris@16 393
Chris@16 394 namespace detail // deduce_target_char<T> and deduce_source_char<T>
Chris@16 395 {
Chris@16 396 // We deduce stream character types in two stages.
Chris@16 397 //
Chris@16 398 // Stage 1 is common for Target and Source. At Stage 1 we get
Chris@16 399 // non normalized character type (may contain unsigned/signed char)
Chris@16 400 // or deduce_character_type_later<T> where T is the original type.
Chris@16 401 // Stage 1 is executed by stream_char_common<T>
Chris@16 402 //
Chris@16 403 // At Stage 2 we normalize character types or try to deduce character
Chris@16 404 // type using metafunctions.
Chris@16 405 // Stage 2 is executed by deduce_target_char_impl<T> and
Chris@16 406 // deduce_source_char_impl<T>
Chris@16 407 //
Chris@16 408 // deduce_target_char<T> and deduce_source_char<T> functions combine
Chris@16 409 // both stages
Chris@16 410
Chris@16 411 template < class T >
Chris@16 412 struct deduce_target_char
Chris@16 413 {
Chris@16 414 typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
Chris@16 415 typedef BOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
Chris@16 416
Chris@16 417 typedef stage2_type type;
Chris@16 418 };
Chris@16 419
Chris@16 420 template < class T >
Chris@16 421 struct deduce_source_char
Chris@16 422 {
Chris@16 423 typedef BOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
Chris@16 424 typedef BOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type;
Chris@16 425
Chris@16 426 typedef stage2_type type;
Chris@16 427 };
Chris@16 428 }
Chris@16 429
Chris@16 430 namespace detail // deduce_char_traits template
Chris@16 431 {
Chris@16 432 // We are attempting to get char_traits<> from Source or Tagret
Chris@16 433 // template parameter. Otherwise we'll be using std::char_traits<Char>
Chris@16 434 template < class Char, class Target, class Source >
Chris@16 435 struct deduce_char_traits
Chris@16 436 {
Chris@16 437 typedef std::char_traits< Char > type;
Chris@16 438 };
Chris@16 439
Chris@16 440 template < class Char, class Traits, class Alloc, class Source >
Chris@16 441 struct deduce_char_traits< Char
Chris@16 442 , std::basic_string< Char, Traits, Alloc >
Chris@16 443 , Source
Chris@16 444 >
Chris@16 445 {
Chris@16 446 typedef Traits type;
Chris@16 447 };
Chris@16 448
Chris@16 449 template < class Char, class Target, class Traits, class Alloc >
Chris@16 450 struct deduce_char_traits< Char
Chris@16 451 , Target
Chris@16 452 , std::basic_string< Char, Traits, Alloc >
Chris@16 453 >
Chris@16 454 {
Chris@16 455 typedef Traits type;
Chris@16 456 };
Chris@16 457
Chris@16 458 template < class Char, class Traits, class Alloc, class Source >
Chris@16 459 struct deduce_char_traits< Char
Chris@16 460 , boost::container::basic_string< Char, Traits, Alloc >
Chris@16 461 , Source
Chris@16 462 >
Chris@16 463 {
Chris@16 464 typedef Traits type;
Chris@16 465 };
Chris@16 466
Chris@16 467 template < class Char, class Target, class Traits, class Alloc >
Chris@16 468 struct deduce_char_traits< Char
Chris@16 469 , Target
Chris@16 470 , boost::container::basic_string< Char, Traits, Alloc >
Chris@16 471 >
Chris@16 472 {
Chris@16 473 typedef Traits type;
Chris@16 474 };
Chris@16 475
Chris@16 476 template < class Char, class Traits, class Alloc1, class Alloc2 >
Chris@16 477 struct deduce_char_traits< Char
Chris@16 478 , std::basic_string< Char, Traits, Alloc1 >
Chris@16 479 , std::basic_string< Char, Traits, Alloc2 >
Chris@16 480 >
Chris@16 481 {
Chris@16 482 typedef Traits type;
Chris@16 483 };
Chris@16 484
Chris@16 485 template<class Char, class Traits, class Alloc1, class Alloc2>
Chris@16 486 struct deduce_char_traits< Char
Chris@16 487 , boost::container::basic_string< Char, Traits, Alloc1 >
Chris@16 488 , boost::container::basic_string< Char, Traits, Alloc2 >
Chris@16 489 >
Chris@16 490 {
Chris@16 491 typedef Traits type;
Chris@16 492 };
Chris@16 493
Chris@16 494 template < class Char, class Traits, class Alloc1, class Alloc2 >
Chris@16 495 struct deduce_char_traits< Char
Chris@16 496 , boost::container::basic_string< Char, Traits, Alloc1 >
Chris@16 497 , std::basic_string< Char, Traits, Alloc2 >
Chris@16 498 >
Chris@16 499 {
Chris@16 500 typedef Traits type;
Chris@16 501 };
Chris@16 502
Chris@16 503 template < class Char, class Traits, class Alloc1, class Alloc2 >
Chris@16 504 struct deduce_char_traits< Char
Chris@16 505 , std::basic_string< Char, Traits, Alloc1 >
Chris@16 506 , boost::container::basic_string< Char, Traits, Alloc2 >
Chris@16 507 >
Chris@16 508 {
Chris@16 509 typedef Traits type;
Chris@16 510 };
Chris@16 511 }
Chris@16 512
Chris@16 513 namespace detail // array_to_pointer_decay<T>
Chris@16 514 {
Chris@16 515 template<class T>
Chris@16 516 struct array_to_pointer_decay
Chris@16 517 {
Chris@16 518 typedef T type;
Chris@16 519 };
Chris@16 520
Chris@16 521 template<class T, std::size_t N>
Chris@16 522 struct array_to_pointer_decay<T[N]>
Chris@16 523 {
Chris@16 524 typedef const T * type;
Chris@16 525 };
Chris@16 526 }
Chris@16 527
Chris@16 528 namespace detail // is_this_float_conversion_optimized<Float, Char>
Chris@16 529 {
Chris@16 530 // this metafunction evaluates to true, if we have optimized comnversion
Chris@16 531 // from Float type to Char array.
Chris@16 532 // Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...)
Chris@16 533 template <typename Float, typename Char>
Chris@16 534 struct is_this_float_conversion_optimized
Chris@16 535 {
Chris@16 536 typedef boost::type_traits::ice_and<
Chris@16 537 boost::is_float<Float>::value,
Chris@16 538 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
Chris@16 539 boost::type_traits::ice_or<
Chris@16 540 boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value,
Chris@16 541 boost::is_same<Char, wchar_t>::value
Chris@16 542 >::value
Chris@16 543 #else
Chris@16 544 boost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value
Chris@16 545 #endif
Chris@16 546 > result_type;
Chris@16 547
Chris@16 548 BOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
Chris@16 549 };
Chris@16 550 }
Chris@16 551
Chris@16 552 namespace detail // lcast_src_length
Chris@16 553 {
Chris@16 554 // Return max. length of string representation of Source;
Chris@16 555 template< class Source // Source type of lexical_cast.
Chris@16 556 >
Chris@16 557 struct lcast_src_length
Chris@16 558 {
Chris@16 559 BOOST_STATIC_CONSTANT(std::size_t, value = 1);
Chris@16 560 // To check coverage, build the test with
Chris@16 561 // bjam --v2 profile optimization=off
Chris@16 562 static void check_coverage() {}
Chris@16 563 };
Chris@16 564
Chris@16 565 // Helper for integral types.
Chris@16 566 // Notes on length calculation:
Chris@16 567 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
Chris@16 568 // "-2,1,4,7,4,8,3,6,4,7"
Chris@16 569 // ^ - is_signed
Chris@16 570 // ^ - 1 digit not counted by digits10
Chris@16 571 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
Chris@16 572 //
Chris@16 573 // Constant is_specialized is used instead of constant 1
Chris@16 574 // to prevent buffer overflow in a rare case when
Chris@16 575 // <boost/limits.hpp> doesn't add missing specialization for
Chris@16 576 // numeric_limits<T> for some integral type T.
Chris@16 577 // When is_specialized is false, the whole expression is 0.
Chris@16 578 template<class Source>
Chris@16 579 struct lcast_src_length_integral
Chris@16 580 {
Chris@16 581 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 582 BOOST_STATIC_CONSTANT(std::size_t, value =
Chris@16 583 std::numeric_limits<Source>::is_signed +
Chris@16 584 std::numeric_limits<Source>::is_specialized + /* == 1 */
Chris@16 585 std::numeric_limits<Source>::digits10 * 2
Chris@16 586 );
Chris@16 587 #else
Chris@16 588 BOOST_STATIC_CONSTANT(std::size_t, value = 156);
Chris@16 589 BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
Chris@16 590 #endif
Chris@16 591 };
Chris@16 592
Chris@16 593 #define BOOST_LCAST_DEF(T) \
Chris@16 594 template<> struct lcast_src_length<T> \
Chris@16 595 : lcast_src_length_integral<T> \
Chris@16 596 { static void check_coverage() {} };
Chris@16 597
Chris@16 598 BOOST_LCAST_DEF(short)
Chris@16 599 BOOST_LCAST_DEF(unsigned short)
Chris@16 600 BOOST_LCAST_DEF(int)
Chris@16 601 BOOST_LCAST_DEF(unsigned int)
Chris@16 602 BOOST_LCAST_DEF(long)
Chris@16 603 BOOST_LCAST_DEF(unsigned long)
Chris@16 604 #if defined(BOOST_HAS_LONG_LONG)
Chris@16 605 BOOST_LCAST_DEF(boost::ulong_long_type)
Chris@16 606 BOOST_LCAST_DEF(boost::long_long_type )
Chris@16 607 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 608 BOOST_LCAST_DEF(unsigned __int64)
Chris@16 609 BOOST_LCAST_DEF( __int64)
Chris@16 610 #endif
Chris@16 611 #ifdef BOOST_HAS_INT128
Chris@16 612 BOOST_LCAST_DEF(boost::int128_type)
Chris@16 613 BOOST_LCAST_DEF(boost::uint128_type)
Chris@16 614 #endif
Chris@16 615
Chris@16 616 #undef BOOST_LCAST_DEF
Chris@16 617
Chris@16 618 #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
Chris@16 619 // Helper for floating point types.
Chris@16 620 // -1.23456789e-123456
Chris@16 621 // ^ sign
Chris@16 622 // ^ leading digit
Chris@16 623 // ^ decimal point
Chris@16 624 // ^^^^^^^^ lcast_precision<Source>::value
Chris@16 625 // ^ "e"
Chris@16 626 // ^ exponent sign
Chris@16 627 // ^^^^^^ exponent (assumed 6 or less digits)
Chris@16 628 // sign + leading digit + decimal point + "e" + exponent sign == 5
Chris@16 629 template<class Source>
Chris@16 630 struct lcast_src_length_floating
Chris@16 631 {
Chris@16 632 BOOST_STATIC_ASSERT(
Chris@16 633 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
Chris@16 634 std::numeric_limits<Source>::min_exponent10 >= -999999L
Chris@16 635 );
Chris@16 636 BOOST_STATIC_CONSTANT(std::size_t, value =
Chris@16 637 5 + lcast_precision<Source>::value + 6
Chris@16 638 );
Chris@16 639 };
Chris@16 640
Chris@16 641 template<>
Chris@16 642 struct lcast_src_length<float>
Chris@16 643 : lcast_src_length_floating<float>
Chris@16 644 {
Chris@16 645 static void check_coverage() {}
Chris@16 646 };
Chris@16 647
Chris@16 648 template<>
Chris@16 649 struct lcast_src_length<double>
Chris@16 650 : lcast_src_length_floating<double>
Chris@16 651 {
Chris@16 652 static void check_coverage() {}
Chris@16 653 };
Chris@16 654
Chris@16 655 template<>
Chris@16 656 struct lcast_src_length<long double>
Chris@16 657 : lcast_src_length_floating<long double>
Chris@16 658 {
Chris@16 659 static void check_coverage() {}
Chris@16 660 };
Chris@16 661
Chris@16 662 #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
Chris@16 663 }
Chris@16 664
Chris@16 665 namespace detail // lexical_cast_stream_traits<Source, Target>
Chris@16 666 {
Chris@16 667 template <class Source, class Target>
Chris@16 668 struct lexical_cast_stream_traits {
Chris@16 669 typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
Chris@16 670 typedef BOOST_DEDUCED_TYPENAME boost::remove_cv<src>::type no_cv_src;
Chris@16 671
Chris@16 672 typedef boost::detail::deduce_source_char<no_cv_src> deduce_src_char_metafunc;
Chris@16 673 typedef BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t;
Chris@16 674 typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_target_char<Target>::type target_char_t;
Chris@16 675
Chris@16 676 typedef BOOST_DEDUCED_TYPENAME boost::detail::widest_char<
Chris@16 677 target_char_t, src_char_t
Chris@16 678 >::type char_type;
Chris@16 679
Chris@16 680 #if !defined(BOOST_NO_CXX11_CHAR16_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 681 BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char16_t, src_char_t>::value
Chris@16 682 && !boost::is_same<char16_t, target_char_t>::value),
Chris@16 683 "Your compiler does not have full support for char16_t" );
Chris@16 684 #endif
Chris@16 685 #if !defined(BOOST_NO_CXX11_CHAR32_T) && defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 686 BOOST_STATIC_ASSERT_MSG(( !boost::is_same<char32_t, src_char_t>::value
Chris@16 687 && !boost::is_same<char32_t, target_char_t>::value),
Chris@16 688 "Your compiler does not have full support for char32_t" );
Chris@16 689 #endif
Chris@16 690
Chris@16 691 typedef BOOST_DEDUCED_TYPENAME boost::detail::deduce_char_traits<
Chris@16 692 char_type, Target, no_cv_src
Chris@16 693 >::type traits;
Chris@16 694
Chris@16 695 typedef boost::type_traits::ice_and<
Chris@16 696 boost::is_same<char, src_char_t>::value, // source is not a wide character based type
Chris@16 697 boost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value, // target type is based on wide character
Chris@16 698 boost::type_traits::ice_not<
Chris@16 699 boost::detail::is_char_or_wchar<no_cv_src>::value // single character widening is optimized
Chris@16 700 >::value // and does not requires stringbuffer
Chris@16 701 > is_string_widening_required_t;
Chris@16 702
Chris@16 703 typedef boost::type_traits::ice_not< boost::type_traits::ice_or<
Chris@16 704 boost::is_integral<no_cv_src>::value,
Chris@16 705 boost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value,
Chris@16 706 boost::detail::is_char_or_wchar<
Chris@16 707 BOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1
Chris@16 708 >::value // then we have no optimization for that type
Chris@16 709 >::value > is_source_input_not_optimized_t;
Chris@16 710
Chris@16 711 // If we have an optimized conversion for
Chris@16 712 // Source, we do not need to construct stringbuf.
Chris@16 713 BOOST_STATIC_CONSTANT(bool, requires_stringbuf =
Chris@16 714 (boost::type_traits::ice_or<
Chris@16 715 is_string_widening_required_t::value, is_source_input_not_optimized_t::value
Chris@16 716 >::value)
Chris@16 717 );
Chris@16 718
Chris@16 719 typedef boost::detail::lcast_src_length<no_cv_src> len_t;
Chris@16 720 };
Chris@16 721 }
Chris@16 722
Chris@16 723 namespace detail // '0', '+' and '-' constants
Chris@16 724 {
Chris@16 725 template < typename Char > struct lcast_char_constants;
Chris@16 726
Chris@16 727 template<>
Chris@16 728 struct lcast_char_constants<char>
Chris@16 729 {
Chris@16 730 BOOST_STATIC_CONSTANT(char, zero = '0');
Chris@16 731 BOOST_STATIC_CONSTANT(char, minus = '-');
Chris@16 732 BOOST_STATIC_CONSTANT(char, plus = '+');
Chris@16 733 BOOST_STATIC_CONSTANT(char, lowercase_e = 'e');
Chris@16 734 BOOST_STATIC_CONSTANT(char, capital_e = 'E');
Chris@16 735 BOOST_STATIC_CONSTANT(char, c_decimal_separator = '.');
Chris@16 736 };
Chris@16 737
Chris@16 738 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 739 template<>
Chris@16 740 struct lcast_char_constants<wchar_t>
Chris@16 741 {
Chris@16 742 BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
Chris@16 743 BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
Chris@16 744 BOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
Chris@16 745 BOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e');
Chris@16 746 BOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E');
Chris@16 747 BOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.');
Chris@16 748 };
Chris@16 749 #endif
Chris@16 750
Chris@16 751 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 752 template<>
Chris@16 753 struct lcast_char_constants<char16_t>
Chris@16 754 {
Chris@16 755 BOOST_STATIC_CONSTANT(char16_t, zero = u'0');
Chris@16 756 BOOST_STATIC_CONSTANT(char16_t, minus = u'-');
Chris@16 757 BOOST_STATIC_CONSTANT(char16_t, plus = u'+');
Chris@16 758 BOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e');
Chris@16 759 BOOST_STATIC_CONSTANT(char16_t, capital_e = u'E');
Chris@16 760 BOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.');
Chris@16 761 };
Chris@16 762 #endif
Chris@16 763
Chris@16 764 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 765 template<>
Chris@16 766 struct lcast_char_constants<char32_t>
Chris@16 767 {
Chris@16 768 BOOST_STATIC_CONSTANT(char32_t, zero = U'0');
Chris@16 769 BOOST_STATIC_CONSTANT(char32_t, minus = U'-');
Chris@16 770 BOOST_STATIC_CONSTANT(char32_t, plus = U'+');
Chris@16 771 BOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e');
Chris@16 772 BOOST_STATIC_CONSTANT(char32_t, capital_e = U'E');
Chris@16 773 BOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.');
Chris@16 774 };
Chris@16 775 #endif
Chris@16 776 }
Chris@16 777
Chris@16 778 namespace detail // lcast_to_unsigned
Chris@16 779 {
Chris@16 780 template<class T>
Chris@16 781 inline
Chris@16 782 BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) BOOST_NOEXCEPT
Chris@16 783 {
Chris@16 784 typedef BOOST_DEDUCED_TYPENAME boost::make_unsigned<T>::type result_type;
Chris@16 785 return static_cast<result_type>(
Chris@16 786 value < 0 ? 0u - static_cast<result_type>(value) : value
Chris@16 787 );
Chris@16 788 }
Chris@16 789 }
Chris@16 790
Chris@16 791 namespace detail // lcast_put_unsigned
Chris@16 792 {
Chris@16 793 template<class Traits, class T, class CharT>
Chris@16 794 CharT* lcast_put_unsigned(const T n_param, CharT* finish)
Chris@16 795 {
Chris@16 796 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 797 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
Chris@16 798 #endif
Chris@16 799
Chris@16 800 typedef typename Traits::int_type int_type;
Chris@16 801 CharT const czero = lcast_char_constants<CharT>::zero;
Chris@16 802 int_type const zero = Traits::to_int_type(czero);
Chris@16 803 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 804 (sizeof(int_type) > sizeof(T))
Chris@16 805 , int_type
Chris@16 806 , T
Chris@16 807 >::type n = n_param;
Chris@16 808
Chris@16 809 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 810 std::locale loc;
Chris@16 811 if (loc != std::locale::classic()) {
Chris@16 812 typedef std::numpunct<CharT> numpunct;
Chris@16 813 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
Chris@16 814 std::string const grouping = np.grouping();
Chris@16 815 std::string::size_type const grouping_size = grouping.size();
Chris@16 816
Chris@16 817 if ( grouping_size && grouping[0] > 0 )
Chris@16 818 {
Chris@16 819
Chris@16 820 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 821 // Check that ulimited group is unreachable:
Chris@16 822 BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
Chris@16 823 #endif
Chris@16 824 CharT thousands_sep = np.thousands_sep();
Chris@16 825 std::string::size_type group = 0; // current group number
Chris@16 826 char last_grp_size = grouping[0];
Chris@16 827 char left = last_grp_size;
Chris@16 828
Chris@16 829 do
Chris@16 830 {
Chris@16 831 if(left == 0)
Chris@16 832 {
Chris@16 833 ++group;
Chris@16 834 if(group < grouping_size)
Chris@16 835 {
Chris@16 836 char const grp_size = grouping[group];
Chris@16 837 last_grp_size = grp_size <= 0 ? static_cast<char>(CHAR_MAX) : grp_size;
Chris@16 838 }
Chris@16 839
Chris@16 840 left = last_grp_size;
Chris@16 841 --finish;
Chris@16 842 Traits::assign(*finish, thousands_sep);
Chris@16 843 }
Chris@16 844
Chris@16 845 --left;
Chris@16 846
Chris@16 847 --finish;
Chris@16 848 int_type const digit = static_cast<int_type>(n % 10U);
Chris@16 849 Traits::assign(*finish, Traits::to_char_type(zero + digit));
Chris@16 850 n /= 10;
Chris@16 851 } while(n);
Chris@16 852 return finish;
Chris@16 853 }
Chris@16 854 }
Chris@16 855 #endif
Chris@16 856 {
Chris@16 857 do
Chris@16 858 {
Chris@16 859 --finish;
Chris@16 860 int_type const digit = static_cast<int_type>(n % 10U);
Chris@16 861 Traits::assign(*finish, Traits::to_char_type(zero + digit));
Chris@16 862 n /= 10;
Chris@16 863 } while(n);
Chris@16 864 }
Chris@16 865
Chris@16 866 return finish;
Chris@16 867 }
Chris@16 868 }
Chris@16 869
Chris@16 870 namespace detail // lcast_ret_unsigned
Chris@16 871 {
Chris@16 872 template<class Traits, class T, class CharT>
Chris@16 873 inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
Chris@16 874 {
Chris@16 875 #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Chris@16 876 BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
Chris@16 877
Chris@16 878 // GCC when used with flag -std=c++0x may not have std::numeric_limits
Chris@16 879 // specializations for __int128 and unsigned __int128 types.
Chris@16 880 // Try compilation with -std=gnu++0x or -std=gnu++11.
Chris@16 881 //
Chris@16 882 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40856
Chris@16 883 BOOST_STATIC_ASSERT_MSG(std::numeric_limits<T>::is_specialized,
Chris@16 884 "std::numeric_limits are not specialized for integral type passed to boost::lexical_cast"
Chris@16 885 );
Chris@16 886 #endif
Chris@16 887 CharT const czero = lcast_char_constants<CharT>::zero;
Chris@16 888 --end;
Chris@16 889 value = 0;
Chris@16 890
Chris@16 891 if (begin > end || *end < czero || *end >= czero + 10)
Chris@16 892 return false;
Chris@16 893 value = static_cast<T>(*end - czero);
Chris@16 894 --end;
Chris@16 895 T multiplier = 1;
Chris@16 896 bool multiplier_overflowed = false;
Chris@16 897
Chris@16 898 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 899 std::locale loc;
Chris@16 900 if (loc != std::locale::classic()) {
Chris@16 901 typedef std::numpunct<CharT> numpunct;
Chris@16 902 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
Chris@16 903 std::string const& grouping = np.grouping();
Chris@16 904 std::string::size_type const grouping_size = grouping.size();
Chris@16 905
Chris@16 906 /* According to Programming languages - C++
Chris@16 907 * we MUST check for correct grouping
Chris@16 908 */
Chris@16 909 if (grouping_size && grouping[0] > 0)
Chris@16 910 {
Chris@16 911 unsigned char current_grouping = 0;
Chris@16 912 CharT const thousands_sep = np.thousands_sep();
Chris@16 913 char remained = static_cast<char>(grouping[current_grouping] - 1);
Chris@16 914 bool shall_we_return = true;
Chris@16 915
Chris@16 916 for(;end>=begin; --end)
Chris@16 917 {
Chris@16 918 if (remained) {
Chris@16 919 T const multiplier_10 = static_cast<T>(multiplier * 10);
Chris@16 920 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
Chris@16 921
Chris@16 922 T const dig_value = static_cast<T>(*end - czero);
Chris@16 923 T const new_sub_value = static_cast<T>(multiplier_10 * dig_value);
Chris@16 924
Chris@16 925 if (*end < czero || *end >= czero + 10
Chris@16 926 /* detecting overflow */
Chris@16 927 || (dig_value && new_sub_value / dig_value != multiplier_10)
Chris@16 928 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
Chris@16 929 || (multiplier_overflowed && dig_value)
Chris@16 930 )
Chris@16 931 return false;
Chris@16 932
Chris@16 933 value = static_cast<T>(value + new_sub_value);
Chris@16 934 multiplier = static_cast<T>(multiplier * 10);
Chris@16 935 --remained;
Chris@16 936 } else {
Chris@16 937 if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
Chris@16 938 {
Chris@16 939 /*
Chris@16 940 * According to Programming languages - C++
Chris@16 941 * Digit grouping is checked. That is, the positions of discarded
Chris@16 942 * separators is examined for consistency with
Chris@16 943 * use_facet<numpunct<charT> >(loc ).grouping()
Chris@16 944 *
Chris@16 945 * BUT what if there is no separators at all and grouping()
Chris@16 946 * is not empty? Well, we have no extraced separators, so we
Chris@16 947 * won`t check them for consistency. This will allow us to
Chris@16 948 * work with "C" locale from other locales
Chris@16 949 */
Chris@16 950 shall_we_return = false;
Chris@16 951 break;
Chris@16 952 } else {
Chris@16 953 if ( begin == end ) return false;
Chris@16 954 if (current_grouping < grouping_size-1 ) ++current_grouping;
Chris@16 955 remained = grouping[current_grouping];
Chris@16 956 }
Chris@16 957 }
Chris@16 958 }
Chris@16 959
Chris@16 960 if (shall_we_return) return true;
Chris@16 961 }
Chris@16 962 }
Chris@16 963 #endif
Chris@16 964 {
Chris@16 965 while ( begin <= end )
Chris@16 966 {
Chris@16 967 T const multiplier_10 = static_cast<T>(multiplier * 10);
Chris@16 968 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
Chris@16 969
Chris@16 970 T const dig_value = static_cast<T>(*end - czero);
Chris@16 971 T const new_sub_value = static_cast<T>(multiplier_10 * dig_value);
Chris@16 972
Chris@16 973 if (*end < czero || *end >= czero + 10
Chris@16 974 /* detecting overflow */
Chris@16 975 || (dig_value && new_sub_value / dig_value != multiplier_10)
Chris@16 976 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
Chris@16 977 || (multiplier_overflowed && dig_value)
Chris@16 978 )
Chris@16 979 return false;
Chris@16 980
Chris@16 981 value = static_cast<T>(value + new_sub_value);
Chris@16 982 multiplier = static_cast<T>(multiplier * 10);
Chris@16 983 --end;
Chris@16 984 }
Chris@16 985 }
Chris@16 986 return true;
Chris@16 987 }
Chris@16 988 }
Chris@16 989
Chris@16 990 namespace detail
Chris@16 991 {
Chris@16 992 template <class CharT>
Chris@16 993 bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) BOOST_NOEXCEPT {
Chris@16 994 for( unsigned int i=0; i < len; ++i ) {
Chris@16 995 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
Chris@16 996 }
Chris@16 997
Chris@16 998 return true;
Chris@16 999 }
Chris@16 1000
Chris@16 1001 /* Returns true and sets the correct value if found NaN or Inf. */
Chris@16 1002 template <class CharT, class T>
Chris@16 1003 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
Chris@16 1004 , const CharT* lc_NAN, const CharT* lc_nan
Chris@16 1005 , const CharT* lc_INFINITY, const CharT* lc_infinity
Chris@16 1006 , const CharT opening_brace, const CharT closing_brace) BOOST_NOEXCEPT
Chris@16 1007 {
Chris@16 1008 using namespace std;
Chris@16 1009 if (begin == end) return false;
Chris@16 1010 const CharT minus = lcast_char_constants<CharT>::minus;
Chris@16 1011 const CharT plus = lcast_char_constants<CharT>::plus;
Chris@16 1012 const int inifinity_size = 8;
Chris@16 1013
Chris@16 1014 bool has_minus = false;
Chris@16 1015 /* Parsing +/- */
Chris@16 1016 if( *begin == minus)
Chris@16 1017 {
Chris@16 1018 ++ begin;
Chris@16 1019 has_minus = true;
Chris@16 1020 }
Chris@16 1021 else if( *begin == plus ) ++begin;
Chris@16 1022
Chris@16 1023 if( end-begin < 3 ) return false;
Chris@16 1024 if( lc_iequal(begin, lc_nan, lc_NAN, 3) )
Chris@16 1025 {
Chris@16 1026 begin += 3;
Chris@16 1027 if (end != begin) /* It is 'nan(...)' or some bad input*/
Chris@16 1028 {
Chris@16 1029 if(end-begin<2) return false; // bad input
Chris@16 1030 -- end;
Chris@16 1031 if( *begin != opening_brace || *end != closing_brace) return false; // bad input
Chris@16 1032 }
Chris@16 1033
Chris@16 1034 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
Chris@16 1035 else value = (boost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
Chris@16 1036 return true;
Chris@16 1037 } else
Chris@16 1038 if (( /* 'INF' or 'inf' */
Chris@16 1039 end-begin==3
Chris@16 1040 &&
Chris@16 1041 lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
Chris@16 1042 )
Chris@16 1043 ||
Chris@16 1044 ( /* 'INFINITY' or 'infinity' */
Chris@16 1045 end-begin==inifinity_size
Chris@16 1046 &&
Chris@16 1047 lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size)
Chris@16 1048 )
Chris@16 1049 )
Chris@16 1050 {
Chris@16 1051 if( !has_minus ) value = std::numeric_limits<T>::infinity();
Chris@16 1052 else value = (boost::math::changesign) (std::numeric_limits<T>::infinity());
Chris@16 1053 return true;
Chris@16 1054 }
Chris@16 1055
Chris@16 1056 return false;
Chris@16 1057 }
Chris@16 1058
Chris@16 1059 template <class CharT, class T>
Chris@16 1060 bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
Chris@16 1061 , const CharT* lc_nan
Chris@16 1062 , const CharT* lc_infinity) BOOST_NOEXCEPT
Chris@16 1063 {
Chris@16 1064 using namespace std;
Chris@16 1065 const CharT minus = lcast_char_constants<CharT>::minus;
Chris@16 1066 if ( (boost::math::isnan)(value) )
Chris@16 1067 {
Chris@16 1068 if ( (boost::math::signbit)(value) )
Chris@16 1069 {
Chris@16 1070 *begin = minus;
Chris@16 1071 ++ begin;
Chris@16 1072 }
Chris@16 1073
Chris@16 1074 memcpy(begin, lc_nan, 3 * sizeof(CharT));
Chris@16 1075 end = begin + 3;
Chris@16 1076 return true;
Chris@16 1077 } else if ( (boost::math::isinf)(value) )
Chris@16 1078 {
Chris@16 1079 if ( (boost::math::signbit)(value) )
Chris@16 1080 {
Chris@16 1081 *begin = minus;
Chris@16 1082 ++ begin;
Chris@16 1083 }
Chris@16 1084
Chris@16 1085 memcpy(begin, lc_infinity, 3 * sizeof(CharT));
Chris@16 1086 end = begin + 3;
Chris@16 1087 return true;
Chris@16 1088 }
Chris@16 1089
Chris@16 1090 return false;
Chris@16 1091 }
Chris@16 1092
Chris@16 1093
Chris@16 1094 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 1095 template <class T>
Chris@16 1096 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) BOOST_NOEXCEPT
Chris@16 1097 {
Chris@16 1098 return parse_inf_nan_impl(begin, end, value
Chris@16 1099 , L"NAN", L"nan"
Chris@16 1100 , L"INFINITY", L"infinity"
Chris@16 1101 , L'(', L')');
Chris@16 1102 }
Chris@16 1103
Chris@16 1104 template <class T>
Chris@16 1105 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) BOOST_NOEXCEPT
Chris@16 1106 {
Chris@16 1107 return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
Chris@16 1108 }
Chris@16 1109
Chris@16 1110 #endif
Chris@16 1111 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 1112 template <class T>
Chris@16 1113 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) BOOST_NOEXCEPT
Chris@16 1114 {
Chris@16 1115 return parse_inf_nan_impl(begin, end, value
Chris@16 1116 , u"NAN", u"nan"
Chris@16 1117 , u"INFINITY", u"infinity"
Chris@16 1118 , u'(', u')');
Chris@16 1119 }
Chris@16 1120
Chris@16 1121 template <class T>
Chris@16 1122 bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) BOOST_NOEXCEPT
Chris@16 1123 {
Chris@16 1124 return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
Chris@16 1125 }
Chris@16 1126 #endif
Chris@16 1127 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 1128 template <class T>
Chris@16 1129 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) BOOST_NOEXCEPT
Chris@16 1130 {
Chris@16 1131 return parse_inf_nan_impl(begin, end, value
Chris@16 1132 , U"NAN", U"nan"
Chris@16 1133 , U"INFINITY", U"infinity"
Chris@16 1134 , U'(', U')');
Chris@16 1135 }
Chris@16 1136
Chris@16 1137 template <class T>
Chris@16 1138 bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) BOOST_NOEXCEPT
Chris@16 1139 {
Chris@16 1140 return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
Chris@16 1141 }
Chris@16 1142 #endif
Chris@16 1143
Chris@16 1144 template <class CharT, class T>
Chris@16 1145 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) BOOST_NOEXCEPT
Chris@16 1146 {
Chris@16 1147 return parse_inf_nan_impl(begin, end, value
Chris@16 1148 , "NAN", "nan"
Chris@16 1149 , "INFINITY", "infinity"
Chris@16 1150 , '(', ')');
Chris@16 1151 }
Chris@16 1152
Chris@16 1153 template <class CharT, class T>
Chris@16 1154 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) BOOST_NOEXCEPT
Chris@16 1155 {
Chris@16 1156 return put_inf_nan_impl(begin, end, value, "nan", "infinity");
Chris@16 1157 }
Chris@16 1158 }
Chris@16 1159
Chris@16 1160
Chris@16 1161 namespace detail // lcast_ret_float
Chris@16 1162 {
Chris@16 1163
Chris@16 1164 // Silence buggy MS warnings like C4244: '+=' : conversion from 'int' to 'unsigned short', possible loss of data
Chris@16 1165 #if defined(_MSC_VER) && (_MSC_VER == 1400)
Chris@16 1166 # pragma warning(push)
Chris@16 1167 # pragma warning(disable:4244)
Chris@16 1168 #endif
Chris@16 1169 template <class T>
Chris@16 1170 struct mantissa_holder_type
Chris@16 1171 {
Chris@16 1172 /* Can not be used with this type */
Chris@16 1173 };
Chris@16 1174
Chris@16 1175 template <>
Chris@16 1176 struct mantissa_holder_type<float>
Chris@16 1177 {
Chris@16 1178 typedef unsigned int type;
Chris@16 1179 typedef double wide_result_t;
Chris@16 1180 };
Chris@16 1181
Chris@16 1182 template <>
Chris@16 1183 struct mantissa_holder_type<double>
Chris@16 1184 {
Chris@16 1185 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Chris@16 1186 typedef long double wide_result_t;
Chris@16 1187 #if defined(BOOST_HAS_LONG_LONG)
Chris@16 1188 typedef boost::ulong_long_type type;
Chris@16 1189 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 1190 typedef unsigned __int64 type;
Chris@16 1191 #endif
Chris@16 1192 #endif
Chris@16 1193 };
Chris@16 1194
Chris@16 1195 template<class Traits, class T, class CharT>
Chris@16 1196 inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end)
Chris@16 1197 {
Chris@16 1198
Chris@16 1199 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 1200 std::locale loc;
Chris@16 1201 typedef std::numpunct<CharT> numpunct;
Chris@16 1202 numpunct const& np = BOOST_USE_FACET(numpunct, loc);
Chris@16 1203 std::string const grouping(
Chris@16 1204 (loc == std::locale::classic())
Chris@16 1205 ? std::string()
Chris@16 1206 : np.grouping()
Chris@16 1207 );
Chris@16 1208 std::string::size_type const grouping_size = grouping.size();
Chris@16 1209 CharT const thousands_sep = static_cast<CharT>(grouping_size ? np.thousands_sep() : 0);
Chris@16 1210 CharT const decimal_point = np.decimal_point();
Chris@16 1211 bool found_grouping = false;
Chris@16 1212 std::string::size_type last_grouping_pos = grouping_size - 1;
Chris@16 1213 #else
Chris@16 1214 CharT const decimal_point = lcast_char_constants<CharT>::c_decimal_separator;
Chris@16 1215 #endif
Chris@16 1216
Chris@16 1217 CharT const czero = lcast_char_constants<CharT>::zero;
Chris@16 1218 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 1219 CharT const plus = lcast_char_constants<CharT>::plus;
Chris@16 1220 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
Chris@16 1221 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
Chris@16 1222
Chris@16 1223 value = static_cast<T>(0);
Chris@16 1224
Chris@16 1225 if (parse_inf_nan(begin, end, value)) return true;
Chris@16 1226
Chris@16 1227 typedef typename Traits::int_type int_type;
Chris@16 1228 typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::type mantissa_type;
Chris@16 1229 typedef BOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::wide_result_t wide_result_t;
Chris@16 1230 int_type const zero = Traits::to_int_type(czero);
Chris@16 1231 if (begin == end) return false;
Chris@16 1232
Chris@16 1233 /* Getting the plus/minus sign */
Chris@16 1234 bool has_minus = false;
Chris@16 1235 if (Traits::eq(*begin, minus) ) {
Chris@16 1236 ++ begin;
Chris@16 1237 has_minus = true;
Chris@16 1238 if (begin == end) return false;
Chris@16 1239 } else if (Traits::eq(*begin, plus) ) {
Chris@16 1240 ++begin;
Chris@16 1241 if (begin == end) return false;
Chris@16 1242 }
Chris@16 1243
Chris@16 1244 bool found_decimal = false;
Chris@16 1245 bool found_number_before_exp = false;
Chris@16 1246 int pow_of_10 = 0;
Chris@16 1247 mantissa_type mantissa=0;
Chris@16 1248 bool is_mantissa_full = false;
Chris@16 1249
Chris@16 1250 char length_since_last_delim = 0;
Chris@16 1251
Chris@16 1252 while ( begin != end )
Chris@16 1253 {
Chris@16 1254 if (found_decimal) {
Chris@16 1255 /* We allow no thousand_separators after decimal point */
Chris@16 1256
Chris@16 1257 mantissa_type tmp_mantissa = mantissa * 10u;
Chris@16 1258 if (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) break;
Chris@16 1259 if ( *begin < czero || *begin >= czero + 10 ) return false;
Chris@16 1260 if ( is_mantissa_full
Chris@16 1261 || tmp_mantissa / 10u != mantissa
Chris@16 1262 || (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) < tmp_mantissa
Chris@16 1263 ) {
Chris@16 1264 is_mantissa_full = true;
Chris@16 1265 ++ begin;
Chris@16 1266 continue;
Chris@16 1267 }
Chris@16 1268
Chris@16 1269 -- pow_of_10;
Chris@16 1270 mantissa = tmp_mantissa;
Chris@16 1271 mantissa += *begin - zero;
Chris@16 1272
Chris@16 1273 found_number_before_exp = true;
Chris@16 1274 } else {
Chris@16 1275
Chris@16 1276 if (*begin >= czero && *begin < czero + 10) {
Chris@16 1277
Chris@16 1278 /* Checking for mantissa overflow. If overflow will
Chris@16 1279 * occur, them we only increase multiplyer
Chris@16 1280 */
Chris@16 1281 mantissa_type tmp_mantissa = mantissa * 10u;
Chris@16 1282 if( !is_mantissa_full
Chris@16 1283 && tmp_mantissa / 10u == mantissa
Chris@16 1284 && (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) >= tmp_mantissa
Chris@16 1285 )
Chris@16 1286 {
Chris@16 1287 mantissa = tmp_mantissa;
Chris@16 1288 mantissa += *begin - zero;
Chris@16 1289 } else
Chris@16 1290 {
Chris@16 1291 is_mantissa_full = true;
Chris@16 1292 ++ pow_of_10;
Chris@16 1293 }
Chris@16 1294
Chris@16 1295 found_number_before_exp = true;
Chris@16 1296 ++ length_since_last_delim;
Chris@16 1297 } else if (Traits::eq(*begin, decimal_point) || Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) {
Chris@16 1298 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 1299 /* If ( we need to check grouping
Chris@16 1300 * and ( grouping missmatches
Chris@16 1301 * or grouping position is incorrect
Chris@16 1302 * or we are using the grouping position 0 twice
Chris@16 1303 * )
Chris@16 1304 * ) then return error
Chris@16 1305 */
Chris@16 1306 if( grouping_size && found_grouping
Chris@16 1307 && (
Chris@16 1308 length_since_last_delim != grouping[0]
Chris@16 1309 || last_grouping_pos>1
Chris@16 1310 || (last_grouping_pos==0 && grouping_size>1)
Chris@16 1311 )
Chris@16 1312 ) return false;
Chris@16 1313 #endif
Chris@16 1314
Chris@16 1315 if(Traits::eq(*begin, decimal_point)) {
Chris@16 1316 ++ begin;
Chris@16 1317 found_decimal = true;
Chris@16 1318 if (!found_number_before_exp && begin==end) return false;
Chris@16 1319 continue;
Chris@16 1320 }else {
Chris@16 1321 if (!found_number_before_exp) return false;
Chris@16 1322 break;
Chris@16 1323 }
Chris@16 1324 }
Chris@16 1325 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 1326 else if (grouping_size && Traits::eq(*begin, thousands_sep)){
Chris@16 1327 if(found_grouping)
Chris@16 1328 {
Chris@16 1329 /* It is not he first time, when we find thousands separator,
Chris@16 1330 * so we need to chek, is the distance between two groupings
Chris@16 1331 * equal to grouping[last_grouping_pos] */
Chris@16 1332
Chris@16 1333 if (length_since_last_delim != grouping[last_grouping_pos] )
Chris@16 1334 {
Chris@16 1335 if (!last_grouping_pos) return false;
Chris@16 1336 else
Chris@16 1337 {
Chris@16 1338 -- last_grouping_pos;
Chris@16 1339 if (length_since_last_delim != grouping[last_grouping_pos]) return false;
Chris@16 1340 }
Chris@16 1341 } else
Chris@16 1342 /* We are calling the grouping[0] twice, when grouping size is more than 1 */
Chris@16 1343 if (grouping_size>1u && last_grouping_pos+1<grouping_size) return false;
Chris@16 1344
Chris@16 1345 } else {
Chris@16 1346 /* Delimiter at the begining ',000' */
Chris@16 1347 if (!length_since_last_delim) return false;
Chris@16 1348
Chris@16 1349 found_grouping = true;
Chris@16 1350 if (length_since_last_delim > grouping[last_grouping_pos] ) return false;
Chris@16 1351 }
Chris@16 1352
Chris@16 1353 length_since_last_delim = 0;
Chris@16 1354 ++ begin;
Chris@16 1355
Chris@16 1356 /* Delimiter at the end '100,' */
Chris@16 1357 if (begin == end) return false;
Chris@16 1358 continue;
Chris@16 1359 }
Chris@16 1360 #endif
Chris@16 1361 else return false;
Chris@16 1362 }
Chris@16 1363
Chris@16 1364 ++begin;
Chris@16 1365 }
Chris@16 1366
Chris@16 1367 // Exponent found
Chris@16 1368 if ( begin != end && (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) ) {
Chris@16 1369 ++ begin;
Chris@16 1370 if ( begin == end ) return false;
Chris@16 1371
Chris@16 1372 bool exp_has_minus = false;
Chris@16 1373 if(Traits::eq(*begin, minus)) {
Chris@16 1374 exp_has_minus = true;
Chris@16 1375 ++ begin;
Chris@16 1376 if ( begin == end ) return false;
Chris@16 1377 } else if (Traits::eq(*begin, plus)) {
Chris@16 1378 ++ begin;
Chris@16 1379 if ( begin == end ) return false;
Chris@16 1380 }
Chris@16 1381
Chris@16 1382 int exp_pow_of_10 = 0;
Chris@16 1383 while ( begin != end )
Chris@16 1384 {
Chris@16 1385 if ( *begin < czero
Chris@16 1386 || *begin >= czero + 10
Chris@16 1387 || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/
Chris@16 1388 return false;
Chris@16 1389
Chris@16 1390 exp_pow_of_10 *= 10;
Chris@16 1391 exp_pow_of_10 += *begin - zero;
Chris@16 1392 ++ begin;
Chris@16 1393 };
Chris@16 1394
Chris@16 1395 if ( exp_pow_of_10 ) {
Chris@16 1396 /* Overflows are checked lower */
Chris@16 1397 if ( exp_has_minus ) {
Chris@16 1398 pow_of_10 -= exp_pow_of_10;
Chris@16 1399 } else {
Chris@16 1400 pow_of_10 += exp_pow_of_10;
Chris@16 1401 }
Chris@16 1402 }
Chris@16 1403 }
Chris@16 1404
Chris@16 1405 /* We need a more accurate algorithm... We can not use current algorithm
Chris@16 1406 * with long doubles (and with doubles if sizeof(double)==sizeof(long double)).
Chris@16 1407 */
Chris@16 1408 const wide_result_t result = std::pow(static_cast<wide_result_t>(10.0), pow_of_10) * mantissa;
Chris@16 1409 value = static_cast<T>( has_minus ? (boost::math::changesign)(result) : result);
Chris@16 1410
Chris@16 1411 if ( (boost::math::isinf)(value) || (boost::math::isnan)(value) ) return false;
Chris@16 1412
Chris@16 1413 return true;
Chris@16 1414 }
Chris@16 1415 // Unsilence buggy MS warnings like C4244: '+=' : conversion from 'int' to 'unsigned short', possible loss of data
Chris@16 1416 #if defined(_MSC_VER) && (_MSC_VER == 1400)
Chris@16 1417 # pragma warning(pop)
Chris@16 1418 #endif
Chris@16 1419 }
Chris@16 1420
Chris@16 1421 namespace detail // parser_buf
Chris@16 1422 {
Chris@16 1423 //
Chris@16 1424 // class parser_buf:
Chris@16 1425 // acts as a stream buffer which wraps around a pair of pointers
Chris@16 1426 //
Chris@16 1427 // This class is copied (and slightly changed) from
Chris@16 1428 // boost/regex/v4/cpp_regex_traits.hpp
Chris@16 1429 // Thanks John Maddock for it! (previous version had some
Chris@16 1430 // problems with libc++ and some other STL implementations)
Chris@16 1431 template <class BufferType, class charT>
Chris@16 1432 class parser_buf : public BufferType {
Chris@16 1433 typedef BufferType base_type;
Chris@16 1434 typedef typename base_type::int_type int_type;
Chris@16 1435 typedef typename base_type::char_type char_type;
Chris@16 1436 typedef typename base_type::pos_type pos_type;
Chris@16 1437 typedef ::std::streamsize streamsize;
Chris@16 1438 typedef typename base_type::off_type off_type;
Chris@16 1439
Chris@16 1440 public:
Chris@16 1441 parser_buf() : base_type() { setbuf(0, 0); }
Chris@16 1442 const charT* getnext() { return this->gptr(); }
Chris@16 1443 #ifndef BOOST_NO_USING_TEMPLATE
Chris@16 1444 using base_type::pptr;
Chris@16 1445 using base_type::pbase;
Chris@16 1446 #else
Chris@16 1447 charT* pptr() const { return base_type::pptr(); }
Chris@16 1448 charT* pbase() const { return base_type::pbase(); }
Chris@16 1449 #endif
Chris@16 1450 base_type* setbuf(char_type* s, streamsize n) {
Chris@16 1451 this->setg(s, s, s + n);
Chris@16 1452 return this;
Chris@16 1453 }
Chris@16 1454
Chris@16 1455 pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) {
Chris@16 1456 if(which & ::std::ios_base::out)
Chris@16 1457 return pos_type(off_type(-1));
Chris@16 1458 off_type size = static_cast<off_type>(this->egptr() - this->eback());
Chris@16 1459 charT* g = this->eback();
Chris@16 1460 if(off_type(sp) <= size)
Chris@16 1461 {
Chris@16 1462 this->setg(g, g + off_type(sp), g + size);
Chris@16 1463 }
Chris@16 1464 return pos_type(off_type(-1));
Chris@16 1465 }
Chris@16 1466
Chris@16 1467 pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
Chris@16 1468 typedef typename boost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
Chris@16 1469
Chris@16 1470 if(which & ::std::ios_base::out)
Chris@16 1471 return pos_type(off_type(-1));
Chris@16 1472 std::ptrdiff_t size = this->egptr() - this->eback();
Chris@16 1473 std::ptrdiff_t pos = this->gptr() - this->eback();
Chris@16 1474 charT* g = this->eback();
Chris@16 1475 switch(static_cast<cast_type>(way))
Chris@16 1476 {
Chris@16 1477 case ::std::ios_base::beg:
Chris@16 1478 if((off < 0) || (off > size))
Chris@16 1479 return pos_type(off_type(-1));
Chris@16 1480 else
Chris@16 1481 this->setg(g, g + off, g + size);
Chris@16 1482 break;
Chris@16 1483 case ::std::ios_base::end:
Chris@16 1484 if((off < 0) || (off > size))
Chris@16 1485 return pos_type(off_type(-1));
Chris@16 1486 else
Chris@16 1487 this->setg(g, g + size - off, g + size);
Chris@16 1488 break;
Chris@16 1489 case ::std::ios_base::cur:
Chris@16 1490 {
Chris@16 1491 std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
Chris@16 1492 if((newpos < 0) || (newpos > size))
Chris@16 1493 return pos_type(off_type(-1));
Chris@16 1494 else
Chris@16 1495 this->setg(g, g + newpos, g + size);
Chris@16 1496 break;
Chris@16 1497 }
Chris@16 1498 default: ;
Chris@16 1499 }
Chris@16 1500 #ifdef BOOST_MSVC
Chris@16 1501 #pragma warning(push)
Chris@16 1502 #pragma warning(disable:4244)
Chris@16 1503 #endif
Chris@16 1504 return static_cast<pos_type>(this->gptr() - this->eback());
Chris@16 1505 #ifdef BOOST_MSVC
Chris@16 1506 #pragma warning(pop)
Chris@16 1507 #endif
Chris@16 1508 }
Chris@16 1509 private:
Chris@16 1510 parser_buf& operator=(const parser_buf&);
Chris@16 1511 parser_buf(const parser_buf&);
Chris@16 1512 };
Chris@16 1513 }
Chris@16 1514
Chris@16 1515 namespace detail
Chris@16 1516 {
Chris@16 1517 struct do_not_construct_out_stream_t{};
Chris@16 1518 }
Chris@16 1519
Chris@16 1520 namespace detail // optimized stream wrapper
Chris@16 1521 {
Chris@16 1522 // String representation of Source has an upper limit.
Chris@16 1523 template< class CharT // a result of widest_char transformation
Chris@16 1524 , class Traits // usually char_traits<CharT>
Chris@16 1525 , bool RequiresStringbuffer
Chris@16 1526 >
Chris@16 1527 class lexical_stream_limited_src
Chris@16 1528 {
Chris@16 1529
Chris@16 1530 #if defined(BOOST_NO_STRINGSTREAM)
Chris@16 1531 typedef std::ostrstream out_stream_t;
Chris@16 1532 #elif defined(BOOST_NO_STD_LOCALE)
Chris@16 1533 typedef std::ostringstream out_stream_t;
Chris@16 1534 typedef parser_buf<std::streambuf, char> buffer_t;
Chris@16 1535 #else
Chris@16 1536 typedef std::basic_ostringstream<CharT, Traits> out_stream_t;
Chris@16 1537 typedef parser_buf<std::basic_streambuf<CharT, Traits>, CharT> buffer_t;
Chris@16 1538 #endif
Chris@16 1539 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 1540 RequiresStringbuffer,
Chris@16 1541 out_stream_t,
Chris@16 1542 do_not_construct_out_stream_t
Chris@16 1543 >::type deduced_out_stream_t;
Chris@16 1544
Chris@16 1545 // A string representation of Source is written to [start, finish).
Chris@16 1546 CharT* start;
Chris@16 1547 CharT* finish;
Chris@16 1548 deduced_out_stream_t out_stream;
Chris@16 1549
Chris@16 1550 public:
Chris@16 1551 lexical_stream_limited_src(CharT* sta, CharT* fin) BOOST_NOEXCEPT
Chris@16 1552 : start(sta)
Chris@16 1553 , finish(fin)
Chris@16 1554 {}
Chris@16 1555
Chris@16 1556 private:
Chris@16 1557 // Undefined:
Chris@16 1558 lexical_stream_limited_src(lexical_stream_limited_src const&);
Chris@16 1559 void operator=(lexical_stream_limited_src const&);
Chris@16 1560
Chris@16 1561 /************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
Chris@16 1562 bool shl_char(CharT ch) BOOST_NOEXCEPT
Chris@16 1563 {
Chris@16 1564 Traits::assign(*start, ch);
Chris@16 1565 finish = start + 1;
Chris@16 1566 return true;
Chris@16 1567 }
Chris@16 1568
Chris@16 1569 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 1570 template <class T>
Chris@16 1571 bool shl_char(T ch)
Chris@16 1572 {
Chris@16 1573 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
Chris@16 1574 "boost::lexical_cast does not support narrowing of char types."
Chris@16 1575 "Use boost::locale instead" );
Chris@16 1576 #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Chris@16 1577 std::locale loc;
Chris@16 1578 CharT const w = BOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
Chris@16 1579 #else
Chris@16 1580 CharT const w = static_cast<CharT>(ch);
Chris@16 1581 #endif
Chris@16 1582 Traits::assign(*start, w);
Chris@16 1583 finish = start + 1;
Chris@16 1584 return true;
Chris@16 1585 }
Chris@16 1586 #endif
Chris@16 1587
Chris@16 1588 bool shl_char_array(CharT const* str) BOOST_NOEXCEPT
Chris@16 1589 {
Chris@16 1590 start = const_cast<CharT*>(str);
Chris@16 1591 finish = start + Traits::length(str);
Chris@16 1592 return true;
Chris@16 1593 }
Chris@16 1594
Chris@16 1595 template <class T>
Chris@16 1596 bool shl_char_array(T const* str)
Chris@16 1597 {
Chris@16 1598 BOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
Chris@16 1599 "boost::lexical_cast does not support narrowing of char types."
Chris@16 1600 "Use boost::locale instead" );
Chris@16 1601 return shl_input_streamable(str);
Chris@16 1602 }
Chris@16 1603
Chris@16 1604 bool shl_char_array_limited(CharT const* str, std::size_t max_size) BOOST_NOEXCEPT
Chris@16 1605 {
Chris@16 1606 start = const_cast<CharT*>(str);
Chris@16 1607 finish = std::find(start, start + max_size, Traits::to_char_type(0));
Chris@16 1608 return true;
Chris@16 1609 }
Chris@16 1610
Chris@16 1611 template<typename InputStreamable>
Chris@16 1612 bool shl_input_streamable(InputStreamable& input)
Chris@16 1613 {
Chris@16 1614 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
Chris@16 1615 // If you have compilation error at this point, than your STL library
Chris@16 1616 // does not support such conversions. Try updating it.
Chris@16 1617 BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value));
Chris@16 1618 #endif
Chris@16 1619
Chris@16 1620 #ifndef BOOST_NO_EXCEPTIONS
Chris@16 1621 out_stream.exceptions(std::ios::badbit);
Chris@16 1622 try {
Chris@16 1623 #endif
Chris@16 1624 bool const result = !(out_stream << input).fail();
Chris@16 1625 const buffer_t* const p = static_cast<buffer_t*>(
Chris@16 1626 static_cast<std::basic_streambuf<CharT, Traits>*>(out_stream.rdbuf())
Chris@16 1627 );
Chris@16 1628 start = p->pbase();
Chris@16 1629 finish = p->pptr();
Chris@16 1630 return result;
Chris@16 1631 #ifndef BOOST_NO_EXCEPTIONS
Chris@16 1632 } catch (const ::std::ios_base::failure& /*f*/) {
Chris@16 1633 return false;
Chris@16 1634 }
Chris@16 1635 #endif
Chris@16 1636 }
Chris@16 1637
Chris@16 1638 template <class T>
Chris@16 1639 inline bool shl_signed(T n)
Chris@16 1640 {
Chris@16 1641 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
Chris@16 1642 if(n < 0)
Chris@16 1643 {
Chris@16 1644 --start;
Chris@16 1645 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 1646 Traits::assign(*start, minus);
Chris@16 1647 }
Chris@16 1648 return true;
Chris@16 1649 }
Chris@16 1650
Chris@16 1651 template <class T, class SomeCharT>
Chris@16 1652 bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end)
Chris@16 1653 {
Chris@16 1654 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1655 lcast_set_precision(out_stream, &val);
Chris@16 1656 return shl_input_streamable(val);
Chris@16 1657 }
Chris@16 1658
Chris@16 1659 static bool shl_real_type(float val, char* begin, char*& end)
Chris@16 1660 { using namespace std;
Chris@16 1661 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1662 const double val_as_double = val;
Chris@16 1663 end = begin +
Chris@16 1664 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
Chris@16 1665 sprintf_s(begin, end-begin,
Chris@16 1666 #else
Chris@16 1667 sprintf(begin,
Chris@16 1668 #endif
Chris@16 1669 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<float>()), val_as_double);
Chris@16 1670 return end > begin;
Chris@16 1671 }
Chris@16 1672
Chris@16 1673 static bool shl_real_type(double val, char* begin, char*& end)
Chris@16 1674 { using namespace std;
Chris@16 1675 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1676 end = begin +
Chris@16 1677 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
Chris@16 1678 sprintf_s(begin, end-begin,
Chris@16 1679 #else
Chris@16 1680 sprintf(begin,
Chris@16 1681 #endif
Chris@16 1682 "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val);
Chris@16 1683 return end > begin;
Chris@16 1684 }
Chris@16 1685
Chris@16 1686 #ifndef __MINGW32__
Chris@16 1687 static bool shl_real_type(long double val, char* begin, char*& end)
Chris@16 1688 { using namespace std;
Chris@16 1689 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1690 end = begin +
Chris@16 1691 #if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
Chris@16 1692 sprintf_s(begin, end-begin,
Chris@16 1693 #else
Chris@16 1694 sprintf(begin,
Chris@16 1695 #endif
Chris@16 1696 "%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double>()), val );
Chris@16 1697 return end > begin;
Chris@16 1698 }
Chris@16 1699 #endif
Chris@16 1700
Chris@16 1701
Chris@16 1702 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_SWPRINTF) && !defined(__MINGW32__)
Chris@16 1703 static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end)
Chris@16 1704 { using namespace std;
Chris@16 1705 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1706 const double val_as_double = val;
Chris@16 1707 end = begin + swprintf(begin, end-begin,
Chris@16 1708 L"%.*g",
Chris@16 1709 static_cast<int>(boost::detail::lcast_get_precision<float >()),
Chris@16 1710 val_as_double );
Chris@16 1711 return end > begin;
Chris@16 1712 }
Chris@16 1713
Chris@16 1714 static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end)
Chris@16 1715 { using namespace std;
Chris@16 1716 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1717 end = begin + swprintf(begin, end-begin,
Chris@16 1718 L"%.*g", static_cast<int>(boost::detail::lcast_get_precision<double >()), val );
Chris@16 1719 return end > begin;
Chris@16 1720 }
Chris@16 1721
Chris@16 1722 static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end)
Chris@16 1723 { using namespace std;
Chris@16 1724 if (put_inf_nan(begin, end, val)) return true;
Chris@16 1725 end = begin + swprintf(begin, end-begin,
Chris@16 1726 L"%.*Lg", static_cast<int>(boost::detail::lcast_get_precision<long double >()), val );
Chris@16 1727 return end > begin;
Chris@16 1728 }
Chris@16 1729 #endif
Chris@16 1730
Chris@16 1731 /************************************ OPERATORS << ( ... ) ********************************/
Chris@16 1732 public:
Chris@16 1733 template<class Alloc>
Chris@16 1734 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
Chris@16 1735 {
Chris@16 1736 start = const_cast<CharT*>(str.data());
Chris@16 1737 finish = start + str.length();
Chris@16 1738 return true;
Chris@16 1739 }
Chris@16 1740
Chris@16 1741 template<class Alloc>
Chris@16 1742 bool operator<<(boost::container::basic_string<CharT,Traits,Alloc> const& str) BOOST_NOEXCEPT
Chris@16 1743 {
Chris@16 1744 start = const_cast<CharT*>(str.data());
Chris@16 1745 finish = start + str.length();
Chris@16 1746 return true;
Chris@16 1747 }
Chris@16 1748
Chris@16 1749 bool operator<<(bool value) BOOST_NOEXCEPT
Chris@16 1750 {
Chris@16 1751 CharT const czero = lcast_char_constants<CharT>::zero;
Chris@16 1752 Traits::assign(*start, Traits::to_char_type(czero + value));
Chris@16 1753 finish = start + 1;
Chris@16 1754 return true;
Chris@16 1755 }
Chris@16 1756
Chris@16 1757 bool operator<<(const iterator_range<CharT*>& rng) BOOST_NOEXCEPT
Chris@16 1758 {
Chris@16 1759 start = rng.begin();
Chris@16 1760 finish = rng.end();
Chris@16 1761 return true;
Chris@16 1762 }
Chris@16 1763
Chris@16 1764 bool operator<<(const iterator_range<const CharT*>& rng) BOOST_NOEXCEPT
Chris@16 1765 {
Chris@16 1766 start = const_cast<CharT*>(rng.begin());
Chris@16 1767 finish = const_cast<CharT*>(rng.end());
Chris@16 1768 return true;
Chris@16 1769 }
Chris@16 1770
Chris@16 1771 bool operator<<(const iterator_range<const signed char*>& rng) BOOST_NOEXCEPT
Chris@16 1772 {
Chris@16 1773 return (*this) << iterator_range<char*>(
Chris@16 1774 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
Chris@16 1775 const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
Chris@16 1776 );
Chris@16 1777 }
Chris@16 1778
Chris@16 1779 bool operator<<(const iterator_range<const unsigned char*>& rng) BOOST_NOEXCEPT
Chris@16 1780 {
Chris@16 1781 return (*this) << iterator_range<char*>(
Chris@16 1782 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
Chris@16 1783 const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
Chris@16 1784 );
Chris@16 1785 }
Chris@16 1786
Chris@16 1787 bool operator<<(const iterator_range<signed char*>& rng) BOOST_NOEXCEPT
Chris@16 1788 {
Chris@16 1789 return (*this) << iterator_range<char*>(
Chris@16 1790 reinterpret_cast<char*>(rng.begin()),
Chris@16 1791 reinterpret_cast<char*>(rng.end())
Chris@16 1792 );
Chris@16 1793 }
Chris@16 1794
Chris@16 1795 bool operator<<(const iterator_range<unsigned char*>& rng) BOOST_NOEXCEPT
Chris@16 1796 {
Chris@16 1797 return (*this) << iterator_range<char*>(
Chris@16 1798 reinterpret_cast<char*>(rng.begin()),
Chris@16 1799 reinterpret_cast<char*>(rng.end())
Chris@16 1800 );
Chris@16 1801 }
Chris@16 1802
Chris@16 1803 bool operator<<(char ch) { return shl_char(ch); }
Chris@16 1804 bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); }
Chris@16 1805 bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); }
Chris@16 1806 #if !defined(BOOST_LCAST_NO_WCHAR_T)
Chris@16 1807 bool operator<<(wchar_t const* str) { return shl_char_array(str); }
Chris@16 1808 bool operator<<(wchar_t * str) { return shl_char_array(str); }
Chris@16 1809 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
Chris@16 1810 bool operator<<(wchar_t ch) { return shl_char(ch); }
Chris@16 1811 #endif
Chris@16 1812 #endif
Chris@16 1813 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 1814 bool operator<<(char16_t ch) { return shl_char(ch); }
Chris@16 1815 bool operator<<(char16_t * str) { return shl_char_array(str); }
Chris@16 1816 bool operator<<(char16_t const * str) { return shl_char_array(str); }
Chris@16 1817 #endif
Chris@16 1818 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 1819 bool operator<<(char32_t ch) { return shl_char(ch); }
Chris@16 1820 bool operator<<(char32_t * str) { return shl_char_array(str); }
Chris@16 1821 bool operator<<(char32_t const * str) { return shl_char_array(str); }
Chris@16 1822 #endif
Chris@16 1823 bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
Chris@16 1824 bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
Chris@16 1825 bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
Chris@16 1826 bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
Chris@16 1827 bool operator<<(char const* str) { return shl_char_array(str); }
Chris@16 1828 bool operator<<(char* str) { return shl_char_array(str); }
Chris@16 1829 bool operator<<(short n) { return shl_signed(n); }
Chris@16 1830 bool operator<<(int n) { return shl_signed(n); }
Chris@16 1831 bool operator<<(long n) { return shl_signed(n); }
Chris@16 1832 bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1833 bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1834 bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1835
Chris@16 1836 #if defined(BOOST_HAS_LONG_LONG)
Chris@16 1837 bool operator<<(boost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1838 bool operator<<(boost::long_long_type n) { return shl_signed(n); }
Chris@16 1839 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 1840 bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1841 bool operator<<( __int64 n) { return shl_signed(n); }
Chris@16 1842 #endif
Chris@16 1843
Chris@16 1844 #ifdef BOOST_HAS_INT128
Chris@16 1845 bool operator<<(const boost::uint128_type& n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
Chris@16 1846 bool operator<<(const boost::int128_type& n) { return shl_signed(n); }
Chris@16 1847 #endif
Chris@16 1848
Chris@16 1849 bool operator<<(float val) { return shl_real_type(val, start, finish); }
Chris@16 1850 bool operator<<(double val) { return shl_real_type(val, start, finish); }
Chris@16 1851 bool operator<<(long double val) {
Chris@16 1852 #ifndef __MINGW32__
Chris@16 1853 return shl_real_type(val, start, finish);
Chris@16 1854 #else
Chris@16 1855 return shl_real_type(static_cast<double>(val), start, finish);
Chris@16 1856 #endif
Chris@16 1857 }
Chris@16 1858
Chris@16 1859 template <std::size_t N>
Chris@16 1860 bool operator<<(boost::array<CharT, N> const& input) BOOST_NOEXCEPT
Chris@16 1861 { return shl_char_array_limited(input.begin(), N); }
Chris@16 1862
Chris@16 1863 template <std::size_t N>
Chris@16 1864 bool operator<<(boost::array<unsigned char, N> const& input) BOOST_NOEXCEPT
Chris@16 1865 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
Chris@16 1866
Chris@16 1867 template <std::size_t N>
Chris@16 1868 bool operator<<(boost::array<signed char, N> const& input) BOOST_NOEXCEPT
Chris@16 1869 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
Chris@16 1870
Chris@16 1871 template <std::size_t N>
Chris@16 1872 bool operator<<(boost::array<const CharT, N> const& input) BOOST_NOEXCEPT
Chris@16 1873 { return shl_char_array_limited(input.begin(), N); }
Chris@16 1874
Chris@16 1875 template <std::size_t N>
Chris@16 1876 bool operator<<(boost::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
Chris@16 1877 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
Chris@16 1878
Chris@16 1879 template <std::size_t N>
Chris@16 1880 bool operator<<(boost::array<const signed char, N> const& input) BOOST_NOEXCEPT
Chris@16 1881 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
Chris@16 1882
Chris@16 1883 #ifndef BOOST_NO_CXX11_HDR_ARRAY
Chris@16 1884 template <std::size_t N>
Chris@16 1885 bool operator<<(std::array<CharT, N> const& input) BOOST_NOEXCEPT
Chris@16 1886 {
Chris@16 1887 if (input.size()) return shl_char_array_limited(&input[0], N);
Chris@16 1888 else return true;
Chris@16 1889 }
Chris@16 1890
Chris@16 1891 template <std::size_t N>
Chris@16 1892 bool operator<<(std::array<unsigned char, N> const& input) BOOST_NOEXCEPT
Chris@16 1893 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
Chris@16 1894
Chris@16 1895 template <std::size_t N>
Chris@16 1896 bool operator<<(std::array<signed char, N> const& input) BOOST_NOEXCEPT
Chris@16 1897 { return ((*this) << reinterpret_cast<boost::array<char, N> const& >(input)); }
Chris@16 1898
Chris@16 1899 template <std::size_t N>
Chris@16 1900 bool operator<<(std::array<const CharT, N> const& input) BOOST_NOEXCEPT
Chris@16 1901 {
Chris@16 1902 if (input.size()) return shl_char_array_limited(&input[0], N);
Chris@16 1903 else return true;
Chris@16 1904 }
Chris@16 1905
Chris@16 1906 template <std::size_t N>
Chris@16 1907 bool operator<<(std::array<const unsigned char, N> const& input) BOOST_NOEXCEPT
Chris@16 1908 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
Chris@16 1909
Chris@16 1910 template <std::size_t N>
Chris@16 1911 bool operator<<(std::array<const signed char, N> const& input) BOOST_NOEXCEPT
Chris@16 1912 { return ((*this) << reinterpret_cast<boost::array<const char, N> const& >(input)); }
Chris@16 1913 #endif
Chris@16 1914
Chris@16 1915 template <class InStreamable>
Chris@16 1916 bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
Chris@16 1917
Chris@16 1918 /************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
Chris@16 1919 private:
Chris@16 1920
Chris@16 1921 template <typename Type>
Chris@16 1922 bool shr_unsigned(Type& output)
Chris@16 1923 {
Chris@16 1924 if (start == finish) return false;
Chris@16 1925 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 1926 CharT const plus = lcast_char_constants<CharT>::plus;
Chris@16 1927 bool has_minus = false;
Chris@16 1928
Chris@16 1929 /* We won`t use `start' any more, so no need in decrementing it after */
Chris@16 1930 if ( Traits::eq(minus,*start) )
Chris@16 1931 {
Chris@16 1932 ++start;
Chris@16 1933 has_minus = true;
Chris@16 1934 } else if ( Traits::eq( plus, *start ) )
Chris@16 1935 {
Chris@16 1936 ++start;
Chris@16 1937 }
Chris@16 1938
Chris@16 1939 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
Chris@16 1940
Chris@16 1941 if (has_minus) {
Chris@16 1942 output = static_cast<Type>(0u - output);
Chris@16 1943 }
Chris@16 1944
Chris@16 1945 return succeed;
Chris@16 1946 }
Chris@16 1947
Chris@16 1948 template <typename Type>
Chris@16 1949 bool shr_signed(Type& output)
Chris@16 1950 {
Chris@16 1951 if (start == finish) return false;
Chris@16 1952 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 1953 CharT const plus = lcast_char_constants<CharT>::plus;
Chris@16 1954 typedef BOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
Chris@16 1955 utype out_tmp =0;
Chris@16 1956 bool has_minus = false;
Chris@16 1957
Chris@16 1958 /* We won`t use `start' any more, so no need in decrementing it after */
Chris@16 1959 if ( Traits::eq(minus,*start) )
Chris@16 1960 {
Chris@16 1961 ++start;
Chris@16 1962 has_minus = true;
Chris@16 1963 } else if ( Traits::eq(plus, *start) )
Chris@16 1964 {
Chris@16 1965 ++start;
Chris@16 1966 }
Chris@16 1967
Chris@16 1968 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
Chris@16 1969 if (has_minus) {
Chris@16 1970 utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
Chris@16 1971 succeed = succeed && out_tmp<=comp_val;
Chris@16 1972 output = static_cast<Type>(0u - out_tmp);
Chris@16 1973 } else {
Chris@16 1974 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
Chris@16 1975 succeed = succeed && out_tmp<=comp_val;
Chris@16 1976 output = out_tmp;
Chris@16 1977 }
Chris@16 1978 return succeed;
Chris@16 1979 }
Chris@16 1980
Chris@16 1981 template<typename InputStreamable>
Chris@16 1982 bool shr_using_base_class(InputStreamable& output)
Chris@16 1983 {
Chris@16 1984 BOOST_STATIC_ASSERT_MSG(
Chris@16 1985 (!boost::is_pointer<InputStreamable>::value),
Chris@16 1986 "boost::lexical_cast can not convert to pointers"
Chris@16 1987 );
Chris@16 1988
Chris@16 1989 #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE)
Chris@16 1990 BOOST_STATIC_ASSERT_MSG((boost::is_same<char, CharT>::value),
Chris@16 1991 "boost::lexical_cast can not convert, because your STL library does not "
Chris@16 1992 "support such conversions. Try updating it."
Chris@16 1993 );
Chris@16 1994 #endif
Chris@16 1995
Chris@16 1996 #if defined(BOOST_NO_STRINGSTREAM)
Chris@16 1997 std::istrstream stream(start, finish - start);
Chris@16 1998 #else
Chris@16 1999
Chris@16 2000 buffer_t buf;
Chris@16 2001 buf.setbuf(start, finish - start);
Chris@16 2002 #if defined(BOOST_NO_STD_LOCALE)
Chris@16 2003 std::istream stream(&buf);
Chris@16 2004 #else
Chris@16 2005 std::basic_istream<CharT, Traits> stream(&buf);
Chris@16 2006 #endif // BOOST_NO_STD_LOCALE
Chris@16 2007 #endif // BOOST_NO_STRINGSTREAM
Chris@16 2008
Chris@16 2009 #ifndef BOOST_NO_EXCEPTIONS
Chris@16 2010 stream.exceptions(std::ios::badbit);
Chris@16 2011 try {
Chris@16 2012 #endif
Chris@16 2013 stream.unsetf(std::ios::skipws);
Chris@16 2014 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
Chris@16 2015
Chris@16 2016 return stream >> output &&
Chris@16 2017 stream.get() ==
Chris@16 2018 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
Chris@16 2019 // GCC 2.9x lacks std::char_traits<>::eof().
Chris@16 2020 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
Chris@16 2021 // configurations, which do provide std::char_traits<>::eof().
Chris@16 2022
Chris@16 2023 EOF;
Chris@16 2024 #else
Chris@16 2025 Traits::eof();
Chris@16 2026 #endif
Chris@16 2027
Chris@16 2028 #ifndef BOOST_NO_EXCEPTIONS
Chris@16 2029 } catch (const ::std::ios_base::failure& /*f*/) {
Chris@16 2030 return false;
Chris@16 2031 }
Chris@16 2032 #endif
Chris@16 2033 }
Chris@16 2034
Chris@16 2035 template<class T>
Chris@16 2036 inline bool shr_xchar(T& output)
Chris@16 2037 {
Chris@16 2038 BOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
Chris@16 2039 "boost::lexical_cast does not support narrowing of character types."
Chris@16 2040 "Use boost::locale instead" );
Chris@16 2041 bool const ok = (finish - start == 1);
Chris@16 2042 if (ok) {
Chris@16 2043 CharT out;
Chris@16 2044 Traits::assign(out, *start);
Chris@16 2045 output = static_cast<T>(out);
Chris@16 2046 }
Chris@16 2047 return ok;
Chris@16 2048 }
Chris@16 2049
Chris@16 2050 /************************************ OPERATORS >> ( ... ) ********************************/
Chris@16 2051 public:
Chris@16 2052 bool operator>>(unsigned short& output) { return shr_unsigned(output); }
Chris@16 2053 bool operator>>(unsigned int& output) { return shr_unsigned(output); }
Chris@16 2054 bool operator>>(unsigned long int& output) { return shr_unsigned(output); }
Chris@16 2055 bool operator>>(short& output) { return shr_signed(output); }
Chris@16 2056 bool operator>>(int& output) { return shr_signed(output); }
Chris@16 2057 bool operator>>(long int& output) { return shr_signed(output); }
Chris@16 2058 #if defined(BOOST_HAS_LONG_LONG)
Chris@16 2059 bool operator>>(boost::ulong_long_type& output) { return shr_unsigned(output); }
Chris@16 2060 bool operator>>(boost::long_long_type& output) { return shr_signed(output); }
Chris@16 2061 #elif defined(BOOST_HAS_MS_INT64)
Chris@16 2062 bool operator>>(unsigned __int64& output) { return shr_unsigned(output); }
Chris@16 2063 bool operator>>(__int64& output) { return shr_signed(output); }
Chris@16 2064 #endif
Chris@16 2065
Chris@16 2066 #ifdef BOOST_HAS_INT128
Chris@16 2067 bool operator>>(boost::uint128_type& output) { return shr_unsigned(output); }
Chris@16 2068 bool operator>>(boost::int128_type& output) { return shr_signed(output); }
Chris@16 2069 #endif
Chris@16 2070
Chris@16 2071 bool operator>>(char& output) { return shr_xchar(output); }
Chris@16 2072 bool operator>>(unsigned char& output) { return shr_xchar(output); }
Chris@16 2073 bool operator>>(signed char& output) { return shr_xchar(output); }
Chris@16 2074 #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
Chris@16 2075 bool operator>>(wchar_t& output) { return shr_xchar(output); }
Chris@16 2076 #endif
Chris@16 2077 #if !defined(BOOST_NO_CXX11_CHAR16_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 2078 bool operator>>(char16_t& output) { return shr_xchar(output); }
Chris@16 2079 #endif
Chris@16 2080 #if !defined(BOOST_NO_CXX11_CHAR32_T) && !defined(BOOST_NO_CXX11_UNICODE_LITERALS)
Chris@16 2081 bool operator>>(char32_t& output) { return shr_xchar(output); }
Chris@16 2082 #endif
Chris@16 2083 template<class Alloc>
Chris@16 2084 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
Chris@16 2085
Chris@16 2086 template<class Alloc>
Chris@16 2087 bool operator>>(boost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
Chris@16 2088
Chris@16 2089
Chris@16 2090 private:
Chris@16 2091 template <std::size_t N, class ArrayT>
Chris@16 2092 bool shr_std_array(ArrayT& output) BOOST_NOEXCEPT
Chris@16 2093 {
Chris@16 2094 using namespace std;
Chris@16 2095 const std::size_t size = finish - start;
Chris@16 2096 if (size > N - 1) { // `-1` because we need to store \0 at the end
Chris@16 2097 return false;
Chris@16 2098 }
Chris@16 2099
Chris@16 2100 memcpy(&output[0], start, size * sizeof(CharT));
Chris@16 2101 output[size] = Traits::to_char_type(0);
Chris@16 2102 return true;
Chris@16 2103 }
Chris@16 2104
Chris@16 2105 public:
Chris@16 2106
Chris@16 2107 template <std::size_t N>
Chris@16 2108 bool operator>>(boost::array<CharT, N>& output) BOOST_NOEXCEPT
Chris@16 2109 {
Chris@16 2110 return shr_std_array<N>(output);
Chris@16 2111 }
Chris@16 2112
Chris@16 2113 template <std::size_t N>
Chris@16 2114 bool operator>>(boost::array<unsigned char, N>& output)
Chris@16 2115 {
Chris@16 2116 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
Chris@16 2117 }
Chris@16 2118
Chris@16 2119 template <std::size_t N>
Chris@16 2120 bool operator>>(boost::array<signed char, N>& output)
Chris@16 2121 {
Chris@16 2122 return ((*this) >> reinterpret_cast<boost::array<char, N>& >(output));
Chris@16 2123 }
Chris@16 2124
Chris@16 2125 #ifndef BOOST_NO_CXX11_HDR_ARRAY
Chris@16 2126 template <std::size_t N>
Chris@16 2127 bool operator>>(std::array<CharT, N>& output) BOOST_NOEXCEPT
Chris@16 2128 {
Chris@16 2129 return shr_std_array<N>(output);
Chris@16 2130 }
Chris@16 2131
Chris@16 2132 template <std::size_t N>
Chris@16 2133 bool operator>>(std::array<unsigned char, N>& output)
Chris@16 2134 {
Chris@16 2135 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
Chris@16 2136 }
Chris@16 2137
Chris@16 2138 template <std::size_t N>
Chris@16 2139 bool operator>>(std::array<signed char, N>& output)
Chris@16 2140 {
Chris@16 2141 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
Chris@16 2142 }
Chris@16 2143 #endif
Chris@16 2144
Chris@16 2145
Chris@16 2146 /*
Chris@16 2147 * case "-0" || "0" || "+0" : output = false; return true;
Chris@16 2148 * case "1" || "+1": output = true; return true;
Chris@16 2149 * default: return false;
Chris@16 2150 */
Chris@16 2151 bool operator>>(bool& output) BOOST_NOEXCEPT
Chris@16 2152 {
Chris@16 2153 CharT const zero = lcast_char_constants<CharT>::zero;
Chris@16 2154 CharT const plus = lcast_char_constants<CharT>::plus;
Chris@16 2155 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 2156
Chris@16 2157 switch(finish-start)
Chris@16 2158 {
Chris@16 2159 case 1:
Chris@16 2160 output = Traits::eq(start[0], zero+1);
Chris@16 2161 return output || Traits::eq(start[0], zero );
Chris@16 2162 case 2:
Chris@16 2163 if ( Traits::eq( plus, *start) )
Chris@16 2164 {
Chris@16 2165 ++start;
Chris@16 2166 output = Traits::eq(start[0], zero +1);
Chris@16 2167 return output || Traits::eq(start[0], zero );
Chris@16 2168 } else
Chris@16 2169 {
Chris@16 2170 output = false;
Chris@16 2171 return Traits::eq( minus, *start)
Chris@16 2172 && Traits::eq( zero, start[1]);
Chris@16 2173 }
Chris@16 2174 default:
Chris@16 2175 output = false; // Suppress warning about uninitalized variable
Chris@16 2176 return false;
Chris@16 2177 }
Chris@16 2178 }
Chris@16 2179
Chris@16 2180 bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
Chris@16 2181
Chris@16 2182 private:
Chris@16 2183 // Not optimised converter
Chris@16 2184 template <class T>
Chris@16 2185 bool float_types_converter_internal(T& output, int /*tag*/) {
Chris@16 2186 if (parse_inf_nan(start, finish, output)) return true;
Chris@16 2187 bool return_value = shr_using_base_class(output);
Chris@16 2188
Chris@16 2189 /* Some compilers and libraries successfully
Chris@16 2190 * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
Chris@16 2191 * We are trying to provide a unified behaviour,
Chris@16 2192 * so we just forbid such conversions (as some
Chris@16 2193 * of the most popular compilers/libraries do)
Chris@16 2194 * */
Chris@16 2195 CharT const minus = lcast_char_constants<CharT>::minus;
Chris@16 2196 CharT const plus = lcast_char_constants<CharT>::plus;
Chris@16 2197 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
Chris@16 2198 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
Chris@16 2199 if ( return_value &&
Chris@16 2200 (
Chris@16 2201 Traits::eq(*(finish-1), lowercase_e) // 1.0e
Chris@16 2202 || Traits::eq(*(finish-1), capital_e) // 1.0E
Chris@16 2203 || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E-
Chris@16 2204 || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+
Chris@16 2205 )
Chris@16 2206 ) return false;
Chris@16 2207
Chris@16 2208 return return_value;
Chris@16 2209 }
Chris@16 2210
Chris@16 2211 // Optimised converter
Chris@16 2212 bool float_types_converter_internal(double& output,char /*tag*/) {
Chris@16 2213 return lcast_ret_float<Traits>(output,start,finish);
Chris@16 2214 }
Chris@16 2215 public:
Chris@16 2216
Chris@16 2217 bool operator>>(double& output)
Chris@16 2218 {
Chris@16 2219 /*
Chris@16 2220 * Some compilers implement long double as double. In that case these types have
Chris@16 2221 * same size, same precision, same max and min values... And it means,
Chris@16 2222 * that current implementation of lcast_ret_float cannot be used for type
Chris@16 2223 * double, because it will give a big precision loss.
Chris@16 2224 * */
Chris@16 2225 boost::mpl::if_c<
Chris@16 2226 #if (defined(BOOST_HAS_LONG_LONG) || defined(BOOST_HAS_MS_INT64)) && !defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
Chris@16 2227 boost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
Chris@16 2228 #else
Chris@16 2229 1,
Chris@16 2230 #endif
Chris@16 2231 int,
Chris@16 2232 char
Chris@16 2233 >::type tag = 0;
Chris@16 2234
Chris@16 2235 return float_types_converter_internal(output, tag);
Chris@16 2236 }
Chris@16 2237
Chris@16 2238 bool operator>>(long double& output)
Chris@16 2239 {
Chris@16 2240 int tag = 0;
Chris@16 2241 return float_types_converter_internal(output, tag);
Chris@16 2242 }
Chris@16 2243
Chris@16 2244 // Generic istream-based algorithm.
Chris@16 2245 // lcast_streambuf_for_target<InputStreamable>::value is true.
Chris@16 2246 template<typename InputStreamable>
Chris@16 2247 bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
Chris@16 2248 };
Chris@16 2249 }
Chris@16 2250
Chris@16 2251 namespace detail
Chris@16 2252 {
Chris@16 2253 template<typename T>
Chris@16 2254 struct is_stdstring
Chris@16 2255 {
Chris@16 2256 BOOST_STATIC_CONSTANT(bool, value = false );
Chris@16 2257 };
Chris@16 2258
Chris@16 2259 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2260 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
Chris@16 2261 {
Chris@16 2262 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2263 };
Chris@16 2264
Chris@16 2265 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2266 struct is_stdstring< boost::container::basic_string<CharT, Traits, Alloc> >
Chris@16 2267 {
Chris@16 2268 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2269 };
Chris@16 2270
Chris@16 2271 template<typename Target, typename Source>
Chris@16 2272 struct is_arithmetic_and_not_xchars
Chris@16 2273 {
Chris@16 2274 BOOST_STATIC_CONSTANT(bool, value =
Chris@16 2275 (
Chris@16 2276 boost::type_traits::ice_and<
Chris@16 2277 boost::is_arithmetic<Source>::value,
Chris@16 2278 boost::is_arithmetic<Target>::value,
Chris@16 2279 boost::type_traits::ice_not<
Chris@16 2280 detail::is_char_or_wchar<Target>::value
Chris@16 2281 >::value,
Chris@16 2282 boost::type_traits::ice_not<
Chris@16 2283 detail::is_char_or_wchar<Source>::value
Chris@16 2284 >::value
Chris@16 2285 >::value
Chris@16 2286 )
Chris@16 2287 );
Chris@16 2288 };
Chris@16 2289
Chris@16 2290 /*
Chris@16 2291 * is_xchar_to_xchar<Target, Source>::value is true, when
Chris@16 2292 * Target and Souce are the same char types, or when
Chris@16 2293 * Target and Souce are char types of the same size.
Chris@16 2294 */
Chris@16 2295 template<typename Target, typename Source>
Chris@16 2296 struct is_xchar_to_xchar
Chris@16 2297 {
Chris@16 2298 BOOST_STATIC_CONSTANT(bool, value =
Chris@16 2299 (
Chris@16 2300 boost::type_traits::ice_or<
Chris@16 2301 boost::type_traits::ice_and<
Chris@16 2302 is_same<Source,Target>::value,
Chris@16 2303 is_char_or_wchar<Target>::value
Chris@16 2304 >::value,
Chris@16 2305 boost::type_traits::ice_and<
Chris@16 2306 boost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
Chris@16 2307 boost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
Chris@16 2308 is_char_or_wchar<Target>::value,
Chris@16 2309 is_char_or_wchar<Source>::value
Chris@16 2310 >::value
Chris@16 2311 >::value
Chris@16 2312 )
Chris@16 2313 );
Chris@16 2314 };
Chris@16 2315
Chris@16 2316 template<typename Target, typename Source>
Chris@16 2317 struct is_char_array_to_stdstring
Chris@16 2318 {
Chris@16 2319 BOOST_STATIC_CONSTANT(bool, value = false );
Chris@16 2320 };
Chris@16 2321
Chris@16 2322 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2323 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
Chris@16 2324 {
Chris@16 2325 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2326 };
Chris@16 2327
Chris@16 2328 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2329 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
Chris@16 2330 {
Chris@16 2331 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2332 };
Chris@16 2333
Chris@16 2334 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2335 struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, CharT* >
Chris@16 2336 {
Chris@16 2337 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2338 };
Chris@16 2339
Chris@16 2340 template<typename CharT, typename Traits, typename Alloc>
Chris@16 2341 struct is_char_array_to_stdstring< boost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
Chris@16 2342 {
Chris@16 2343 BOOST_STATIC_CONSTANT(bool, value = true );
Chris@16 2344 };
Chris@16 2345
Chris@16 2346 #if (defined _MSC_VER)
Chris@16 2347 # pragma warning( push )
Chris@16 2348 # pragma warning( disable : 4701 ) // possible use of ... before initialization
Chris@16 2349 # pragma warning( disable : 4702 ) // unreachable code
Chris@16 2350 # pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
Chris@16 2351 #endif
Chris@16 2352 template<typename Target, typename Source>
Chris@16 2353 struct lexical_cast_do_cast
Chris@16 2354 {
Chris@16 2355 static inline Target lexical_cast_impl(const Source& arg)
Chris@16 2356 {
Chris@16 2357 typedef lexical_cast_stream_traits<Source, Target> stream_trait;
Chris@16 2358
Chris@16 2359 typedef detail::lexical_stream_limited_src<
Chris@16 2360 BOOST_DEDUCED_TYPENAME stream_trait::char_type,
Chris@16 2361 BOOST_DEDUCED_TYPENAME stream_trait::traits,
Chris@16 2362 stream_trait::requires_stringbuf
Chris@16 2363 > interpreter_type;
Chris@16 2364
Chris@16 2365 // Target type must be default constructible
Chris@16 2366 Target result;
Chris@16 2367
Chris@16 2368 BOOST_DEDUCED_TYPENAME stream_trait::char_type buf[stream_trait::len_t::value + 1];
Chris@16 2369 stream_trait::len_t::check_coverage();
Chris@16 2370
Chris@16 2371 interpreter_type interpreter(buf, buf + stream_trait::len_t::value + 1);
Chris@16 2372
Chris@16 2373 // Disabling ADL, by directly specifying operators.
Chris@16 2374 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
Chris@16 2375 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
Chris@16 2376
Chris@16 2377 return result;
Chris@16 2378 }
Chris@16 2379 };
Chris@16 2380 #if (defined _MSC_VER)
Chris@16 2381 # pragma warning( pop )
Chris@16 2382 #endif
Chris@16 2383
Chris@16 2384 template <typename Source>
Chris@16 2385 struct lexical_cast_copy
Chris@16 2386 {
Chris@16 2387 static inline const Source& lexical_cast_impl(const Source &arg) BOOST_NOEXCEPT
Chris@16 2388 {
Chris@16 2389 return arg;
Chris@16 2390 }
Chris@16 2391 };
Chris@16 2392
Chris@16 2393 template <class Source, class Target >
Chris@16 2394 struct detect_precision_loss
Chris@16 2395 {
Chris@16 2396 typedef boost::numeric::Trunc<Source> Rounder;
Chris@16 2397 typedef Source source_type ;
Chris@16 2398
Chris@16 2399 typedef BOOST_DEDUCED_TYPENAME mpl::if_<
Chris@16 2400 boost::is_arithmetic<Source>, Source, Source const&
Chris@16 2401 >::type argument_type ;
Chris@16 2402
Chris@16 2403 static source_type nearbyint ( argument_type s )
Chris@16 2404 {
Chris@16 2405 const source_type near_int = Rounder::nearbyint(s);
Chris@16 2406 if (near_int) {
Chris@16 2407 const source_type orig_div_round = s / near_int;
Chris@16 2408 const source_type eps = std::numeric_limits<source_type>::epsilon();
Chris@16 2409
Chris@16 2410 if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps)
Chris@16 2411 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
Chris@16 2412 }
Chris@16 2413
Chris@16 2414 return s ;
Chris@16 2415 }
Chris@16 2416
Chris@16 2417 typedef typename Rounder::round_style round_style;
Chris@16 2418 } ;
Chris@16 2419
Chris@16 2420 template <class Source, class Target >
Chris@16 2421 struct nothrow_overflow_handler
Chris@16 2422 {
Chris@16 2423 void operator() ( boost::numeric::range_check_result r )
Chris@16 2424 {
Chris@16 2425 if (r != boost::numeric::cInRange)
Chris@16 2426 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
Chris@16 2427 }
Chris@16 2428 } ;
Chris@16 2429
Chris@16 2430 template <typename Target, typename Source>
Chris@16 2431 struct lexical_cast_dynamic_num_not_ignoring_minus
Chris@16 2432 {
Chris@16 2433 static inline Target lexical_cast_impl(const Source &arg)
Chris@16 2434 {
Chris@16 2435 return boost::numeric::converter<
Chris@16 2436 Target,
Chris@16 2437 Source,
Chris@16 2438 boost::numeric::conversion_traits<Target,Source>,
Chris@16 2439 nothrow_overflow_handler<Source, Target>,
Chris@16 2440 detect_precision_loss<Source, Target>
Chris@16 2441 >::convert(arg);
Chris@16 2442 }
Chris@16 2443 };
Chris@16 2444
Chris@16 2445 template <typename Target, typename Source>
Chris@16 2446 struct lexical_cast_dynamic_num_ignoring_minus
Chris@16 2447 {
Chris@16 2448 static inline Target lexical_cast_impl(const Source &arg)
Chris@16 2449 {
Chris@16 2450 typedef BOOST_DEDUCED_TYPENAME boost::mpl::eval_if_c<
Chris@16 2451 boost::is_float<Source>::value,
Chris@16 2452 boost::mpl::identity<Source>,
Chris@16 2453 boost::make_unsigned<Source>
Chris@16 2454 >::type usource_t;
Chris@16 2455
Chris@16 2456 typedef boost::numeric::converter<
Chris@16 2457 Target,
Chris@16 2458 usource_t,
Chris@16 2459 boost::numeric::conversion_traits<Target,usource_t>,
Chris@16 2460 nothrow_overflow_handler<usource_t, Target>,
Chris@16 2461 detect_precision_loss<usource_t, Target>
Chris@16 2462 > converter_t;
Chris@16 2463
Chris@16 2464 return (
Chris@16 2465 arg < 0 ? static_cast<Target>(0u - converter_t::convert(0u - arg)) : converter_t::convert(arg)
Chris@16 2466 );
Chris@16 2467 }
Chris@16 2468 };
Chris@16 2469
Chris@16 2470 /*
Chris@16 2471 * lexical_cast_dynamic_num follows the rules:
Chris@16 2472 * 1) If Source can be converted to Target without precision loss and
Chris@16 2473 * without overflows, then assign Source to Target and return
Chris@16 2474 *
Chris@16 2475 * 2) If Source is less than 0 and Target is an unsigned integer,
Chris@16 2476 * then negate Source, check the requirements of rule 1) and if
Chris@16 2477 * successful, assign static_casted Source to Target and return
Chris@16 2478 *
Chris@16 2479 * 3) Otherwise throw a bad_lexical_cast exception
Chris@16 2480 *
Chris@16 2481 *
Chris@16 2482 * Rule 2) required because boost::lexical_cast has the behavior of
Chris@16 2483 * stringstream, which uses the rules of scanf for conversions. And
Chris@16 2484 * in the C99 standard for unsigned input value minus sign is
Chris@16 2485 * optional, so if a negative number is read, no errors will arise
Chris@16 2486 * and the result will be the two's complement.
Chris@16 2487 */
Chris@16 2488 template <typename Target, typename Source>
Chris@16 2489 struct lexical_cast_dynamic_num
Chris@16 2490 {
Chris@16 2491 static inline Target lexical_cast_impl(const Source &arg)
Chris@16 2492 {
Chris@16 2493 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 2494 boost::type_traits::ice_and<
Chris@16 2495 boost::type_traits::ice_or<
Chris@16 2496 boost::is_signed<Source>::value,
Chris@16 2497 boost::is_float<Source>::value
Chris@16 2498 >::value,
Chris@16 2499 boost::type_traits::ice_not<
Chris@16 2500 boost::is_same<Source, bool>::value
Chris@16 2501 >::value,
Chris@16 2502 boost::type_traits::ice_not<
Chris@16 2503 boost::is_same<Target, bool>::value
Chris@16 2504 >::value,
Chris@16 2505 boost::is_unsigned<Target>::value
Chris@16 2506 >::value,
Chris@16 2507 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
Chris@16 2508 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
Chris@16 2509 >::type caster_type;
Chris@16 2510
Chris@16 2511 return caster_type::lexical_cast_impl(arg);
Chris@16 2512 }
Chris@16 2513 };
Chris@16 2514 }
Chris@16 2515
Chris@16 2516 template <typename Target, typename Source>
Chris@16 2517 inline Target lexical_cast(const Source &arg)
Chris@16 2518 {
Chris@16 2519 typedef BOOST_DEDUCED_TYPENAME boost::detail::array_to_pointer_decay<Source>::type src;
Chris@16 2520
Chris@16 2521 typedef BOOST_DEDUCED_TYPENAME boost::type_traits::ice_or<
Chris@16 2522 boost::detail::is_xchar_to_xchar<Target, src >::value,
Chris@16 2523 boost::detail::is_char_array_to_stdstring<Target, src >::value,
Chris@16 2524 boost::type_traits::ice_and<
Chris@16 2525 boost::is_same<Target, src >::value,
Chris@16 2526 boost::detail::is_stdstring<Target >::value
Chris@16 2527 >::value
Chris@16 2528 > shall_we_copy_t;
Chris@16 2529
Chris@16 2530 typedef BOOST_DEDUCED_TYPENAME
Chris@16 2531 boost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t;
Chris@16 2532
Chris@16 2533 typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 2534 shall_we_copy_t::value,
Chris@16 2535 boost::detail::lexical_cast_copy<src >,
Chris@16 2536 BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Chris@16 2537 shall_we_copy_with_dynamic_check_t::value,
Chris@16 2538 boost::detail::lexical_cast_dynamic_num<Target, src >,
Chris@16 2539 boost::detail::lexical_cast_do_cast<Target, src >
Chris@16 2540 >::type
Chris@16 2541 >::type caster_type;
Chris@16 2542
Chris@16 2543 return caster_type::lexical_cast_impl(arg);
Chris@16 2544 }
Chris@16 2545
Chris@16 2546 template <typename Target>
Chris@16 2547 inline Target lexical_cast(const char* chars, std::size_t count)
Chris@16 2548 {
Chris@16 2549 return ::boost::lexical_cast<Target>(
Chris@16 2550 ::boost::iterator_range<const char*>(chars, chars + count)
Chris@16 2551 );
Chris@16 2552 }
Chris@16 2553
Chris@16 2554
Chris@16 2555 template <typename Target>
Chris@16 2556 inline Target lexical_cast(const unsigned char* chars, std::size_t count)
Chris@16 2557 {
Chris@16 2558 return ::boost::lexical_cast<Target>(
Chris@16 2559 ::boost::iterator_range<const unsigned char*>(chars, chars + count)
Chris@16 2560 );
Chris@16 2561 }
Chris@16 2562
Chris@16 2563 template <typename Target>
Chris@16 2564 inline Target lexical_cast(const signed char* chars, std::size_t count)
Chris@16 2565 {
Chris@16 2566 return ::boost::lexical_cast<Target>(
Chris@16 2567 ::boost::iterator_range<const signed char*>(chars, chars + count)
Chris@16 2568 );
Chris@16 2569 }
Chris@16 2570
Chris@16 2571 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 2572 template <typename Target>
Chris@16 2573 inline Target lexical_cast(const wchar_t* chars, std::size_t count)
Chris@16 2574 {
Chris@16 2575 return ::boost::lexical_cast<Target>(
Chris@16 2576 ::boost::iterator_range<const wchar_t*>(chars, chars + count)
Chris@16 2577 );
Chris@16 2578 }
Chris@16 2579 #endif
Chris@16 2580 #ifndef BOOST_NO_CXX11_CHAR16_T
Chris@16 2581 template <typename Target>
Chris@16 2582 inline Target lexical_cast(const char16_t* chars, std::size_t count)
Chris@16 2583 {
Chris@16 2584 return ::boost::lexical_cast<Target>(
Chris@16 2585 ::boost::iterator_range<const char16_t*>(chars, chars + count)
Chris@16 2586 );
Chris@16 2587 }
Chris@16 2588 #endif
Chris@16 2589 #ifndef BOOST_NO_CXX11_CHAR32_T
Chris@16 2590 template <typename Target>
Chris@16 2591 inline Target lexical_cast(const char32_t* chars, std::size_t count)
Chris@16 2592 {
Chris@16 2593 return ::boost::lexical_cast<Target>(
Chris@16 2594 ::boost::iterator_range<const char32_t*>(chars, chars + count)
Chris@16 2595 );
Chris@16 2596 }
Chris@16 2597 #endif
Chris@16 2598
Chris@16 2599 } // namespace boost
Chris@16 2600
Chris@16 2601 #else // #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Chris@16 2602
Chris@16 2603 namespace boost {
Chris@16 2604 namespace detail
Chris@16 2605 {
Chris@16 2606
Chris@16 2607 // selectors for choosing stream character type
Chris@16 2608 template<typename Type>
Chris@16 2609 struct stream_char
Chris@16 2610 {
Chris@16 2611 typedef char type;
Chris@16 2612 };
Chris@16 2613
Chris@16 2614 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 2615 #ifndef BOOST_NO_INTRINSIC_WCHAR_T
Chris@16 2616 template<>
Chris@16 2617 struct stream_char<wchar_t>
Chris@16 2618 {
Chris@16 2619 typedef wchar_t type;
Chris@16 2620 };
Chris@16 2621 #endif
Chris@16 2622
Chris@16 2623 template<>
Chris@16 2624 struct stream_char<wchar_t *>
Chris@16 2625 {
Chris@16 2626 typedef wchar_t type;
Chris@16 2627 };
Chris@16 2628
Chris@16 2629 template<>
Chris@16 2630 struct stream_char<const wchar_t *>
Chris@16 2631 {
Chris@16 2632 typedef wchar_t type;
Chris@16 2633 };
Chris@16 2634
Chris@16 2635 template<>
Chris@16 2636 struct stream_char<std::wstring>
Chris@16 2637 {
Chris@16 2638 typedef wchar_t type;
Chris@16 2639 };
Chris@16 2640 #endif
Chris@16 2641
Chris@16 2642 // stream wrapper for handling lexical conversions
Chris@16 2643 template<typename Target, typename Source, typename Traits>
Chris@16 2644 class lexical_stream
Chris@16 2645 {
Chris@16 2646 private:
Chris@16 2647 typedef typename widest_char<
Chris@16 2648 typename stream_char<Target>::type,
Chris@16 2649 typename stream_char<Source>::type>::type char_type;
Chris@16 2650
Chris@16 2651 typedef Traits traits_type;
Chris@16 2652
Chris@16 2653 public:
Chris@16 2654 lexical_stream(char_type* = 0, char_type* = 0)
Chris@16 2655 {
Chris@16 2656 stream.unsetf(std::ios::skipws);
Chris@16 2657 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
Chris@16 2658 }
Chris@16 2659 ~lexical_stream()
Chris@16 2660 {
Chris@16 2661 #if defined(BOOST_NO_STRINGSTREAM)
Chris@16 2662 stream.freeze(false);
Chris@16 2663 #endif
Chris@16 2664 }
Chris@16 2665 bool operator<<(const Source &input)
Chris@16 2666 {
Chris@16 2667 return !(stream << input).fail();
Chris@16 2668 }
Chris@16 2669 template<typename InputStreamable>
Chris@16 2670 bool operator>>(InputStreamable &output)
Chris@16 2671 {
Chris@16 2672 return !is_pointer<InputStreamable>::value &&
Chris@16 2673 stream >> output &&
Chris@16 2674 stream.get() ==
Chris@16 2675 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
Chris@16 2676 // GCC 2.9x lacks std::char_traits<>::eof().
Chris@16 2677 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
Chris@16 2678 // configurations, which do provide std::char_traits<>::eof().
Chris@16 2679
Chris@16 2680 EOF;
Chris@16 2681 #else
Chris@16 2682 traits_type::eof();
Chris@16 2683 #endif
Chris@16 2684 }
Chris@16 2685
Chris@16 2686 bool operator>>(std::string &output)
Chris@16 2687 {
Chris@16 2688 #if defined(BOOST_NO_STRINGSTREAM)
Chris@16 2689 stream << '\0';
Chris@16 2690 #endif
Chris@16 2691 stream.str().swap(output);
Chris@16 2692 return true;
Chris@16 2693 }
Chris@16 2694 #ifndef BOOST_LCAST_NO_WCHAR_T
Chris@16 2695 bool operator>>(std::wstring &output)
Chris@16 2696 {
Chris@16 2697 stream.str().swap(output);
Chris@16 2698 return true;
Chris@16 2699 }
Chris@16 2700 #endif
Chris@16 2701
Chris@16 2702 private:
Chris@16 2703 #if defined(BOOST_NO_STRINGSTREAM)
Chris@16 2704 std::strstream stream;
Chris@16 2705 #elif defined(BOOST_NO_STD_LOCALE)
Chris@16 2706 std::stringstream stream;
Chris@16 2707 #else
Chris@16 2708 std::basic_stringstream<char_type,traits_type> stream;
Chris@16 2709 #endif
Chris@16 2710 };
Chris@16 2711 }
Chris@16 2712
Chris@16 2713 // call-by-value fallback version (deprecated)
Chris@16 2714
Chris@16 2715 template<typename Target, typename Source>
Chris@16 2716 Target lexical_cast(Source arg)
Chris@16 2717 {
Chris@16 2718 typedef typename detail::widest_char<
Chris@16 2719 BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
Chris@16 2720 , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
Chris@16 2721 >::type char_type;
Chris@16 2722
Chris@16 2723 typedef std::char_traits<char_type> traits;
Chris@16 2724 detail::lexical_stream<Target, Source, traits> interpreter;
Chris@16 2725 Target result;
Chris@16 2726
Chris@16 2727 if(!(interpreter << arg && interpreter >> result))
Chris@16 2728 BOOST_LCAST_THROW_BAD_CAST(Source, Target);
Chris@16 2729 return result;
Chris@16 2730 }
Chris@16 2731
Chris@16 2732 } // namespace boost
Chris@16 2733
Chris@16 2734 #endif
Chris@16 2735
Chris@16 2736 // Copyright Kevlin Henney, 2000-2005.
Chris@16 2737 // Copyright Alexander Nasonov, 2006-2010.
Chris@16 2738 // Copyright Antony Polukhin, 2011-2013.
Chris@16 2739 //
Chris@16 2740 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 2741 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 2742 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 2743
Chris@16 2744 #undef BOOST_LCAST_THROW_BAD_CAST
Chris@16 2745 #undef BOOST_LCAST_NO_WCHAR_T
Chris@16 2746
Chris@16 2747 #endif // BOOST_LEXICAL_CAST_INCLUDED
Chris@16 2748