| /*============================================================================= |
| Copyright (c) 2001-2014 Joel de Guzman |
| Copyright (c) 2001-2011 Hartmut Kaiser |
| |
| 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) |
| ================================================_==============================*/ |
| #if !defined(BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM) |
| #define BOOST_SPIRIT_X3_PRINT_ATTRIBUTE_JANUARY_20_2013_0814AM |
| |
| #include <boost/variant.hpp> |
| #include <boost/optional/optional.hpp> |
| #include <boost/fusion/include/is_sequence.hpp> |
| #include <boost/fusion/include/for_each.hpp> |
| #include <boost/spirit/home/x3/support/traits/attribute_category.hpp> |
| #include <boost/spirit/home/x3/support/traits/is_variant.hpp> |
| #ifdef BOOST_SPIRIT_X3_UNICODE |
| # include <boost/spirit/home/support/char_encoding/unicode.hpp> |
| #endif |
| |
| namespace boost { namespace spirit { namespace x3 { namespace traits |
| { |
| template <typename Out, typename T> |
| void print_attribute(Out& out, T const& val); |
| |
| template <typename Out> |
| inline void print_attribute(Out&, unused_type) {} |
| |
| /////////////////////////////////////////////////////////////////////////// |
| namespace detail |
| { |
| template <typename Out> |
| struct print_fusion_sequence |
| { |
| print_fusion_sequence(Out& out) |
| : out(out), is_first(true) {} |
| |
| typedef void result_type; |
| |
| template <typename T> |
| void operator()(T const& val) const |
| { |
| if (is_first) |
| is_first = false; |
| else |
| out << ", "; |
| x3::traits::print_attribute(out, val); |
| } |
| |
| Out& out; |
| mutable bool is_first; |
| }; |
| |
| // print elements in a variant |
| template <typename Out> |
| struct print_visitor : static_visitor<> |
| { |
| print_visitor(Out& out) : out(out) {} |
| |
| template <typename T> |
| void operator()(T const& val) const |
| { |
| x3::traits::print_attribute(out, val); |
| } |
| |
| Out& out; |
| }; |
| } |
| |
| template <typename Out, typename T, typename Enable = void> |
| struct print_attribute_debug |
| { |
| // for unused_type |
| static void call(Out& out, unused_type, unused_attribute) |
| { |
| out << "unused"; |
| } |
| |
| // for plain data types |
| template <typename T_> |
| static void call(Out& out, T_ const& val, plain_attribute) |
| { |
| out << val; |
| } |
| |
| #ifdef BOOST_SPIRIT_X3_UNICODE |
| static void call(Out& out, char_encoding::unicode::char_type val, plain_attribute) |
| { |
| if (val >= 0 && val < 127) |
| { |
| if (iscntrl(val)) |
| out << "\\" << std::oct << int(val) << std::dec; |
| else if (isprint(val)) |
| out << char(val); |
| else |
| out << "\\x" << std::hex << int(val) << std::dec; |
| } |
| else |
| out << "\\x" << std::hex << int(val) << std::dec; |
| } |
| |
| static void call(Out& out, char val, plain_attribute tag) |
| { |
| call(out, static_cast<char_encoding::unicode::char_type>(val), tag); |
| } |
| #endif |
| |
| // for fusion data types |
| template <typename T_> |
| static void call(Out& out, T_ const& val, tuple_attribute) |
| { |
| out << '['; |
| fusion::for_each(val, detail::print_fusion_sequence<Out>(out)); |
| out << ']'; |
| } |
| |
| // stl container |
| template <typename T_> |
| static void call(Out& out, T_ const& val, container_attribute) |
| { |
| out << '['; |
| if (!traits::is_empty(val)) |
| { |
| bool first = true; |
| typename container_iterator<T_ const>::type iend = traits::end(val); |
| for (typename container_iterator<T_ const>::type i = traits::begin(val); |
| !traits::compare(i, iend); traits::next(i)) |
| { |
| if (!first) |
| out << ", "; |
| first = false; |
| x3::traits::print_attribute(out, traits::deref(i)); |
| } |
| } |
| out << ']'; |
| } |
| |
| // for variant types |
| template <typename T_> |
| static void call(Out& out, T_ const& val, variant_attribute) |
| { |
| apply_visitor(detail::print_visitor<Out>(out), val); |
| } |
| |
| // for optional types |
| template <typename T_> |
| static void call(Out& out, T_ const& val, optional_attribute) |
| { |
| if (val) |
| x3::traits::print_attribute(out, *val); |
| else |
| out << "[empty]"; |
| } |
| |
| // main entry point |
| static void call(Out& out, T const& val) |
| { |
| call(out, val, typename attribute_category<T>::type()); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Out, typename T> |
| inline void print_attribute(Out& out, T const& val) |
| { |
| print_attribute_debug<Out, T>::call(out, val); |
| } |
| }}}} |
| |
| #endif |