]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/spirit/test/x3/attribute_type_check.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / spirit / test / x3 / attribute_type_check.cpp
1 #include <boost/spirit/home/x3.hpp>
2
3 #include <boost/core/lightweight_test.hpp>
4 #include <boost/fusion/include/vector.hpp>
5 #include <boost/fusion/include/make_vector.hpp>
6 #include <boost/fusion/include/equal_to.hpp>
7 #include <boost/type_traits/is_same.hpp>
8 #include <boost/optional.hpp>
9 #include <string>
10
11 namespace x3 = boost::spirit::x3;
12
13 // just an `attr` with added type checker
14 template <typename Value, typename Expected>
15 struct checked_attr_parser : x3::attr_parser<Value>
16 {
17 using base_t = x3::attr_parser<Value>;
18
19 checked_attr_parser(Value const& value) : base_t(value) {}
20 checked_attr_parser(Value&& value) : base_t(std::move(value)) {}
21
22 template <typename Iterator, typename Context
23 , typename RuleContext, typename Attribute>
24 bool parse(Iterator& first, Iterator const& last
25 , Context const& ctx, RuleContext& rctx, Attribute& attr_) const
26 {
27 static_assert(boost::is_same<Expected, Attribute>::value,
28 "attribute type check failed");
29 return base_t::parse(first, last, ctx, rctx, attr_);
30 }
31 };
32
33 template <typename Expected, typename Value>
34 static inline checked_attr_parser<boost::decay_t<Value>, Expected>
35 checked_attr(Value&& value) { return { std::forward<Value>(value) }; }
36
37 // instantiate our type checker
38 // (checks attribute value just to be sure we are ok)
39 template <typename Value, typename Expr>
40 static void test_expr(Value const& v, Expr&& expr)
41 {
42 char const* it = "";
43 Value r;
44 BOOST_TEST((x3::parse(it, it, std::forward<Expr>(expr), r)));
45 BOOST_TEST((r == v));
46 }
47
48 template <typename Expr, typename Attribute>
49 static void gen_sequence(Attribute const& attribute, Expr&& expr)
50 {
51 test_expr(attribute, expr);
52 test_expr(attribute, expr >> x3::eps);
53 }
54
55 template <typename Expected, typename... ExpectedTail, typename Attribute, typename Expr, typename Value, typename... Tail>
56 static void gen_sequence(Attribute const& attribute, Expr&& expr, Value const& v, Tail const&... tail)
57 {
58 gen_sequence<ExpectedTail...>(attribute, expr >> checked_attr<Expected>(v), tail...);
59 gen_sequence<ExpectedTail...>(attribute, expr >> x3::eps >> checked_attr<Expected>(v), tail...);
60 gen_sequence<ExpectedTail...>(attribute, expr >> (x3::eps >> checked_attr<Expected>(v)), tail...);
61 }
62
63 template <typename Expected, typename... ExpectedTail, typename Attribute, typename Value, typename... Tail>
64 static void gen_sequence_tests(Attribute const& attribute, Value const& v, Tail const&... tail)
65 {
66 gen_sequence<ExpectedTail...>(attribute, checked_attr<Expected>(v), tail...);
67 gen_sequence<ExpectedTail...>(attribute, x3::eps >> checked_attr<Expected>(v), tail...);
68 }
69
70 template <typename Expected, typename Value>
71 static void gen_single_item_tests(Value const& v)
72 {
73 Expected attribute(v);
74 gen_sequence(attribute, checked_attr<Expected>(v));
75 gen_sequence(attribute, x3::eps >> checked_attr<Expected>(v));
76 }
77
78 template <typename Expected, typename... ExpectedTail, typename Value, typename... Tail>
79 static void gen_single_item_tests(Value const& v, Tail const&... tail)
80 {
81 gen_single_item_tests<Expected>(v);
82 gen_single_item_tests<ExpectedTail...>(tail...);
83 }
84
85 template <typename... Expected, typename... Values>
86 static void gen_tests(Values const&... values)
87 {
88 gen_single_item_tests<Expected...>(values...);
89
90 boost::fusion::vector<Expected...> attribute = boost::fusion::make_vector(values...);
91 gen_sequence_tests<Expected...>(attribute, values...);
92 }
93
94 template <typename... Attributes>
95 void make_test(Attributes const&... attrs)
96 {
97 // I would like to place all of this in a single call
98 // but it requires tremendous amount of heap to compile
99 gen_tests<Attributes...>(attrs...);
100 gen_tests<
101 boost::optional<Attributes>...
102 , boost::fusion::vector<Attributes>...
103 >(attrs..., attrs...);
104 gen_tests<
105 boost::optional<boost::fusion::vector<Attributes>>...
106 , boost::fusion::vector<boost::optional<Attributes>>...
107 >(boost::fusion::vector<Attributes>(attrs)..., attrs...);
108 }
109
110 int main()
111 {
112 make_test<int, std::string>(123, "hello");
113 return boost::report_errors();
114 }