• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*=============================================================================
2     Copyright (c) 1998-2003 Joel de Guzman
3     Copyright (c)      2003 Martin Wille
4     http://spirit.sourceforge.net/
5 
6     Use, modification and distribution is subject to the Boost Software
7     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8     http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
10 #include <iostream>
11 #include <string>
12 #include <boost/detail/lightweight_test.hpp>
13 #include <boost/spirit/include/classic_core.hpp>
14 #include <boost/spirit/include/classic_symbols.hpp>
15 #include <boost/swap.hpp>
16 #include "symbols.hpp"
17 
18 ///////////////////////////////////////////////////////////////////////////////
19 using namespace std;
20 using namespace BOOST_SPIRIT_CLASSIC_NS;
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 
equal(IteratorT p,IteratorT q)24 template <typename IteratorT> bool equal(IteratorT p, IteratorT q)
25 {
26     while (*p && *p == *q) {
27         ++p;
28         ++q;
29     }
30     return *p == *q;
31 }
32 
33 template <class SymbolsT, typename CharT>
docheck(SymbolsT const & sym,CharT const * candidate,bool hit,CharT const * result,int length)34 void docheck(
35     SymbolsT const& sym,
36     CharT const* candidate,
37     bool hit,
38     CharT const* result,
39     int length)
40 {
41     parse_info<CharT const*> info = parse(candidate, sym);
42 
43 #define correctly_matched hit == info.hit
44 #define correct_match_length unsigned(length) == info.length
45 #define correct_tail equal(candidate + (hit ? 1 : 0) * length, result)
46 
47     BOOST_TEST(correctly_matched);
48 
49     if (hit) {
50         BOOST_TEST(correct_match_length);
51         BOOST_TEST(correct_tail);
52     }
53     else {
54         BOOST_TEST(correct_tail);
55     }
56 }
57 
58 template <typename T> struct store_action
59 {
store_actionstore_action60     store_action(T const& v) : value(v) {}
operator ()store_action61     void operator()(T& v) const { v = value; }
62 
63   private:
64     T const value;
65 };
66 
store(T const & v)67 template <typename T> store_action<T> store(T const& v) { return v; }
68 
69 template <typename T> struct check_action
70 {
check_actioncheck_action71     check_action(T const& v) : value(v) {}
72 
73 #define correct_value_stored (v == value)
operator ()check_action74     void operator()(T const& v) const { BOOST_TEST(correct_value_stored); }
75 
76   private:
77     T const value;
78 };
79 
docheck(T const & v)80 template <typename T> check_action<T> docheck(T const& v) { return v; }
81 
default_constructible()82 static void default_constructible()
83 { // this actually a compile time test
84     symbols<int, char, quickbook::tst<int, char> > ns1;
85     symbols<int, wchar_t, quickbook::tst<int, wchar_t> > ws1;
86     symbols<std::string, char, quickbook::tst<std::string, char> > ns2;
87     symbols<std::string, wchar_t, quickbook::tst<std::string, wchar_t> > ws2;
88 
89     (void)ns1;
90     (void)ws1;
91     (void)ns2;
92     (void)ws2;
93 }
94 
95 typedef symbols<int, char, quickbook::tst<int, char> > nsymbols;
96 typedef symbols<int, wchar_t, quickbook::tst<int, wchar_t> > wsymbols;
97 
narrow_match_tests()98 static void narrow_match_tests()
99 {
100     nsymbols sym;
101     sym = "pineapple", "orange", "banana", "applepie", "apple";
102 
103     docheck(sym, "pineapple", true, "", 9);
104     docheck(sym, "orange", true, "", 6);
105     docheck(sym, "banana", true, "", 6);
106     docheck(sym, "apple", true, "", 5);
107     docheck(sym, "pizza", false, "pizza", -1);
108     docheck(sym, "steak", false, "steak", -1);
109     docheck(sym, "applepie", true, "", 8);
110     docheck(sym, "bananarama", true, "rama", 6);
111     docheck(sym, "applet", true, "t", 5);
112     docheck(sym, "applepi", true, "pi", 5);
113     docheck(sym, "appl", false, "appl", -1);
114 
115     docheck(sym, "pineapplez", true, "z", 9);
116     docheck(sym, "orangez", true, "z", 6);
117     docheck(sym, "bananaz", true, "z", 6);
118     docheck(sym, "applez", true, "z", 5);
119     docheck(sym, "pizzaz", false, "pizzaz", -1);
120     docheck(sym, "steakz", false, "steakz", -1);
121     docheck(sym, "applepiez", true, "z", 8);
122     docheck(sym, "bananaramaz", true, "ramaz", 6);
123     docheck(sym, "appletz", true, "tz", 5);
124     docheck(sym, "applepix", true, "pix", 5);
125 }
126 
narrow_copy_ctor_tests()127 static void narrow_copy_ctor_tests()
128 {
129     nsymbols sym;
130     sym = "pineapple", "orange", "banana", "applepie", "apple";
131 
132     nsymbols sym2(sym);
133     docheck(sym2, "pineapple", true, "", 9);
134     docheck(sym2, "pizza", false, "pizza", -1);
135     docheck(sym2, "bananarama", true, "rama", 6);
136 }
137 
narrow_assigment_operator_tests()138 static void narrow_assigment_operator_tests()
139 {
140     nsymbols sym;
141     sym = "pineapple", "orange", "banana", "applepie", "apple";
142 
143     nsymbols sym2;
144     sym2 = sym;
145 
146     docheck(sym2, "pineapple", true, "", 9);
147     docheck(sym2, "pizza", false, "pizza", -1);
148     docheck(sym2, "bananarama", true, "rama", 6);
149 }
150 
narrow_swap_tests()151 static void narrow_swap_tests()
152 {
153     nsymbols sym, sym2;
154     sym = "pineapple", "orange", "banana", "applepie", "apple";
155     sym2 = "potato", "cucumber", "cauliflower", "carrot";
156 
157     boost::swap(sym, sym2);
158 
159     docheck(sym2, "pineapple", true, "", 9);
160     docheck(sym2, "pizza", false, "pizza", -1);
161     docheck(sym2, "bananarama", true, "rama", 6);
162     docheck(sym, "potatoe", true, "e", 6);
163     docheck(sym, "cauliflour", false, "cauliflour", -1);
164 }
165 
narrow_value_tests()166 static void narrow_value_tests()
167 { // also tests the add member functions
168     nsymbols sym;
169 
170     sym = "orange", "banana";
171     sym.add("pineapple", 1234);
172     sym.add("lemon");
173 
174     parse("orange", sym[store(12345)]);
175     parse("orange", sym[docheck(12345)]);
176     parse("pineapple", sym[docheck(1234)]);
177     parse("banana", sym[docheck(int())]);
178     parse("lemon", sym[docheck(int())]);
179 }
180 
narrow_free_functions_tests()181 static void narrow_free_functions_tests()
182 {
183     nsymbols sym;
184 
185 #define add_returned_non_null_value (res != 0)
186 #define add_returned_null (res == 0)
187 #define find_returned_non_null_value (res != 0)
188 #define find_returned_null (res == 0)
189 
190     int* res = add(sym, "pineapple");
191     BOOST_TEST(add_returned_non_null_value);
192     res = add(sym, "pineapple");
193     BOOST_TEST(add_returned_null);
194 
195     res = find(sym, "pineapple");
196     BOOST_TEST(find_returned_non_null_value);
197     res = find(sym, "banana");
198     BOOST_TEST(find_returned_null);
199 }
200 
wide_match_tests()201 static void wide_match_tests()
202 {
203     wsymbols sym;
204     sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
205 
206     docheck(sym, L"pineapple", true, L"", 9);
207     docheck(sym, L"orange", true, L"", 6);
208     docheck(sym, L"banana", true, L"", 6);
209     docheck(sym, L"apple", true, L"", 5);
210     docheck(sym, L"pizza", false, L"pizza", -1);
211     docheck(sym, L"steak", false, L"steak", -1);
212     docheck(sym, L"applepie", true, L"", 8);
213     docheck(sym, L"bananarama", true, L"rama", 6);
214     docheck(sym, L"applet", true, L"t", 5);
215     docheck(sym, L"applepi", true, L"pi", 5);
216     docheck(sym, L"appl", false, L"appl", -1);
217 
218     docheck(sym, L"pineapplez", true, L"z", 9);
219     docheck(sym, L"orangez", true, L"z", 6);
220     docheck(sym, L"bananaz", true, L"z", 6);
221     docheck(sym, L"applez", true, L"z", 5);
222     docheck(sym, L"pizzaz", false, L"pizzaz", -1);
223     docheck(sym, L"steakz", false, L"steakz", -1);
224     docheck(sym, L"applepiez", true, L"z", 8);
225     docheck(sym, L"bananaramaz", true, L"ramaz", 6);
226     docheck(sym, L"appletz", true, L"tz", 5);
227     docheck(sym, L"applepix", true, L"pix", 5);
228 }
229 
wide_copy_ctor_tests()230 static void wide_copy_ctor_tests()
231 {
232     wsymbols sym;
233     sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
234 
235     wsymbols sym2(sym);
236     docheck(sym2, L"pineapple", true, L"", 9);
237     docheck(sym2, L"pizza", false, L"pizza", -1);
238     docheck(sym2, L"bananarama", true, L"rama", 6);
239 }
240 
wide_assigment_operator_tests()241 static void wide_assigment_operator_tests()
242 {
243     wsymbols sym;
244     sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
245 
246     wsymbols sym2;
247     sym2 = sym;
248 
249     docheck(sym2, L"pineapple", true, L"", 9);
250     docheck(sym2, L"pizza", false, L"pizza", -1);
251     docheck(sym2, L"bananarama", true, L"rama", 6);
252 }
253 
wide_swap_tests()254 static void wide_swap_tests()
255 {
256     wsymbols sym, sym2;
257     sym = L"pineapple", L"orange", L"banana", L"applepie", L"apple";
258     sym2 = L"potato", L"cucumber", L"cauliflower", L"carrot";
259 
260     boost::swap(sym, sym2);
261 
262     docheck(sym2, L"pineapple", true, L"", 9);
263     docheck(sym2, L"pizza", false, L"pizza", -1);
264     docheck(sym2, L"bananarama", true, L"rama", 6);
265     docheck(sym, L"potatoe", true, L"e", 6);
266     docheck(sym, L"cauliflour", false, L"cauliflour", -1);
267 }
268 
wide_value_tests()269 static void wide_value_tests()
270 { // also tests the add member functions
271     wsymbols sym;
272 
273     sym = L"orange", L"banana";
274     sym.add(L"pineapple", 1234);
275     sym.add(L"lemon");
276 
277     parse(L"orange", sym[store(12345)]);
278     parse(L"orange", sym[docheck(12345)]);
279     parse(L"pineapple", sym[docheck(1234)]);
280     parse(L"banana", sym[docheck(int())]);
281     parse(L"lemon", sym[docheck(int())]);
282 }
283 
wide_free_functions_tests()284 static void wide_free_functions_tests()
285 {
286     wsymbols sym;
287 
288     int* res = add(sym, L"pineapple");
289     BOOST_TEST(add_returned_non_null_value);
290     res = add(sym, L"pineapple");
291     BOOST_TEST(add_returned_null);
292 
293     res = find(sym, L"pineapple");
294     BOOST_TEST(find_returned_non_null_value);
295     res = find(sym, L"banana");
296     BOOST_TEST(find_returned_null);
297 }
298 
free_add_find_functions_tests()299 static void free_add_find_functions_tests()
300 {
301     nsymbols sym;
302     BOOST_TEST(*add(sym, "a", 0) == 0);
303     BOOST_TEST(*add(sym, "a2", 1) == 1);
304     BOOST_TEST(add(sym, "a2", 2) == 0);
305     BOOST_TEST(find(sym, "a2"));
306     BOOST_TEST(find(sym, "a"));
307 }
308 
309 // The original teneray search tree implementation contained a bug when
310 // inserting duplicate values. I want this implementation to be as
311 // close as possible to the original (so they can be easily switched)
312 // so check that the bug remains the same.
313 
314 struct check_parse_value
315 {
check_parse_valuecheck_parse_value316     explicit check_parse_value(int value) : value_(value) {}
317 
operator ()check_parse_value318     void operator()(int value) const { BOOST_TEST(value == value_); }
319 
320     int value_;
321 };
322 
323 // My version is different to the original, if there's an existing value
324 // it replaces it with the new one.
325 
duplicate_add_tests()326 static void duplicate_add_tests()
327 {
328     char const* foo1 = "foo";
329     char const* foo2 = foo1 + 3;
330 
331     nsymbols sym;
332     sym.add(foo1, foo2, 1);
333     nsymbols sym2 = sym;
334     sym.add(foo1, foo2, 2);
335     sym2.add(foo1, foo2, 3);
336 
337     BOOST_TEST(find(sym, "foo") && *find(sym, "foo") == 2);
338     BOOST_TEST(find(sym2, "foo") && *find(sym2, "foo") == 3);
339 
340     parse_info<char const*> info;
341 
342     info = parse("foo ", sym[check_parse_value(2)]);
343     BOOST_TEST(info.hit && info.length == 3);
344 
345     info = parse("foo", sym[check_parse_value(2)]);
346     BOOST_TEST(info.hit && info.length == 3);
347 
348     info = parse("foo ", sym2[check_parse_value(3)]);
349     BOOST_TEST(info.hit && info.length == 3);
350 
351     info = parse("foo", sym2[check_parse_value(3)]);
352     BOOST_TEST(info.hit && info.length == 3);
353 }
354 
main()355 int main()
356 {
357     default_constructible();
358     narrow_match_tests();
359     narrow_copy_ctor_tests();
360     narrow_assigment_operator_tests();
361     narrow_swap_tests();
362     narrow_value_tests();
363     narrow_free_functions_tests();
364     wide_match_tests();
365     wide_copy_ctor_tests();
366     wide_assigment_operator_tests();
367     wide_swap_tests();
368     wide_value_tests();
369     wide_free_functions_tests();
370     free_add_find_functions_tests();
371     duplicate_add_tests();
372 
373     return boost::report_errors();
374 }
375