Files
boost_conversion/include/boost/lexical_cast.hpp
T
Eric Niebler ef06decf65 Merged revisions 41161-41246 via svnmerge from
https://svn.boost.org/svn/boost/trunk

........
  r41161 | bemandawes | 2007-11-16 15:21:47 -0800 (Fri, 16 Nov 2007) | 1 line
  
  Fix markup error
........
  r41163 | bgubenko | 2007-11-16 17:28:10 -0800 (Fri, 16 Nov 2007) | 1 line
  
  mark some fusion library tests for acc toolset
........
  r41164 | djowel | 2007-11-16 17:51:04 -0800 (Fri, 16 Nov 2007) | 1 line
  
  fix for trac ticket #1450
........
  r41165 | lbourdev | 2007-11-16 19:38:25 -0800 (Fri, 16 Nov 2007) | 10 lines
  
  Updated to version 2.1.2
  Added support for more compilers.
  Added new flag GIL_NONWORD_POINTER_ALIGNMENT_SUPPORTED to indicate whether dereferencing on non-word
  boundary is supported. Enabling this flag improves performance.
  Fixed two bugs related to non-byte-aligned images. The image alignment parameter is now specified in
  bytes, and has a default of 0, which means "packed" alignment. In particular, for non-byte-aligned
  images alignment of 0 means there are no padding bits at the ends of rows.
  Added the allocator as an optional parameter to image constructors and image recreate methods.
........
  r41167 | grafik | 2007-11-16 20:11:49 -0800 (Fri, 16 Nov 2007) | 1 line
  
  Add "--out-xml=xyz.xml" option that dumps the output of all actions, and the test.jam information, to the given file. Changes are mostly from Dave.
........
  r41169 | johnmaddock | 2007-11-17 02:00:43 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Ooops, check on wrong index, now fixed.
........
  r41170 | johnmaddock | 2007-11-17 04:17:05 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Fix WinCE issues.
........
  r41172 | johnmaddock | 2007-11-17 10:41:29 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Changed test to catch throw exceptions from thread creation.
........
  r41173 | bemandawes | 2007-11-17 12:13:16 -0800 (Sat, 17 Nov 2007) | 1 line
  
  // Add or correct comment identifying Boost library this header is associated with.
........
  r41174 | grafik | 2007-11-17 12:14:24 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Add in Dave's comments, and expand information in XML output to include action names, sources, properties, bjam info, and platform info. This required one minor change to actions to keep track of the action object generating the targets.
........
  r41175 | nesotto | 2007-11-17 12:22:05 -0800 (Sat, 17 Nov 2007) | 1 line
  
  minor update of comments
........
  r41176 | nesotto | 2007-11-17 12:22:20 -0800 (Sat, 17 Nov 2007) | 1 line
  
  last updates
........
  r41177 | nesotto | 2007-11-17 12:44:29 -0800 (Sat, 17 Nov 2007) | 1 line
  
  works after local test with vc8
........
  r41178 | nesotto | 2007-11-17 13:02:22 -0800 (Sat, 17 Nov 2007) | 1 line
  
  added missing header
........
  r41180 | nesotto | 2007-11-17 13:19:13 -0800 (Sat, 17 Nov 2007) | 1 line
  
  iostream macro patch
........
  r41181 | nesotto | 2007-11-17 13:21:53 -0800 (Sat, 17 Nov 2007) | 1 line
  
  removed some warnings
........
  r41182 | grafik | 2007-11-17 13:22:40 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Add working dir to build description, move jam version to an attribute.
........
  r41183 | nesotto | 2007-11-17 13:24:16 -0800 (Sat, 17 Nov 2007) | 1 line
  
  macro patch
........
  r41185 | nesotto | 2007-11-17 13:43:32 -0800 (Sat, 17 Nov 2007) | 1 line
  
  minor change to define the value type of the iterators better
........
  r41186 | grafik | 2007-11-17 14:09:26 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Change "actual" to the more natural "target", and change "target" to "path". Add bjam command and bb version to XML.
........
  r41187 | bemandawes | 2007-11-17 14:48:06 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Add or correct comment identifying Boost library this header is associated with.
........
  r41188 | andreas_huber69 | 2007-11-17 16:08:46 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Added markup for statechart failures on msvc-8.0~wm5~stlport5.1
