]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
f67539c2 TL |
7 | #ifndef BOOST_SPIRIT_KARMA_DIRECTIVE_AS_HPP |
8 | #define BOOST_SPIRIT_KARMA_DIRECTIVE_AS_HPP | |
7c673cae FG |
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 | ||
83 | 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> | |
94 | 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> | |
105 | 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; | |
120 | 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; | |
131 | 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; | |
142 | 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 |