1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // Copyright (c) 2010 Bryce Lelbach 3 // 4 // Distributed under the Boost Software License, Version 1.0. (See accompanying 5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_SPIRIT_KARMA_DIRECTIVE_AS_HPP 8 #define BOOST_SPIRIT_KARMA_DIRECTIVE_AS_HPP 9 10 #if defined(_MSC_VER) 11 #pragma once 12 #endif 13 14 #include <boost/spirit/home/karma/meta_compiler.hpp> 15 #include <boost/spirit/home/karma/generator.hpp> 16 #include <boost/spirit/home/karma/domain.hpp> 17 #include <boost/spirit/home/karma/detail/output_iterator.hpp> 18 #include <boost/spirit/home/karma/detail/as.hpp> 19 #include <boost/spirit/home/support/unused.hpp> 20 #include <boost/spirit/home/support/info.hpp> 21 #include <boost/spirit/home/support/common_terminals.hpp> 22 #include <boost/spirit/home/support/has_semantic_action.hpp> 23 #include <boost/spirit/home/support/handles_container.hpp> 24 #include <boost/spirit/home/support/assert_msg.hpp> 25 #include <boost/spirit/home/support/container.hpp> 26 #include <boost/spirit/home/karma/detail/attributes.hpp> 27 28 namespace boost { namespace spirit { namespace karma 29 { 30 template <typename T> 31 struct as 32 : stateful_tag_type<T, tag::as> 33 { 34 BOOST_SPIRIT_ASSERT_MSG( 35 (traits::is_container<T>::type::value), 36 error_type_must_be_a_container, 37 (T)); 38 }; 39 }}} 40 41 namespace boost { namespace spirit 42 { 43 /////////////////////////////////////////////////////////////////////////// 44 // Enablers 45 /////////////////////////////////////////////////////////////////////////// 46 // enables as_string[...] 47 template <> 48 struct use_directive<karma::domain, tag::as_string> 49 : mpl::true_ {}; 50 51 // enables as_wstring[...] 52 template <> 53 struct use_directive<karma::domain, tag::as_wstring> 54 : mpl::true_ {}; 55 56 // enables as<T>[...] 57 template <typename T> 58 struct use_directive<karma::domain, tag::stateful_tag<T, tag::as> > 59 : mpl::true_ 60 {}; 61 }} 62 63 namespace boost { namespace spirit { namespace karma 64 { 65 #ifndef BOOST_SPIRIT_NO_PREDEFINED_TERMINALS 66 using spirit::as_string; 67 using spirit::as_wstring; 68 #endif 69 using spirit::as_string_type; 70 using spirit::as_wstring_type; 71 72 /////////////////////////////////////////////////////////////////////////// 73 // as_directive allows to hook custom conversions to string into the 74 // output generation process 75 /////////////////////////////////////////////////////////////////////////// 76 template <typename Subject, typename T> 77 struct as_directive 78 : unary_generator<as_directive<Subject, T> > 79 { 80 typedef Subject subject_type; 81 typedef typename subject_type::properties properties; 82 as_directiveboost::spirit::karma::as_directive83 as_directive(Subject const& subject) 84 : subject(subject) {} 85 86 template <typename Context, typename Iterator> 87 struct attribute 88 { 89 typedef T type; 90 }; 91 92 template <typename OutputIterator, typename Context, typename Delimiter 93 , typename Attribute> generateboost::spirit::karma::as_directive94 bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d 95 , Attribute const& attr) const 96 { 97 if (!traits::valid_as<T>(attr)) 98 return false; 99 100 return subject.generate(sink, ctx, d, traits::as<T>(attr)) && 101 karma::delimit_out(sink, d); // always do post-delimiting 102 } 103 104 template <typename Context> whatboost::spirit::karma::as_directive105 info what(Context& context) const 106 { 107 return info("as", subject.what(context)); 108 } 109 110 Subject subject; 111 }; 112 113 /////////////////////////////////////////////////////////////////////////// 114 // Generator generators: make_xxx function (objects) 115 /////////////////////////////////////////////////////////////////////////// 116 template <typename Subject, typename Modifiers> 117 struct make_directive<tag::as_string, Subject, Modifiers> 118 { 119 typedef as_directive<Subject, std::string> result_type; operator ()boost::spirit::karma::make_directive120 result_type operator()(unused_type, Subject const& subject 121 , unused_type) const 122 { 123 return result_type(subject); 124 } 125 }; 126 127 template <typename Subject, typename Modifiers> 128 struct make_directive<tag::as_wstring, Subject, Modifiers> 129 { 130 typedef as_directive<Subject, std::basic_string<wchar_t> > result_type; operator ()boost::spirit::karma::make_directive131 result_type operator()(unused_type, Subject const& subject 132 , unused_type) const 133 { 134 return result_type(subject); 135 } 136 }; 137 138 template <typename T, typename Subject, typename Modifiers> 139 struct make_directive<tag::stateful_tag<T, tag::as>, Subject, Modifiers> 140 { 141 typedef as_directive<Subject, T> result_type; operator ()boost::spirit::karma::make_directive142 result_type operator()(unused_type, Subject const& subject 143 , unused_type) const 144 { 145 return result_type(subject); 146 } 147 }; 148 }}} 149 150 namespace boost { namespace spirit { namespace traits 151 { 152 /////////////////////////////////////////////////////////////////////////// 153 template <typename Subject, typename T> 154 struct has_semantic_action<karma::as_directive<Subject, T> > 155 : unary_has_semantic_action<Subject> {}; 156 157 /////////////////////////////////////////////////////////////////////////// 158 template <typename Subject, typename T, typename Attribute 159 , typename Context, typename Iterator> 160 struct handles_container<karma::as_directive<Subject, T>, Attribute 161 , Context, Iterator> 162 : mpl::false_ {}; // always dereference attribute if used in sequences 163 }}} 164 165 #endif 166