You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
221 lines
6.7 KiB
221 lines
6.7 KiB
// ---------------------------------------------------------------------------- |
|
// 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 <boost/property_tree/ptree_fwd.hpp> |
|
|
|
#include <boost/optional.hpp> |
|
#include <boost/optional/optional_io.hpp> |
|
#include <boost/utility/enable_if.hpp> |
|
#include <boost/type_traits/decay.hpp> |
|
#include <boost/type_traits/integral_constant.hpp> |
|
#include <sstream> |
|
#include <string> |
|
#include <locale> |
|
#include <limits> |
|
|
|
namespace boost { namespace property_tree |
|
{ |
|
|
|
template <typename Ch, typename Traits, typename E, typename Enabler = void> |
|
struct customize_stream |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, const E& e) { |
|
s << e; |
|
} |
|
static void extract(std::basic_istream<Ch, Traits>& s, E& e) { |
|
s >> e; |
|
if(!s.eof()) { |
|
s >> std::ws; |
|
} |
|
} |
|
}; |
|
|
|
// No whitespace skipping for single characters. |
|
template <typename Ch, typename Traits> |
|
struct customize_stream<Ch, Traits, Ch, void> |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, Ch e) { |
|
s << e; |
|
} |
|
static void extract(std::basic_istream<Ch, Traits>& 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 <bool is_specialized> |
|
struct is_inexact_impl |
|
{ |
|
template <typename T> |
|
struct test |
|
{ |
|
typedef boost::false_type type; |
|
}; |
|
}; |
|
template <> |
|
struct is_inexact_impl<true> |
|
{ |
|
template <typename T> |
|
struct test |
|
{ |
|
typedef boost::integral_constant<bool, |
|
!std::numeric_limits<T>::is_exact> type; |
|
}; |
|
}; |
|
|
|
template <typename F> |
|
struct is_inexact |
|
{ |
|
typedef typename boost::decay<F>::type decayed; |
|
typedef typename is_inexact_impl< |
|
std::numeric_limits<decayed>::is_specialized |
|
>::BOOST_NESTED_TEMPLATE test<decayed>::type type; |
|
static const bool value = type::value; |
|
}; |
|
} |
|
|
|
template <typename Ch, typename Traits, typename F> |
|
struct customize_stream<Ch, Traits, F, |
|
typename boost::enable_if< detail::is_inexact<F> >::type |
|
> |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, const F& e) { |
|
s.precision(std::numeric_limits<F>::digits10 + 1); |
|
s << e; |
|
} |
|
static void extract(std::basic_istream<Ch, Traits>& s, F& e) { |
|
s >> e; |
|
if(!s.eof()) { |
|
s >> std::ws; |
|
} |
|
} |
|
}; |
|
|
|
template <typename Ch, typename Traits> |
|
struct customize_stream<Ch, Traits, bool, void> |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, bool e) { |
|
s.setf(std::ios_base::boolalpha); |
|
s << e; |
|
} |
|
static void extract(std::basic_istream<Ch, Traits>& 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 <typename Ch, typename Traits> |
|
struct customize_stream<Ch, Traits, signed char, void> |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, signed char e) { |
|
s << (int)e; |
|
} |
|
static void extract(std::basic_istream<Ch, Traits>& s, signed char& e) { |
|
int i; |
|
s >> i; |
|
// out of range? |
|
if(i > (std::numeric_limits<signed char>::max)() || |
|
i < (std::numeric_limits<signed char>::min)()) |
|
{ |
|
s.clear(); // guarantees eof to be unset |
|
return; |
|
} |
|
e = (signed char)i; |
|
if(!s.eof()) { |
|
s >> std::ws; |
|
} |
|
} |
|
}; |
|
|
|
template <typename Ch, typename Traits> |
|
struct customize_stream<Ch, Traits, unsigned char, void> |
|
{ |
|
static void insert(std::basic_ostream<Ch, Traits>& s, unsigned char e) { |
|
s << (unsigned)e; |
|
} |
|
static void extract(std::basic_istream<Ch,Traits>& s, unsigned char& e){ |
|
unsigned i; |
|
s >> i; |
|
// out of range? |
|
if(i > (std::numeric_limits<unsigned char>::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 <typename Ch, typename Traits, typename Alloc, typename E> |
|
class stream_translator |
|
{ |
|
typedef customize_stream<Ch, Traits, E> customized; |
|
public: |
|
typedef std::basic_string<Ch, Traits, Alloc> internal_type; |
|
typedef E external_type; |
|
|
|
explicit stream_translator(std::locale loc = std::locale()) |
|
: m_loc(loc) |
|
{} |
|
|
|
boost::optional<E> get_value(const internal_type &v) { |
|
std::basic_istringstream<Ch, Traits, Alloc> iss(v); |
|
iss.imbue(m_loc); |
|
E e; |
|
customized::extract(iss, e); |
|
if(iss.fail() || iss.bad() || iss.get() != Traits::eof()) { |
|
return boost::optional<E>(); |
|
} |
|
return e; |
|
} |
|
boost::optional<internal_type> put_value(const E &v) { |
|
std::basic_ostringstream<Ch, Traits, Alloc> oss; |
|
oss.imbue(m_loc); |
|
customized::insert(oss, v); |
|
if(oss) { |
|
return oss.str(); |
|
} |
|
return boost::optional<internal_type>(); |
|
} |
|
|
|
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 <typename Ch, typename Traits, typename Alloc, typename E> |
|
struct translator_between<std::basic_string<Ch, Traits, Alloc>, E> |
|
{ |
|
typedef stream_translator<Ch, Traits, Alloc, E> type; |
|
}; |
|
|
|
}} |
|
|
|
#endif
|
|
|