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