lexical_cast.hpp 38 KB

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