........
  r41192 | grafik | 2007-11-17 22:42:14 -0800 (Sat, 17 Nov 2007) | 1 line
  
  Add to XML output the known targets and dependencies to allow creation of the full build dependency graph. Merge from Dave's Bitten branch.
........
  r41193 | johnmaddock | 2007-11-18 02:07:14 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Ooops: previous commit broke platforms/compilers with no long double support, added workaround as fix.
........
  r41194 | igaztanaga | 2007-11-18 02:41:57 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Interprocess changes to support systems with filesystem-based shared memory
........
  r41195 | igaztanaga | 2007-11-18 02:43:35 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Added scapegoat trees and an option to store the hash value in the hook for unordered containers
........
  r41196 | igaztanaga | 2007-11-18 02:44:56 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Added scapegoat trees and an option to store the hash value in the hook for unordered containers
........
  r41197 | igaztanaga | 2007-11-18 02:51:19 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Interprocess changes to support systems with filesystem-based shared memory
........
  r41198 | igaztanaga | 2007-11-18 02:54:48 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Interprocess changes to support systems with filesystem-based shared memory
........
  r41199 | johnmaddock | 2007-11-18 04:23:37 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Added missing template argument to specialisations.
........
  r41200 | johnmaddock | 2007-11-18 04:24:42 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Fix IMB xlc error limits, added workarounds where these were missed by the last commit.
........
  r41201 | t_schwinger | 2007-11-18 06:06:47 -0800 (Sun, 18 Nov 2007) | 3 lines
  
  adds comment to fusion aCC failure markup
........
  r41202 | danieljames | 2007-11-18 08:10:12 -0800 (Sun, 18 Nov 2007) | 2 lines
  
  Move the instructions for running regression tests to the new site. Fixes #1265.
........
  r41210 | danieljames | 2007-11-18 12:18:04 -0800 (Sun, 18 Nov 2007) | 2 lines
  
  Move the 'implementation variations' page to the new site. Fixes #1355.
........
  r41211 | eric_niebler | 2007-11-18 12:19:55 -0800 (Sun, 18 Nov 2007) | 1 line
  
  vc6 doesn't like BOOST_MPL_ASSERT_MSG
........
  r41212 | grafik | 2007-11-18 12:24:25 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Inspection report fixes.
........
  r41213 | grafik | 2007-11-18 12:53:28 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Cleanup tools/regression to remove obsolete runner scripts, move existing docs to doc subdir, and clean html docs into valid xhtml.
........
  r41214 | grafik | 2007-11-18 13:02:51 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Add missing <cstring> include, for std::strchr function.
........
  r41215 | grafik | 2007-11-18 13:07:26 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Add keyword tags.
........
  r41216 | niels_dekker | 2007-11-18 14:11:57 -0800 (Sun, 18 Nov 2007) | 1 line
  
  Code refactoring: removed private base classes of value_initialized, as suggested by Fernando Cacciola.
........
  r41217 | djowel | 2007-11-18 16:05:43 -0800 (Sun, 18 Nov 2007) | 1 line
  
  added link to docs
........
  r41218 | johnmaddock | 2007-11-19 02:02:16 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Oops: added missing template specialisation argument.
........
  r41219 | johnmaddock | 2007-11-19 02:20:36 -0800 (Mon, 19 Nov 2007) | 1 line
  
  No user32.lib on WinCE
........
  r41220 | joaquin | 2007-11-19 03:08:11 -0800 (Mon, 19 Nov 2007) | 1 line
  
  moved some ADL stuff out of a potentially name-hiding scope
........
  r41221 | troyer | 2007-11-19 04:15:58 -0800 (Mon, 19 Nov 2007) | 1 line
  
  made complex seriaqlization more portable
........
  r41222 | anthonyw | 2007-11-19 04:17:31 -0800 (Mon, 19 Nov 2007) | 1 line
  
  fixed TSS cleanup on 64-bit Windows
........
  r41223 | anthonyw | 2007-11-19 04:29:14 -0800 (Mon, 19 Nov 2007) | 1 line
  
  fixed problems with TSS cleanup when using LoadLibrary and when threads finish after thread_specific_ptr instance has been destroyed
