1
// ----------------------------------------------------------------------------
2
// Copyright (C) 2009 Sebastian Redl
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)
8
// For more information, see www.boost.org
9
// ----------------------------------------------------------------------------
11
#ifndef LIBLAS_BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
12
#define LIBLAS_BOOST_PROPERTY_TREE_STREAM_TRANSLATOR_HPP_INCLUDED
14
#include <liblas/external/property_tree/ptree_fwd.hpp>
16
#include <boost/optional.hpp>
17
#include <boost/optional/optional_io.hpp>
18
#include <boost/utility/enable_if.hpp>
19
#include <boost/type_traits/decay.hpp>
20
#include <boost/type_traits/integral_constant.hpp>
26
namespace liblas { namespace property_tree
29
template <typename Ch, typename Traits, typename E, typename Enabler = void>
30
struct customize_stream
32
static void insert(std::basic_ostream<Ch, Traits>& s, const E& e) {
35
static void extract(std::basic_istream<Ch, Traits>& s, E& e) {
43
// No whitespace skipping for single characters.
44
template <typename Ch, typename Traits>
45
struct customize_stream<Ch, Traits, Ch, void>
47
static void insert(std::basic_ostream<Ch, Traits>& s, Ch e) {
50
static void extract(std::basic_istream<Ch, Traits>& s, Ch& e) {
51
s.unsetf(std::ios_base::skipws);
56
// Ugly workaround for numeric_traits that don't have members when not
57
// specialized, e.g. MSVC.
60
template <bool is_specialized>
61
struct is_inexact_impl
66
typedef boost::false_type type;
70
struct is_inexact_impl<true>
75
typedef boost::integral_constant<bool,
76
!std::numeric_limits<T>::is_exact> type;
83
typedef typename boost::decay<F>::type decayed;
84
typedef typename is_inexact_impl<
85
std::numeric_limits<decayed>::is_specialized
86
>::BOOST_NESTED_TEMPLATE test<decayed>::type type;
87
static const bool value = type::value;
91
template <typename Ch, typename Traits, typename F>
92
struct customize_stream<Ch, Traits, F,
93
typename boost::enable_if< detail::is_inexact<F> >::type
96
static void insert(std::basic_ostream<Ch, Traits>& s, const F& e) {
97
s.precision(std::numeric_limits<F>::digits10 + 1);
100
static void extract(std::basic_istream<Ch, Traits>& s, F& e) {
108
template <typename Ch, typename Traits>
109
struct customize_stream<Ch, Traits, bool, void>
111
static void insert(std::basic_ostream<Ch, Traits>& s, bool e) {
112
s.setf(std::ios_base::boolalpha);
115
static void extract(std::basic_istream<Ch, Traits>& s, bool& e) {
118
// Try again in word form.
120
s.setf(std::ios_base::boolalpha);
129
template <typename Ch, typename Traits>
130
struct customize_stream<Ch, Traits, signed char, void>
132
static void insert(std::basic_ostream<Ch, Traits>& s, signed char e) {
135
static void extract(std::basic_istream<Ch, Traits>& s, signed char& e) {
139
if(i > (std::numeric_limits<signed char>::max)() ||
140
i < (std::numeric_limits<signed char>::min)())
142
s.clear(); // guarantees eof to be unset
152
template <typename Ch, typename Traits>
153
struct customize_stream<Ch, Traits, unsigned char, void>
155
static void insert(std::basic_ostream<Ch, Traits>& s, unsigned char e) {
158
static void extract(std::basic_istream<Ch,Traits>& s, unsigned char& e){
162
if(i > (std::numeric_limits<unsigned char>::max)()) {
163
s.clear(); // guarantees eof to be unset
166
e = (unsigned char)i;
173
/// Implementation of Translator that uses the stream overloads.
174
template <typename Ch, typename Traits, typename Alloc, typename E>
175
class stream_translator
177
typedef customize_stream<Ch, Traits, E> customized;
179
typedef std::basic_string<Ch, Traits, Alloc> internal_type;
180
typedef E external_type;
182
explicit stream_translator(std::locale loc = std::locale())
186
boost::optional<E> get_value(const internal_type &v) {
187
std::basic_istringstream<Ch, Traits, Alloc> iss(v);
190
customized::extract(iss, e);
191
if(iss.fail() || iss.bad() || iss.get() != Traits::eof()) {
192
return boost::optional<E>();
196
boost::optional<internal_type> put_value(const E &v) {
197
std::basic_ostringstream<Ch, Traits, Alloc> oss;
199
customized::insert(oss, v);
203
return boost::optional<internal_type>();
210
// This is the default translator when basic_string is the internal type.
211
// Unless the external type is also basic_string, in which case
212
// id_translator takes over.
213
template <typename Ch, typename Traits, typename Alloc, typename E>
214
struct translator_between<std::basic_string<Ch, Traits, Alloc>, E>
216
typedef stream_translator<Ch, Traits, Alloc, E> type;