Chris@16: // ---------------------------------------------------------------------------- Chris@16: // Copyright (C) 2009 Sebastian Redl Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: // Chris@16: // For more information, see www.boost.org Chris@16: // ---------------------------------------------------------------------------- Chris@16: Chris@16: #ifndef BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED Chris@16: #define BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace property_tree Chris@16: { Chris@16: Chris@16: template Chris@16: struct customize_stream Chris@16: { Chris@16: static void insert(std::basic_ostream& s, const E& e) { Chris@16: s << e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, E& e) { Chris@16: s >> e; Chris@16: if(!s.eof()) { Chris@16: s >> std::ws; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: // No whitespace skipping for single characters. Chris@16: template Chris@16: struct customize_stream Chris@16: { Chris@16: static void insert(std::basic_ostream& s, Ch e) { Chris@16: s << e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, Ch& e) { Chris@16: s.unsetf(std::ios_base::skipws); Chris@16: s >> e; Chris@16: } Chris@16: }; Chris@16: Chris@16: // Ugly workaround for numeric_traits that don't have members when not Chris@16: // specialized, e.g. MSVC. Chris@16: namespace detail Chris@16: { Chris@16: template Chris@16: struct is_inexact_impl Chris@16: { Chris@16: template Chris@16: struct test Chris@16: { Chris@16: typedef boost::false_type type; Chris@16: }; Chris@16: }; Chris@16: template <> Chris@16: struct is_inexact_impl Chris@16: { Chris@16: template Chris@16: struct test Chris@16: { Chris@16: typedef boost::integral_constant::is_exact> type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct is_inexact Chris@16: { Chris@16: typedef typename boost::decay::type decayed; Chris@16: typedef typename is_inexact_impl< Chris@16: std::numeric_limits::is_specialized Chris@16: >::BOOST_NESTED_TEMPLATE test::type type; Chris@16: static const bool value = type::value; Chris@16: }; Chris@16: } Chris@16: Chris@16: template Chris@16: struct customize_stream >::type Chris@16: > Chris@16: { Chris@16: static void insert(std::basic_ostream& s, const F& e) { Chris@101: #ifndef BOOST_NO_CXX11_NUMERIC_LIMITS Chris@101: s.precision(std::numeric_limits::max_digits10); Chris@101: #else Chris@101: s.precision(std::numeric_limits::digits10 + 2); Chris@101: #endif Chris@16: s << e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, F& e) { Chris@16: s >> e; Chris@16: if(!s.eof()) { Chris@16: s >> std::ws; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct customize_stream Chris@16: { Chris@16: static void insert(std::basic_ostream& s, bool e) { Chris@16: s.setf(std::ios_base::boolalpha); Chris@16: s << e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, bool& e) { Chris@16: s >> e; Chris@16: if(s.fail()) { Chris@16: // Try again in word form. Chris@16: s.clear(); Chris@16: s.setf(std::ios_base::boolalpha); Chris@16: s >> e; Chris@16: } Chris@16: if(!s.eof()) { Chris@16: s >> std::ws; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct customize_stream Chris@16: { Chris@16: static void insert(std::basic_ostream& s, signed char e) { Chris@16: s << (int)e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, signed char& e) { Chris@16: int i; Chris@16: s >> i; Chris@16: // out of range? Chris@16: if(i > (std::numeric_limits::max)() || Chris@16: i < (std::numeric_limits::min)()) Chris@16: { Chris@16: s.clear(); // guarantees eof to be unset Chris@101: e = 0; Chris@101: s.setstate(std::ios_base::badbit); Chris@16: return; Chris@16: } Chris@16: e = (signed char)i; Chris@16: if(!s.eof()) { Chris@16: s >> std::ws; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct customize_stream Chris@16: { Chris@16: static void insert(std::basic_ostream& s, unsigned char e) { Chris@16: s << (unsigned)e; Chris@16: } Chris@16: static void extract(std::basic_istream& s, unsigned char& e){ Chris@16: unsigned i; Chris@16: s >> i; Chris@16: // out of range? Chris@16: if(i > (std::numeric_limits::max)()) { Chris@16: s.clear(); // guarantees eof to be unset Chris@101: e = 0; Chris@101: s.setstate(std::ios_base::badbit); Chris@16: return; Chris@16: } Chris@16: e = (unsigned char)i; Chris@16: if(!s.eof()) { Chris@16: s >> std::ws; Chris@16: } Chris@16: } Chris@16: }; Chris@16: Chris@16: /// Implementation of Translator that uses the stream overloads. Chris@16: template Chris@16: class stream_translator Chris@16: { Chris@16: typedef customize_stream customized; Chris@16: public: Chris@16: typedef std::basic_string internal_type; Chris@16: typedef E external_type; Chris@16: Chris@16: explicit stream_translator(std::locale loc = std::locale()) Chris@16: : m_loc(loc) Chris@16: {} Chris@16: Chris@16: boost::optional get_value(const internal_type &v) { Chris@16: std::basic_istringstream iss(v); Chris@16: iss.imbue(m_loc); Chris@16: E e; Chris@16: customized::extract(iss, e); Chris@16: if(iss.fail() || iss.bad() || iss.get() != Traits::eof()) { Chris@16: return boost::optional(); Chris@16: } Chris@16: return e; Chris@16: } Chris@16: boost::optional put_value(const E &v) { Chris@16: std::basic_ostringstream oss; Chris@16: oss.imbue(m_loc); Chris@16: customized::insert(oss, v); Chris@16: if(oss) { Chris@16: return oss.str(); Chris@16: } Chris@16: return boost::optional(); Chris@16: } Chris@16: Chris@16: private: Chris@16: std::locale m_loc; Chris@16: }; Chris@16: Chris@16: // This is the default translator when basic_string is the internal type. Chris@16: // Unless the external type is also basic_string, in which case Chris@16: // id_translator takes over. Chris@16: template Chris@16: struct translator_between, E> Chris@16: { Chris@16: typedef stream_translator type; Chris@16: }; Chris@16: Chris@16: }} Chris@16: Chris@16: #endif