........
  r41224 | garcia | 2007-11-19 05:28:00 -0800 (Mon, 19 Nov 2007) | 2 lines
  
  A bunch of review volunteers.
........
  r41225 | garcia | 2007-11-19 06:01:34 -0800 (Mon, 19 Nov 2007) | 2 lines
  
  Added boost.range update
........
  r41226 | anthonyw | 2007-11-19 06:29:22 -0800 (Mon, 19 Nov 2007) | 1 line
  
  added copyright
........
  r41227 | aaron_windsor | 2007-11-19 07:28:26 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Cleaning up #includes to avoid errors on gcc 4.1 and above.
........
  r41234 | igaztanaga | 2007-11-19 08:55:23 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Fixed errors detected by gcc-4.3
........
  r41235 | hljin | 2007-11-19 09:26:12 -0800 (Mon, 19 Nov 2007) | 1 line
  
  GIL: updated the design guide based on the new changes
........
  r41236 | grafik | 2007-11-19 09:44:31 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Make quietly actions really quiet by not printing the command output. The output for the quietly actions is still available through "__ACTION_RULE__".
........
  r41237 | grafik | 2007-11-19 10:02:43 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Add architecture and instruction-set values for HP/PA-RISC.
........
  r41238 | igaztanaga | 2007-11-19 10:09:13 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Corrected ifdef
........
  r41240 | igaztanaga | 2007-11-19 10:32:12 -0800 (Mon, 19 Nov 2007) | 1 line
  
  Fixed 64 bit std::size_t specialization error
........
  r41241 | hljin | 2007-11-19 10:34:59 -0800 (Mon, 19 Nov 2007) | 1 line
  
  GIL: broke the main test into small tests
........
  r41242 | bgubenko | 2007-11-19 11:25:21 -0800 (Mon, 19 Nov 2007) | 1 line
  
  add OSPLAT=PARISC for HP-UX PA-RISC
........


[SVN r41247]
2007-11-20 07:41:38 +00:00

1102 lines
34 KiB
C++

