lexical_cast.hpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214
  1. #ifndef BOOST_LEXICAL_CAST_INCLUDED
  2. #define BOOST_LEXICAL_CAST_INCLUDED
  3. // Boost lexical_cast.hpp header -------------------------------------------//
  4. //
  5. // See http://www.boost.org/libs/conversion for documentation.
  6. // See end of this header for rights and permissions.
  7. //
  8. // what: lexical_cast custom keyword cast
  9. // who: contributed by Kevlin Henney,
  10. // enhanced with contributions from Terje Slettebo,
  11. // with additional fixes and suggestions from Gennaro Prota,
  12. // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov,
  13. // Alexander Nasonov and other Boosters
  14. // when: November 2000, March 2003, June 2005, June 2006
  15. #include <climits>
  16. #include <cstddef>
  17. #include <istream>
  18. #include <string>
  19. #include <typeinfo>
  20. #include <exception>
  21. #include <boost/config.hpp>
  22. #include <boost/limits.hpp>
  23. #include <boost/mpl/if.hpp>
  24. #include <boost/throw_exception.hpp>
  25. #include <boost/type_traits/is_pointer.hpp>
  26. #include <boost/type_traits/make_unsigned.hpp>
  27. #include <boost/call_traits.hpp>
  28. #include <boost/static_assert.hpp>
  29. #include <boost/detail/lcast_precision.hpp>
  30. #include <boost/detail/workaround.hpp>
  31. #ifndef BOOST_NO_STD_LOCALE
  32. #include <locale>
  33. #endif
  34. #ifdef BOOST_NO_STRINGSTREAM
  35. #include <strstream>
  36. #else
  37. #include <sstream>
  38. #endif
  39. #if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_WSTRING)
  40. #define BOOST_LCAST_NO_WCHAR_T
  41. #endif
  42. #ifdef BOOST_NO_TYPEID
  43. #define BOOST_LCAST_THROW_BAD_CAST(S, T) throw_exception(bad_lexical_cast())
  44. #else
  45. #define BOOST_LCAST_THROW_BAD_CAST(Source, Target) \
  46. throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)))
  47. #endif
  48. namespace boost
  49. {
  50. // exception used to indicate runtime lexical_cast failure
  51. class bad_lexical_cast : public std::bad_cast
  52. #if defined(__BORLANDC__) && BOOST_WORKAROUND( __BORLANDC__, < 0x560 )
  53. // under bcc32 5.5.1 bad_cast doesn't derive from exception
  54. , public std::exception
  55. #endif
  56. {
  57. public:
  58. bad_lexical_cast() :
  59. #ifndef BOOST_NO_TYPEID
  60. source(&typeid(void)), target(&typeid(void))
  61. #else
  62. source(0), target(0) // this breaks getters
  63. #endif
  64. {
  65. }
  66. bad_lexical_cast(
  67. const std::type_info &source_type_arg,
  68. const std::type_info &target_type_arg) :
  69. source(&source_type_arg), target(&target_type_arg)
  70. {
  71. }
  72. const std::type_info &source_type() const
  73. {
  74. return *source;
  75. }
  76. const std::type_info &target_type() const
  77. {
  78. return *target;
  79. }
  80. virtual const char *what() const throw()
  81. {
  82. return "bad lexical cast: "
  83. "source type value could not be interpreted as target";
  84. }
  85. virtual ~bad_lexical_cast() throw()
  86. {
  87. }
  88. private:
  89. const std::type_info *source;
  90. const std::type_info *target;
  91. };
  92. namespace detail // selectors for choosing stream character type
  93. {
  94. template<typename Type>
  95. struct stream_char
  96. {
  97. typedef char type;
  98. };
  99. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  100. template<class CharT, class Traits, class Alloc>
  101. struct stream_char< std::basic_string<CharT,Traits,Alloc> >
  102. {
  103. typedef CharT type;
  104. };
  105. #endif
  106. #ifndef BOOST_LCAST_NO_WCHAR_T
  107. #ifndef BOOST_NO_INTRINSIC_WCHAR_T
  108. template<>
  109. struct stream_char<wchar_t>
  110. {
  111. typedef wchar_t type;
  112. };
  113. #endif
  114. template<>
  115. struct stream_char<wchar_t *>
  116. {
  117. typedef wchar_t type;
  118. };
  119. template<>
  120. struct stream_char<const wchar_t *>
  121. {
  122. typedef wchar_t type;
  123. };
  124. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  125. template<>
  126. struct stream_char<std::wstring>
  127. {
  128. typedef wchar_t type;
  129. };
  130. #endif
  131. #endif
  132. template<typename TargetChar, typename SourceChar>
  133. struct widest_char
  134. {
  135. typedef TargetChar type;
  136. };
  137. template<>
  138. struct widest_char<char, wchar_t>
  139. {
  140. typedef wchar_t type;
  141. };
  142. }
  143. namespace detail // deduce_char_traits template
  144. {
  145. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  146. template<class CharT, class Target, class Source>
  147. struct deduce_char_traits
  148. {
  149. typedef std::char_traits<CharT> type;
  150. };
  151. template<class CharT, class Traits, class Alloc, class Source>
  152. struct deduce_char_traits< CharT
  153. , std::basic_string<CharT,Traits,Alloc>
  154. , Source
  155. >
  156. {
  157. typedef Traits type;
  158. };
  159. template<class CharT, class Target, class Traits, class Alloc>
  160. struct deduce_char_traits< CharT
  161. , Target
  162. , std::basic_string<CharT,Traits,Alloc>
  163. >
  164. {
  165. typedef Traits type;
  166. };
  167. template<class CharT, class Traits, class Alloc1, class Alloc2>
  168. struct deduce_char_traits< CharT
  169. , std::basic_string<CharT,Traits,Alloc1>
  170. , std::basic_string<CharT,Traits,Alloc2>
  171. >
  172. {
  173. typedef Traits type;
  174. };
  175. #endif
  176. }
  177. namespace detail // lcast_src_length
  178. {
  179. // Return max. length of string representation of Source;
  180. // 0 if unlimited (with exceptions for some types, see below).
  181. // Values with limited string representation are placed to
  182. // the buffer locally defined in lexical_cast function.
  183. // 1 is returned for few types such as CharT const* or
  184. // std::basic_string<CharT> that already have an internal
  185. // buffer ready to be reused by lexical_stream_limited_src.
  186. // Each specialization should have a correspondent operator<<
  187. // defined in lexical_stream_limited_src.
  188. template< class CharT // A result of widest_char transformation.
  189. , class Source // Source type of lexical_cast.
  190. >
  191. struct lcast_src_length
  192. {
  193. BOOST_STATIC_CONSTANT(std::size_t, value = 0);
  194. // To check coverage, build the test with
  195. // bjam --v2 profile optimization=off
  196. static void check_coverage() {}
  197. };
  198. template<>
  199. struct lcast_src_length<char, bool>
  200. {
  201. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  202. static void check_coverage() {}
  203. };
  204. template<>
  205. struct lcast_src_length<char, char>
  206. {
  207. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  208. static void check_coverage() {}
  209. };
  210. // No specializations for:
  211. // lcast_src_length<char, signed char>
  212. // lcast_src_length<char, unsigned char>
  213. // lcast_src_length<char, signed char*>
  214. // lcast_src_length<char, unsigned char*>
  215. // lcast_src_length<char, signed char const*>
  216. // lcast_src_length<char, unsigned char const*>
  217. #ifndef BOOST_LCAST_NO_WCHAR_T
  218. template<>
  219. struct lcast_src_length<wchar_t, bool>
  220. {
  221. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  222. static void check_coverage() {}
  223. };
  224. template<>
  225. struct lcast_src_length<wchar_t, char>
  226. {
  227. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  228. static void check_coverage() {}
  229. };
  230. #ifndef BOOST_NO_INTRINSIC_WCHAR_T
  231. template<>
  232. struct lcast_src_length<wchar_t, wchar_t>
  233. {
  234. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  235. static void check_coverage() {}
  236. };
  237. #endif
  238. #endif
  239. template<>
  240. struct lcast_src_length<char, char const*>
  241. {
  242. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  243. static void check_coverage() {}
  244. };
  245. template<>
  246. struct lcast_src_length<char, char*>
  247. {
  248. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  249. static void check_coverage() {}
  250. };
  251. #ifndef BOOST_LCAST_NO_WCHAR_T
  252. template<>
  253. struct lcast_src_length<wchar_t, wchar_t const*>
  254. {
  255. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  256. static void check_coverage() {}
  257. };
  258. template<>
  259. struct lcast_src_length<wchar_t, wchar_t*>
  260. {
  261. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  262. static void check_coverage() {}
  263. };
  264. #endif
  265. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  266. template<class CharT, class Traits, class Alloc>
  267. struct lcast_src_length< CharT, std::basic_string<CharT,Traits,Alloc> >
  268. {
  269. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  270. static void check_coverage() {}
  271. };
  272. #else
  273. template<>
  274. struct lcast_src_length< char, std::basic_string<char> >
  275. {
  276. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  277. static void check_coverage() {}
  278. };
  279. #ifndef BOOST_LCAST_NO_WCHAR_T
  280. template<>
  281. struct lcast_src_length< wchar_t, std::basic_string<wchar_t> >
  282. {
  283. BOOST_STATIC_CONSTANT(std::size_t, value = 1);
  284. static void check_coverage() {}
  285. };
  286. #endif
  287. #endif
  288. // Helper for integral types.
  289. // Notes on length calculation:
  290. // Max length for 32bit int with grouping "\1" and thousands_sep ',':
  291. // "-2,1,4,7,4,8,3,6,4,7"
  292. // ^ - is_signed
  293. // ^ - 1 digit not counted by digits10
  294. // ^^^^^^^^^^^^^^^^^^ - digits10 * 2
  295. //
  296. // Constant is_specialized is used instead of constant 1
  297. // to prevent buffer overflow in a rare case when
  298. // <boost/limits.hpp> doesn't add missing specialization for
  299. // numeric_limits<T> for some integral type T.
  300. // When is_specialized is false, the whole expression is 0.
  301. template<class Source>
  302. struct lcast_src_length_integral
  303. {
  304. #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
  305. BOOST_STATIC_CONSTANT(std::size_t, value =
  306. std::numeric_limits<Source>::is_signed +
  307. std::numeric_limits<Source>::is_specialized + // == 1
  308. std::numeric_limits<Source>::digits10 * 2
  309. );
  310. #else
  311. BOOST_STATIC_CONSTANT(std::size_t, value = 156);
  312. BOOST_STATIC_ASSERT(sizeof(Source) * CHAR_BIT <= 256);
  313. #endif
  314. };
  315. #define BOOST_LCAST_DEF1(CharT, T) \
  316. template<> struct lcast_src_length<CharT, T> \
  317. : lcast_src_length_integral<T> \
  318. { static void check_coverage() {} };
  319. #ifdef BOOST_LCAST_NO_WCHAR_T
  320. #define BOOST_LCAST_DEF(T) BOOST_LCAST_DEF1(char, T)
  321. #else
  322. #define BOOST_LCAST_DEF(T) \
  323. BOOST_LCAST_DEF1(char, T) \
  324. BOOST_LCAST_DEF1(wchar_t, T)
  325. #endif
  326. BOOST_LCAST_DEF(short)
  327. BOOST_LCAST_DEF(unsigned short)
  328. BOOST_LCAST_DEF(int)
  329. BOOST_LCAST_DEF(unsigned int)
  330. BOOST_LCAST_DEF(long)
  331. BOOST_LCAST_DEF(unsigned long)
  332. #if defined(BOOST_HAS_LONG_LONG)
  333. BOOST_LCAST_DEF(boost::ulong_long_type)
  334. BOOST_LCAST_DEF(boost::long_long_type )
  335. #elif defined(BOOST_HAS_MS_INT64)
  336. BOOST_LCAST_DEF(unsigned __int64)
  337. BOOST_LCAST_DEF( __int64)
  338. #endif
  339. #undef BOOST_LCAST_DEF
  340. #undef BOOST_LCAST_DEF1
  341. #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
  342. // Helper for floating point types.
  343. // -1.23456789e-123456
  344. // ^ sign
  345. // ^ leading digit
  346. // ^ decimal point
  347. // ^^^^^^^^ lcast_precision<Source>::value
  348. // ^ "e"
  349. // ^ exponent sign
  350. // ^^^^^^ exponent (assumed 6 or less digits)
  351. // sign + leading digit + decimal point + "e" + exponent sign == 5
  352. template<class Source>
  353. struct lcast_src_length_floating
  354. {
  355. BOOST_STATIC_ASSERT(
  356. std::numeric_limits<Source>::max_exponent10 <= 999999L &&
  357. std::numeric_limits<Source>::min_exponent10 >= -999999L
  358. );
  359. BOOST_STATIC_CONSTANT(std::size_t, value =
  360. 5 + lcast_precision<Source>::value + 6
  361. );
  362. };
  363. template<>
  364. struct lcast_src_length<char,float>
  365. : lcast_src_length_floating<float>
  366. {
  367. static void check_coverage() {}
  368. };
  369. template<>
  370. struct lcast_src_length<char,double>
  371. : lcast_src_length_floating<double>
  372. {
  373. static void check_coverage() {}
  374. };
  375. template<>
  376. struct lcast_src_length<char,long double>
  377. : lcast_src_length_floating<long double>
  378. {
  379. static void check_coverage() {}
  380. };
  381. #ifndef BOOST_LCAST_NO_WCHAR_T
  382. template<>
  383. struct lcast_src_length<wchar_t,float>
  384. : lcast_src_length_floating<float>
  385. {
  386. static void check_coverage() {}
  387. };
  388. template<>
  389. struct lcast_src_length<wchar_t,double>
  390. : lcast_src_length_floating<double>
  391. {
  392. static void check_coverage() {}
  393. };
  394. template<>
  395. struct lcast_src_length<wchar_t,long double>
  396. : lcast_src_length_floating<long double>
  397. {
  398. static void check_coverage() {}
  399. };
  400. #endif // #ifndef BOOST_LCAST_NO_WCHAR_T
  401. #endif // #ifndef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
  402. }
  403. namespace detail // '0' and '-' constants
  404. {
  405. template<typename CharT> struct lcast_char_constants;
  406. template<>
  407. struct lcast_char_constants<char>
  408. {
  409. BOOST_STATIC_CONSTANT(char, zero = '0');
  410. BOOST_STATIC_CONSTANT(char, minus = '-');
  411. };
  412. #ifndef BOOST_LCAST_NO_WCHAR_T
  413. template<>
  414. struct lcast_char_constants<wchar_t>
  415. {
  416. BOOST_STATIC_CONSTANT(wchar_t, zero = L'0');
  417. BOOST_STATIC_CONSTANT(wchar_t, minus = L'-');
  418. };
  419. #endif
  420. }
  421. namespace detail // lexical_streambuf_fake
  422. {
  423. struct lexical_streambuf_fake
  424. {
  425. };
  426. }
  427. namespace detail // lcast_to_unsigned
  428. {
  429. #if (defined _MSC_VER)
  430. # pragma warning( push )
  431. // C4146: unary minus operator applied to unsigned type, result still unsigned
  432. # pragma warning( disable : 4146 )
  433. #elif defined( __BORLANDC__ )
  434. # pragma option push -w-8041
  435. #endif
  436. template<class T>
  437. inline
  438. BOOST_DEDUCED_TYPENAME make_unsigned<T>::type lcast_to_unsigned(T value)
  439. {
  440. typedef BOOST_DEDUCED_TYPENAME make_unsigned<T>::type result_type;
  441. result_type uvalue = static_cast<result_type>(value);
  442. return value < 0 ? -uvalue : uvalue;
  443. }
  444. #if (defined _MSC_VER)
  445. # pragma warning( pop )
  446. #elif defined( __BORLANDC__ )
  447. # pragma option pop
  448. #endif
  449. }
  450. namespace detail // lcast_put_unsigned
  451. {
  452. template<class Traits, class T, class CharT>
  453. CharT* lcast_put_unsigned(T n, CharT* finish)
  454. {
  455. #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
  456. BOOST_STATIC_ASSERT(!std::numeric_limits<T>::is_signed);
  457. #endif
  458. #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
  459. // TODO: use BOOST_NO_STD_LOCALE
  460. std::locale loc;
  461. typedef std::numpunct<CharT> numpunct;
  462. numpunct const& np = BOOST_USE_FACET(numpunct, loc);
  463. std::string const& grouping = np.grouping();
  464. std::string::size_type const grouping_size = grouping.size();
  465. CharT thousands_sep = grouping_size ? np.thousands_sep() : 0;
  466. std::string::size_type group = 0; // current group number
  467. char last_grp_size = grouping[0] <= 0 ? CHAR_MAX : grouping[0];
  468. // a) Since grouping is const, grouping[grouping.size()] returns 0.
  469. // b) It's safe to assume here and below that CHAR_MAX
  470. // is equivalent to unlimited grouping:
  471. #ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
  472. BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits10 < CHAR_MAX);
  473. #endif
  474. char left = last_grp_size;
  475. #endif
  476. typedef typename Traits::int_type int_type;
  477. CharT const czero = lcast_char_constants<CharT>::zero;
  478. int_type const zero = Traits::to_int_type(czero);
  479. do
  480. {
  481. #ifndef BOOST_LEXICAL_CAST_ASSUME_C_LOCALE
  482. if(left == 0)
  483. {
  484. ++group;
  485. if(group < grouping_size)
  486. {
  487. char const grp_size = grouping[group];
  488. last_grp_size = grp_size <= 0 ? CHAR_MAX : grp_size;
  489. }
  490. left = last_grp_size;
  491. --finish;
  492. Traits::assign(*finish, thousands_sep);
  493. }
  494. --left;
  495. #endif
  496. --finish;
  497. int_type const digit = static_cast<int_type>(n % 10U);
  498. Traits::assign(*finish, Traits::to_char_type(zero + digit));
  499. n /= 10;
  500. } while(n);
  501. return finish;
  502. }
  503. }
  504. namespace detail // stream wrapper for handling lexical conversions
  505. {
  506. template<typename Target, typename Source, typename Traits>
  507. class lexical_stream
  508. {
  509. private:
  510. typedef typename widest_char<
  511. typename stream_char<Target>::type,
  512. typename stream_char<Source>::type>::type char_type;
  513. typedef Traits traits_type;
  514. public:
  515. lexical_stream(char_type* = 0, char_type* = 0)
  516. {
  517. stream.unsetf(std::ios::skipws);
  518. lcast_set_precision(stream, static_cast<Source*>(0), static_cast<Target*>(0) );
  519. }
  520. ~lexical_stream()
  521. {
  522. #if defined(BOOST_NO_STRINGSTREAM)
  523. stream.freeze(false);
  524. #endif
  525. }
  526. bool operator<<(const Source &input)
  527. {
  528. return !(stream << input).fail();
  529. }
  530. template<typename InputStreamable>
  531. bool operator>>(InputStreamable &output)
  532. {
  533. return !is_pointer<InputStreamable>::value &&
  534. stream >> output &&
  535. stream.get() ==
  536. #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
  537. // GCC 2.9x lacks std::char_traits<>::eof().
  538. // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
  539. // configurations, which do provide std::char_traits<>::eof().
  540. EOF;
  541. #else
  542. traits_type::eof();
  543. #endif
  544. }
  545. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  546. bool operator>>(std::string &output)
  547. {
  548. #if defined(BOOST_NO_STRINGSTREAM)
  549. stream << '\0';
  550. #endif
  551. stream.str().swap(output);
  552. return true;
  553. }
  554. #ifndef BOOST_LCAST_NO_WCHAR_T
  555. bool operator>>(std::wstring &output)
  556. {
  557. stream.str().swap(output);
  558. return true;
  559. }
  560. #endif
  561. #else
  562. bool operator>>(std::basic_string<char_type,traits_type>& output)
  563. {
  564. stream.str().swap(output);
  565. return true;
  566. }
  567. template<class Alloc>
  568. bool operator>>(std::basic_string<char_type,traits_type,Alloc>& out)
  569. {
  570. std::basic_string<char_type,traits_type> str(stream.str());
  571. out.assign(str.begin(), str.end());
  572. return true;
  573. }
  574. #endif
  575. private:
  576. #if defined(BOOST_NO_STRINGSTREAM)
  577. std::strstream stream;
  578. #elif defined(BOOST_NO_STD_LOCALE)
  579. std::stringstream stream;
  580. #else
  581. std::basic_stringstream<char_type,traits_type> stream;
  582. #endif
  583. };
  584. }
  585. namespace detail // optimized stream wrapper
  586. {
  587. // String representation of Source has an upper limit.
  588. template< class CharT // a result of widest_char transformation
  589. , class Base // lexical_streambuf_fake or basic_streambuf<CharT>
  590. , class Traits // usually char_traits<CharT>
  591. >
  592. class lexical_stream_limited_src : public Base
  593. {
  594. // A string representation of Source is written to [start, finish).
  595. // Currently, it is assumed that [start, finish) is big enough
  596. // to hold a string representation of any Source value.
  597. CharT* start;
  598. CharT* finish;
  599. private:
  600. static void widen_and_assign(char*p, char ch)
  601. {
  602. Traits::assign(*p, ch);
  603. }
  604. #ifndef BOOST_LCAST_NO_WCHAR_T
  605. static void widen_and_assign(wchar_t* p, char ch)
  606. {
  607. // TODO: use BOOST_NO_STD_LOCALE
  608. std::locale loc;
  609. wchar_t w = BOOST_USE_FACET(std::ctype<wchar_t>, loc).widen(ch);
  610. Traits::assign(*p, w);
  611. }
  612. static void widen_and_assign(wchar_t* p, wchar_t ch)
  613. {
  614. Traits::assign(*p, ch);
  615. }
  616. static void widen_and_assign(char*, wchar_t ch); // undefined
  617. #endif
  618. template<class OutputStreamable>
  619. bool lcast_put(const OutputStreamable& input)
  620. {
  621. this->setp(start, finish);
  622. std::basic_ostream<CharT> stream(static_cast<Base*>(this));
  623. lcast_set_precision(stream, static_cast<OutputStreamable*>(0));
  624. bool const result = !(stream << input).fail();
  625. finish = this->pptr();
  626. return result;
  627. }
  628. // Undefined:
  629. lexical_stream_limited_src(lexical_stream_limited_src const&);
  630. void operator=(lexical_stream_limited_src const&);
  631. public:
  632. lexical_stream_limited_src(CharT* sta, CharT* fin)
  633. : start(sta)
  634. , finish(fin)
  635. {}
  636. public: // output
  637. template<class Alloc>
  638. bool operator<<(std::basic_string<CharT,Traits,Alloc> const& str)
  639. {
  640. start = const_cast<CharT*>(str.data());
  641. finish = start + str.length();
  642. return true;
  643. }
  644. bool operator<<(bool);
  645. bool operator<<(char);
  646. #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  647. bool operator<<(wchar_t);
  648. #endif
  649. bool operator<<(CharT const*);
  650. bool operator<<(short);
  651. bool operator<<(int);
  652. bool operator<<(long);
  653. bool operator<<(unsigned short);
  654. bool operator<<(unsigned int);
  655. bool operator<<(unsigned long);
  656. #if defined(BOOST_HAS_LONG_LONG)
  657. bool operator<<(boost::ulong_long_type);
  658. bool operator<<(boost::long_long_type );
  659. #elif defined(BOOST_HAS_MS_INT64)
  660. bool operator<<(unsigned __int64);
  661. bool operator<<( __int64);
  662. #endif
  663. // These three operators use ostream and streambuf.
  664. // lcast_streambuf_for_source<T>::value is true.
  665. bool operator<<(float);
  666. bool operator<<(double);
  667. bool operator<<(long double);
  668. public: // input
  669. // Generic istream-based algorithm.
  670. // lcast_streambuf_for_target<InputStreamable>::value is true.
  671. template<typename InputStreamable>
  672. bool operator>>(InputStreamable& output)
  673. {
  674. #if (defined _MSC_VER)
  675. # pragma warning( push )
  676. // conditional expression is constant
  677. # pragma warning( disable : 4127 )
  678. #endif
  679. if(is_pointer<InputStreamable>::value)
  680. return false;
  681. this->setg(start, start, finish);
  682. std::basic_istream<CharT> stream(static_cast<Base*>(this));
  683. stream.unsetf(std::ios::skipws);
  684. lcast_set_precision(stream, static_cast<InputStreamable*>(0));
  685. #if (defined _MSC_VER)
  686. # pragma warning( pop )
  687. #endif
  688. return stream >> output &&
  689. stream.get() ==
  690. #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
  691. // GCC 2.9x lacks std::char_traits<>::eof().
  692. // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3
  693. // configurations, which do provide std::char_traits<>::eof().
  694. EOF;
  695. #else
  696. Traits::eof();
  697. #endif
  698. }
  699. bool operator>>(CharT&);
  700. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  701. // This #if is in sync with lcast_streambuf_for_target
  702. bool operator>>(std::string&);
  703. #ifndef BOOST_LCAST_NO_WCHAR_T
  704. bool operator>>(std::wstring&);
  705. #endif
  706. #else
  707. template<class Alloc>
  708. bool operator>>(std::basic_string<CharT,Traits,Alloc>& str)
  709. {
  710. str.assign(start, finish);
  711. return true;
  712. }
  713. #endif
  714. };
  715. template<typename CharT, class Base, class Traits>
  716. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  717. bool value)
  718. {
  719. typedef typename Traits::int_type int_type;
  720. CharT const czero = lcast_char_constants<CharT>::zero;
  721. int_type const zero = Traits::to_int_type(czero);
  722. Traits::assign(*start, Traits::to_char_type(zero + value));
  723. finish = start + 1;
  724. return true;
  725. }
  726. template<typename CharT, class Base, class Traits>
  727. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  728. char ch)
  729. {
  730. widen_and_assign(start, ch);
  731. finish = start + 1;
  732. return true;
  733. }
  734. #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  735. template<typename CharT, class Base, class Traits>
  736. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  737. wchar_t ch)
  738. {
  739. widen_and_assign(start, ch);
  740. finish = start + 1;
  741. return true;
  742. }
  743. #endif
  744. template<typename CharT, class Base, class Traits>
  745. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  746. short n)
  747. {
  748. start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
  749. if(n < 0)
  750. {
  751. --start;
  752. CharT const minus = lcast_char_constants<CharT>::minus;
  753. Traits::assign(*start, minus);
  754. }
  755. return true;
  756. }
  757. template<typename CharT, class Base, class Traits>
  758. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  759. int n)
  760. {
  761. start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
  762. if(n < 0)
  763. {
  764. --start;
  765. CharT const minus = lcast_char_constants<CharT>::minus;
  766. Traits::assign(*start, minus);
  767. }
  768. return true;
  769. }
  770. template<typename CharT, class Base, class Traits>
  771. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  772. long n)
  773. {
  774. start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
  775. if(n < 0)
  776. {
  777. --start;
  778. CharT const minus = lcast_char_constants<CharT>::minus;
  779. Traits::assign(*start, minus);
  780. }
  781. return true;
  782. }
  783. #if defined(BOOST_HAS_LONG_LONG)
  784. template<typename CharT, class Base, class Traits>
  785. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  786. boost::long_long_type n)
  787. {
  788. start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
  789. if(n < 0)
  790. {
  791. --start;
  792. CharT const minus = lcast_char_constants<CharT>::minus;
  793. Traits::assign(*start, minus);
  794. }
  795. return true;
  796. }
  797. #elif defined(BOOST_HAS_MS_INT64)
  798. template<typename CharT, class Base, class Traits>
  799. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  800. __int64 n)
  801. {
  802. start = lcast_put_unsigned<Traits>(lcast_to_unsigned(n), finish);
  803. if(n < 0)
  804. {
  805. --start;
  806. CharT const minus = lcast_char_constants<CharT>::minus;
  807. Traits::assign(*start, minus);
  808. }
  809. return true;
  810. }
  811. #endif
  812. template<typename CharT, class Base, class Traits>
  813. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  814. unsigned short n)
  815. {
  816. start = lcast_put_unsigned<Traits>(n, finish);
  817. return true;
  818. }
  819. template<typename CharT, class Base, class Traits>
  820. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  821. unsigned int n)
  822. {
  823. start = lcast_put_unsigned<Traits>(n, finish);
  824. return true;
  825. }
  826. template<typename CharT, class Base, class Traits>
  827. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  828. unsigned long n)
  829. {
  830. start = lcast_put_unsigned<Traits>(n, finish);
  831. return true;
  832. }
  833. #if defined(BOOST_HAS_LONG_LONG)
  834. template<typename CharT, class Base, class Traits>
  835. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  836. boost::ulong_long_type n)
  837. {
  838. start = lcast_put_unsigned<Traits>(n, finish);
  839. return true;
  840. }
  841. #elif defined(BOOST_HAS_MS_INT64)
  842. template<typename CharT, class Base, class Traits>
  843. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  844. unsigned __int64 n)
  845. {
  846. start = lcast_put_unsigned<Traits>(n, finish);
  847. return true;
  848. }
  849. #endif
  850. template<typename CharT, class Base, class Traits>
  851. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  852. float val)
  853. {
  854. return this->lcast_put(val);
  855. }
  856. template<typename CharT, class Base, class Traits>
  857. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  858. double val)
  859. {
  860. return this->lcast_put(val);
  861. }
  862. template<typename CharT, class Base, class Traits>
  863. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  864. long double val)
  865. {
  866. return this->lcast_put(val);
  867. }
  868. template<typename CharT, class Base, class Traits>
  869. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator<<(
  870. CharT const* str)
  871. {
  872. start = const_cast<CharT*>(str);
  873. finish = start + Traits::length(str);
  874. return true;
  875. }
  876. template<typename CharT, class Base, class Traits>
  877. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
  878. CharT& output)
  879. {
  880. bool const ok = (finish - start == 1);
  881. if(ok)
  882. Traits::assign(output, *start);
  883. return ok;
  884. }
  885. #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  886. template<typename CharT, class Base, class Traits>
  887. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
  888. std::string& str)
  889. {
  890. str.assign(start, finish);
  891. return true;
  892. }
  893. #ifndef BOOST_LCAST_NO_WCHAR_T
  894. template<typename CharT, class Base, class Traits>
  895. inline bool lexical_stream_limited_src<CharT,Base,Traits>::operator>>(
  896. std::wstring& str)
  897. {
  898. str.assign(start, finish);
  899. return true;
  900. }
  901. #endif
  902. #endif
  903. }
  904. namespace detail // lcast_streambuf_for_source
  905. {
  906. // Returns true if optimized stream wrapper needs ostream for writing.
  907. template<class Source>
  908. struct lcast_streambuf_for_source
  909. {
  910. BOOST_STATIC_CONSTANT(bool, value = false);
  911. };
  912. template<>
  913. struct lcast_streambuf_for_source<float>
  914. {
  915. BOOST_STATIC_CONSTANT(bool, value = true);
  916. };
  917. template<>
  918. struct lcast_streambuf_for_source<double>
  919. {
  920. BOOST_STATIC_CONSTANT(bool, value = true);
  921. };
  922. template<>
  923. struct lcast_streambuf_for_source<long double>
  924. {
  925. BOOST_STATIC_CONSTANT(bool, value = true);
  926. };
  927. }
  928. namespace detail // lcast_streambuf_for_target
  929. {
  930. // Returns true if optimized stream wrapper needs istream for reading.
  931. template<class Target>
  932. struct lcast_streambuf_for_target
  933. {
  934. BOOST_STATIC_CONSTANT(bool, value = true);
  935. };
  936. template<>
  937. struct lcast_streambuf_for_target<char>
  938. {
  939. BOOST_STATIC_CONSTANT(bool, value = false);
  940. };
  941. #if !defined(BOOST_LCAST_NO_WCHAR_T) && !defined(BOOST_NO_INTRINSIC_WCHAR_T)
  942. template<>
  943. struct lcast_streambuf_for_target<wchar_t>
  944. {
  945. BOOST_STATIC_CONSTANT(bool, value = false);
  946. };
  947. #endif
  948. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  949. template<class Traits, class Alloc>
  950. struct lcast_streambuf_for_target<
  951. std::basic_string<char,Traits,Alloc> >
  952. {
  953. BOOST_STATIC_CONSTANT(bool, value = false);
  954. };
  955. #ifndef BOOST_LCAST_NO_WCHAR_T
  956. template<class Traits, class Alloc>
  957. struct lcast_streambuf_for_target<
  958. std::basic_string<wchar_t,Traits,Alloc> >
  959. {
  960. BOOST_STATIC_CONSTANT(bool, value = false);
  961. };
  962. #endif
  963. #else
  964. template<>
  965. struct lcast_streambuf_for_target<std::string>
  966. {
  967. BOOST_STATIC_CONSTANT(bool, value = false);
  968. };
  969. #ifndef BOOST_LCAST_NO_WCHAR_T
  970. template<>
  971. struct lcast_streambuf_for_target<std::wstring>
  972. {
  973. BOOST_STATIC_CONSTANT(bool, value = false);
  974. };
  975. #endif
  976. #endif
  977. }
  978. #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  979. // call-by-const reference version
  980. namespace detail
  981. {
  982. template<class T>
  983. struct array_to_pointer_decay
  984. {
  985. typedef T type;
  986. };
  987. template<class T, std::size_t N>
  988. struct array_to_pointer_decay<T[N]>
  989. {
  990. typedef const T * type;
  991. };
  992. #if (defined _MSC_VER)
  993. # pragma warning( push )
  994. # pragma warning( disable : 4701 ) // possible use of ... before initialization
  995. # pragma warning( disable : 4702 ) // unreachable code
  996. #endif
  997. template< typename Target
  998. , typename Source
  999. , bool Unlimited // string representation of Source is unlimited
  1000. , typename CharT
  1001. >
  1002. Target lexical_cast(
  1003. BOOST_DEDUCED_TYPENAME boost::call_traits<Source>::param_type arg,
  1004. CharT* buf, std::size_t src_len)
  1005. {
  1006. typedef BOOST_DEDUCED_TYPENAME
  1007. deduce_char_traits<CharT,Target,Source>::type traits;
  1008. typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
  1009. lcast_streambuf_for_target<Target>::value ||
  1010. lcast_streambuf_for_source<Source>::value
  1011. , std::basic_streambuf<CharT>
  1012. , lexical_streambuf_fake
  1013. >::type base;
  1014. BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
  1015. Unlimited
  1016. , detail::lexical_stream<Target,Source,traits>
  1017. , detail::lexical_stream_limited_src<CharT,base,traits>
  1018. >::type interpreter(buf, buf + src_len);
  1019. Target result;
  1020. if(!(interpreter << arg && interpreter >> result))
  1021. BOOST_LCAST_THROW_BAD_CAST(Source, Target);
  1022. return result;
  1023. }
  1024. #if (defined _MSC_VER)
  1025. # pragma warning( pop )
  1026. #endif
  1027. }
  1028. template<typename Target, typename Source>
  1029. inline Target lexical_cast(const Source &arg)
  1030. {
  1031. typedef typename detail::array_to_pointer_decay<Source>::type src;
  1032. typedef typename detail::widest_char<
  1033. typename detail::stream_char<Target>::type
  1034. , typename detail::stream_char<src>::type
  1035. >::type char_type;
  1036. typedef detail::lcast_src_length<char_type, src> lcast_src_length;
  1037. std::size_t const src_len = lcast_src_length::value;
  1038. char_type buf[src_len + 1];
  1039. lcast_src_length::check_coverage();
  1040. return detail::lexical_cast<Target, src, !src_len>(arg, buf, src_len);
  1041. }
  1042. #else
  1043. // call-by-value fallback version (deprecated)
  1044. template<typename Target, typename Source>
  1045. Target lexical_cast(Source arg)
  1046. {
  1047. typedef typename detail::widest_char<
  1048. BOOST_DEDUCED_TYPENAME detail::stream_char<Target>::type
  1049. , BOOST_DEDUCED_TYPENAME detail::stream_char<Source>::type
  1050. >::type char_type;
  1051. typedef std::char_traits<char_type> traits;
  1052. detail::lexical_stream<Target, Source, traits> interpreter;
  1053. Target result;
  1054. if(!(interpreter << arg && interpreter >> result))
  1055. #ifndef BOOST_NO_TYPEID
  1056. throw_exception(bad_lexical_cast(typeid(Source), typeid(Target)));
  1057. #else
  1058. throw_exception(bad_lexical_cast());
  1059. #endif
  1060. return result;
  1061. }
  1062. #endif
  1063. }
  1064. // Copyright Kevlin Henney, 2000-2005.
  1065. // Copyright Alexander Nasonov, 2006-2007.
  1066. //
  1067. // Distributed under the Boost Software License, Version 1.0. (See
  1068. // accompanying file LICENSE_1_0.txt or copy at
  1069. // http://www.boost.org/LICENSE_1_0.txt)
  1070. #undef BOOST_LCAST_NO_WCHAR_T
  1071. #endif