/Src/Dependencies/Boost/boost/property_tree/stream_translator.hpp

http://hadesmem.googlecode.com/ · C++ Header · 221 lines · 183 code · 19 blank · 19 comment · 13 complexity · 5465455482a3e6fb5a6f7c0211dc5c4f MD5 · raw file

  1. // ----------------------------------------------------------------------------
  2. // Copyright (C) 2009 Sebastian Redl
  3. //
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // For more information, see www.boost.org
  9. // ----------------------------------------------------------------------------
  10. #ifndef BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
  11. #define BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
  12. #include <boost/property_tree/ptree_fwd.hpp>
  13. #include <boost/optional.hpp>
  14. #include <boost/optional/optional_io.hpp>
  15. #include <boost/utility/enable_if.hpp>
  16. #include <boost/type_traits/decay.hpp>
  17. #include <boost/type_traits/integral_constant.hpp>
  18. #include <sstream>
  19. #include <string>
  20. #include <locale>
  21. #include <limits>
  22. namespace boost { namespace property_tree
  23. {
  24. template <typename Ch, typename Traits, typename E, typename Enabler = void>
  25. struct customize_stream
  26. {
  27. static void insert(std::basic_ostream<Ch, Traits>& s, const E& e) {
  28. s << e;
  29. }
  30. static void extract(std::basic_istream<Ch, Traits>& s, E& e) {
  31. s >> e;
  32. if(!s.eof()) {
  33. s >> std::ws;
  34. }
  35. }
  36. };
  37. // No whitespace skipping for single characters.
  38. template <typename Ch, typename Traits>
  39. struct customize_stream<Ch, Traits, Ch, void>
  40. {
  41. static void insert(std::basic_ostream<Ch, Traits>& s, Ch e) {
  42. s << e;
  43. }
  44. static void extract(std::basic_istream<Ch, Traits>& s, Ch& e) {
  45. s.unsetf(std::ios_base::skipws);
  46. s >> e;
  47. }
  48. };
  49. // Ugly workaround for numeric_traits that don't have members when not
  50. // specialized, e.g. MSVC.
  51. namespace detail
  52. {
  53. template <bool is_specialized>
  54. struct is_inexact_impl
  55. {
  56. template <typename T>
  57. struct test
  58. {
  59. typedef boost::false_type type;
  60. };
  61. };
  62. template <>
  63. struct is_inexact_impl<true>
  64. {
  65. template <typename T>
  66. struct test
  67. {
  68. typedef boost::integral_constant<bool,
  69. !std::numeric_limits<T>::is_exact> type;
  70. };
  71. };
  72. template <typename F>
  73. struct is_inexact
  74. {
  75. typedef typename boost::decay<F>::type decayed;
  76. typedef typename is_inexact_impl<
  77. std::numeric_limits<decayed>::is_specialized
  78. >::BOOST_NESTED_TEMPLATE test<decayed>::type type;
  79. static const bool value = type::value;
  80. };
  81. }
  82. template <typename Ch, typename Traits, typename F>
  83. struct customize_stream<Ch, Traits, F,
  84. typename boost::enable_if< detail::is_inexact<F> >::type
  85. >
  86. {
  87. static void insert(std::basic_ostream<Ch, Traits>& s, const F& e) {
  88. s.precision(std::numeric_limits<F>::digits10 + 1);
  89. s << e;
  90. }
  91. static void extract(std::basic_istream<Ch, Traits>& s, F& e) {
  92. s >> e;
  93. if(!s.eof()) {
  94. s >> std::ws;
  95. }
  96. }
  97. };
  98. template <typename Ch, typename Traits>
  99. struct customize_stream<Ch, Traits, bool, void>
  100. {
  101. static void insert(std::basic_ostream<Ch, Traits>& s, bool e) {
  102. s.setf(std::ios_base::boolalpha);
  103. s << e;
  104. }
  105. static void extract(std::basic_istream<Ch, Traits>& s, bool& e) {
  106. s >> e;
  107. if(s.fail()) {
  108. // Try again in word form.
  109. s.clear();
  110. s.setf(std::ios_base::boolalpha);
  111. s >> e;
  112. }
  113. if(!s.eof()) {
  114. s >> std::ws;
  115. }
  116. }
  117. };
  118. template <typename Ch, typename Traits>
  119. struct customize_stream<Ch, Traits, signed char, void>
  120. {
  121. static void insert(std::basic_ostream<Ch, Traits>& s, signed char e) {
  122. s << (int)e;
  123. }
  124. static void extract(std::basic_istream<Ch, Traits>& s, signed char& e) {
  125. int i;
  126. s >> i;
  127. // out of range?
  128. if(i > (std::numeric_limits<signed char>::max)() ||
  129. i < (std::numeric_limits<signed char>::min)())
  130. {
  131. s.clear(); // guarantees eof to be unset
  132. return;
  133. }
  134. e = (signed char)i;
  135. if(!s.eof()) {
  136. s >> std::ws;
  137. }
  138. }
  139. };
  140. template <typename Ch, typename Traits>
  141. struct customize_stream<Ch, Traits, unsigned char, void>
  142. {
  143. static void insert(std::basic_ostream<Ch, Traits>& s, unsigned char e) {
  144. s << (unsigned)e;
  145. }
  146. static void extract(std::basic_istream<Ch,Traits>& s, unsigned char& e){
  147. unsigned i;
  148. s >> i;
  149. // out of range?
  150. if(i > (std::numeric_limits<unsigned char>::max)()) {
  151. s.clear(); // guarantees eof to be unset
  152. return;
  153. }
  154. e = (unsigned char)i;
  155. if(!s.eof()) {
  156. s >> std::ws;
  157. }
  158. }
  159. };
  160. /// Implementation of Translator that uses the stream overloads.
  161. template <typename Ch, typename Traits, typename Alloc, typename E>
  162. class stream_translator
  163. {
  164. typedef customize_stream<Ch, Traits, E> customized;
  165. public:
  166. typedef std::basic_string<Ch, Traits, Alloc> internal_type;
  167. typedef E external_type;
  168. explicit stream_translator(std::locale loc = std::locale())
  169. : m_loc(loc)
  170. {}
  171. boost::optional<E> get_value(const internal_type &v) {
  172. std::basic_istringstream<Ch, Traits, Alloc> iss(v);
  173. iss.imbue(m_loc);
  174. E e;
  175. customized::extract(iss, e);
  176. if(iss.fail() || iss.bad() || iss.get() != Traits::eof()) {
  177. return boost::optional<E>();
  178. }
  179. return e;
  180. }
  181. boost::optional<internal_type> put_value(const E &v) {
  182. std::basic_ostringstream<Ch, Traits, Alloc> oss;
  183. oss.imbue(m_loc);
  184. customized::insert(oss, v);
  185. if(oss) {
  186. return oss.str();
  187. }
  188. return boost::optional<internal_type>();
  189. }
  190. private:
  191. std::locale m_loc;
  192. };
  193. // This is the default translator when basic_string is the internal type.
  194. // Unless the external type is also basic_string, in which case
  195. // id_translator takes over.
  196. template <typename Ch, typename Traits, typename Alloc, typename E>
  197. struct translator_between<std::basic_string<Ch, Traits, Alloc>, E>
  198. {
  199. typedef stream_translator<Ch, Traits, Alloc, E> type;
  200. };
  201. }}
  202. #endif