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