#ifndef BOOST_LEXICAL_CAST_INCLUDED
#define BOOST_LEXICAL_CAST_INCLUDED
// Boost lexical_cast.hpp header -------------------------------------------//
//
// See http://www.boost.org/libs/converston for documentation.
// See end of this header for rights and permissions.
//
// what: lexical_cast custom keyword cast
// who: contributed by Kevlin Henney,
// enhanced with contributions from Terje Slettebo,
// with additional fixes and suggestions from Gennaro Prota,
// Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
// Alexander Nasonov and other Boosters
// when: November 2000, March 2003, June 2005, June 2006
#include <climits>
#include <cstddef>
#include <istream>
#include <locale>
#include <string>
#include <typeinfo>
#include <boost/config.hpp>
#include <boost/limits.hpp>
#include <boost/mpl/if.hpp>
#include <boost/throw_exception.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/call_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/lcast_precision.hpp>
#ifdef BOOST_NO_STRINGSTREAM
#include <strstream>
#else
#include <sstream>
#endif
#if defined(BOOST_NO_STRINGSTREAM) || \
defined(BOOST_NO_STD_WSTRING) || \
defined(BOOST_NO_STD_LOCALE)
#define DISABLE_WIDE_CHAR_SUPPORT
#endif
namespace boost
{
// exception used to indicate runtime lexical_cast failure
class bad_lexical_cast : public std::bad_cast
{
public:
bad_lexical_cast() :
source(&typeid(void)), target(&typeid(void))
{
}
bad_lexical_cast(
const std::type_info &source_type_arg,
const std::type_info &target_type_arg) :
source(&source_type_arg), target(&target_type_arg)
{
}
const std::type_info &source_type() const
{
return *source;
}
const std::type_info &target_type() const
{
return *target;
}
virtual const char *what() const throw()
{
return "bad lexical cast: "
"source type value could not be interpreted as target";
}
virtual ~bad_lexical_cast() throw()
{
}
private:
const std::type_info *source;
const std::type_info *target;
};
namespace detail // selectors for choosing stream character type
{
template<typename Type>
struct stream_char
{
typedef char type;
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
template<>
struct stream_char<wchar_t>
{
typedef wchar_t type;
};
#endif
template<>
struct stream_char<wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<const wchar_t *>
{
typedef wchar_t type;
};
template<>
struct stream_char<std::wstring>
{
typedef wchar_t type;
};
#endif
template<typename TargetChar, typename SourceChar>
struct widest_char
{
typedef TargetChar type;
};
template<>
struct widest_char<char, wchar_t>
{
typedef wchar_t type;
};
}
namespace detail // lcast_src_length
{
// Return max. length of string representation of Source;
// 0 if unlimited (with exceptions for some types, see below).
// Values with limited string representation are placed to
// the buffer locally defined in lexical_cast function.
// 1 is returned for few types such as CharT const* or
// std::basic_string<CharT> that already have an internal
// buffer ready to be reused by lexical_stream_limited_src.
// Each specialization should have a correspondent operator<<
// defined in lexical_stream_limited_src.
template< class CharT // A result of widest_char transformation.
, class Source // Source type of lexical_cast.
>
struct lcast_src_length
{
BOOST_STATIC_CONSTANT(std::size_t, value = 0);
// To check coverage, build the test with
// bjam --v2 profile optimization=off
static void check_coverage() {}
};
template<>
struct lcast_src_length<char, bool>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
template<>
struct lcast_src_length<char, char>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
// No specializations for:
// lcast_src_length<char, signed char>
// lcast_src_length<char, unsigned char>
// lcast_src_length<char, signed char*>
// lcast_src_length<char, unsigned char*>
// lcast_src_length<char, signed char const*>
// lcast_src_length<char, unsigned char const*>
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_src_length<wchar_t, bool>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
template<>
struct lcast_src_length<wchar_t, char>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#ifndef BOOST_NO_INTRINSIC_WCHAR_T
template<>
struct lcast_src_length<wchar_t, wchar_t>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#endif
#endif
template<>
struct lcast_src_length<char, char const*>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
template<>
struct lcast_src_length<char, char*>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_src_length<wchar_t, wchar_t const*>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
template<>
struct lcast_src_length<wchar_t, wchar_t*>
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<class CharT, class Traits, class Alloc>
struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#else
template<>
struct lcast_src_length< char, std::basic_string<char> >
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
{
BOOST_STATIC_CONSTANT(std::size_t, value = 1);
static void check_coverage() {}
};
#endif
#endif
// Helper for integral types.
// Notes on length calculation:
// Max length for 32bit int with grouping "\1" and thousands_sep ',':
// "-2,1,4,7,4,8,3,6,4,7"
// ^ - is_signed
// ^ - 1 digit not counted by digits10
// ^^^^^^^^^^^^^^^^^^ - digits10 * 2
//
// Constant is_specialized is used instead of constant 1
// to prevent buffer overflow in a rare case when
// <boost/limits.hpp> doesn't add missing specialization for
// numeric_limits<T> for some integral type T.
// When is_specialized is false, the whole expression is 0.
template<class Source>
struct lcast_src_length_integral
{
#if !defined(__BORLANDC__) || __BORLANDC__ >= 0x581
BOOST_STATIC_CONSTANT(std::size_t, value =
std::numeric_limits<Source>::is_signed +
std::numeric_limits<Source>::is_specialized + // == 1
std::numeric_limits<Source>::digits10 * 2
);
#else
BOOST_STATIC_CONSTANT(std::size_t, value = 156); // 256bit integers
#endif
};
#define BOOST_AUX_LEXICAL_CAST_DEF1(CharT, T) template<> \
struct lcast_src_length<CharT, T> : lcast_src_length_integral<T> \
{ static void check_coverage() {} };
#ifdef DISABLE_WIDE_CHAR_SUPPORT
#define BOOST_AUX_LEXICAL_CAST_DEF(T) BOOST_AUX_LEXICAL_CAST_DEF1(char, T)
#else
#define BOOST_AUX_LEXICAL_CAST_DEF(T) \
BOOST_AUX_LEXICAL_CAST_DEF1(char, T) \
BOOST_AUX_LEXICAL_CAST_DEF1(wchar_t, T)
#endif
BOOST_AUX_LEXICAL_CAST_DEF(short)
BOOST_AUX_LEXICAL_CAST_DEF(unsigned short)
BOOST_AUX_LEXICAL_CAST_DEF(int)
BOOST_AUX_LEXICAL_CAST_DEF(unsigned int)
BOOST_AUX_LEXICAL_CAST_DEF(long)
BOOST_AUX_LEXICAL_CAST_DEF(unsigned long)
#if defined(BOOST_HAS_LONG_LONG)
BOOST_AUX_LEXICAL_CAST_DEF(boost::ulong_long_type)
BOOST_AUX_LEXICAL_CAST_DEF(boost::long_long_type )
#elif defined(BOOST_HAS_MS_INT64)
BOOST_AUX_LEXICAL_CAST_DEF(unsigned __int64)
BOOST_AUX_LEXICAL_CAST_DEF( __int64)
#endif
#undef BOOST_AUX_LEXICAL_CAST_DEF
#undef BOOST_AUX_LEXICAL_CAST_DEF1
#ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
// This #if is in sync with lcast_precision
// Helper for floating point types.
// -1.23456789e-123456
// ^ sign
// ^ leading digit
// ^ decimal point
// ^^^^^^^^ lcast_precision<Source>::value
// ^ "e"
// ^ exponent sign
// ^^^^^^ exponent (assumed 6 or less digits)
// sign + leading digit + decimal point + "e" + exponent sign == 5
template<class Source>
struct lcast_src_length_floating
{
BOOST_STATIC_ASSERT(
std::numeric_limits<Source>::max_exponent10 <= 999999L &&
std::numeric_limits<Source>::min_exponent10 >= -999999L
);
BOOST_STATIC_CONSTANT(std::size_t, value =
5 + lcast_precision<Source>::value + 6
);
};
template<>
struct lcast_src_length<char,float>
: lcast_src_length_floating<float>
{
static void check_coverage() {}
};
template<>
struct lcast_src_length<char,double>
: lcast_src_length_floating<double>
{
static void check_coverage() {}
};
template<>
struct lcast_src_length<char,long double>
: lcast_src_length_floating<long double>
{
static void check_coverage() {}
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_src_length<wchar_t,float>
: lcast_src_length_floating<float>
{
static void check_coverage() {}
};
template<>
struct lcast_src_length<wchar_t,double>
: lcast_src_length_floating<double>
{
static void check_coverage() {}
};
template<>
struct lcast_src_length<wchar_t,long double>
: lcast_src_length_floating<long double>
{
static void check_coverage() {}
};
#endif // #ifndef DISABLE_WIDE_CHAR_SUPPORT
#endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
}
namespace detail // '0' and '-' constants
{
template<typename CharT> struct lcast_char_constants;
template<>
struct lcast_char_constants<char>
{
BOOST_STATIC_CONSTANT(char, zero = '0');
BOOST_STATIC_CONSTANT(char, minus = '-');
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_char_constants<wchar_t>
{
BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
};
#endif
}
namespace detail // lexical_streambuf and lexical_streambuf_fake
{
template<typename CharT>
class lexical_streambuf : public std::basic_streambuf<CharT>
{
};
template<typename CharT>
struct lexical_streambuf_fake
{
};
}
namespace detail // lcast_to_unsigned
{
#if (defined _MSC_VER)
# pragma warning( push )
// C4146: unary minus operator applied to unsigned type, result still unsigned
# pragma warning( disable : 4146 )
#endif
inline unsigned int lcast_to_unsigned(int value)
{
unsigned int uval = value;
return value < 0 ? -uval : uval;
}
inline unsigned long lcast_to_unsigned(long value)
{
unsigned long uval = value;
return value < 0 ? -uval : uval;
}
#if defined(BOOST_HAS_LONG_LONG)
inline boost::ulong_long_type lcast_to_unsigned(boost::long_long_type v)
{
boost::ulong_long_type uval = v;
return v < 0 ? -uval : uval;
}
#elif defined(BOOST_HAS_MS_INT64)
inline unsigned __int64 lcast_to_unsigned(__int64 value)
{
unsigned __int64 uval = value;
return value < 0 ? -uval : uval;
}
#endif
#if (defined _MSC_VER)
# pragma warning( pop ) // C4146: unary minus operator applied to unsigned type, result still unsigned
#endif
}
namespace detail // lcast_put_unsigned
{
// I'd personally put lcast_put_unsigned in .cpp file if not
// boost practice for header-only libraries (Alexander Nasonov).
template<typename T, typename CharT>
CharT* lcast_put_unsigned(T n, CharT* finish)
{
CharT thousands_sep = 0;
#ifdef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
char const* grouping = "";
std::size_t const grouping_size = 0;
#else
std::locale loc;
typedef std::numpunct<CharT> numpunct;
numpunct const& np = BOOST_USE_FACET(numpunct, loc);
std::string const& grouping = np.grouping();
std::string::size_type const grouping_size = grouping.size();
if(grouping_size)
thousands_sep = np.thousands_sep();
#endif
std::string::size_type group = 0; // current group number
char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
// a) Since grouping is const, grouping[grouping.size()] returns 0.
// b) It's safe to assume here and below that CHAR_MAX
// is equivalent to unlimited grouping:
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
#endif
char left = last_grp_size;
do
{
if(left == 0)
{
++group;
if(group < grouping_size)
{
char const grp_size = grouping[group];
last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
}
left = last_grp_size;
--finish;
*finish = thousands_sep;
}
--left;
--finish;
int const digit = static_cast<int>(n % 10);
int const cdigit = digit + lcast_char_constants<CharT>::zero;
*finish = static_cast<char>(cdigit);
n /= 10;
} while(n);
return finish;
}
}
namespace detail // stream wrapper for handling lexical conversions
{
template<typename Target, typename Source>
class lexical_stream
{
private:
typedef typename widest_char<
typename stream_char<Target>::type,
typename stream_char<Source>::type>::type char_type;
public:
lexical_stream(char_type* = 0, char_type* = 0)
{
stream.unsetf(std::ios::skipws);
lcast_set_precision(stream, (Source*)0, (Target*)0);
}
~lexical_stream()
{
#if defined(BOOST_NO_STRINGSTREAM)
stream.freeze(false);
#endif
}
bool operator<<(const Source &input)
{
return !(stream << input).fail();
}
template<typename InputStreamable>
bool operator>>(InputStreamable &output)
{
return !is_pointer<InputStreamable>::value &&
stream >> output &&
stream.get() ==
#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
// GCC 2.9x lacks std::char_traits<>::eof().
// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
// configurations, which do provide std::char_traits<>::eof().
EOF;
#else
std::char_traits<char_type>::eof();
#endif
}
bool operator>>(std::string &output)
{
#if defined(BOOST_NO_STRINGSTREAM)
stream << '\0';
#endif
stream.str().swap(output);
return true;
}
#ifndef DISABLE_WIDE_CHAR_SUPPORT
bool operator>>(std::wstring &output)
{
stream.str().swap(output);
return true;
}
#endif
private:
#if defined(BOOST_NO_STRINGSTREAM)
std::strstream stream;
#elif defined(BOOST_NO_STD_LOCALE)
std::stringstream stream;
#else
std::basic_stringstream<char_type> stream;
#endif
};
}
namespace detail // optimized stream wrapper
{
// String representation of Source has an upper limit.
template< class CharT // a result of widest_char transformation
, class Base // lexical_streambuf or lexical_streambuf_fake
>
class lexical_stream_limited_src : public Base
{
// A string representation of Source is written to [start, finish).
// Currently, it is assumed that [start, finish) is big enough
// to hold a string representation of any Source value.
CharT* start;
CharT* finish;
private:
static void widen_and_assign(char*p, char ch)
{
*p = ch;
}
#ifndef DISABLE_WIDE_CHAR_SUPPORT
static void widen_and_assign(wchar_t* p, char ch)
{
std::locale loc;
*p = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
}
static void widen_and_assign(wchar_t* p, wchar_t ch)
{
*p = ch;
}
static void widen_and_assign(char*, wchar_t ch); // undefined
#endif
template<class OutputStreamable>
bool lcast_put(const OutputStreamable& input)
{
this->setp(start, finish);
std::basic_ostream<CharT> stream(static_cast<Base*>(this));
lcast_set_precision(stream, (OutputStreamable*)0);
bool const result = !(stream << input).fail();
finish = this->pptr();
return result;
}
// Undefined:
lexical_stream_limited_src(lexical_stream_limited_src const&);
void operator=(lexical_stream_limited_src const&);
public:
lexical_stream_limited_src(CharT* start, CharT* finish)
: start(start)
, finish(finish)
{}
public: // output
template<class Traits, class Alloc>
bool operator<<(std::basic_string<CharT, Traits, Alloc> const& str)
{
start = const_cast<CharT*>(str.data());
finish = start + str.length();
return true;
}
bool operator<<(bool);
bool operator<<(char);
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
bool operator<<(wchar_t);
#endif
bool operator<<(CharT const*);
bool operator<<(short);
bool operator<<(int);
bool operator<<(long);
bool operator<<(unsigned short);
bool operator<<(unsigned int);
bool operator<<(unsigned long);
#if defined(BOOST_HAS_LONG_LONG)
bool operator<<(boost::ulong_long_type);
bool operator<<(boost::long_long_type );
#elif defined(BOOST_HAS_MS_INT64)
bool operator<<(unsigned __int64);
bool operator<<( __int64);
#endif
// These three operators use ostream and streambuf.
// lcast_streambuf_for_source<T>::value is true.
bool operator<<(float);
bool operator<<(double);
bool operator<<(long double);
public: // input
// Generic istream-based algorithm.
// lcast_streambuf_for_target<InputStreamable>::value is true.
template<typename InputStreamable>
bool operator>>(InputStreamable& output)
{
#if (defined _MSC_VER)
# pragma warning( push )
// conditional expression is constant
# pragma warning( disable : 4127 )
#endif
if(is_pointer<InputStreamable>::value)
return false;
this->setg(start, start, finish);
std::basic_istream<CharT> stream(static_cast<Base*>(this));
stream.unsetf(std::ios::skipws);
lcast_set_precision(stream, (InputStreamable*)0);
#if (defined _MSC_VER)
# pragma warning( pop )
#endif
return stream >> output &&
stream.get() ==
#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
// GCC 2.9x lacks std::char_traits<>::eof().
// We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
// configurations, which do provide std::char_traits<>::eof().
EOF;
#else
std::char_traits<CharT>::eof();
#endif
}
bool operator>>(CharT&);
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// This #if is in sync with lcast_streambuf_for_target
bool operator>>(std::string&);
#ifndef DISABLE_WIDE_CHAR_SUPPORT
bool operator>>(std::wstring&);
#endif
#else
template<class Traits, class Alloc>
bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
{
str.assign(start, finish);
return true;
}
#endif
};
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
bool value)
{
*start = value + lcast_char_constants<CharT>::zero;
finish = start + 1;
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(char ch)
{
widen_and_assign(start, ch);
finish = start + 1;
return true;
}
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
wchar_t ch)
{
widen_and_assign(start, ch);
finish = start + 1;
return true;
}
#endif
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(short n)
{
start = lcast_put_unsigned(lcast_to_unsigned(n), finish);
if(n < 0)
*--start = lcast_char_constants<CharT>::minus;
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(int n)
{
start = lcast_put_unsigned(lcast_to_unsigned(n), finish);
if(n < 0)
*--start = lcast_char_constants<CharT>::minus;
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(long n)
{
start = lcast_put_unsigned(lcast_to_unsigned(n), finish);
if(n < 0)
*--start = lcast_char_constants<CharT>::minus;
return true;
}
#if defined(BOOST_HAS_LONG_LONG)
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
boost::long_long_type n)
{
start = lcast_put_unsigned(lcast_to_unsigned(n), finish);
if(n < 0)
*--start = lcast_char_constants<CharT>::minus;
return true;
}
#elif defined(BOOST_HAS_MS_INT64)
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
__int64 n)
{
start = lcast_put_unsigned(lcast_to_unsigned(n), finish);
if(n < 0)
*--start = lcast_char_constants<CharT>::minus;
return true;
}
#endif
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
unsigned short n)
{
start = lcast_put_unsigned(+n, finish);
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
unsigned int n)
{
start = lcast_put_unsigned(n, finish);
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
unsigned long n)
{
start = lcast_put_unsigned(n, finish);
return true;
}
#if defined(BOOST_HAS_LONG_LONG)
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
boost::ulong_long_type n)
{
start = lcast_put_unsigned(n, finish);
return true;
}
#elif defined(BOOST_HAS_MS_INT64)
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
unsigned __int64 n)
{
start = lcast_put_unsigned(n, finish);
return true;
}
#endif
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
float val)
{
return this->lcast_put(val);
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
double val)
{
return this->lcast_put(val);
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
long double val)
{
return this->lcast_put(val);
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator<<(
CharT const* str)
{
start = const_cast<CharT*>(str);
finish = start + std::char_traits<CharT>::length(str);
return true;
}
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator>>(
CharT& output)
{
bool const ok = (finish - start == 1);
if(ok)
output = *start;
return ok;
}
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator>>(
std::string& str)
{
str.assign(start, finish);
return true;
}
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<typename CharT, class Base>
inline bool lexical_stream_limited_src<CharT,Base>::operator>>(
std::wstring& str)
{
str.assign(start, finish);
return true;
}
#endif
#endif
}
namespace detail // lcast_streambuf_for_source
{
// Returns true if optimized stream wrapper uses ostream for formatting.
template<class Source>
struct lcast_streambuf_for_source
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<>
struct lcast_streambuf_for_source<float>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<>
struct lcast_streambuf_for_source<double>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<>
struct lcast_streambuf_for_source<long double>
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
}
namespace detail // lcast_streambuf_for_target
{
// Returns true if optimized stream wrapper use istream for reading.
template<class Target>
struct lcast_streambuf_for_target
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<>
struct lcast_streambuf_for_target<char>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#if !defined(DISABLE_WIDE_CHAR_SUPPORT) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
template<>
struct lcast_streambuf_for_target<wchar_t>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<class Traits, class Alloc>
struct lcast_streambuf_for_target<
std::basic_string<char,Traits,Alloc> >
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<class Traits, class Alloc>
struct lcast_streambuf_for_target<
std::basic_string<wchar_t,Traits,Alloc> >
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#endif
#else
template<>
struct lcast_streambuf_for_target<std::string>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#ifndef DISABLE_WIDE_CHAR_SUPPORT
template<>
struct lcast_streambuf_for_target<std::wstring>
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
#endif
#endif
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// call-by-const reference version
namespace detail
{
template<class T>
struct array_to_pointer_decay
{
typedef T type;
};
template<class T, std::size_t N>
struct array_to_pointer_decay<T[N]>
{
typedef const T * type;
};
template< typename Target
, typename Source
, bool Unlimited // string representation of Source is unlimited
, typename CharT
>
Target lexical_cast(
BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
CharT* buf, std::size_t src_len)
{
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
lcast_streambuf_for_target<Target>::value ||
lcast_streambuf_for_source<Source>::value
, lexical_streambuf<CharT>
, lexical_streambuf_fake<CharT>
>::type base;
BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
Unlimited
, detail::lexical_stream<Target, Source>
, detail::lexical_stream_limited_src<CharT,base>
>::type interpreter(buf, buf + src_len);
// The original form, reproduced below, is more elegant
// but yields a spurious C4701 warning ("possible use of
// "result" before initialization") with VC7.1 (/W4).
//
// Target result;
//
// if(!(interpreter << arg && interpreter >> result))
// throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
// return result;
if(interpreter << arg) {
Target result;
if (interpreter >> result)
return result;
}
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return Target(); // normally never reached (throw_exception)
}
}
template<typename Target, typename Source>
inline Target lexical_cast(const Source &arg)
{
typedef typename detail::array_to_pointer_decay<Source>::type src;
typedef typename detail::widest_char<
typename detail::stream_char<Target>::type
, typename detail::stream_char<src>::type
>::type char_type;
typedef detail::lcast_src_length<char_type, src> lcast_src_length;
std::size_t const src_len = lcast_src_length::value;
char_type buf[src_len + 1];
lcast_src_length::check_coverage();
return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
}
#else
// call-by-value fallback version (deprecated)
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
detail::lexical_stream<Target, Source> interpreter;
Target result;
if(!(interpreter << arg && interpreter >> result))
throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
return result;
}
#endif
}
// Copyright Kevlin Henney, 2000-2005.
// Copyright Alexander Nasonov, 2006.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#undef DISABLE_WIDE_CHAR_SUPPORT
#endif