1 //  Copyright (c) 2001-2011 Hartmut Kaiser
2 //
3 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
4 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 #if !defined(BOOST_PP_IS_ITERATING)
7 
8 #if !defined(BOOST_SPIRIT_KARMA_GENERATE_ATTR_APR_23_2009_0541PM)
9 #define BOOST_SPIRIT_KARMA_GENERATE_ATTR_APR_23_2009_0541PM
10 
11 #include <boost/spirit/home/karma/generate.hpp>
12 
13 #include <boost/fusion/include/vector.hpp>
14 #include <boost/preprocessor/cat.hpp>
15 #include <boost/preprocessor/iterate.hpp>
16 #include <boost/preprocessor/repetition/enum.hpp>
17 #include <boost/preprocessor/repetition/enum_params.hpp>
18 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
19 
20 #define BOOST_PP_FILENAME_1 <boost/spirit/home/karma/generate_attr.hpp>
21 #define BOOST_PP_ITERATION_LIMITS (2, SPIRIT_ARGUMENTS_LIMIT)
22 #include BOOST_PP_ITERATE()
23 
24 #endif
25 
26 ///////////////////////////////////////////////////////////////////////////////
27 //
28 //  Preprocessor vertical repetition code
29 //
30 ///////////////////////////////////////////////////////////////////////////////
31 #else // defined(BOOST_PP_IS_ITERATING)
32 
33 #define N BOOST_PP_ITERATION()
34 #define BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE(z, n, A)                       \
35     BOOST_PP_CAT(A, n) const&
36 
37 namespace boost { namespace spirit { namespace karma
38 {
39     ///////////////////////////////////////////////////////////////////////////
40     template <typename OutputIterator, typename Properties, typename Expr
41       , BOOST_PP_ENUM_PARAMS(N, typename A)>
42     inline bool
generate(detail::output_iterator<OutputIterator,Properties> & sink,Expr const & expr,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))43     generate(
44         detail::output_iterator<OutputIterator, Properties>& sink
45       , Expr const& expr
46       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
47     {
48         // Report invalid expression error as early as possible.
49         // If you got an error_invalid_expression error message here,
50         // then the expression (expr) is not a valid spirit karma expression.
51         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
52 
53         typedef fusion::vector<
54             BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
55         > vector_type;
56 
57         vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
58         return compile<karma::domain>(expr).generate(sink, unused, unused, attr);
59     }
60 
61     template <typename OutputIterator, typename Expr
62       , BOOST_PP_ENUM_PARAMS(N, typename A)>
63     inline bool
generate(OutputIterator & sink_,Expr const & expr,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))64     generate(
65         OutputIterator& sink_
66       , Expr const& expr
67       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
68     {
69         typedef traits::properties_of<
70             typename result_of::compile<karma::domain, Expr>::type
71         > properties;
72 
73         // wrap user supplied iterator into our own output iterator
74         detail::output_iterator<OutputIterator
75           , mpl::int_<properties::value> > sink(sink_);
76         return karma::generate(sink, expr, BOOST_PP_ENUM_PARAMS(N, attr));
77     }
78 
79     template <typename OutputIterator, typename Expr
80       , BOOST_PP_ENUM_PARAMS(N, typename A)>
81     inline bool
generate(OutputIterator const & sink_,Expr const & expr,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))82     generate(
83         OutputIterator const& sink_
84       , Expr const& expr
85       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
86     {
87         OutputIterator sink = sink_;
88         return karma::generate(sink, expr, BOOST_PP_ENUM_PARAMS(N, attr));
89     }
90 
91     ///////////////////////////////////////////////////////////////////////////
92     template <typename OutputIterator, typename Properties, typename Expr
93       , typename Delimiter, BOOST_PP_ENUM_PARAMS(N, typename A)>
94     inline bool
generate_delimited(detail::output_iterator<OutputIterator,Properties> & sink,Expr const & expr,Delimiter const & delimiter,BOOST_SCOPED_ENUM (delimit_flag)pre_delimit,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))95     generate_delimited(
96         detail::output_iterator<OutputIterator, Properties>& sink
97       , Expr const& expr
98       , Delimiter const& delimiter
99       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
100       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
101     {
102         // Report invalid expression error as early as possible.
103         // If you got an error_invalid_expression error message here,
104         // then either the expression (expr) or skipper is not a valid
105         // spirit karma expression.
106         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
107         BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Delimiter);
108 
109         typename result_of::compile<karma::domain, Delimiter>::type const
110             delimiter_ = compile<karma::domain>(delimiter);
111 
112         if (pre_delimit == delimit_flag::predelimit &&
113             !karma::delimit_out(sink, delimiter_))
114         {
115             return false;
116         }
117 
118         typedef fusion::vector<
119             BOOST_PP_ENUM(N, BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE, A)
120         > vector_type;
121 
122         vector_type attr (BOOST_PP_ENUM_PARAMS(N, attr));
123         return compile<karma::domain>(expr).
124             generate(sink, unused, delimiter_, attr);
125     }
126 
127     template <typename OutputIterator, typename Expr, typename Delimiter
128       , BOOST_PP_ENUM_PARAMS(N, typename A)>
129     inline bool
generate_delimited(OutputIterator & sink_,Expr const & expr,Delimiter const & delimiter,BOOST_SCOPED_ENUM (delimit_flag)pre_delimit,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))130     generate_delimited(
131         OutputIterator& sink_
132       , Expr const& expr
133       , Delimiter const& delimiter
134       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
135       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
136     {
137         typedef traits::properties_of<
138             typename result_of::compile<karma::domain, Expr>::type
139         > properties;
140         typedef traits::properties_of<
141             typename result_of::compile<karma::domain, Delimiter>::type
142         > delimiter_properties;
143 
144         // wrap user supplied iterator into our own output iterator
145         detail::output_iterator<OutputIterator
146           , mpl::int_<properties::value | delimiter_properties::value>
147         > sink(sink_);
148         return karma::generate_delimited(sink, expr, delimiter, pre_delimit
149           , BOOST_PP_ENUM_PARAMS(N, attr));
150     }
151 
152     template <typename OutputIterator, typename Expr, typename Delimiter
153       , BOOST_PP_ENUM_PARAMS(N, typename A)>
154     inline bool
generate_delimited(OutputIterator const & sink_,Expr const & expr,Delimiter const & delimiter,BOOST_SCOPED_ENUM (delimit_flag)pre_delimit,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))155     generate_delimited(
156         OutputIterator const& sink_
157       , Expr const& expr
158       , Delimiter const& delimiter
159       , BOOST_SCOPED_ENUM(delimit_flag) pre_delimit
160       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
161     {
162         OutputIterator sink = sink_;
163         return karma::generate_delimited(sink, expr, delimiter, pre_delimit
164           , BOOST_PP_ENUM_PARAMS(N, attr));
165     }
166 
167     ///////////////////////////////////////////////////////////////////////////
168     template <typename OutputIterator, typename Expr, typename Delimiter
169       , BOOST_PP_ENUM_PARAMS(N, typename A)>
170     inline bool
generate_delimited(OutputIterator & sink_,Expr const & expr,Delimiter const & delimiter,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))171     generate_delimited(
172         OutputIterator& sink_
173       , Expr const& expr
174       , Delimiter const& delimiter
175       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
176     {
177         typedef traits::properties_of<
178             typename result_of::compile<karma::domain, Expr>::type
179         > properties;
180         typedef traits::properties_of<
181             typename result_of::compile<karma::domain, Delimiter>::type
182         > delimiter_properties;
183 
184         // wrap user supplied iterator into our own output iterator
185         detail::output_iterator<OutputIterator
186           , mpl::int_<properties::value | delimiter_properties::value>
187         > sink(sink_);
188         return karma::generate_delimited(sink, expr, delimiter
189           , delimit_flag::dont_predelimit, BOOST_PP_ENUM_PARAMS(N, attr));
190     }
191 
192     template <typename OutputIterator, typename Expr, typename Delimiter
193       , BOOST_PP_ENUM_PARAMS(N, typename A)>
194     inline bool
generate_delimited(OutputIterator const & sink_,Expr const & expr,Delimiter const & delimiter,BOOST_PP_ENUM_BINARY_PARAMS (N,A,const & attr))195     generate_delimited(
196         OutputIterator const& sink_
197       , Expr const& expr
198       , Delimiter const& delimiter
199       , BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& attr))
200     {
201         OutputIterator sink = sink_;
202         return karma::generate_delimited(sink, expr, delimiter
203           , delimit_flag::dont_predelimit, BOOST_PP_ENUM_PARAMS(N, attr));
204     }
205 
206 }}}
207 
208 #undef BOOST_SPIRIT_KARMA_ATTRIBUTE_REFERENCE
209 #undef N
210 
211 #endif // defined(BOOST_PP_IS_ITERATING)
212 
213