blob: 828a1f11bdf6210e3e9531eb68f8c31299b92215 [file] [log] [blame]
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001#ifndef NDNBOOST_LEXICAL_CAST_INCLUDED
2#define NDNBOOST_LEXICAL_CAST_INCLUDED
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07003
4// MS compatible compilers support #pragma once
5
6#if defined(_MSC_VER) && (_MSC_VER >= 1020)
7# pragma once
8#endif
9
10// Boost lexical_cast.hpp header -------------------------------------------//
11//
12// See http://www.boost.org/libs/conversion for documentation.
13// See end of this header for rights and permissions.
14//
15// what: lexical_cast custom keyword cast
16// who: contributed by Kevlin Henney,
17// enhanced with contributions from Terje Slettebo,
18// with additional fixes and suggestions from Gennaro Prota,
19// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
20// Alexander Nasonov, Antony Polukhin, Justin Viiret, Michael Hofmann,
21// Cheng Yang, Matthew Bradbury, David W. Birdsall, Pavel Korzh and other Boosters
22// when: November 2000, March 2003, June 2005, June 2006, March 2011 - 2013
23
24#include <ndnboost/config.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -070025#if defined(NDNBOOST_NO_STRINGSTREAM) || defined(NDNBOOST_NO_STD_WSTRING)
26#define NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070027#endif
28
29#include <climits>
30#include <cstddef>
31#include <string>
32#include <cstring>
33#include <cstdio>
34#include <typeinfo>
35#include <exception>
36#include <ndnboost/limits.hpp>
37#include <ndnboost/mpl/if.hpp>
38#include <ndnboost/throw_exception.hpp>
39#include <ndnboost/type_traits/ice.hpp>
40#include <ndnboost/type_traits/is_pointer.hpp>
41#include <ndnboost/static_assert.hpp>
42#include <ndnboost/detail/lcast_precision.hpp>
43#include <ndnboost/detail/workaround.hpp>
44
45
Jeff Thompson3d613fd2013-10-15 15:39:04 -070046#ifndef NDNBOOST_NO_STD_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070047# include <locale>
48#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -070049# ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070050 // Getting error at this point means, that your STL library is old/lame/misconfigured.
Jeff Thompson3d613fd2013-10-15 15:39:04 -070051 // If nothing can be done with STL library, define NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE,
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070052 // but beware: lexical_cast will understand only 'C' locale delimeters and thousands
53 // separators.
Jeff Thompson3d613fd2013-10-15 15:39:04 -070054# error "Unable to use <locale> header. Define NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE to force "
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070055# error "ndnboost::lexical_cast to use only 'C' locale during conversions."
56# endif
57#endif
58
Jeff Thompson3d613fd2013-10-15 15:39:04 -070059#ifdef NDNBOOST_NO_STRINGSTREAM
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070060#include <strstream>
61#else
62#include <sstream>
63#endif
64
Jeff Thompson3d613fd2013-10-15 15:39:04 -070065#ifdef NDNBOOST_NO_TYPEID
66#define NDNBOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070067#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -070068#define NDNBOOST_LCAST_THROW_BAD_CAST(Source, Target) \
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070069 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
70#endif
71
Jeff Thompson3d613fd2013-10-15 15:39:04 -070072#if (defined(NDNBOOST_LCAST_HAS_INT128) && !defined(__GNUC__)) || GCC_VERSION > 40700
73#define NDNBOOST_LCAST_HAS_INT128
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070074#endif
75
76
77namespace ndnboost
78{
79 // exception used to indicate runtime lexical_cast failure
Jeff Thompson3d613fd2013-10-15 15:39:04 -070080 class NDNBOOST_SYMBOL_VISIBLE bad_lexical_cast :
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070081 // workaround MSVC bug with std::bad_cast when _HAS_EXCEPTIONS == 0
Jeff Thompson3d613fd2013-10-15 15:39:04 -070082#if defined(NDNBOOST_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070083 public std::exception
84#else
85 public std::bad_cast
86#endif
87
Jeff Thompson3d613fd2013-10-15 15:39:04 -070088#if defined(__BORLANDC__) && NDNBOOST_WORKAROUND( __BORLANDC__, < 0x560 )
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070089 // under bcc32 5.5.1 bad_cast doesn't derive from exception
90 , public std::exception
91#endif
92
93 {
94 public:
Jeff Thompson3d613fd2013-10-15 15:39:04 -070095 bad_lexical_cast() NDNBOOST_NOEXCEPT :
96#ifndef NDNBOOST_NO_TYPEID
Jeff Thompsonef2d5a42013-08-22 19:09:24 -070097 source(&typeid(void)), target(&typeid(void))
98#else
99 source(0), target(0) // this breaks getters
100#endif
101 {
102 }
103
104 bad_lexical_cast(
105 const std::type_info &source_type_arg,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700106 const std::type_info &target_type_arg) NDNBOOST_NOEXCEPT :
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700107 source(&source_type_arg), target(&target_type_arg)
108 {
109 }
110
111 const std::type_info &source_type() const
112 {
113 return *source;
114 }
115 const std::type_info &target_type() const
116 {
117 return *target;
118 }
119
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700120#ifndef NDNBOOST_NO_CXX11_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700121 virtual const char *what() const noexcept
122#else
123 virtual const char *what() const throw()
124#endif
125 {
126 return "bad lexical cast: "
127 "source type value could not be interpreted as target";
128 }
129
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700130#ifndef NDNBOOST_NO_CXX11_NOEXCEPT
131 virtual ~bad_lexical_cast() NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700132#else
133 virtual ~bad_lexical_cast() throw()
134#endif
135 {}
136 private:
137 const std::type_info *source;
138 const std::type_info *target;
139 };
140
141 namespace detail // widest_char
142 {
143 template <typename TargetChar, typename SourceChar>
144 struct widest_char
145 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700146 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700147 (sizeof(TargetChar) > sizeof(SourceChar))
148 , TargetChar
149 , SourceChar >::type type;
150 };
151 }
152} // namespace ndnboost
153
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700154#if !defined(NDNBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) && !defined(__PGIC__)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700155
156#include <cmath>
157#include <istream>
158
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700159#ifndef NDNBOOST_NO_CXX11_HDR_ARRAY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700160#include <array>
161#endif
162
163#include <ndnboost/array.hpp>
164#include <ndnboost/numeric/conversion/cast.hpp>
165#include <ndnboost/type_traits/make_unsigned.hpp>
166#include <ndnboost/type_traits/is_signed.hpp>
167#include <ndnboost/type_traits/is_integral.hpp>
168#include <ndnboost/type_traits/is_arithmetic.hpp>
169#include <ndnboost/type_traits/remove_pointer.hpp>
170#include <ndnboost/type_traits/has_left_shift.hpp>
171#include <ndnboost/type_traits/has_right_shift.hpp>
172#include <ndnboost/math/special_functions/sign.hpp>
173#include <ndnboost/math/special_functions/fpclassify.hpp>
174#include <ndnboost/range/iterator_range_core.hpp>
175#include <ndnboost/container/container_fwd.hpp>
176#include <ndnboost/integer.hpp>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700177#ifndef NDNBOOST_NO_CWCHAR
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700178# include <cwchar>
179#endif
180
181namespace ndnboost {
182
183 namespace detail // is_char_or_wchar<...>
184 {
185 // returns true, if T is one of the character types
186 template < typename T >
187 struct is_char_or_wchar
188 {
189 typedef ndnboost::type_traits::ice_or<
190 ndnboost::is_same< T, char >::value,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700191 #ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700192 ndnboost::is_same< T, wchar_t >::value,
193 #endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700194 #ifndef NDNBOOST_NO_CXX11_CHAR16_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700195 ndnboost::is_same< T, char16_t >::value,
196 #endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700197 #ifndef NDNBOOST_NO_CXX11_CHAR32_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700198 ndnboost::is_same< T, char32_t >::value,
199 #endif
200 ndnboost::is_same< T, unsigned char >::value,
201 ndnboost::is_same< T, signed char >::value
202 > result_type;
203
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700204 NDNBOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700205 };
206 }
207
208 namespace detail // normalize_single_byte_char<Char>
209 {
210 // Converts signed/unsigned char to char
211 template < class Char >
212 struct normalize_single_byte_char
213 {
214 typedef Char type;
215 };
216
217 template <>
218 struct normalize_single_byte_char< signed char >
219 {
220 typedef char type;
221 };
222
223 template <>
224 struct normalize_single_byte_char< unsigned char >
225 {
226 typedef char type;
227 };
228 }
229
230 namespace detail // deduce_character_type_later<T>
231 {
232 // Helper type, meaning that stram character for T must be deduced
233 // at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
234 template < class T > struct deduce_character_type_later {};
235 }
236
237 namespace detail // stream_char_common<T>
238 {
239 // Selectors to choose stream character type (common for Source and Target)
240 // Returns one of char, wchar_t, char16_t, char32_t or deduce_character_type_later<T> types
241 // Executed on Stage 1 (See deduce_source_char<T> and deduce_target_char<T>)
242 template < typename Type >
243 struct stream_char_common: public ndnboost::mpl::if_c<
244 ndnboost::detail::is_char_or_wchar< Type >::value,
245 Type,
246 ndnboost::detail::deduce_character_type_later< Type >
247 > {};
248
249 template < typename Char >
250 struct stream_char_common< Char* >: public ndnboost::mpl::if_c<
251 ndnboost::detail::is_char_or_wchar< Char >::value,
252 Char,
253 ndnboost::detail::deduce_character_type_later< Char* >
254 > {};
255
256 template < typename Char >
257 struct stream_char_common< const Char* >: public ndnboost::mpl::if_c<
258 ndnboost::detail::is_char_or_wchar< Char >::value,
259 Char,
260 ndnboost::detail::deduce_character_type_later< const Char* >
261 > {};
262
263 template < typename Char >
264 struct stream_char_common< ndnboost::iterator_range< Char* > >: public ndnboost::mpl::if_c<
265 ndnboost::detail::is_char_or_wchar< Char >::value,
266 Char,
267 ndnboost::detail::deduce_character_type_later< ndnboost::iterator_range< Char* > >
268 > {};
269
270 template < typename Char >
271 struct stream_char_common< ndnboost::iterator_range< const Char* > >: public ndnboost::mpl::if_c<
272 ndnboost::detail::is_char_or_wchar< Char >::value,
273 Char,
274 ndnboost::detail::deduce_character_type_later< ndnboost::iterator_range< const Char* > >
275 > {};
276
277 template < class Char, class Traits, class Alloc >
278 struct stream_char_common< std::basic_string< Char, Traits, Alloc > >
279 {
280 typedef Char type;
281 };
282
283 template < class Char, class Traits, class Alloc >
284 struct stream_char_common< ndnboost::container::basic_string< Char, Traits, Alloc > >
285 {
286 typedef Char type;
287 };
288
289 template < typename Char, std::size_t N >
290 struct stream_char_common< ndnboost::array< Char, N > >: public ndnboost::mpl::if_c<
291 ndnboost::detail::is_char_or_wchar< Char >::value,
292 Char,
293 ndnboost::detail::deduce_character_type_later< ndnboost::array< Char, N > >
294 > {};
295
296 template < typename Char, std::size_t N >
297 struct stream_char_common< ndnboost::array< const Char, N > >: public ndnboost::mpl::if_c<
298 ndnboost::detail::is_char_or_wchar< Char >::value,
299 Char,
300 ndnboost::detail::deduce_character_type_later< ndnboost::array< const Char, N > >
301 > {};
302
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700303#ifndef NDNBOOST_NO_CXX11_HDR_ARRAY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700304 template < typename Char, std::size_t N >
305 struct stream_char_common< std::array<Char, N > >: public ndnboost::mpl::if_c<
306 ndnboost::detail::is_char_or_wchar< Char >::value,
307 Char,
308 ndnboost::detail::deduce_character_type_later< std::array< Char, N > >
309 > {};
310
311 template < typename Char, std::size_t N >
312 struct stream_char_common< std::array< const Char, N > >: public ndnboost::mpl::if_c<
313 ndnboost::detail::is_char_or_wchar< Char >::value,
314 Char,
315 ndnboost::detail::deduce_character_type_later< std::array< const Char, N > >
316 > {};
317#endif
318
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700319#ifdef NDNBOOST_LCAST_HAS_INT128
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700320 template <> struct stream_char_common< ndnboost::int128_type >: public ndnboost::mpl::identity< char > {};
321 template <> struct stream_char_common< ndnboost::uint128_type >: public ndnboost::mpl::identity< char > {};
322#endif
323
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700324#if !defined(NDNBOOST_LCAST_NO_WCHAR_T) && defined(NDNBOOST_NO_INTRINSIC_WCHAR_T)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700325 template <>
326 struct stream_char_common< wchar_t >
327 {
328 typedef char type;
329 };
330#endif
331 }
332
333 namespace detail // deduce_source_char_impl<T>
334 {
335 // If type T is `deduce_character_type_later` type, then tries to deduce
336 // character type using ndnboost::has_left_shift<T> metafunction.
337 // Otherwise supplied type T is a character type, that must be normalized
338 // using normalize_single_byte_char<Char>.
339 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
340 template < class Char >
341 struct deduce_source_char_impl
342 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700343 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::normalize_single_byte_char< Char >::type type;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700344 };
345
346 template < class T >
347 struct deduce_source_char_impl< deduce_character_type_later< T > >
348 {
349 typedef ndnboost::has_left_shift< std::basic_ostream< char >, T > result_t;
350
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700351#if defined(NDNBOOST_LCAST_NO_WCHAR_T)
352 NDNBOOST_STATIC_ASSERT_MSG((result_t::value),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700353 "Source type is not std::ostream`able and std::wostream`s are not supported by your STL implementation");
354 typedef char type;
355#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700356 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700357 result_t::value, char, wchar_t
358 >::type type;
359
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700360 NDNBOOST_STATIC_ASSERT_MSG((result_t::value || ndnboost::has_left_shift< std::basic_ostream< type >, T >::value),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700361 "Source type is neither std::ostream`able nor std::wostream`able");
362#endif
363 };
364 }
365
366 namespace detail // deduce_target_char_impl<T>
367 {
368 // If type T is `deduce_character_type_later` type, then tries to deduce
369 // character type using ndnboost::has_right_shift<T> metafunction.
370 // Otherwise supplied type T is a character type, that must be normalized
371 // using normalize_single_byte_char<Char>.
372 // Executed at Stage 2 (See deduce_source_char<T> and deduce_target_char<T>)
373 template < class Char >
374 struct deduce_target_char_impl
375 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700376 typedef NDNBOOST_DEDUCED_TYPENAME normalize_single_byte_char< Char >::type type;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700377 };
378
379 template < class T >
380 struct deduce_target_char_impl< deduce_character_type_later<T> >
381 {
382 typedef ndnboost::has_right_shift<std::basic_istream<char>, T > result_t;
383
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700384#if defined(NDNBOOST_LCAST_NO_WCHAR_T)
385 NDNBOOST_STATIC_ASSERT_MSG((result_t::value),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700386 "Target type is not std::istream`able and std::wistream`s are not supported by your STL implementation");
387 typedef char type;
388#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700389 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700390 result_t::value, char, wchar_t
391 >::type type;
392
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700393 NDNBOOST_STATIC_ASSERT_MSG((result_t::value || ndnboost::has_right_shift<std::basic_istream<wchar_t>, T >::value),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700394 "Target type is neither std::istream`able nor std::wistream`able");
395#endif
396 };
397 }
398
399 namespace detail // deduce_target_char<T> and deduce_source_char<T>
400 {
401 // We deduce stream character types in two stages.
402 //
403 // Stage 1 is common for Target and Source. At Stage 1 we get
404 // non normalized character type (may contain unsigned/signed char)
405 // or deduce_character_type_later<T> where T is the original type.
406 // Stage 1 is executed by stream_char_common<T>
407 //
408 // At Stage 2 we normalize character types or try to deduce character
409 // type using metafunctions.
410 // Stage 2 is executed by deduce_target_char_impl<T> and
411 // deduce_source_char_impl<T>
412 //
413 // deduce_target_char<T> and deduce_source_char<T> functions combine
414 // both stages
415
416 template < class T >
417 struct deduce_target_char
418 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700419 typedef NDNBOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
420 typedef NDNBOOST_DEDUCED_TYPENAME deduce_target_char_impl< stage1_type >::type stage2_type;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700421
422 typedef stage2_type type;
423 };
424
425 template < class T >
426 struct deduce_source_char
427 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700428 typedef NDNBOOST_DEDUCED_TYPENAME stream_char_common< T >::type stage1_type;
429 typedef NDNBOOST_DEDUCED_TYPENAME deduce_source_char_impl< stage1_type >::type stage2_type;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700430
431 typedef stage2_type type;
432 };
433 }
434
435 namespace detail // deduce_char_traits template
436 {
437 // We are attempting to get char_traits<> from Source or Tagret
438 // template parameter. Otherwise we'll be using std::char_traits<Char>
439 template < class Char, class Target, class Source >
440 struct deduce_char_traits
441 {
442 typedef std::char_traits< Char > type;
443 };
444
445 template < class Char, class Traits, class Alloc, class Source >
446 struct deduce_char_traits< Char
447 , std::basic_string< Char, Traits, Alloc >
448 , Source
449 >
450 {
451 typedef Traits type;
452 };
453
454 template < class Char, class Target, class Traits, class Alloc >
455 struct deduce_char_traits< Char
456 , Target
457 , std::basic_string< Char, Traits, Alloc >
458 >
459 {
460 typedef Traits type;
461 };
462
463 template < class Char, class Traits, class Alloc, class Source >
464 struct deduce_char_traits< Char
465 , ndnboost::container::basic_string< Char, Traits, Alloc >
466 , Source
467 >
468 {
469 typedef Traits type;
470 };
471
472 template < class Char, class Target, class Traits, class Alloc >
473 struct deduce_char_traits< Char
474 , Target
475 , ndnboost::container::basic_string< Char, Traits, Alloc >
476 >
477 {
478 typedef Traits type;
479 };
480
481 template < class Char, class Traits, class Alloc1, class Alloc2 >
482 struct deduce_char_traits< Char
483 , std::basic_string< Char, Traits, Alloc1 >
484 , std::basic_string< Char, Traits, Alloc2 >
485 >
486 {
487 typedef Traits type;
488 };
489
490 template<class Char, class Traits, class Alloc1, class Alloc2>
491 struct deduce_char_traits< Char
492 , ndnboost::container::basic_string< Char, Traits, Alloc1 >
493 , ndnboost::container::basic_string< Char, Traits, Alloc2 >
494 >
495 {
496 typedef Traits type;
497 };
498
499 template < class Char, class Traits, class Alloc1, class Alloc2 >
500 struct deduce_char_traits< Char
501 , ndnboost::container::basic_string< Char, Traits, Alloc1 >
502 , std::basic_string< Char, Traits, Alloc2 >
503 >
504 {
505 typedef Traits type;
506 };
507
508 template < class Char, class Traits, class Alloc1, class Alloc2 >
509 struct deduce_char_traits< Char
510 , std::basic_string< Char, Traits, Alloc1 >
511 , ndnboost::container::basic_string< Char, Traits, Alloc2 >
512 >
513 {
514 typedef Traits type;
515 };
516 }
517
518 namespace detail // array_to_pointer_decay<T>
519 {
520 template<class T>
521 struct array_to_pointer_decay
522 {
523 typedef T type;
524 };
525
526 template<class T, std::size_t N>
527 struct array_to_pointer_decay<T[N]>
528 {
529 typedef const T * type;
530 };
531 }
532
533 namespace detail // is_this_float_conversion_optimized<Float, Char>
534 {
535 // this metafunction evaluates to true, if we have optimized comnversion
536 // from Float type to Char array.
537 // Must be in sync with lexical_stream_limited_src<Char, ...>::shl_real_type(...)
538 template <typename Float, typename Char>
539 struct is_this_float_conversion_optimized
540 {
541 typedef ndnboost::type_traits::ice_and<
542 ndnboost::is_float<Float>::value,
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700543#if !defined(NDNBOOST_LCAST_NO_WCHAR_T) && !defined(NDNBOOST_NO_SWPRINTF) && !defined(__MINGW32__)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700544 ndnboost::type_traits::ice_or<
545 ndnboost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value,
546 ndnboost::is_same<Char, wchar_t>::value
547 >::value
548#else
549 ndnboost::type_traits::ice_eq<sizeof(Char), sizeof(char) >::value
550#endif
551 > result_type;
552
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700553 NDNBOOST_STATIC_CONSTANT(bool, value = (result_type::value) );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700554 };
555 }
556
557 namespace detail // lcast_src_length
558 {
559 // Return max. length of string representation of Source;
560 template< class Source // Source type of lexical_cast.
561 >
562 struct lcast_src_length
563 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700564 NDNBOOST_STATIC_CONSTANT(std::size_t, value = 1);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700565 // To check coverage, build the test with
566 // bjam --v2 profile optimization=off
567 static void check_coverage() {}
568 };
569
570 // Helper for integral types.
571 // Notes on length calculation:
572 // Max length for 32bit int with grouping "\1" and thousands_sep ',':
573 // "-2,1,4,7,4,8,3,6,4,7"
574 // ^ - is_signed
575 // ^ - 1 digit not counted by digits10
576 // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
577 //
578 // Constant is_specialized is used instead of constant 1
579 // to prevent buffer overflow in a rare case when
580 // <ndnboost/limits.hpp> doesn't add missing specialization for
581 // numeric_limits<T> for some integral type T.
582 // When is_specialized is false, the whole expression is 0.
583 template<class Source>
584 struct lcast_src_length_integral
585 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700586#ifndef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
587 NDNBOOST_STATIC_CONSTANT(std::size_t, value =
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700588 std::numeric_limits<Source>::is_signed +
589 std::numeric_limits<Source>::is_specialized + /* == 1 */
590 std::numeric_limits<Source>::digits10 * 2
591 );
592#else
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700593 NDNBOOST_STATIC_CONSTANT(std::size_t, value = 156);
594 NDNBOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700595#endif
596 };
597
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700598#define NDNBOOST_LCAST_DEF(T) \
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700599 template<> struct lcast_src_length<T> \
600 : lcast_src_length_integral<T> \
601 { static void check_coverage() {} };
602
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700603 NDNBOOST_LCAST_DEF(short)
604 NDNBOOST_LCAST_DEF(unsigned short)
605 NDNBOOST_LCAST_DEF(int)
606 NDNBOOST_LCAST_DEF(unsigned int)
607 NDNBOOST_LCAST_DEF(long)
608 NDNBOOST_LCAST_DEF(unsigned long)
609#if defined(NDNBOOST_HAS_LONG_LONG)
610 NDNBOOST_LCAST_DEF(ndnboost::ulong_long_type)
611 NDNBOOST_LCAST_DEF(ndnboost::long_long_type )
612#elif defined(NDNBOOST_HAS_MS_INT64)
613 NDNBOOST_LCAST_DEF(unsigned __int64)
614 NDNBOOST_LCAST_DEF( __int64)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700615#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700616#ifdef NDNBOOST_LCAST_HAS_INT128
617 NDNBOOST_LCAST_DEF(ndnboost::int128_type)
618 NDNBOOST_LCAST_DEF(ndnboost::uint128_type)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700619#endif
620
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700621#undef NDNBOOST_LCAST_DEF
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700622
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700623#ifndef NDNBOOST_LCAST_NO_COMPILE_TIME_PRECISION
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700624 // Helper for floating point types.
625 // -1.23456789e-123456
626 // ^ sign
627 // ^ leading digit
628 // ^ decimal point
629 // ^^^^^^^^ lcast_precision<Source>::value
630 // ^ "e"
631 // ^ exponent sign
632 // ^^^^^^ exponent (assumed 6 or less digits)
633 // sign + leading digit + decimal point + "e" + exponent sign == 5
634 template<class Source>
635 struct lcast_src_length_floating
636 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700637 NDNBOOST_STATIC_ASSERT(
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700638 std::numeric_limits<Source>::max_exponent10 <= 999999L &&
639 std::numeric_limits<Source>::min_exponent10 >= -999999L
640 );
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700641 NDNBOOST_STATIC_CONSTANT(std::size_t, value =
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700642 5 + lcast_precision<Source>::value + 6
643 );
644 };
645
646 template<>
647 struct lcast_src_length<float>
648 : lcast_src_length_floating<float>
649 {
650 static void check_coverage() {}
651 };
652
653 template<>
654 struct lcast_src_length<double>
655 : lcast_src_length_floating<double>
656 {
657 static void check_coverage() {}
658 };
659
660 template<>
661 struct lcast_src_length<long double>
662 : lcast_src_length_floating<long double>
663 {
664 static void check_coverage() {}
665 };
666
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700667#endif // #ifndef NDNBOOST_LCAST_NO_COMPILE_TIME_PRECISION
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700668 }
669
670 namespace detail // lexical_cast_stream_traits<Source, Target>
671 {
672 template <class Source, class Target>
673 struct lexical_cast_stream_traits {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700674 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::array_to_pointer_decay<Source>::type src;
675 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::remove_cv<src>::type no_cv_src;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700676
677 typedef ndnboost::detail::deduce_source_char<no_cv_src> deduce_src_char_metafunc;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700678 typedef NDNBOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::type src_char_t;
679 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::deduce_target_char<Target>::type target_char_t;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700680
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700681 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::widest_char<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700682 target_char_t, src_char_t
683 >::type char_type;
684
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700685#if !defined(NDNBOOST_NO_CXX11_CHAR16_T) && defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
686 NDNBOOST_STATIC_ASSERT_MSG(( !ndnboost::is_same<char16_t, src_char_t>::value
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700687 && !ndnboost::is_same<char16_t, target_char_t>::value),
688 "Your compiler does not have full support for char16_t" );
689#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700690#if !defined(NDNBOOST_NO_CXX11_CHAR32_T) && defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
691 NDNBOOST_STATIC_ASSERT_MSG(( !ndnboost::is_same<char32_t, src_char_t>::value
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700692 && !ndnboost::is_same<char32_t, target_char_t>::value),
693 "Your compiler does not have full support for char32_t" );
694#endif
695
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700696 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::deduce_char_traits<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700697 char_type, Target, no_cv_src
698 >::type traits;
699
700 typedef ndnboost::type_traits::ice_and<
701 ndnboost::is_same<char, src_char_t>::value, // source is not a wide character based type
702 ndnboost::type_traits::ice_ne<sizeof(char), sizeof(target_char_t) >::value, // target type is based on wide character
703 ndnboost::type_traits::ice_not<
704 ndnboost::detail::is_char_or_wchar<no_cv_src>::value // single character widening is optimized
705 >::value // and does not requires stringbuffer
706 > is_string_widening_required_t;
707
708 typedef ndnboost::type_traits::ice_not< ndnboost::type_traits::ice_or<
709 ndnboost::is_integral<no_cv_src>::value,
710 ndnboost::detail::is_this_float_conversion_optimized<no_cv_src, char_type >::value,
711 ndnboost::detail::is_char_or_wchar<
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700712 NDNBOOST_DEDUCED_TYPENAME deduce_src_char_metafunc::stage1_type // if we did not get character type at stage1
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700713 >::value // then we have no optimization for that type
714 >::value > is_source_input_not_optimized_t;
715
716 // If we have an optimized conversion for
717 // Source, we do not need to construct stringbuf.
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700718 NDNBOOST_STATIC_CONSTANT(bool, requires_stringbuf =
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700719 (ndnboost::type_traits::ice_or<
720 is_string_widening_required_t::value, is_source_input_not_optimized_t::value
721 >::value)
722 );
723
724 typedef ndnboost::detail::lcast_src_length<no_cv_src> len_t;
725 };
726 }
727
728 namespace detail // '0', '+' and '-' constants
729 {
730 template < typename Char > struct lcast_char_constants;
731
732 template<>
733 struct lcast_char_constants<char>
734 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700735 NDNBOOST_STATIC_CONSTANT(char, zero = '0');
736 NDNBOOST_STATIC_CONSTANT(char, minus = '-');
737 NDNBOOST_STATIC_CONSTANT(char, plus = '+');
738 NDNBOOST_STATIC_CONSTANT(char, lowercase_e = 'e');
739 NDNBOOST_STATIC_CONSTANT(char, capital_e = 'E');
740 NDNBOOST_STATIC_CONSTANT(char, c_decimal_separator = '.');
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700741 };
742
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700743#ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700744 template<>
745 struct lcast_char_constants<wchar_t>
746 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700747 NDNBOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
748 NDNBOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
749 NDNBOOST_STATIC_CONSTANT(wchar_t, plus = L'+');
750 NDNBOOST_STATIC_CONSTANT(wchar_t, lowercase_e = L'e');
751 NDNBOOST_STATIC_CONSTANT(wchar_t, capital_e = L'E');
752 NDNBOOST_STATIC_CONSTANT(wchar_t, c_decimal_separator = L'.');
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700753 };
754#endif
755
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700756#if !defined(NDNBOOST_NO_CXX11_CHAR16_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700757 template<>
758 struct lcast_char_constants<char16_t>
759 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700760 NDNBOOST_STATIC_CONSTANT(char16_t, zero = u'0');
761 NDNBOOST_STATIC_CONSTANT(char16_t, minus = u'-');
762 NDNBOOST_STATIC_CONSTANT(char16_t, plus = u'+');
763 NDNBOOST_STATIC_CONSTANT(char16_t, lowercase_e = u'e');
764 NDNBOOST_STATIC_CONSTANT(char16_t, capital_e = u'E');
765 NDNBOOST_STATIC_CONSTANT(char16_t, c_decimal_separator = u'.');
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700766 };
767#endif
768
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700769#if !defined(NDNBOOST_NO_CXX11_CHAR32_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700770 template<>
771 struct lcast_char_constants<char32_t>
772 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700773 NDNBOOST_STATIC_CONSTANT(char32_t, zero = U'0');
774 NDNBOOST_STATIC_CONSTANT(char32_t, minus = U'-');
775 NDNBOOST_STATIC_CONSTANT(char32_t, plus = U'+');
776 NDNBOOST_STATIC_CONSTANT(char32_t, lowercase_e = U'e');
777 NDNBOOST_STATIC_CONSTANT(char32_t, capital_e = U'E');
778 NDNBOOST_STATIC_CONSTANT(char32_t, c_decimal_separator = U'.');
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700779 };
780#endif
781 }
782
783 namespace detail // lcast_to_unsigned
784 {
785 template<class T>
786 inline
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700787 NDNBOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700788 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700789 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::make_unsigned<T>::type result_type;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700790 return static_cast<result_type>(
791 value < 0 ? 0u - static_cast<result_type>(value) : value
792 );
793 }
794 }
795
796 namespace detail // lcast_put_unsigned
797 {
798 template<class Traits, class T, class CharT>
799 CharT* lcast_put_unsigned(const T n_param, CharT* finish)
800 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700801#ifndef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
802 NDNBOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700803#endif
804
805 typedef typename Traits::int_type int_type;
806 CharT const czero = lcast_char_constants<CharT>::zero;
807 int_type const zero = Traits::to_int_type(czero);
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700808 NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700809 (sizeof(int_type) > sizeof(T))
810 , int_type
811 , T
812 >::type n = n_param;
813
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700814#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700815 std::locale loc;
816 if (loc != std::locale::classic()) {
817 typedef std::numpunct<CharT> numpunct;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700818 numpunct const& np = NDNBOOST_USE_FACET(numpunct, loc);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700819 std::string const grouping = np.grouping();
820 std::string::size_type const grouping_size = grouping.size();
821
822 if ( grouping_size && grouping[0] > 0 )
823 {
824
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700825#ifndef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700826 // Check that ulimited group is unreachable:
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700827 NDNBOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700828#endif
829 CharT thousands_sep = np.thousands_sep();
830 std::string::size_type group = 0; // current group number
831 char last_grp_size = grouping[0];
832 char left = last_grp_size;
833
834 do
835 {
836 if(left == 0)
837 {
838 ++group;
839 if(group < grouping_size)
840 {
841 char const grp_size = grouping[group];
842 last_grp_size = grp_size <= 0 ? static_cast<char>(CHAR_MAX) : grp_size;
843 }
844
845 left = last_grp_size;
846 --finish;
847 Traits::assign(*finish, thousands_sep);
848 }
849
850 --left;
851
852 --finish;
853 int_type const digit = static_cast<int_type>(n % 10U);
854 Traits::assign(*finish, Traits::to_char_type(zero + digit));
855 n /= 10;
856 } while(n);
857 return finish;
858 }
859 }
860#endif
861 {
862 do
863 {
864 --finish;
865 int_type const digit = static_cast<int_type>(n % 10U);
866 Traits::assign(*finish, Traits::to_char_type(zero + digit));
867 n /= 10;
868 } while(n);
869 }
870
871 return finish;
872 }
873 }
874
875 namespace detail // lcast_ret_unsigned
876 {
877 template<class Traits, class T, class CharT>
878 inline bool lcast_ret_unsigned(T& value, const CharT* const begin, const CharT* end)
879 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700880#ifndef NDNBOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
881 NDNBOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700882#endif
883 CharT const czero = lcast_char_constants<CharT>::zero;
884 --end;
885 value = 0;
886
887 if (begin > end || *end < czero || *end >= czero + 10)
888 return false;
889 value = static_cast<T>(*end - czero);
890 --end;
891 T multiplier = 1;
892 bool multiplier_overflowed = false;
893
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700894#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700895 std::locale loc;
896 if (loc != std::locale::classic()) {
897 typedef std::numpunct<CharT> numpunct;
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700898 numpunct const& np = NDNBOOST_USE_FACET(numpunct, loc);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700899 std::string const& grouping = np.grouping();
900 std::string::size_type const grouping_size = grouping.size();
901
902 /* According to Programming languages - C++
903 * we MUST check for correct grouping
904 */
905 if (grouping_size && grouping[0] > 0)
906 {
907 unsigned char current_grouping = 0;
908 CharT const thousands_sep = np.thousands_sep();
909 char remained = static_cast<char>(grouping[current_grouping] - 1);
910 bool shall_we_return = true;
911
912 for(;end>=begin; --end)
913 {
914 if (remained) {
915 T const multiplier_10 = static_cast<T>(multiplier * 10);
916 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
917
918 T const dig_value = static_cast<T>(*end - czero);
919 T const new_sub_value = static_cast<T>(multiplier_10 * dig_value);
920
921 if (*end < czero || *end >= czero + 10
922 /* detecting overflow */
923 || (dig_value && new_sub_value / dig_value != multiplier_10)
924 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
925 || (multiplier_overflowed && dig_value)
926 )
927 return false;
928
929 value = static_cast<T>(value + new_sub_value);
930 multiplier = static_cast<T>(multiplier * 10);
931 --remained;
932 } else {
933 if ( !Traits::eq(*end, thousands_sep) ) //|| begin == end ) return false;
934 {
935 /*
936 * According to Programming languages - C++
937 * Digit grouping is checked. That is, the positions of discarded
938 * separators is examined for consistency with
939 * use_facet<numpunct<charT> >(loc ).grouping()
940 *
941 * BUT what if there is no separators at all and grouping()
942 * is not empty? Well, we have no extraced separators, so we
943 * won`t check them for consistency. This will allow us to
944 * work with "C" locale from other locales
945 */
946 shall_we_return = false;
947 break;
948 } else {
949 if ( begin == end ) return false;
950 if (current_grouping < grouping_size-1 ) ++current_grouping;
951 remained = grouping[current_grouping];
952 }
953 }
954 }
955
956 if (shall_we_return) return true;
957 }
958 }
959#endif
960 {
961 while ( begin <= end )
962 {
963 T const multiplier_10 = static_cast<T>(multiplier * 10);
964 if (multiplier_10 / 10 != multiplier) multiplier_overflowed = true;
965
966 T const dig_value = static_cast<T>(*end - czero);
967 T const new_sub_value = static_cast<T>(multiplier_10 * dig_value);
968
969 if (*end < czero || *end >= czero + 10
970 /* detecting overflow */
971 || (dig_value && new_sub_value / dig_value != multiplier_10)
972 || static_cast<T>((std::numeric_limits<T>::max)()-new_sub_value) < value
973 || (multiplier_overflowed && dig_value)
974 )
975 return false;
976
977 value = static_cast<T>(value + new_sub_value);
978 multiplier = static_cast<T>(multiplier * 10);
979 --end;
980 }
981 }
982 return true;
983 }
984 }
985
986 namespace detail
987 {
988 template <class CharT>
Jeff Thompson3d613fd2013-10-15 15:39:04 -0700989 bool lc_iequal(const CharT* val, const CharT* lcase, const CharT* ucase, unsigned int len) NDNBOOST_NOEXCEPT {
Jeff Thompsonef2d5a42013-08-22 19:09:24 -0700990 for( unsigned int i=0; i < len; ++i ) {
991 if ( val[i] != lcase[i] && val[i] != ucase[i] ) return false;
992 }
993
994 return true;
995 }
996
997 /* Returns true and sets the correct value if found NaN or Inf. */
998 template <class CharT, class T>
999 inline bool parse_inf_nan_impl(const CharT* begin, const CharT* end, T& value
1000 , const CharT* lc_NAN, const CharT* lc_nan
1001 , const CharT* lc_INFINITY, const CharT* lc_infinity
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001002 , const CharT opening_brace, const CharT closing_brace) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001003 {
1004 using namespace std;
1005 if (begin == end) return false;
1006 const CharT minus = lcast_char_constants<CharT>::minus;
1007 const CharT plus = lcast_char_constants<CharT>::plus;
1008 const int inifinity_size = 8;
1009
1010 bool has_minus = false;
1011 /* Parsing +/- */
1012 if( *begin == minus)
1013 {
1014 ++ begin;
1015 has_minus = true;
1016 }
1017 else if( *begin == plus ) ++begin;
1018
1019 if( end-begin < 3 ) return false;
1020 if( lc_iequal(begin, lc_nan, lc_NAN, 3) )
1021 {
1022 begin += 3;
1023 if (end != begin) /* It is 'nan(...)' or some bad input*/
1024 {
1025 if(end-begin<2) return false; // bad input
1026 -- end;
1027 if( *begin != opening_brace || *end != closing_brace) return false; // bad input
1028 }
1029
1030 if( !has_minus ) value = std::numeric_limits<T>::quiet_NaN();
1031 else value = (ndnboost::math::changesign) (std::numeric_limits<T>::quiet_NaN());
1032 return true;
1033 } else
1034 if (( /* 'INF' or 'inf' */
1035 end-begin==3
1036 &&
1037 lc_iequal(begin, lc_infinity, lc_INFINITY, 3)
1038 )
1039 ||
1040 ( /* 'INFINITY' or 'infinity' */
1041 end-begin==inifinity_size
1042 &&
1043 lc_iequal(begin, lc_infinity, lc_INFINITY, inifinity_size)
1044 )
1045 )
1046 {
1047 if( !has_minus ) value = std::numeric_limits<T>::infinity();
1048 else value = (ndnboost::math::changesign) (std::numeric_limits<T>::infinity());
1049 return true;
1050 }
1051
1052 return false;
1053 }
1054
1055 template <class CharT, class T>
1056 bool put_inf_nan_impl(CharT* begin, CharT*& end, const T& value
1057 , const CharT* lc_nan
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001058 , const CharT* lc_infinity) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001059 {
1060 using namespace std;
1061 const CharT minus = lcast_char_constants<CharT>::minus;
1062 if ( (ndnboost::math::isnan)(value) )
1063 {
1064 if ( (ndnboost::math::signbit)(value) )
1065 {
1066 *begin = minus;
1067 ++ begin;
1068 }
1069
1070 memcpy(begin, lc_nan, 3 * sizeof(CharT));
1071 end = begin + 3;
1072 return true;
1073 } else if ( (ndnboost::math::isinf)(value) )
1074 {
1075 if ( (ndnboost::math::signbit)(value) )
1076 {
1077 *begin = minus;
1078 ++ begin;
1079 }
1080
1081 memcpy(begin, lc_infinity, 3 * sizeof(CharT));
1082 end = begin + 3;
1083 return true;
1084 }
1085
1086 return false;
1087 }
1088
1089
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001090#ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001091 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001092 bool parse_inf_nan(const wchar_t* begin, const wchar_t* end, T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001093 {
1094 return parse_inf_nan_impl(begin, end, value
1095 , L"NAN", L"nan"
1096 , L"INFINITY", L"infinity"
1097 , L'(', L')');
1098 }
1099
1100 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001101 bool put_inf_nan(wchar_t* begin, wchar_t*& end, const T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001102 {
1103 return put_inf_nan_impl(begin, end, value, L"nan", L"infinity");
1104 }
1105
1106#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001107#if !defined(NDNBOOST_NO_CXX11_CHAR16_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001108 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001109 bool parse_inf_nan(const char16_t* begin, const char16_t* end, T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001110 {
1111 return parse_inf_nan_impl(begin, end, value
1112 , u"NAN", u"nan"
1113 , u"INFINITY", u"infinity"
1114 , u'(', u')');
1115 }
1116
1117 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001118 bool put_inf_nan(char16_t* begin, char16_t*& end, const T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001119 {
1120 return put_inf_nan_impl(begin, end, value, u"nan", u"infinity");
1121 }
1122#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001123#if !defined(NDNBOOST_NO_CXX11_CHAR32_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001124 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001125 bool parse_inf_nan(const char32_t* begin, const char32_t* end, T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001126 {
1127 return parse_inf_nan_impl(begin, end, value
1128 , U"NAN", U"nan"
1129 , U"INFINITY", U"infinity"
1130 , U'(', U')');
1131 }
1132
1133 template <class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001134 bool put_inf_nan(char32_t* begin, char32_t*& end, const T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001135 {
1136 return put_inf_nan_impl(begin, end, value, U"nan", U"infinity");
1137 }
1138#endif
1139
1140 template <class CharT, class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001141 bool parse_inf_nan(const CharT* begin, const CharT* end, T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001142 {
1143 return parse_inf_nan_impl(begin, end, value
1144 , "NAN", "nan"
1145 , "INFINITY", "infinity"
1146 , '(', ')');
1147 }
1148
1149 template <class CharT, class T>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001150 bool put_inf_nan(CharT* begin, CharT*& end, const T& value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001151 {
1152 return put_inf_nan_impl(begin, end, value, "nan", "infinity");
1153 }
1154 }
1155
1156
1157 namespace detail // lcast_ret_float
1158 {
1159
1160// Silence buggy MS warnings like C4244: '+=' : conversion from 'int' to 'unsigned short', possible loss of data
1161#if defined(_MSC_VER) && (_MSC_VER == 1400)
1162# pragma warning(push)
1163# pragma warning(disable:4244)
1164#endif
1165 template <class T>
1166 struct mantissa_holder_type
1167 {
1168 /* Can not be used with this type */
1169 };
1170
1171 template <>
1172 struct mantissa_holder_type<float>
1173 {
1174 typedef unsigned int type;
1175 typedef double wide_result_t;
1176 };
1177
1178 template <>
1179 struct mantissa_holder_type<double>
1180 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001181#ifndef NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001182 typedef long double wide_result_t;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001183#if defined(NDNBOOST_HAS_LONG_LONG)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001184 typedef ndnboost::ulong_long_type type;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001185#elif defined(NDNBOOST_HAS_MS_INT64)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001186 typedef unsigned __int64 type;
1187#endif
1188#endif
1189 };
1190
1191 template<class Traits, class T, class CharT>
1192 inline bool lcast_ret_float(T& value, const CharT* begin, const CharT* end)
1193 {
1194
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001195#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001196 std::locale loc;
1197 typedef std::numpunct<CharT> numpunct;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001198 numpunct const& np = NDNBOOST_USE_FACET(numpunct, loc);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001199 std::string const grouping(
1200 (loc == std::locale::classic())
1201 ? std::string()
1202 : np.grouping()
1203 );
1204 std::string::size_type const grouping_size = grouping.size();
1205 CharT const thousands_sep = static_cast<CharT>(grouping_size ? np.thousands_sep() : 0);
1206 CharT const decimal_point = np.decimal_point();
1207 bool found_grouping = false;
1208 std::string::size_type last_grouping_pos = grouping_size - 1;
1209#else
1210 CharT const decimal_point = lcast_char_constants<CharT>::c_decimal_separator;
1211#endif
1212
1213 CharT const czero = lcast_char_constants<CharT>::zero;
1214 CharT const minus = lcast_char_constants<CharT>::minus;
1215 CharT const plus = lcast_char_constants<CharT>::plus;
1216 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
1217 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
1218
1219 value = static_cast<T>(0);
1220
1221 if (parse_inf_nan(begin, end, value)) return true;
1222
1223 typedef typename Traits::int_type int_type;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001224 typedef NDNBOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::type mantissa_type;
1225 typedef NDNBOOST_DEDUCED_TYPENAME mantissa_holder_type<T>::wide_result_t wide_result_t;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001226 int_type const zero = Traits::to_int_type(czero);
1227 if (begin == end) return false;
1228
1229 /* Getting the plus/minus sign */
1230 bool has_minus = false;
1231 if (Traits::eq(*begin, minus) ) {
1232 ++ begin;
1233 has_minus = true;
1234 if (begin == end) return false;
1235 } else if (Traits::eq(*begin, plus) ) {
1236 ++begin;
1237 if (begin == end) return false;
1238 }
1239
1240 bool found_decimal = false;
1241 bool found_number_before_exp = false;
1242 int pow_of_10 = 0;
1243 mantissa_type mantissa=0;
1244 bool is_mantissa_full = false;
1245
1246 char length_since_last_delim = 0;
1247
1248 while ( begin != end )
1249 {
1250 if (found_decimal) {
1251 /* We allow no thousand_separators after decimal point */
1252
1253 mantissa_type tmp_mantissa = mantissa * 10u;
1254 if (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) break;
1255 if ( *begin < czero || *begin >= czero + 10 ) return false;
1256 if ( is_mantissa_full
1257 || tmp_mantissa / 10u != mantissa
1258 || (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) < tmp_mantissa
1259 ) {
1260 is_mantissa_full = true;
1261 ++ begin;
1262 continue;
1263 }
1264
1265 -- pow_of_10;
1266 mantissa = tmp_mantissa;
1267 mantissa += *begin - zero;
1268
1269 found_number_before_exp = true;
1270 } else {
1271
1272 if (*begin >= czero && *begin < czero + 10) {
1273
1274 /* Checking for mantissa overflow. If overflow will
1275 * occur, them we only increase multiplyer
1276 */
1277 mantissa_type tmp_mantissa = mantissa * 10u;
1278 if( !is_mantissa_full
1279 && tmp_mantissa / 10u == mantissa
1280 && (std::numeric_limits<mantissa_type>::max)()-(*begin - zero) >= tmp_mantissa
1281 )
1282 {
1283 mantissa = tmp_mantissa;
1284 mantissa += *begin - zero;
1285 } else
1286 {
1287 is_mantissa_full = true;
1288 ++ pow_of_10;
1289 }
1290
1291 found_number_before_exp = true;
1292 ++ length_since_last_delim;
1293 } else if (Traits::eq(*begin, decimal_point) || Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001294#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001295 /* If ( we need to check grouping
1296 * and ( grouping missmatches
1297 * or grouping position is incorrect
1298 * or we are using the grouping position 0 twice
1299 * )
1300 * ) then return error
1301 */
1302 if( grouping_size && found_grouping
1303 && (
1304 length_since_last_delim != grouping[0]
1305 || last_grouping_pos>1
1306 || (last_grouping_pos==0 && grouping_size>1)
1307 )
1308 ) return false;
1309#endif
1310
1311 if(Traits::eq(*begin, decimal_point)) {
1312 ++ begin;
1313 found_decimal = true;
1314 if (!found_number_before_exp && begin==end) return false;
1315 continue;
1316 }else {
1317 if (!found_number_before_exp) return false;
1318 break;
1319 }
1320 }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001321#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001322 else if (grouping_size && Traits::eq(*begin, thousands_sep)){
1323 if(found_grouping)
1324 {
1325 /* It is not he first time, when we find thousands separator,
1326 * so we need to chek, is the distance between two groupings
1327 * equal to grouping[last_grouping_pos] */
1328
1329 if (length_since_last_delim != grouping[last_grouping_pos] )
1330 {
1331 if (!last_grouping_pos) return false;
1332 else
1333 {
1334 -- last_grouping_pos;
1335 if (length_since_last_delim != grouping[last_grouping_pos]) return false;
1336 }
1337 } else
1338 /* We are calling the grouping[0] twice, when grouping size is more than 1 */
1339 if (grouping_size>1u && last_grouping_pos+1<grouping_size) return false;
1340
1341 } else {
1342 /* Delimiter at the begining ',000' */
1343 if (!length_since_last_delim) return false;
1344
1345 found_grouping = true;
1346 if (length_since_last_delim > grouping[last_grouping_pos] ) return false;
1347 }
1348
1349 length_since_last_delim = 0;
1350 ++ begin;
1351
1352 /* Delimiter at the end '100,' */
1353 if (begin == end) return false;
1354 continue;
1355 }
1356#endif
1357 else return false;
1358 }
1359
1360 ++begin;
1361 }
1362
1363 // Exponent found
1364 if ( begin != end && (Traits::eq(*begin, lowercase_e) || Traits::eq(*begin, capital_e)) ) {
1365 ++ begin;
1366 if ( begin == end ) return false;
1367
1368 bool exp_has_minus = false;
1369 if(Traits::eq(*begin, minus)) {
1370 exp_has_minus = true;
1371 ++ begin;
1372 if ( begin == end ) return false;
1373 } else if (Traits::eq(*begin, plus)) {
1374 ++ begin;
1375 if ( begin == end ) return false;
1376 }
1377
1378 int exp_pow_of_10 = 0;
1379 while ( begin != end )
1380 {
1381 if ( *begin < czero
1382 || *begin >= czero + 10
1383 || exp_pow_of_10 * 10 < exp_pow_of_10) /* Overflows are checked lower more precisely*/
1384 return false;
1385
1386 exp_pow_of_10 *= 10;
1387 exp_pow_of_10 += *begin - zero;
1388 ++ begin;
1389 };
1390
1391 if ( exp_pow_of_10 ) {
1392 /* Overflows are checked lower */
1393 if ( exp_has_minus ) {
1394 pow_of_10 -= exp_pow_of_10;
1395 } else {
1396 pow_of_10 += exp_pow_of_10;
1397 }
1398 }
1399 }
1400
1401 /* We need a more accurate algorithm... We can not use current algorithm
1402 * with long doubles (and with doubles if sizeof(double)==sizeof(long double)).
1403 */
1404 const wide_result_t result = std::pow(static_cast<wide_result_t>(10.0), pow_of_10) * mantissa;
1405 value = static_cast<T>( has_minus ? (ndnboost::math::changesign)(result) : result);
1406
1407 if ( (ndnboost::math::isinf)(value) || (ndnboost::math::isnan)(value) ) return false;
1408
1409 return true;
1410 }
1411// Unsilence buggy MS warnings like C4244: '+=' : conversion from 'int' to 'unsigned short', possible loss of data
1412#if defined(_MSC_VER) && (_MSC_VER == 1400)
1413# pragma warning(pop)
1414#endif
1415 }
1416
1417 namespace detail // parser_buf
1418 {
1419 //
1420 // class parser_buf:
1421 // acts as a stream buffer which wraps around a pair of pointers
1422 //
1423 // This class is copied (and slightly changed) from
Jeff Thompson9939dcd2013-10-15 15:12:24 -07001424 // ndnboost/regex/v4/cpp_regex_traits.hpp
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001425 // Thanks John Maddock for it! (previous version had some
1426 // problems with libc++ and some other STL implementations)
1427 template <class BufferType, class charT>
1428 class parser_buf : public BufferType {
1429 typedef BufferType base_type;
1430 typedef typename base_type::int_type int_type;
1431 typedef typename base_type::char_type char_type;
1432 typedef typename base_type::pos_type pos_type;
1433 typedef ::std::streamsize streamsize;
1434 typedef typename base_type::off_type off_type;
1435
1436 public:
1437 parser_buf() : base_type() { setbuf(0, 0); }
1438 const charT* getnext() { return this->gptr(); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001439#ifndef NDNBOOST_NO_USING_TEMPLATE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001440 using base_type::pptr;
1441 using base_type::pbase;
1442#else
1443 charT* pptr() const { return base_type::pptr(); }
1444 charT* pbase() const { return base_type::pbase(); }
1445#endif
1446 base_type* setbuf(char_type* s, streamsize n) {
1447 this->setg(s, s, s + n);
1448 return this;
1449 }
1450
1451 pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) {
1452 if(which & ::std::ios_base::out)
1453 return pos_type(off_type(-1));
1454 off_type size = static_cast<off_type>(this->egptr() - this->eback());
1455 charT* g = this->eback();
1456 if(off_type(sp) <= size)
1457 {
1458 this->setg(g, g + off_type(sp), g + size);
1459 }
1460 return pos_type(off_type(-1));
1461 }
1462
1463 pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
1464 typedef typename ndnboost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
1465
1466 if(which & ::std::ios_base::out)
1467 return pos_type(off_type(-1));
1468 std::ptrdiff_t size = this->egptr() - this->eback();
1469 std::ptrdiff_t pos = this->gptr() - this->eback();
1470 charT* g = this->eback();
1471 switch(static_cast<cast_type>(way))
1472 {
1473 case ::std::ios_base::beg:
1474 if((off < 0) || (off > size))
1475 return pos_type(off_type(-1));
1476 else
1477 this->setg(g, g + off, g + size);
1478 break;
1479 case ::std::ios_base::end:
1480 if((off < 0) || (off > size))
1481 return pos_type(off_type(-1));
1482 else
1483 this->setg(g, g + size - off, g + size);
1484 break;
1485 case ::std::ios_base::cur:
1486 {
1487 std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
1488 if((newpos < 0) || (newpos > size))
1489 return pos_type(off_type(-1));
1490 else
1491 this->setg(g, g + newpos, g + size);
1492 break;
1493 }
1494 default: ;
1495 }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001496#ifdef NDNBOOST_MSVC
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001497#pragma warning(push)
1498#pragma warning(disable:4244)
1499#endif
1500 return static_cast<pos_type>(this->gptr() - this->eback());
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001501#ifdef NDNBOOST_MSVC
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001502#pragma warning(pop)
1503#endif
1504 }
1505 private:
1506 parser_buf& operator=(const parser_buf&);
1507 parser_buf(const parser_buf&);
1508 };
1509 }
1510
1511 namespace detail
1512 {
1513 struct do_not_construct_out_stream_t{};
1514 }
1515
1516 namespace detail // optimized stream wrapper
1517 {
1518 // String representation of Source has an upper limit.
1519 template< class CharT // a result of widest_char transformation
1520 , class Traits // usually char_traits<CharT>
1521 , bool RequiresStringbuffer
1522 >
1523 class lexical_stream_limited_src
1524 {
1525
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001526#if defined(NDNBOOST_NO_STRINGSTREAM)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001527 typedef std::ostrstream out_stream_t;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001528#elif defined(NDNBOOST_NO_STD_LOCALE)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001529 typedef std::ostringstream out_stream_t;
1530 typedef parser_buf<std::streambuf, char> buffer_t;
1531#else
1532 typedef std::basic_ostringstream<CharT, Traits> out_stream_t;
1533 typedef parser_buf<std::basic_streambuf<CharT, Traits>, CharT> buffer_t;
1534#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001535 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001536 RequiresStringbuffer,
1537 out_stream_t,
1538 do_not_construct_out_stream_t
1539 >::type deduced_out_stream_t;
1540
1541 // A string representation of Source is written to [start, finish).
1542 CharT* start;
1543 CharT* finish;
1544 deduced_out_stream_t out_stream;
1545
1546 public:
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001547 lexical_stream_limited_src(CharT* sta, CharT* fin) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001548 : start(sta)
1549 , finish(fin)
1550 {}
1551
1552 private:
1553 // Undefined:
1554 lexical_stream_limited_src(lexical_stream_limited_src const&);
1555 void operator=(lexical_stream_limited_src const&);
1556
1557/************************************ HELPER FUNCTIONS FOR OPERATORS << ( ... ) ********************************/
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001558 bool shl_char(CharT ch) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001559 {
1560 Traits::assign(*start, ch);
1561 finish = start + 1;
1562 return true;
1563 }
1564
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001565#ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001566 template <class T>
1567 bool shl_char(T ch)
1568 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001569 NDNBOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)) ,
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001570 "ndnboost::lexical_cast does not support narrowing of char types."
1571 "Use ndnboost::locale instead" );
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001572#ifndef NDNBOOST_LEXICAL_CAST_ASSUME_C_LOCALE
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001573 std::locale loc;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001574 CharT const w = NDNBOOST_USE_FACET(std::ctype<CharT>, loc).widen(ch);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001575#else
1576 CharT const w = static_cast<CharT>(ch);
1577#endif
1578 Traits::assign(*start, w);
1579 finish = start + 1;
1580 return true;
1581 }
1582#endif
1583
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001584 bool shl_char_array(CharT const* str) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001585 {
1586 start = const_cast<CharT*>(str);
1587 finish = start + Traits::length(str);
1588 return true;
1589 }
1590
1591 template <class T>
1592 bool shl_char_array(T const* str)
1593 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001594 NDNBOOST_STATIC_ASSERT_MSG(( sizeof(T) <= sizeof(CharT)),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001595 "ndnboost::lexical_cast does not support narrowing of char types."
1596 "Use ndnboost::locale instead" );
1597 return shl_input_streamable(str);
1598 }
1599
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001600 bool shl_char_array_limited(CharT const* str, std::size_t max_size) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001601 {
1602 start = const_cast<CharT*>(str);
1603 finish = std::find(start, start + max_size, Traits::to_char_type(0));
1604 return true;
1605 }
1606
1607 template<typename InputStreamable>
1608 bool shl_input_streamable(InputStreamable& input)
1609 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001610#if defined(NDNBOOST_NO_STRINGSTREAM) || defined(NDNBOOST_NO_STD_LOCALE)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001611 // If you have compilation error at this point, than your STL library
1612 // does not support such conversions. Try updating it.
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001613 NDNBOOST_STATIC_ASSERT((ndnboost::is_same<char, CharT>::value));
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001614#endif
1615 bool const result = !(out_stream << input).fail();
1616 const buffer_t* const p = static_cast<buffer_t*>(
1617 static_cast<std::basic_streambuf<CharT, Traits>*>(out_stream.rdbuf())
1618 );
1619 start = p->pbase();
1620 finish = p->pptr();
1621 return result;
1622 }
1623
1624 template <class T>
1625 inline bool shl_signed(T n)
1626 {
1627 start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
1628 if(n < 0)
1629 {
1630 --start;
1631 CharT const minus = lcast_char_constants<CharT>::minus;
1632 Traits::assign(*start, minus);
1633 }
1634 return true;
1635 }
1636
1637 template <class T, class SomeCharT>
1638 bool shl_real_type(const T& val, SomeCharT* begin, SomeCharT*& end)
1639 {
1640 if (put_inf_nan(begin, end, val)) return true;
1641 lcast_set_precision(out_stream, &val);
1642 return shl_input_streamable(val);
1643 }
1644
1645 static bool shl_real_type(float val, char* begin, char*& end)
1646 { using namespace std;
1647 if (put_inf_nan(begin, end, val)) return true;
1648 const double val_as_double = val;
1649 end = begin +
1650#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1651 sprintf_s(begin, end-begin,
1652#else
1653 sprintf(begin,
1654#endif
1655 "%.*g", static_cast<int>(ndnboost::detail::lcast_get_precision<float>()), val_as_double);
1656 return end > begin;
1657 }
1658
1659 static bool shl_real_type(double val, char* begin, char*& end)
1660 { using namespace std;
1661 if (put_inf_nan(begin, end, val)) return true;
1662 end = begin +
1663#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1664 sprintf_s(begin, end-begin,
1665#else
1666 sprintf(begin,
1667#endif
1668 "%.*g", static_cast<int>(ndnboost::detail::lcast_get_precision<double>()), val);
1669 return end > begin;
1670 }
1671
1672#ifndef __MINGW32__
1673 static bool shl_real_type(long double val, char* begin, char*& end)
1674 { using namespace std;
1675 if (put_inf_nan(begin, end, val)) return true;
1676 end = begin +
1677#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__SGI_STL_PORT) && !defined(_STLPORT_VERSION)
1678 sprintf_s(begin, end-begin,
1679#else
1680 sprintf(begin,
1681#endif
1682 "%.*Lg", static_cast<int>(ndnboost::detail::lcast_get_precision<long double>()), val );
1683 return end > begin;
1684 }
1685#endif
1686
1687
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001688#if !defined(NDNBOOST_LCAST_NO_WCHAR_T) && !defined(NDNBOOST_NO_SWPRINTF) && !defined(__MINGW32__)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001689 static bool shl_real_type(float val, wchar_t* begin, wchar_t*& end)
1690 { using namespace std;
1691 if (put_inf_nan(begin, end, val)) return true;
1692 const double val_as_double = val;
1693 end = begin + swprintf(begin, end-begin,
1694 L"%.*g",
1695 static_cast<int>(ndnboost::detail::lcast_get_precision<float >()),
1696 val_as_double );
1697 return end > begin;
1698 }
1699
1700 static bool shl_real_type(double val, wchar_t* begin, wchar_t*& end)
1701 { using namespace std;
1702 if (put_inf_nan(begin, end, val)) return true;
1703 end = begin + swprintf(begin, end-begin,
1704 L"%.*g", static_cast<int>(ndnboost::detail::lcast_get_precision<double >()), val );
1705 return end > begin;
1706 }
1707
1708 static bool shl_real_type(long double val, wchar_t* begin, wchar_t*& end)
1709 { using namespace std;
1710 if (put_inf_nan(begin, end, val)) return true;
1711 end = begin + swprintf(begin, end-begin,
1712 L"%.*Lg", static_cast<int>(ndnboost::detail::lcast_get_precision<long double >()), val );
1713 return end > begin;
1714 }
1715#endif
1716
1717/************************************ OPERATORS << ( ... ) ********************************/
1718 public:
1719 template<class Alloc>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001720 bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001721 {
1722 start = const_cast<CharT*>(str.data());
1723 finish = start + str.length();
1724 return true;
1725 }
1726
1727 template<class Alloc>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001728 bool operator<<(ndnboost::container::basic_string<CharT,Traits,Alloc> const& str) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001729 {
1730 start = const_cast<CharT*>(str.data());
1731 finish = start + str.length();
1732 return true;
1733 }
1734
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001735 bool operator<<(bool value) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001736 {
1737 CharT const czero = lcast_char_constants<CharT>::zero;
1738 Traits::assign(*start, Traits::to_char_type(czero + value));
1739 finish = start + 1;
1740 return true;
1741 }
1742
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001743 bool operator<<(const iterator_range<CharT*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001744 {
1745 start = rng.begin();
1746 finish = rng.end();
1747 return true;
1748 }
1749
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001750 bool operator<<(const iterator_range<const CharT*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001751 {
1752 start = const_cast<CharT*>(rng.begin());
1753 finish = const_cast<CharT*>(rng.end());
1754 return true;
1755 }
1756
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001757 bool operator<<(const iterator_range<const signed char*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001758 {
1759 return (*this) << iterator_range<char*>(
1760 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
1761 const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
1762 );
1763 }
1764
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001765 bool operator<<(const iterator_range<const unsigned char*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001766 {
1767 return (*this) << iterator_range<char*>(
1768 const_cast<char*>(reinterpret_cast<const char*>(rng.begin())),
1769 const_cast<char*>(reinterpret_cast<const char*>(rng.end()))
1770 );
1771 }
1772
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001773 bool operator<<(const iterator_range<signed char*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001774 {
1775 return (*this) << iterator_range<char*>(
1776 reinterpret_cast<char*>(rng.begin()),
1777 reinterpret_cast<char*>(rng.end())
1778 );
1779 }
1780
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001781 bool operator<<(const iterator_range<unsigned char*>& rng) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001782 {
1783 return (*this) << iterator_range<char*>(
1784 reinterpret_cast<char*>(rng.begin()),
1785 reinterpret_cast<char*>(rng.end())
1786 );
1787 }
1788
1789 bool operator<<(char ch) { return shl_char(ch); }
1790 bool operator<<(unsigned char ch) { return ((*this) << static_cast<char>(ch)); }
1791 bool operator<<(signed char ch) { return ((*this) << static_cast<char>(ch)); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001792#if !defined(NDNBOOST_LCAST_NO_WCHAR_T)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001793 bool operator<<(wchar_t const* str) { return shl_char_array(str); }
1794 bool operator<<(wchar_t * str) { return shl_char_array(str); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001795#ifndef NDNBOOST_NO_INTRINSIC_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001796 bool operator<<(wchar_t ch) { return shl_char(ch); }
1797#endif
1798#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001799#if !defined(NDNBOOST_NO_CXX11_CHAR16_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001800 bool operator<<(char16_t ch) { return shl_char(ch); }
1801 bool operator<<(char16_t * str) { return shl_char_array(str); }
1802 bool operator<<(char16_t const * str) { return shl_char_array(str); }
1803#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001804#if !defined(NDNBOOST_NO_CXX11_CHAR32_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001805 bool operator<<(char32_t ch) { return shl_char(ch); }
1806 bool operator<<(char32_t * str) { return shl_char_array(str); }
1807 bool operator<<(char32_t const * str) { return shl_char_array(str); }
1808#endif
1809 bool operator<<(unsigned char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1810 bool operator<<(unsigned char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1811 bool operator<<(signed char const* ch) { return ((*this) << reinterpret_cast<char const*>(ch)); }
1812 bool operator<<(signed char * ch) { return ((*this) << reinterpret_cast<char *>(ch)); }
1813 bool operator<<(char const* str) { return shl_char_array(str); }
1814 bool operator<<(char* str) { return shl_char_array(str); }
1815 bool operator<<(short n) { return shl_signed(n); }
1816 bool operator<<(int n) { return shl_signed(n); }
1817 bool operator<<(long n) { return shl_signed(n); }
1818 bool operator<<(unsigned short n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1819 bool operator<<(unsigned int n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1820 bool operator<<(unsigned long n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1821
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001822#if defined(NDNBOOST_HAS_LONG_LONG)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001823 bool operator<<(ndnboost::ulong_long_type n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1824 bool operator<<(ndnboost::long_long_type n) { return shl_signed(n); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001825#elif defined(NDNBOOST_HAS_MS_INT64)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001826 bool operator<<(unsigned __int64 n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1827 bool operator<<( __int64 n) { return shl_signed(n); }
1828#endif
1829
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001830#ifdef NDNBOOST_LCAST_HAS_INT128
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001831 bool operator<<(const ndnboost::uint128_type& n) { start = lcast_put_unsigned<Traits>(n, finish); return true; }
1832 bool operator<<(const ndnboost::int128_type& n) { return shl_signed(n); }
1833#endif
1834
1835 bool operator<<(float val) { return shl_real_type(val, start, finish); }
1836 bool operator<<(double val) { return shl_real_type(val, start, finish); }
1837 bool operator<<(long double val) {
1838#ifndef __MINGW32__
1839 return shl_real_type(val, start, finish);
1840#else
1841 return shl_real_type(static_cast<double>(val), start, finish);
1842#endif
1843 }
1844
1845 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001846 bool operator<<(ndnboost::array<CharT, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001847 { return shl_char_array_limited(input.begin(), N); }
1848
1849 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001850 bool operator<<(ndnboost::array<unsigned char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001851 { return ((*this) << reinterpret_cast<ndnboost::array<char, N> const& >(input)); }
1852
1853 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001854 bool operator<<(ndnboost::array<signed char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001855 { return ((*this) << reinterpret_cast<ndnboost::array<char, N> const& >(input)); }
1856
1857 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001858 bool operator<<(ndnboost::array<const CharT, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001859 { return shl_char_array_limited(input.begin(), N); }
1860
1861 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001862 bool operator<<(ndnboost::array<const unsigned char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001863 { return ((*this) << reinterpret_cast<ndnboost::array<const char, N> const& >(input)); }
1864
1865 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001866 bool operator<<(ndnboost::array<const signed char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001867 { return ((*this) << reinterpret_cast<ndnboost::array<const char, N> const& >(input)); }
1868
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001869#ifndef NDNBOOST_NO_CXX11_HDR_ARRAY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001870 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001871 bool operator<<(std::array<CharT, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001872 {
1873 if (input.size()) return shl_char_array_limited(&input[0], N);
1874 else return true;
1875 }
1876
1877 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001878 bool operator<<(std::array<unsigned char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001879 { return ((*this) << reinterpret_cast<ndnboost::array<char, N> const& >(input)); }
1880
1881 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001882 bool operator<<(std::array<signed char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001883 { return ((*this) << reinterpret_cast<ndnboost::array<char, N> const& >(input)); }
1884
1885 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001886 bool operator<<(std::array<const CharT, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001887 {
1888 if (input.size()) return shl_char_array_limited(&input[0], N);
1889 else return true;
1890 }
1891
1892 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001893 bool operator<<(std::array<const unsigned char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001894 { return ((*this) << reinterpret_cast<ndnboost::array<const char, N> const& >(input)); }
1895
1896 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001897 bool operator<<(std::array<const signed char, N> const& input) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001898 { return ((*this) << reinterpret_cast<ndnboost::array<const char, N> const& >(input)); }
1899#endif
1900
1901 template <class InStreamable>
1902 bool operator<<(const InStreamable& input) { return shl_input_streamable(input); }
1903
1904/************************************ HELPER FUNCTIONS FOR OPERATORS >> ( ... ) ********************************/
1905 private:
1906
1907 template <typename Type>
1908 bool shr_unsigned(Type& output)
1909 {
1910 if (start == finish) return false;
1911 CharT const minus = lcast_char_constants<CharT>::minus;
1912 CharT const plus = lcast_char_constants<CharT>::plus;
1913 bool has_minus = false;
1914
1915 /* We won`t use `start' any more, so no need in decrementing it after */
1916 if ( Traits::eq(minus,*start) )
1917 {
1918 ++start;
1919 has_minus = true;
1920 } else if ( Traits::eq( plus, *start ) )
1921 {
1922 ++start;
1923 }
1924
1925 bool const succeed = lcast_ret_unsigned<Traits>(output, start, finish);
1926
1927 if (has_minus) {
1928 output = static_cast<Type>(0u - output);
1929 }
1930
1931 return succeed;
1932 }
1933
1934 template <typename Type>
1935 bool shr_signed(Type& output)
1936 {
1937 if (start == finish) return false;
1938 CharT const minus = lcast_char_constants<CharT>::minus;
1939 CharT const plus = lcast_char_constants<CharT>::plus;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001940 typedef NDNBOOST_DEDUCED_TYPENAME make_unsigned<Type>::type utype;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001941 utype out_tmp =0;
1942 bool has_minus = false;
1943
1944 /* We won`t use `start' any more, so no need in decrementing it after */
1945 if ( Traits::eq(minus,*start) )
1946 {
1947 ++start;
1948 has_minus = true;
1949 } else if ( Traits::eq(plus, *start) )
1950 {
1951 ++start;
1952 }
1953
1954 bool succeed = lcast_ret_unsigned<Traits>(out_tmp, start, finish);
1955 if (has_minus) {
1956 utype const comp_val = (static_cast<utype>(1) << std::numeric_limits<Type>::digits);
1957 succeed = succeed && out_tmp<=comp_val;
1958 output = static_cast<Type>(0u - out_tmp);
1959 } else {
1960 utype const comp_val = static_cast<utype>((std::numeric_limits<Type>::max)());
1961 succeed = succeed && out_tmp<=comp_val;
1962 output = out_tmp;
1963 }
1964 return succeed;
1965 }
1966
1967 template<typename InputStreamable>
1968 bool shr_using_base_class(InputStreamable& output)
1969 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001970 NDNBOOST_STATIC_ASSERT_MSG(
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001971 (!ndnboost::is_pointer<InputStreamable>::value),
1972 "ndnboost::lexical_cast can not convert to pointers"
1973 );
1974
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001975#if defined(NDNBOOST_NO_STRINGSTREAM) || defined(NDNBOOST_NO_STD_LOCALE)
1976 NDNBOOST_STATIC_ASSERT_MSG((ndnboost::is_same<char, CharT>::value),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001977 "ndnboost::lexical_cast can not convert, because your STL library does not "
1978 "support such conversions. Try updating it."
1979 );
1980#endif
1981
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001982#if defined(NDNBOOST_NO_STRINGSTREAM)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001983 std::istrstream stream(start, finish - start);
1984#else
1985
1986 buffer_t buf;
1987 buf.setbuf(start, finish - start);
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001988#if defined(NDNBOOST_NO_STD_LOCALE)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001989 std::istream stream(&buf);
1990#else
1991 std::basic_istream<CharT, Traits> stream(&buf);
Jeff Thompson3d613fd2013-10-15 15:39:04 -07001992#endif // NDNBOOST_NO_STD_LOCALE
1993#endif // NDNBOOST_NO_STRINGSTREAM
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07001994
1995 stream.unsetf(std::ios::skipws);
1996 lcast_set_precision(stream, static_cast<InputStreamable*>(0));
1997
1998 return stream >> output &&
1999 stream.get() ==
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002000#if defined(__GNUC__) && (__GNUC__<3) && defined(NDNBOOST_NO_STD_WSTRING)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002001 // GCC 2.9x lacks std::char_traits<>::eof().
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002002 // We use NDNBOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002003 // configurations, which do provide std::char_traits<>::eof().
2004
2005 EOF;
2006#else
2007 Traits::eof();
2008#endif
2009 }
2010
2011 template<class T>
2012 inline bool shr_xchar(T& output)
2013 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002014 NDNBOOST_STATIC_ASSERT_MSG(( sizeof(CharT) == sizeof(T) ),
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002015 "ndnboost::lexical_cast does not support narrowing of character types."
2016 "Use ndnboost::locale instead" );
2017 bool const ok = (finish - start == 1);
2018 if (ok) {
2019 CharT out;
2020 Traits::assign(out, *start);
2021 output = static_cast<T>(out);
2022 }
2023 return ok;
2024 }
2025
2026/************************************ OPERATORS >> ( ... ) ********************************/
2027 public:
2028 bool operator>>(unsigned short& output) { return shr_unsigned(output); }
2029 bool operator>>(unsigned int& output) { return shr_unsigned(output); }
2030 bool operator>>(unsigned long int& output) { return shr_unsigned(output); }
2031 bool operator>>(short& output) { return shr_signed(output); }
2032 bool operator>>(int& output) { return shr_signed(output); }
2033 bool operator>>(long int& output) { return shr_signed(output); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002034#if defined(NDNBOOST_HAS_LONG_LONG)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002035 bool operator>>(ndnboost::ulong_long_type& output) { return shr_unsigned(output); }
2036 bool operator>>(ndnboost::long_long_type& output) { return shr_signed(output); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002037#elif defined(NDNBOOST_HAS_MS_INT64)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002038 bool operator>>(unsigned __int64& output) { return shr_unsigned(output); }
2039 bool operator>>(__int64& output) { return shr_signed(output); }
2040#endif
2041
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002042#ifdef NDNBOOST_LCAST_HAS_INT128
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002043 bool operator>>(ndnboost::uint128_type& output) { return shr_unsigned(output); }
2044 bool operator>>(ndnboost::int128_type& output) { return shr_signed(output); }
2045#endif
2046
2047 bool operator>>(char& output) { return shr_xchar(output); }
2048 bool operator>>(unsigned char& output) { return shr_xchar(output); }
2049 bool operator>>(signed char& output) { return shr_xchar(output); }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002050#if !defined(NDNBOOST_LCAST_NO_WCHAR_T) && !defined(NDNBOOST_NO_INTRINSIC_WCHAR_T)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002051 bool operator>>(wchar_t& output) { return shr_xchar(output); }
2052#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002053#if !defined(NDNBOOST_NO_CXX11_CHAR16_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002054 bool operator>>(char16_t& output) { return shr_xchar(output); }
2055#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002056#if !defined(NDNBOOST_NO_CXX11_CHAR32_T) && !defined(NDNBOOST_NO_CXX11_UNICODE_LITERALS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002057 bool operator>>(char32_t& output) { return shr_xchar(output); }
2058#endif
2059 template<class Alloc>
2060 bool operator>>(std::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
2061
2062 template<class Alloc>
2063 bool operator>>(ndnboost::container::basic_string<CharT,Traits,Alloc>& str) { str.assign(start, finish); return true; }
2064
2065
2066 private:
2067 template <std::size_t N, class ArrayT>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002068 bool shr_std_array(ArrayT& output) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002069 {
2070 using namespace std;
2071 const std::size_t size = finish - start;
2072 if (size > N - 1) { // `-1` because we need to store \0 at the end
2073 return false;
2074 }
2075
2076 memcpy(&output[0], start, size * sizeof(CharT));
2077 output[size] = Traits::to_char_type(0);
2078 return true;
2079 }
2080
2081 public:
2082
2083 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002084 bool operator>>(ndnboost::array<CharT, N>& output) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002085 {
2086 return shr_std_array<N>(output);
2087 }
2088
2089 template <std::size_t N>
2090 bool operator>>(ndnboost::array<unsigned char, N>& output)
2091 {
2092 return ((*this) >> reinterpret_cast<ndnboost::array<char, N>& >(output));
2093 }
2094
2095 template <std::size_t N>
2096 bool operator>>(ndnboost::array<signed char, N>& output)
2097 {
2098 return ((*this) >> reinterpret_cast<ndnboost::array<char, N>& >(output));
2099 }
2100
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002101#ifndef NDNBOOST_NO_CXX11_HDR_ARRAY
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002102 template <std::size_t N>
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002103 bool operator>>(std::array<CharT, N>& output) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002104 {
2105 return shr_std_array<N>(output);
2106 }
2107
2108 template <std::size_t N>
2109 bool operator>>(std::array<unsigned char, N>& output)
2110 {
2111 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
2112 }
2113
2114 template <std::size_t N>
2115 bool operator>>(std::array<signed char, N>& output)
2116 {
2117 return ((*this) >> reinterpret_cast<std::array<char, N>& >(output));
2118 }
2119#endif
2120
2121
2122 /*
2123 * case "-0" || "0" || "+0" : output = false; return true;
2124 * case "1" || "+1": output = true; return true;
2125 * default: return false;
2126 */
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002127 bool operator>>(bool& output) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002128 {
2129 CharT const zero = lcast_char_constants<CharT>::zero;
2130 CharT const plus = lcast_char_constants<CharT>::plus;
2131 CharT const minus = lcast_char_constants<CharT>::minus;
2132
2133 switch(finish-start)
2134 {
2135 case 1:
2136 output = Traits::eq(start[0], zero+1);
2137 return output || Traits::eq(start[0], zero );
2138 case 2:
2139 if ( Traits::eq( plus, *start) )
2140 {
2141 ++start;
2142 output = Traits::eq(start[0], zero +1);
2143 return output || Traits::eq(start[0], zero );
2144 } else
2145 {
2146 output = false;
2147 return Traits::eq( minus, *start)
2148 && Traits::eq( zero, start[1]);
2149 }
2150 default:
2151 output = false; // Suppress warning about uninitalized variable
2152 return false;
2153 }
2154 }
2155
2156 bool operator>>(float& output) { return lcast_ret_float<Traits>(output,start,finish); }
2157
2158 private:
2159 // Not optimised converter
2160 template <class T>
2161 bool float_types_converter_internal(T& output, int /*tag*/) {
2162 if (parse_inf_nan(start, finish, output)) return true;
2163 bool return_value = shr_using_base_class(output);
2164
2165 /* Some compilers and libraries successfully
2166 * parse 'inf', 'INFINITY', '1.0E', '1.0E-'...
2167 * We are trying to provide a unified behaviour,
2168 * so we just forbid such conversions (as some
2169 * of the most popular compilers/libraries do)
2170 * */
2171 CharT const minus = lcast_char_constants<CharT>::minus;
2172 CharT const plus = lcast_char_constants<CharT>::plus;
2173 CharT const capital_e = lcast_char_constants<CharT>::capital_e;
2174 CharT const lowercase_e = lcast_char_constants<CharT>::lowercase_e;
2175 if ( return_value &&
2176 (
2177 Traits::eq(*(finish-1), lowercase_e) // 1.0e
2178 || Traits::eq(*(finish-1), capital_e) // 1.0E
2179 || Traits::eq(*(finish-1), minus) // 1.0e- or 1.0E-
2180 || Traits::eq(*(finish-1), plus) // 1.0e+ or 1.0E+
2181 )
2182 ) return false;
2183
2184 return return_value;
2185 }
2186
2187 // Optimised converter
2188 bool float_types_converter_internal(double& output,char /*tag*/) {
2189 return lcast_ret_float<Traits>(output,start,finish);
2190 }
2191 public:
2192
2193 bool operator>>(double& output)
2194 {
2195 /*
2196 * Some compilers implement long double as double. In that case these types have
2197 * same size, same precision, same max and min values... And it means,
2198 * that current implementation of lcast_ret_float cannot be used for type
2199 * double, because it will give a big precision loss.
2200 * */
2201 ndnboost::mpl::if_c<
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002202#if (defined(NDNBOOST_HAS_LONG_LONG) || defined(NDNBOOST_HAS_MS_INT64)) && !defined(NDNBOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002203 ndnboost::type_traits::ice_eq< sizeof(double), sizeof(long double) >::value,
2204#else
2205 1,
2206#endif
2207 int,
2208 char
2209 >::type tag = 0;
2210
2211 return float_types_converter_internal(output, tag);
2212 }
2213
2214 bool operator>>(long double& output)
2215 {
2216 int tag = 0;
2217 return float_types_converter_internal(output, tag);
2218 }
2219
2220 // Generic istream-based algorithm.
2221 // lcast_streambuf_for_target<InputStreamable>::value is true.
2222 template<typename InputStreamable>
2223 bool operator>>(InputStreamable& output) { return shr_using_base_class(output); }
2224 };
2225 }
2226
2227 namespace detail
2228 {
2229 template<typename T>
2230 struct is_stdstring
2231 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002232 NDNBOOST_STATIC_CONSTANT(bool, value = false );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002233 };
2234
2235 template<typename CharT, typename Traits, typename Alloc>
2236 struct is_stdstring< std::basic_string<CharT, Traits, Alloc> >
2237 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002238 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002239 };
2240
2241 template<typename CharT, typename Traits, typename Alloc>
2242 struct is_stdstring< ndnboost::container::basic_string<CharT, Traits, Alloc> >
2243 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002244 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002245 };
2246
2247 template<typename Target, typename Source>
2248 struct is_arithmetic_and_not_xchars
2249 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002250 NDNBOOST_STATIC_CONSTANT(bool, value =
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002251 (
2252 ndnboost::type_traits::ice_and<
2253 ndnboost::is_arithmetic<Source>::value,
2254 ndnboost::is_arithmetic<Target>::value,
2255 ndnboost::type_traits::ice_not<
2256 detail::is_char_or_wchar<Target>::value
2257 >::value,
2258 ndnboost::type_traits::ice_not<
2259 detail::is_char_or_wchar<Source>::value
2260 >::value
2261 >::value
2262 )
2263 );
2264 };
2265
2266 /*
2267 * is_xchar_to_xchar<Target, Source>::value is true, when
2268 * Target and Souce are the same char types, or when
2269 * Target and Souce are char types of the same size.
2270 */
2271 template<typename Target, typename Source>
2272 struct is_xchar_to_xchar
2273 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002274 NDNBOOST_STATIC_CONSTANT(bool, value =
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002275 (
2276 ndnboost::type_traits::ice_or<
2277 ndnboost::type_traits::ice_and<
2278 is_same<Source,Target>::value,
2279 is_char_or_wchar<Target>::value
2280 >::value,
2281 ndnboost::type_traits::ice_and<
2282 ndnboost::type_traits::ice_eq< sizeof(char),sizeof(Target)>::value,
2283 ndnboost::type_traits::ice_eq< sizeof(char),sizeof(Source)>::value,
2284 is_char_or_wchar<Target>::value,
2285 is_char_or_wchar<Source>::value
2286 >::value
2287 >::value
2288 )
2289 );
2290 };
2291
2292 template<typename Target, typename Source>
2293 struct is_char_array_to_stdstring
2294 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002295 NDNBOOST_STATIC_CONSTANT(bool, value = false );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002296 };
2297
2298 template<typename CharT, typename Traits, typename Alloc>
2299 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, CharT* >
2300 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002301 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002302 };
2303
2304 template<typename CharT, typename Traits, typename Alloc>
2305 struct is_char_array_to_stdstring< std::basic_string<CharT, Traits, Alloc>, const CharT* >
2306 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002307 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002308 };
2309
2310 template<typename CharT, typename Traits, typename Alloc>
2311 struct is_char_array_to_stdstring< ndnboost::container::basic_string<CharT, Traits, Alloc>, CharT* >
2312 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002313 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002314 };
2315
2316 template<typename CharT, typename Traits, typename Alloc>
2317 struct is_char_array_to_stdstring< ndnboost::container::basic_string<CharT, Traits, Alloc>, const CharT* >
2318 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002319 NDNBOOST_STATIC_CONSTANT(bool, value = true );
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002320 };
2321
2322#if (defined _MSC_VER)
2323# pragma warning( push )
2324# pragma warning( disable : 4701 ) // possible use of ... before initialization
2325# pragma warning( disable : 4702 ) // unreachable code
2326# pragma warning( disable : 4267 ) // conversion from 'size_t' to 'unsigned int'
2327#endif
2328 template<typename Target, typename Source>
2329 struct lexical_cast_do_cast
2330 {
2331 static inline Target lexical_cast_impl(const Source& arg)
2332 {
2333 typedef lexical_cast_stream_traits<Source, Target> stream_trait;
2334
2335 typedef detail::lexical_stream_limited_src<
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002336 NDNBOOST_DEDUCED_TYPENAME stream_trait::char_type,
2337 NDNBOOST_DEDUCED_TYPENAME stream_trait::traits,
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002338 stream_trait::requires_stringbuf
2339 > interpreter_type;
2340
2341 // Target type must be default constructible
2342 Target result;
2343
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002344 NDNBOOST_DEDUCED_TYPENAME stream_trait::char_type buf[stream_trait::len_t::value + 1];
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002345 stream_trait::len_t::check_coverage();
2346
2347 interpreter_type interpreter(buf, buf + stream_trait::len_t::value + 1);
2348
2349 // Disabling ADL, by directly specifying operators.
2350 if(!(interpreter.operator <<(arg) && interpreter.operator >>(result)))
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002351 NDNBOOST_LCAST_THROW_BAD_CAST(Source, Target);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002352
2353 return result;
2354 }
2355 };
2356#if (defined _MSC_VER)
2357# pragma warning( pop )
2358#endif
2359
2360 template <typename Source>
2361 struct lexical_cast_copy
2362 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002363 static inline const Source& lexical_cast_impl(const Source &arg) NDNBOOST_NOEXCEPT
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002364 {
2365 return arg;
2366 }
2367 };
2368
2369 template <class Source, class Target >
2370 struct detect_precision_loss
2371 {
2372 typedef ndnboost::numeric::Trunc<Source> Rounder;
2373 typedef Source source_type ;
2374
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002375 typedef NDNBOOST_DEDUCED_TYPENAME mpl::if_<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002376 ndnboost::is_arithmetic<Source>, Source, Source const&
2377 >::type argument_type ;
2378
2379 static source_type nearbyint ( argument_type s )
2380 {
2381 const source_type near_int = Rounder::nearbyint(s);
2382 if (near_int) {
2383 const source_type orig_div_round = s / near_int;
2384 const source_type eps = std::numeric_limits<source_type>::epsilon();
2385
2386 if ((orig_div_round > 1 ? orig_div_round - 1 : 1 - orig_div_round) > eps)
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002387 NDNBOOST_LCAST_THROW_BAD_CAST(Source, Target);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002388 }
2389
2390 return s ;
2391 }
2392
2393 typedef typename Rounder::round_style round_style;
2394 } ;
2395
2396 template <class Source, class Target >
2397 struct nothrow_overflow_handler
2398 {
2399 void operator() ( ndnboost::numeric::range_check_result r )
2400 {
2401 if (r != ndnboost::numeric::cInRange)
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002402 NDNBOOST_LCAST_THROW_BAD_CAST(Source, Target);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002403 }
2404 } ;
2405
2406 template <typename Target, typename Source>
2407 struct lexical_cast_dynamic_num_not_ignoring_minus
2408 {
2409 static inline Target lexical_cast_impl(const Source &arg)
2410 {
2411 return ndnboost::numeric::converter<
2412 Target,
2413 Source,
2414 ndnboost::numeric::conversion_traits<Target,Source>,
2415 nothrow_overflow_handler<Source, Target>,
2416 detect_precision_loss<Source, Target>
2417 >::convert(arg);
2418 }
2419 };
2420
2421 template <typename Target, typename Source>
2422 struct lexical_cast_dynamic_num_ignoring_minus
2423 {
2424 static inline Target lexical_cast_impl(const Source &arg)
2425 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002426 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::eval_if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002427 ndnboost::is_float<Source>::value,
2428 ndnboost::mpl::identity<Source>,
2429 ndnboost::make_unsigned<Source>
2430 >::type usource_t;
2431
2432 typedef ndnboost::numeric::converter<
2433 Target,
2434 usource_t,
2435 ndnboost::numeric::conversion_traits<Target,usource_t>,
2436 nothrow_overflow_handler<usource_t, Target>,
2437 detect_precision_loss<usource_t, Target>
2438 > converter_t;
2439
2440 return (
2441 arg < 0 ? static_cast<Target>(0u - converter_t::convert(0u - arg)) : converter_t::convert(arg)
2442 );
2443 }
2444 };
2445
2446 /*
2447 * lexical_cast_dynamic_num follows the rules:
2448 * 1) If Source can be converted to Target without precision loss and
2449 * without overflows, then assign Source to Target and return
2450 *
2451 * 2) If Source is less than 0 and Target is an unsigned integer,
2452 * then negate Source, check the requirements of rule 1) and if
2453 * successful, assign static_casted Source to Target and return
2454 *
2455 * 3) Otherwise throw a bad_lexical_cast exception
2456 *
2457 *
2458 * Rule 2) required because ndnboost::lexical_cast has the behavior of
2459 * stringstream, which uses the rules of scanf for conversions. And
2460 * in the C99 standard for unsigned input value minus sign is
2461 * optional, so if a negative number is read, no errors will arise
2462 * and the result will be the two's complement.
2463 */
2464 template <typename Target, typename Source>
2465 struct lexical_cast_dynamic_num
2466 {
2467 static inline Target lexical_cast_impl(const Source &arg)
2468 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002469 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002470 ndnboost::type_traits::ice_and<
2471 ndnboost::type_traits::ice_or<
2472 ndnboost::is_signed<Source>::value,
2473 ndnboost::is_float<Source>::value
2474 >::value,
2475 ndnboost::type_traits::ice_not<
2476 ndnboost::is_same<Source, bool>::value
2477 >::value,
2478 ndnboost::type_traits::ice_not<
2479 ndnboost::is_same<Target, bool>::value
2480 >::value,
2481 ndnboost::is_unsigned<Target>::value
2482 >::value,
2483 lexical_cast_dynamic_num_ignoring_minus<Target, Source>,
2484 lexical_cast_dynamic_num_not_ignoring_minus<Target, Source>
2485 >::type caster_type;
2486
2487 return caster_type::lexical_cast_impl(arg);
2488 }
2489 };
2490 }
2491
2492 template <typename Target, typename Source>
2493 inline Target lexical_cast(const Source &arg)
2494 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002495 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::detail::array_to_pointer_decay<Source>::type src;
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002496
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002497 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::type_traits::ice_or<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002498 ndnboost::detail::is_xchar_to_xchar<Target, src >::value,
2499 ndnboost::detail::is_char_array_to_stdstring<Target, src >::value,
2500 ndnboost::type_traits::ice_and<
2501 ndnboost::is_same<Target, src >::value,
2502 ndnboost::detail::is_stdstring<Target >::value
2503 >::value
2504 > shall_we_copy_t;
2505
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002506 typedef NDNBOOST_DEDUCED_TYPENAME
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002507 ndnboost::detail::is_arithmetic_and_not_xchars<Target, src > shall_we_copy_with_dynamic_check_t;
2508
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002509 typedef NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002510 shall_we_copy_t::value,
2511 ndnboost::detail::lexical_cast_copy<src >,
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002512 NDNBOOST_DEDUCED_TYPENAME ndnboost::mpl::if_c<
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002513 shall_we_copy_with_dynamic_check_t::value,
2514 ndnboost::detail::lexical_cast_dynamic_num<Target, src >,
2515 ndnboost::detail::lexical_cast_do_cast<Target, src >
2516 >::type
2517 >::type caster_type;
2518
2519 return caster_type::lexical_cast_impl(arg);
2520 }
2521
2522 template <typename Target>
2523 inline Target lexical_cast(const char* chars, std::size_t count)
2524 {
2525 return ::ndnboost::lexical_cast<Target>(
2526 ::ndnboost::iterator_range<const char*>(chars, chars + count)
2527 );
2528 }
2529
2530
2531 template <typename Target>
2532 inline Target lexical_cast(const unsigned char* chars, std::size_t count)
2533 {
2534 return ::ndnboost::lexical_cast<Target>(
2535 ::ndnboost::iterator_range<const unsigned char*>(chars, chars + count)
2536 );
2537 }
2538
2539 template <typename Target>
2540 inline Target lexical_cast(const signed char* chars, std::size_t count)
2541 {
2542 return ::ndnboost::lexical_cast<Target>(
2543 ::ndnboost::iterator_range<const signed char*>(chars, chars + count)
2544 );
2545 }
2546
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002547#ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002548 template <typename Target>
2549 inline Target lexical_cast(const wchar_t* chars, std::size_t count)
2550 {
2551 return ::ndnboost::lexical_cast<Target>(
2552 ::ndnboost::iterator_range<const wchar_t*>(chars, chars + count)
2553 );
2554 }
2555#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002556#ifndef NDNBOOST_NO_CHAR16_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002557 template <typename Target>
2558 inline Target lexical_cast(const char16_t* chars, std::size_t count)
2559 {
2560 return ::ndnboost::lexical_cast<Target>(
2561 ::ndnboost::iterator_range<const char16_t*>(chars, chars + count)
2562 );
2563 }
2564#endif
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002565#ifndef NDNBOOST_NO_CHAR32_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002566 template <typename Target>
2567 inline Target lexical_cast(const char32_t* chars, std::size_t count)
2568 {
2569 return ::ndnboost::lexical_cast<Target>(
2570 ::ndnboost::iterator_range<const char32_t*>(chars, chars + count)
2571 );
2572 }
2573#endif
2574
2575} // namespace ndnboost
2576
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002577#else // #ifndef NDNBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002578
2579namespace ndnboost {
2580 namespace detail
2581 {
2582
2583 // selectors for choosing stream character type
2584 template<typename Type>
2585 struct stream_char
2586 {
2587 typedef char type;
2588 };
2589
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002590#ifndef NDNBOOST_LCAST_NO_WCHAR_T
2591#ifndef NDNBOOST_NO_INTRINSIC_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002592 template<>
2593 struct stream_char<wchar_t>
2594 {
2595 typedef wchar_t type;
2596 };
2597#endif
2598
2599 template<>
2600 struct stream_char<wchar_t *>
2601 {
2602 typedef wchar_t type;
2603 };
2604
2605 template<>
2606 struct stream_char<const wchar_t *>
2607 {
2608 typedef wchar_t type;
2609 };
2610
2611 template<>
2612 struct stream_char<std::wstring>
2613 {
2614 typedef wchar_t type;
2615 };
2616#endif
2617
2618 // stream wrapper for handling lexical conversions
2619 template<typename Target, typename Source, typename Traits>
2620 class lexical_stream
2621 {
2622 private:
2623 typedef typename widest_char<
2624 typename stream_char<Target>::type,
2625 typename stream_char<Source>::type>::type char_type;
2626
2627 typedef Traits traits_type;
2628
2629 public:
2630 lexical_stream(char_type* = 0, char_type* = 0)
2631 {
2632 stream.unsetf(std::ios::skipws);
2633 lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
2634 }
2635 ~lexical_stream()
2636 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002637 #if defined(NDNBOOST_NO_STRINGSTREAM)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002638 stream.freeze(false);
2639 #endif
2640 }
2641 bool operator<<(const Source &input)
2642 {
2643 return !(stream << input).fail();
2644 }
2645 template<typename InputStreamable>
2646 bool operator>>(InputStreamable &output)
2647 {
2648 return !is_pointer<InputStreamable>::value &&
2649 stream >> output &&
2650 stream.get() ==
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002651#if defined(__GNUC__) && (__GNUC__<3) && defined(NDNBOOST_NO_STD_WSTRING)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002652// GCC 2.9x lacks std::char_traits<>::eof().
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002653// We use NDNBOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002654// configurations, which do provide std::char_traits<>::eof().
2655
2656 EOF;
2657#else
2658 traits_type::eof();
2659#endif
2660 }
2661
2662 bool operator>>(std::string &output)
2663 {
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002664 #if defined(NDNBOOST_NO_STRINGSTREAM)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002665 stream << '\0';
2666 #endif
2667 stream.str().swap(output);
2668 return true;
2669 }
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002670 #ifndef NDNBOOST_LCAST_NO_WCHAR_T
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002671 bool operator>>(std::wstring &output)
2672 {
2673 stream.str().swap(output);
2674 return true;
2675 }
2676 #endif
2677
2678 private:
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002679 #if defined(NDNBOOST_NO_STRINGSTREAM)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002680 std::strstream stream;
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002681 #elif defined(NDNBOOST_NO_STD_LOCALE)
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002682 std::stringstream stream;
2683 #else
2684 std::basic_stringstream<char_type,traits_type> stream;
2685 #endif
2686 };
2687 }
2688
2689 // call-by-value fallback version (deprecated)
2690
2691 template<typename Target, typename Source>
2692 Target lexical_cast(Source arg)
2693 {
2694 typedef typename detail::widest_char<
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002695 NDNBOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
2696 , NDNBOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002697 >::type char_type;
2698
2699 typedef std::char_traits<char_type> traits;
2700 detail::lexical_stream<Target, Source, traits> interpreter;
2701 Target result;
2702
2703 if(!(interpreter << arg && interpreter >> result))
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002704 NDNBOOST_LCAST_THROW_BAD_CAST(Source, Target);
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002705 return result;
2706 }
2707
2708} // namespace ndnboost
2709
2710#endif
2711
2712// Copyright Kevlin Henney, 2000-2005.
2713// Copyright Alexander Nasonov, 2006-2010.
2714// Copyright Antony Polukhin, 2011-2013.
2715//
2716// Distributed under the Boost Software License, Version 1.0. (See
2717// accompanying file LICENSE_1_0.txt or copy at
2718// http://www.boost.org/LICENSE_1_0.txt)
2719
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002720#undef NDNBOOST_LCAST_THROW_BAD_CAST
2721#undef NDNBOOST_LCAST_NO_WCHAR_T
2722#undef NDNBOOST_LCAST_HAS_INT128
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002723
Jeff Thompson3d613fd2013-10-15 15:39:04 -07002724#endif // NDNBOOST_LEXICAL_CAST_INCLUDED
Jeff Thompsonef2d5a42013-08-22 19:09:24 -07002725