1 /*=============================================================================
2     Copyright (c) 2001-2015 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4 
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #include <boost/detail/lightweight_test.hpp>
9 #include <boost/spirit/home/x3.hpp>
10 #include <boost/fusion/include/std_pair.hpp>
11 
12 #include <iostream>
13 #include <map>
14 #include <unordered_map>
15 #include <boost/unordered_map.hpp>
16 #include <vector>
17 #include <list>
18 #include <deque>
19 #include <set>
20 #include <unordered_set>
21 #include <boost/unordered_set.hpp>
22 #include <string>
23 #include "test.hpp"
24 
25 namespace x3 = boost::spirit::x3;
26 
27 
28 // check if we did not break user defined specializations
29 namespace check_substitute {
30 template <typename T> struct foo {};
31 template <typename T> struct bar { using type = T; };
32 template <typename T> struct is_bar : std::false_type {};
33 template <typename T> struct is_bar<bar<T>> : std::true_type {};
34 }
35 
36 namespace boost { namespace spirit { namespace x3 { namespace traits {
37 using namespace check_substitute;
38 
39 template <typename T, typename U>
40 struct is_substitute<foo<T>, foo<U>> : is_substitute<T, U> {};
41 
42 template <typename T, typename U>
43 struct is_substitute<T, U, std::enable_if_t<is_bar<T>::value && is_bar<U>::value>>
44   : is_substitute<typename T::type, typename U::type> {};
45 }}}}
46 
47 namespace check_substitute {
48 using x3::traits::is_substitute;
49 static_assert(is_substitute<foo<int>, foo<int>>::value, "is_substitute problem");
50 static_assert(!is_substitute<foo<int>, foo<long>>::value, "is_substitute problem");
51 static_assert(is_substitute<bar<int>, bar<int>>::value, "is_substitute problem");
52 static_assert(!is_substitute<bar<int>, bar<long>>::value, "is_substitute problem");
53 }
54 
55 
56 x3::rule<class pair_rule, std::pair<std::string,std::string>> const pair_rule("pair");
57 x3::rule<class string_rule, std::string> const string_rule("string");
58 
59 auto const pair_rule_def = string_rule > x3::lit('=') > string_rule;
60 auto const string_rule_def = x3::lexeme[*x3::alnum];
61 
BOOST_SPIRIT_DEFINE(pair_rule,string_rule)62 BOOST_SPIRIT_DEFINE(pair_rule, string_rule)
63 
64 template <typename Container>
65 void test_map_support()
66 {
67     using spirit_test::test_attr;
68 
69     Container container;
70     Container const compare {{"k1", "v1"}, {"k2", "v2"}};
71     auto const rule = pair_rule % x3::lit(',');
72 
73     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container));
74     BOOST_TEST(container.size() == 2);
75     BOOST_TEST(container == compare);
76 
77     // test sequences parsing into containers
78     auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule;
79     container.clear();
80     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container));
81 
82     // test parsing container into container
83     auto const cic_rule = pair_rule >> +(',' >> pair_rule);
84     container.clear();
85     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container));
86 }
87 
88 template <typename Container>
test_multimap_support()89 void test_multimap_support()
90 {
91     using spirit_test::test_attr;
92 
93     Container container;
94     Container const compare {{"k1", "v1"}, {"k2", "v2"}, {"k2", "v3"}};
95     auto const rule = pair_rule % x3::lit(',');
96 
97     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", rule, container));
98     BOOST_TEST(container.size() == 3);
99     BOOST_TEST(container == compare);
100 
101     // test sequences parsing into containers
102     auto const seq_rule = pair_rule >> ',' >> pair_rule >> ',' >> pair_rule;
103     container.clear();
104     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", seq_rule, container));
105 
106     // test parsing container into container
107     auto const cic_rule = pair_rule >> +(',' >> pair_rule);
108     container.clear();
109     BOOST_TEST(test_attr("k1=v1,k2=v2,k2=v3", cic_rule, container));
110 }
111 
112 template <typename Container>
test_sequence_support()113 void test_sequence_support()
114 {
115     using spirit_test::test_attr;
116 
117     Container container;
118     Container const compare {"e1", "e2", "e2"};
119     auto const rule = string_rule % x3::lit(',');
120 
121     BOOST_TEST(test_attr("e1,e2,e2", rule, container));
122     BOOST_TEST(container.size() == 3);
123     BOOST_TEST(container == compare);
124 
125     // test sequences parsing into containers
126     auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
127     container.clear();
128     BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
129 
130     // test parsing container into container
131     auto const cic_rule = string_rule >> +(',' >> string_rule);
132     container.clear();
133     BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
134 }
135 
136 template <typename Container>
test_set_support()137 void test_set_support()
138 {
139     using spirit_test::test_attr;
140 
141     Container container;
142     Container const compare {"e1", "e2"};
143     auto const rule = string_rule % x3::lit(',');
144 
145     BOOST_TEST(test_attr("e1,e2,e2", rule, container));
146     BOOST_TEST(container.size() == 2);
147     BOOST_TEST(container == compare);
148 
149     // test sequences parsing into containers
150     auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
151     container.clear();
152     BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
153 
154     // test parsing container into container
155     auto const cic_rule = string_rule >> +(',' >> string_rule);
156     container.clear();
157     BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
158 }
159 
160 template <typename Container>
test_multiset_support()161 void test_multiset_support()
162 {
163     using spirit_test::test_attr;
164 
165     Container container;
166     Container const compare {"e1", "e2", "e2"};
167     auto const rule = string_rule % x3::lit(',');
168 
169     BOOST_TEST(test_attr("e1,e2,e2", rule, container));
170     BOOST_TEST(container.size() == 3);
171     BOOST_TEST(container == compare);
172 
173     // test sequences parsing into containers
174     auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
175     container.clear();
176     BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
177 
178     // test parsing container into container
179     auto const cic_rule = string_rule >> +(',' >> string_rule);
180     container.clear();
181     BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
182 }
183 
184 template <typename Container>
test_string_support()185 void test_string_support()
186 {
187     using spirit_test::test_attr;
188 
189     Container container;
190     Container const compare {"e1e2e2"};
191     auto const rule = string_rule % x3::lit(',');
192 
193     BOOST_TEST(test_attr("e1,e2,e2", rule, container));
194     BOOST_TEST(container.size() == 6);
195     BOOST_TEST(container == compare);
196 
197     // test sequences parsing into containers
198     auto const seq_rule = string_rule >> ',' >> string_rule >> ',' >> string_rule;
199     container.clear();
200     BOOST_TEST(test_attr("e1,e2,e2", seq_rule, container));
201 
202     // test parsing container into container
203     auto const cic_rule = string_rule >> +(',' >> string_rule);
204     container.clear();
205     BOOST_TEST(test_attr("e1,e2,e2", cic_rule, container));
206 }
207 
208 int
main()209 main()
210 {
211     using x3::traits::is_associative;
212 
213     // ------------------------------------------------------------------
214 
215     static_assert(is_associative<std::set<int>>::value, "is_associative problem");
216     static_assert(is_associative<std::unordered_set<int>>::value, "is_associative problem");
217     static_assert(is_associative<boost::unordered_set<int>>::value, "is_associative problem");
218     static_assert(is_associative<std::multiset<int>>::value, "is_associative problem");
219     static_assert(is_associative<std::unordered_multiset<int>>::value, "is_associative problem");
220     static_assert(is_associative<boost::unordered_multiset<int>>::value, "is_associative problem");
221     static_assert(is_associative<std::map<int,int>>::value, "is_associative problem");
222     static_assert(is_associative<std::unordered_map<int,int>>::value, "is_associative problem");
223     static_assert(is_associative<boost::unordered_map<int,int>>::value, "is_associative problem");
224     static_assert(is_associative<std::multimap<int,int>>::value, "is_associative problem");
225     static_assert(is_associative<std::unordered_multimap<int,int>>::value, "is_associative problem");
226     static_assert(is_associative<boost::unordered_multimap<int,int>>::value, "is_associative problem");
227 
228     static_assert(!is_associative<std::vector<int>>::value, "is_associative problem");
229     static_assert(!is_associative<std::string>::value, "is_associative problem");
230     static_assert(!is_associative<std::deque<int>>::value, "is_associative problem");
231     static_assert(!is_associative<std::list<int>>::value, "is_associative problem");
232 
233     // ------------------------------------------------------------------
234 
235     test_string_support<std::string>();
236 
237     test_sequence_support<std::vector<std::string>>();
238     test_sequence_support<std::list<std::string>>();
239     test_sequence_support<std::deque<std::string>>();
240 
241     test_set_support<std::set<std::string>>();
242     test_set_support<std::unordered_set<std::string>>();
243     test_set_support<boost::unordered_set<std::string>>();
244 
245     test_multiset_support<std::multiset<std::string>>();
246     test_multiset_support<std::unordered_multiset<std::string>>();
247     test_multiset_support<boost::unordered_multiset<std::string>>();
248 
249     test_map_support<std::map<std::string,std::string>>();
250     test_map_support<std::unordered_map<std::string,std::string>>();
251     test_map_support<boost::unordered_map<std::string,std::string>>();
252 
253     test_multimap_support<std::multimap<std::string,std::string>>();
254     test_multimap_support<std::unordered_multimap<std::string,std::string>>();
255     test_multimap_support<boost::unordered_multimap<std::string,std::string>>();
256 
257     return boost::report_errors();
258 }
259