]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/spirit/home/x3/core/detail/parse_into_container.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / spirit / home / x3 / core / detail / parse_into_container.hpp
CommitLineData
7c673cae
FG
1/*=============================================================================
2 Copyright (c) 2001-2014 Joel de Guzman
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=============================================================================*/
11fdf7f2
TL
7#if !defined(BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM)
8#define BOOST_SPIRIT_X3_PARSE_INTO_CONTAINER_JAN_15_2013_0957PM
7c673cae
FG
9
10#include <type_traits>
11
12#include <boost/spirit/home/x3/support/traits/container_traits.hpp>
7c673cae 13#include <boost/spirit/home/x3/support/traits/attribute_of.hpp>
92f5a8d4 14#include <boost/spirit/home/x3/support/traits/pseudo_attribute.hpp>
7c673cae
FG
15#include <boost/spirit/home/x3/support/traits/handles_container.hpp>
16#include <boost/spirit/home/x3/support/traits/has_attribute.hpp>
17#include <boost/spirit/home/x3/support/traits/is_substitute.hpp>
18#include <boost/spirit/home/x3/support/traits/move_to.hpp>
19#include <boost/mpl/and.hpp>
11fdf7f2 20#include <boost/fusion/include/at_key.hpp>
7c673cae
FG
21#include <boost/fusion/include/front.hpp>
22#include <boost/fusion/include/back.hpp>
23#include <boost/variant/apply_visitor.hpp>
92f5a8d4 24#include <iterator> // for std::make_move_iterator
7c673cae
FG
25
26namespace boost { namespace spirit { namespace x3 { namespace detail
27{
28 template <typename Attribute, typename Value>
29 struct saver_visitor;
30
31 // save to associative fusion container where Key is simple type
32 template <typename Key, typename Enable = void>
33 struct save_to_assoc_attr
34 {
35 template <typename Value, typename Attribute>
36 static void call(const Key, Value& value, Attribute& attr)
37 {
38 traits::move_to(value, fusion::at_key<Key>(attr));
39 }
40 };
41
7c673cae
FG
42 // save to associative fusion container where Key
43 // is variant over possible keys
44 template <typename ...T>
45 struct save_to_assoc_attr<variant<T...> >
46 {
47 typedef variant<T...> variant_t;
48
49 template <typename Value, typename Attribute>
50 static void call(const variant_t key, Value& value, Attribute& attr)
51 {
52 apply_visitor(saver_visitor<Attribute, Value>(attr, value), key);
53 }
54 };
11fdf7f2 55
7c673cae
FG
56 template <typename Attribute, typename Value>
57 struct saver_visitor : boost::static_visitor<void>
58 {
59 saver_visitor(Attribute& attr, Value& value)
60 : attr(attr), value(value) {};
61
62 Attribute& attr;
63 Value& value;
64
65 template <typename Key>
66 void operator()(Key) const
67 {
68 save_to_assoc_attr<Key>::call(Key(), value,attr);
69 }
70 };
71
72 template <typename Parser, typename Container, typename Context>
73 struct parser_accepts_container
74 : traits::is_substitute<
75 typename traits::attribute_of<Parser, Context>::type
76 , Container
77 >
78 {};
79
80 template <typename Parser>
81 struct parse_into_container_base_impl
82 {
83 private:
84
85 // Parser has attribute (synthesize; Attribute is a container)
86 template <typename Iterator, typename Context
87 , typename RContext, typename Attribute>
88 static bool call_synthesize_x(
89 Parser const& parser
90 , Iterator& first, Iterator const& last
91 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
92 {
93 // synthesized attribute needs to be value initialized
92f5a8d4 94 using value_type = typename traits::container_value<Attribute>::type;
20effc67 95 value_type val{};
7c673cae
FG
96
97 if (!parser.parse(first, last, context, rcontext, val))
98 return false;
99
100 // push the parsed value into our attribute
92f5a8d4 101 traits::push_back(attr, static_cast<value_type&&>(val));
7c673cae
FG
102 return true;
103 }
104
105 // Parser has attribute (synthesize; Attribute is a container)
106 template <typename Iterator, typename Context
107 , typename RContext, typename Attribute>
108 static bool call_synthesize_x(
109 Parser const& parser
110 , Iterator& first, Iterator const& last
111 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
112 {
113 return parser.parse(first, last, context, rcontext, attr);
114 }
115
116 // Parser has attribute (synthesize; Attribute is a container)
117 template <typename Iterator, typename Context
118 , typename RContext, typename Attribute>
119 static bool call_synthesize(
120 Parser const& parser
121 , Iterator& first, Iterator const& last
122 , Context const& context, RContext& rcontext, Attribute& attr)
123 {
124 typedef
125 parser_accepts_container<Parser, Attribute, Context>
126 parser_accepts_container;
127
128 return call_synthesize_x(parser, first, last, context, rcontext, attr
129 , parser_accepts_container());
130 }
131
132 // Parser has attribute (synthesize; Attribute is a single element fusion sequence)
133 template <typename Iterator, typename Context
134 , typename RContext, typename Attribute>
135 static bool call_synthesize_into_fusion_seq(Parser const& parser
136 , Iterator& first, Iterator const& last, Context const& context
137 , RContext& rcontext, Attribute& attr, mpl::false_ /* is_associative */)
138 {
139 static_assert(traits::has_size<Attribute, 1>::value,
140 "Expecting a single element fusion sequence");
141 return call_synthesize(parser, first, last, context, rcontext,
142 fusion::front(attr));
143 }
144
145 // Parser has attribute (synthesize; Attribute is fusion map sequence)
146 template <typename Iterator, typename Context, typename RContext, typename Attribute>
147 static bool call_synthesize_into_fusion_seq(
148 Parser const& parser
149 , Iterator& first, Iterator const& last, Context const& context
150 , RContext& rcontext, Attribute& attr, mpl::true_ /*is_associative*/)
151 {
152 using attribute_type = typename traits::attribute_of<Parser, Context>::type;
153 static_assert(traits::has_size<attribute_type, 2>::value,
154 "To parse directly into fusion map parser must produce 2 element attr");
155
156 // use type of first element of attribute as key
157 using key = typename std::remove_reference<
158 typename fusion::result_of::front<attribute_type>::type>::type;
159
160 attribute_type attr_;
161 if (!parser.parse(first, last, context, rcontext, attr_))
162 return false;
163
164 save_to_assoc_attr<key>::call(fusion::front(attr_), fusion::back(attr_), attr);
165 return true;
166 }
167
168 template <typename Iterator, typename Context, typename RContext, typename Attribute>
169 static bool call_synthesize_dispatch_by_seq(Parser const& parser
170 , Iterator& first, Iterator const& last, Context const& context
171 , RContext& rcontext, Attribute& attr, mpl::true_ /*is_sequence*/)
172 {
173 return call_synthesize_into_fusion_seq(
174 parser, first, last, context, rcontext, attr
175 , fusion::traits::is_associative<Attribute>());
176 }
177
178 template <typename Iterator, typename Context, typename RContext, typename Attribute>
179 static bool call_synthesize_dispatch_by_seq(Parser const& parser
180 , Iterator& first, Iterator const& last, Context const& context
181 , RContext& rcontext, Attribute& attr, mpl::false_ /*is_sequence*/)
182 {
183 return call_synthesize(parser, first, last, context, rcontext, attr);
184 }
185
186 // Parser has attribute (synthesize)
187 template <typename Iterator, typename Context, typename RContext, typename Attribute>
188 static bool call(Parser const& parser
189 , Iterator& first, Iterator const& last, Context const& context
190 , RContext& rcontext, Attribute& attr, mpl::true_)
191 {
192 return call_synthesize_dispatch_by_seq(parser, first, last, context, rcontext, attr
193 , fusion::traits::is_sequence<Attribute>());
194 }
195
196 // Parser has no attribute (pass unused)
197 template <typename Iterator, typename Context, typename RContext, typename Attribute>
198 static bool call(
199 Parser const& parser
200 , Iterator& first, Iterator const& last, Context const& context
b32b8144 201 , RContext& rcontext, Attribute& /* attr */, mpl::false_)
7c673cae
FG
202 {
203 return parser.parse(first, last, context, rcontext, unused);
204 }
205
206
207 public:
208
209 template <typename Iterator, typename Context, typename RContext, typename Attribute>
210 static bool call(Parser const& parser
211 , Iterator& first, Iterator const& last, Context const& context
212 , RContext& rcontext, Attribute& attr)
213 {
214 return call(parser, first, last, context, rcontext, attr
215 , mpl::bool_<traits::has_attribute<Parser, Context>::value>());
216 }
217 };
218
219 template <typename Parser, typename Context, typename RContext, typename Enable = void>
220 struct parse_into_container_impl : parse_into_container_base_impl<Parser> {};
221
92f5a8d4 222 template <typename Parser, typename Iterator, typename Container, typename Context>
7c673cae
FG
223 struct parser_attr_is_substitute_for_container_value
224 : traits::is_substitute<
92f5a8d4
TL
225 typename traits::pseudo_attribute<
226 Context
227 , typename traits::attribute_of<Parser, Context>::type
228 , Iterator
229 >::type
7c673cae
FG
230 , typename traits::container_value<Container>::type
231 >
232 {};
233
234 template <typename Parser, typename Context, typename RContext>
235 struct parse_into_container_impl<Parser, Context, RContext,
236 typename enable_if<traits::handles_container<Parser, Context>>::type>
237 {
238 template <typename Iterator, typename Attribute>
239 static bool call(
240 Parser const& parser
241 , Iterator& first, Iterator const& last
242 , Context const& context, RContext& rcontext, Attribute& attr, mpl::false_)
243 {
244 return parse_into_container_base_impl<Parser>::call(
245 parser, first, last, context, rcontext, attr);
246 }
247
11fdf7f2
TL
248 template <typename Iterator>
249 static bool call(
250 Parser const& parser
251 , Iterator& first, Iterator const& last
252 , Context const& context, RContext& rcontext, unused_type attr, mpl::true_)
253 {
254 return parser.parse(first, last, context, rcontext, attr);
255 }
256
7c673cae
FG
257 template <typename Iterator, typename Attribute>
258 static bool call(
259 Parser const& parser
260 , Iterator& first, Iterator const& last
261 , Context const& context, RContext& rcontext, Attribute& attr, mpl::true_)
262 {
11fdf7f2 263 if (traits::is_empty(attr))
b32b8144
FG
264 return parser.parse(first, last, context, rcontext, attr);
265 Attribute rest;
266 bool r = parser.parse(first, last, context, rcontext, rest);
267 if (r)
92f5a8d4
TL
268 traits::append(attr, std::make_move_iterator(rest.begin()),
269 std::make_move_iterator(rest.end()));
b32b8144 270 return r;
7c673cae
FG
271 }
272
273 template <typename Iterator, typename Attribute>
274 static bool call(Parser const& parser
275 , Iterator& first, Iterator const& last
276 , Context const& context, RContext& rcontext, Attribute& attr)
277 {
278 typedef parser_accepts_container<
279 Parser, Attribute, Context>
280 parser_accepts_container;
281
282 typedef parser_attr_is_substitute_for_container_value<
92f5a8d4 283 Parser, Iterator, Attribute, Context>
7c673cae
FG
284 parser_attr_is_substitute_for_container_value;
285
286 typedef mpl::or_<
287 parser_accepts_container
288 , mpl::not_<parser_attr_is_substitute_for_container_value>>
289 pass_attibute_as_is;
290
291 return call(parser, first, last, context, rcontext, attr,
292 pass_attibute_as_is());
293 }
294 };
295
296 template <typename Parser, typename Iterator, typename Context
297 , typename RContext, typename Attribute>
298 bool parse_into_container(
299 Parser const& parser
300 , Iterator& first, Iterator const& last, Context const& context
301 , RContext& rcontext, Attribute& attr)
302 {
303 return parse_into_container_impl<Parser, Context, RContext>::call(
304 parser, first, last, context, rcontext, attr);
305 }
306
307}}}}
308
309#endif