1 /*=============================================================================
2     Copyright (c) 2001-2015 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 =============================================================================*/
7 #include <boost/detail/lightweight_test.hpp>
8 #include <boost/spirit/home/x3/string/tst.hpp>
9 #include <boost/spirit/home/x3/string/tst_map.hpp>
10 #include <boost/spirit/home/x3/support/no_case.hpp>
11 #include <boost/spirit/home/support/char_encoding/standard.hpp>
12 #include <boost/spirit/home/support/char_encoding/standard_wide.hpp>
13 #include <string>
14 #include <cctype>
15 #include <iostream>
16 
17 namespace
18 {
19     template <typename TST, typename Char>
add(TST & tst,Char const * s,int data)20     void add(TST& tst, Char const* s, int data)
21     {
22         Char const* last = s;
23         while (*last)
24             last++;
25         tst.add(s, last, data);
26     }
27 
28     template <typename TST, typename Char>
remove(TST & tst,Char const * s)29     void remove(TST& tst, Char const* s)
30     {
31         Char const* last = s;
32         while (*last)
33             last++;
34         tst.remove(s, last);
35     }
36 
37     template <typename TST, typename Char, typename CaseCompare>
docheck(TST const & tst,CaseCompare const & comp,Char const * s,bool expected,int N=0,int val=-1)38     void docheck(TST const& tst, CaseCompare const& comp, Char const* s, bool expected, int N = 0, int val = -1)
39     {
40         Char const* first = s;
41         Char const* last = s;
42         while (*last)
43             last++;
44         int* r = tst.find(s, last,comp);
45         BOOST_TEST((r != 0) == expected);
46         if (r != 0)
47             BOOST_TEST((s-first) == N);
48         if (r)
49             BOOST_TEST(*r == val);
50     }
51 
52     struct printer
53     {
54         template <typename String, typename Data>
operator ()__anon80aef55a0111::printer55         void operator()(String const& s, Data const& data)
56         {
57             std::cout << "    " << s << ": " << data << std::endl;
58         }
59     };
60 
61     template <typename TST>
print(TST const & tst)62     void print(TST const& tst)
63     {
64         std::cout << '[' << std::endl;
65         tst.for_each(printer());
66         std::cout << ']' << std::endl;
67     }
68 
69 }
70 
71 boost::spirit::x3::case_compare<boost::spirit::char_encoding::standard> ncomp;
72 boost::spirit::x3::case_compare<boost::spirit::char_encoding::standard_wide> wcomp;
73 boost::spirit::x3::no_case_compare<boost::spirit::char_encoding::standard> nc_ncomp;
74 boost::spirit::x3::no_case_compare<boost::spirit::char_encoding::standard_wide> nc_wcomp;
75 
76 template <typename Lookup, typename WideLookup>
tests()77 void tests()
78 {
79     { // basic tests
80         Lookup lookup;
81 
82         docheck(lookup, ncomp, "not-yet-there", false);
83         docheck(lookup, ncomp, "", false);
84 
85         add(lookup, "apple", 123);
86         docheck(lookup, ncomp, "apple", true, 5, 123); // full match
87         docheck(lookup, ncomp, "banana", false); // no-match
88         docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match
89 
90         add(lookup, "applepie", 456);
91         docheck(lookup, ncomp, "applepie", true, 8, 456); // full match
92         docheck(lookup, ncomp, "banana", false); // no-match
93         docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match
94         docheck(lookup, ncomp, "apple", true, 5, 123); // full match
95         docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match
96     }
97 
98     { // variation of above
99         Lookup lookup;
100 
101         add(lookup, "applepie", 456);
102         add(lookup, "apple", 123);
103 
104         docheck(lookup, ncomp, "applepie", true, 8, 456); // full match
105         docheck(lookup, ncomp, "banana", false); // no-match
106         docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match
107         docheck(lookup, ncomp, "apple", true, 5, 123); // full match
108         docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match
109     }
110     { // variation of above
111         Lookup lookup;
112 
113         add(lookup, "applepie", 456);
114         add(lookup, "apple", 123);
115 
116         docheck(lookup, ncomp, "applepie", true, 8, 456); // full match
117         docheck(lookup, ncomp, "banana", false); // no-match
118         docheck(lookup, ncomp, "applepiexxx", true, 8, 456); // partial match
119         docheck(lookup, ncomp, "apple", true, 5, 123); // full match
120         docheck(lookup, ncomp, "applexxx", true, 5, 123); // partial match
121     }
122 
123     { // narrow char tests
124         Lookup lookup;
125         add(lookup, "pineapple", 1);
126         add(lookup, "orange", 2);
127         add(lookup, "banana", 3);
128         add(lookup, "applepie", 4);
129         add(lookup, "apple", 5);
130 
131         docheck(lookup, ncomp, "pineapple", true, 9, 1);
132         docheck(lookup, ncomp, "orange", true, 6, 2);
133         docheck(lookup, ncomp, "banana", true, 6, 3);
134         docheck(lookup, ncomp, "apple", true, 5, 5);
135         docheck(lookup, ncomp, "pizza", false);
136         docheck(lookup, ncomp, "steak", false);
137         docheck(lookup, ncomp, "applepie", true, 8, 4);
138         docheck(lookup, ncomp, "bananarama", true, 6, 3);
139         docheck(lookup, ncomp, "applet", true, 5, 5);
140         docheck(lookup, ncomp, "applepi", true, 5, 5);
141         docheck(lookup, ncomp, "appl", false);
142 
143         docheck(lookup, ncomp, "pineapplez", true, 9, 1);
144         docheck(lookup, ncomp, "orangez", true, 6, 2);
145         docheck(lookup, ncomp, "bananaz", true, 6, 3);
146         docheck(lookup, ncomp, "applez", true, 5, 5);
147         docheck(lookup, ncomp, "pizzaz", false);
148         docheck(lookup, ncomp, "steakz", false);
149         docheck(lookup, ncomp, "applepiez", true, 8, 4);
150         docheck(lookup, ncomp, "bananaramaz", true, 6, 3);
151         docheck(lookup, ncomp, "appletz", true, 5, 5);
152         docheck(lookup, ncomp, "applepix", true, 5, 5);
153     }
154 
155     { // wide char tests
156         WideLookup lookup;
157         add(lookup, L"pineapple", 1);
158         add(lookup, L"orange", 2);
159         add(lookup, L"banana", 3);
160         add(lookup, L"applepie", 4);
161         add(lookup, L"apple", 5);
162 
163         docheck(lookup, wcomp, L"pineapple", true, 9, 1);
164         docheck(lookup, wcomp, L"orange", true, 6, 2);
165         docheck(lookup, wcomp, L"banana", true, 6, 3);
166         docheck(lookup, wcomp, L"apple", true, 5, 5);
167         docheck(lookup, wcomp, L"pizza", false);
168         docheck(lookup, wcomp, L"steak", false);
169         docheck(lookup, wcomp, L"applepie", true, 8, 4);
170         docheck(lookup, wcomp, L"bananarama", true, 6, 3);
171         docheck(lookup, wcomp, L"applet", true, 5, 5);
172         docheck(lookup, wcomp, L"applepi", true, 5, 5);
173         docheck(lookup, wcomp, L"appl", false);
174 
175         docheck(lookup, wcomp, L"pineapplez", true, 9, 1);
176         docheck(lookup, wcomp, L"orangez", true, 6, 2);
177         docheck(lookup, wcomp, L"bananaz", true, 6, 3);
178         docheck(lookup, wcomp, L"applez", true, 5, 5);
179         docheck(lookup, wcomp, L"pizzaz", false);
180         docheck(lookup, wcomp, L"steakz", false);
181         docheck(lookup, wcomp, L"applepiez", true, 8, 4);
182         docheck(lookup, wcomp, L"bananaramaz", true, 6, 3);
183         docheck(lookup, wcomp, L"appletz", true, 5, 5);
184         docheck(lookup, wcomp, L"applepix", true, 5, 5);
185     }
186 
187     { // test remove
188         Lookup lookup;
189         add(lookup, "pineapple", 1);
190         add(lookup, "orange", 2);
191         add(lookup, "banana", 3);
192         add(lookup, "applepie", 4);
193         add(lookup, "apple", 5);
194 
195         docheck(lookup, ncomp, "pineapple", true, 9, 1);
196         docheck(lookup, ncomp, "orange", true, 6, 2);
197         docheck(lookup, ncomp, "banana", true, 6, 3);
198         docheck(lookup, ncomp, "apple", true, 5, 5);
199         docheck(lookup, ncomp, "applepie", true, 8, 4);
200         docheck(lookup, ncomp, "bananarama", true, 6, 3);
201         docheck(lookup, ncomp, "applet", true, 5, 5);
202         docheck(lookup, ncomp, "applepi", true, 5, 5);
203         docheck(lookup, ncomp, "appl", false);
204 
205         remove(lookup, "banana");
206         docheck(lookup, ncomp, "pineapple", true, 9, 1);
207         docheck(lookup, ncomp, "orange", true, 6, 2);
208         docheck(lookup, ncomp, "banana", false);
209         docheck(lookup, ncomp, "apple", true, 5, 5);
210         docheck(lookup, ncomp, "applepie", true, 8, 4);
211         docheck(lookup, ncomp, "bananarama", false);
212         docheck(lookup, ncomp, "applet", true, 5, 5);
213         docheck(lookup, ncomp, "applepi", true, 5, 5);
214         docheck(lookup, ncomp, "appl", false);
215 
216         remove(lookup, "apple");
217         docheck(lookup, ncomp, "pineapple", true, 9, 1);
218         docheck(lookup, ncomp, "orange", true, 6, 2);
219         docheck(lookup, ncomp, "apple", false);
220         docheck(lookup, ncomp, "applepie", true, 8, 4);
221         docheck(lookup, ncomp, "applet", false);
222         docheck(lookup, ncomp, "applepi", false);
223         docheck(lookup, ncomp, "appl", false);
224 
225         remove(lookup, "orange");
226         docheck(lookup, ncomp, "pineapple", true, 9, 1);
227         docheck(lookup, ncomp, "orange", false);
228         docheck(lookup, ncomp, "applepie", true, 8, 4);
229 
230         remove(lookup, "pineapple");
231         docheck(lookup, ncomp, "pineapple", false);
232         docheck(lookup, ncomp, "orange", false);
233         docheck(lookup, ncomp, "applepie", true, 8, 4);
234 
235         remove(lookup, "applepie");
236         docheck(lookup, ncomp, "applepie", false);
237     }
238 
239     { // copy/assign/clear test
240         Lookup lookupa;
241         add(lookupa, "pineapple", 1);
242         add(lookupa, "orange", 2);
243         add(lookupa, "banana", 3);
244         add(lookupa, "applepie", 4);
245         add(lookupa, "apple", 5);
246 
247         Lookup lookupb(lookupa); // copy ctor
248         docheck(lookupb, ncomp, "pineapple", true, 9, 1);
249         docheck(lookupb, ncomp, "orange", true, 6, 2);
250         docheck(lookupb, ncomp, "banana", true, 6, 3);
251         docheck(lookupb, ncomp, "apple", true, 5, 5);
252         docheck(lookupb, ncomp, "pizza", false);
253         docheck(lookupb, ncomp, "steak", false);
254         docheck(lookupb, ncomp, "applepie", true, 8, 4);
255         docheck(lookupb, ncomp, "bananarama", true, 6, 3);
256         docheck(lookupb, ncomp, "applet", true, 5, 5);
257         docheck(lookupb, ncomp, "applepi", true, 5, 5);
258         docheck(lookupb, ncomp, "appl", false);
259 
260         lookupb.clear(); // clear
261         docheck(lookupb, ncomp, "pineapple", false);
262         docheck(lookupb, ncomp, "orange", false);
263         docheck(lookupb, ncomp, "banana", false);
264         docheck(lookupb, ncomp, "apple", false);
265         docheck(lookupb, ncomp, "applepie", false);
266         docheck(lookupb, ncomp, "bananarama", false);
267         docheck(lookupb, ncomp, "applet", false);
268         docheck(lookupb, ncomp, "applepi", false);
269         docheck(lookupb, ncomp, "appl", false);
270 
271         lookupb = lookupa; // assign
272         docheck(lookupb, ncomp, "pineapple", true, 9, 1);
273         docheck(lookupb, ncomp, "orange", true, 6, 2);
274         docheck(lookupb, ncomp, "banana", true, 6, 3);
275         docheck(lookupb, ncomp, "apple", true, 5, 5);
276         docheck(lookupb, ncomp, "pizza", false);
277         docheck(lookupb, ncomp, "steak", false);
278         docheck(lookupb, ncomp, "applepie", true, 8, 4);
279         docheck(lookupb, ncomp, "bananarama", true, 6, 3);
280         docheck(lookupb, ncomp, "applet", true, 5, 5);
281         docheck(lookupb, ncomp, "applepi", true, 5, 5);
282         docheck(lookupb, ncomp, "appl", false);
283     }
284 
285     { // test for_each
286         Lookup lookup;
287         add(lookup, "pineapple", 1);
288         add(lookup, "orange", 2);
289         add(lookup, "banana", 3);
290         add(lookup, "applepie", 4);
291         add(lookup, "apple", 5);
292 
293         print(lookup);
294     }
295 
296     { // case insensitive tests
297         Lookup lookup;
298 
299         // NOTE: make sure all entries are in lower-case!!!
300         add(lookup, "pineapple", 1);
301         add(lookup, "orange", 2);
302         add(lookup, "banana", 3);
303         add(lookup, "applepie", 4);
304         add(lookup, "apple", 5);
305 
306         docheck(lookup, nc_ncomp, "pineapple", true, 9, 1);
307         docheck(lookup, nc_ncomp, "orange", true, 6, 2);
308         docheck(lookup, nc_ncomp, "banana", true, 6, 3);
309         docheck(lookup, nc_ncomp, "apple", true, 5, 5);
310         docheck(lookup, nc_ncomp, "applepie", true, 8, 4);
311 
312         docheck(lookup, nc_ncomp, "PINEAPPLE", true, 9, 1);
313         docheck(lookup, nc_ncomp, "ORANGE", true, 6, 2);
314         docheck(lookup, nc_ncomp, "BANANA", true, 6, 3);
315         docheck(lookup, nc_ncomp, "APPLE", true, 5, 5);
316         docheck(lookup, nc_ncomp, "APPLEPIE", true, 8, 4);
317 
318         docheck(lookup, nc_ncomp, "pineApple", true, 9, 1);
319         docheck(lookup, nc_ncomp, "orangE", true, 6, 2);
320         docheck(lookup, nc_ncomp, "Banana", true, 6, 3);
321         docheck(lookup, nc_ncomp, "aPPLe", true, 5, 5);
322         docheck(lookup, nc_ncomp, "ApplePie", true, 8, 4);
323 
324         print(lookup);
325     }
326 }
327 
main()328 int main()
329 {
330     using boost::spirit::x3::tst;
331     using boost::spirit::x3::tst_map;
332 
333     tests<tst<char, int>, tst<wchar_t, int> >();
334 //~    tests<tst_map<char, int>, tst_map<wchar_t, int> >();
335 
336     return boost::report_errors();
337 }
338