1 /*=============================================================================
2     Copyright (c) 2003 Giovanni Bajo
3     http://spirit.sourceforge.net/
4 
5     Use, modification and distribution is subject to the Boost Software
6     License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7     http://www.boost.org/LICENSE_1_0.txt)
8 =============================================================================*/
9 #include <boost/detail/lightweight_test.hpp>
10 #include <cstdio>
11 #include <iostream>
12 #include <boost/concept_check.hpp>
13 #include <boost/spirit/include/classic_file_iterator.hpp>
14 
15 // This checks for a namespace related problem in VC8
16 // The problem can be avoided by not using "using namespace std;" in the
17 // Spirit headers
18 namespace vc8_bug_1 { struct plus {}; }
19 namespace vc8_bug_2 { using namespace vc8_bug_1; struct test : plus {}; }
20 
21 
22 using namespace std;
23 using namespace BOOST_SPIRIT_CLASSIC_NS;
24 
25 namespace {
26 
27 static const char* TMP_FILE = "file_iter.tmp";
28 
CreateTempFile(void)29 bool CreateTempFile(void)
30 {
31     FILE* f = fopen(TMP_FILE, "wb");
32 
33     if (!f)
34         return false;
35 
36     for (int i=0;i<256;i++)
37     {
38         unsigned char ci = (unsigned char)i;
39 
40         if (fwrite(&ci,1,1,f) == 0)
41         {
42             fclose(f);
43             return false;
44         }
45     }
46 
47     fclose(f);
48     return true;
49 }
50 
51 template <typename ITER>
RunTest(void)52 void RunTest(void)
53 {
54     // Check constructor opening a file
55     ITER a(TMP_FILE);
56     BOOST_TEST(!!a);
57 
58     // Assert dereference (twice: derefence
59     //  must not move the iterator)
60     BOOST_TEST(*a == 0);
61     BOOST_TEST(*a == 0);
62 
63     // Check random access
64     BOOST_TEST(a[123] == 123);
65 
66     // Check copy constructor and operator==
67     ITER c(a);
68     BOOST_TEST(c == a);
69     BOOST_TEST(!(c != a));
70 
71     // Check assignment operator
72     ITER d; d = a;
73     BOOST_TEST(d == a);
74     BOOST_TEST(!(d != a));
75 
76     // Check make_end()
77     ITER b(a.make_end());
78     BOOST_TEST(!!b);
79     BOOST_TEST(a != b);
80     BOOST_TEST(a+256 == b);
81     BOOST_TEST(a == b-256);
82 
83     // Check copy constructor on non-trivial position
84     BOOST_TEST(*ITER(a+67) == 67);
85 
86     // Check increment
87     ++a; ++a; a++; a++;
88     BOOST_TEST(*a == 4);
89     BOOST_TEST(a == c+4);
90 
91     // Check decrement
92     --a; --a; a--; a--;
93     BOOST_TEST(*a == 0);
94     BOOST_TEST(a == c);
95 
96     // Check end iterator increment/decrement
97     --b; b--;
98     BOOST_TEST(*b == 254);
99     BOOST_TEST(a+254 == b);
100     ++b; b++;
101     BOOST_TEST(a+256 == b);
102 
103     // Check order
104     a += 128;
105     BOOST_TEST(c < a);
106     BOOST_TEST(a < b);
107     BOOST_TEST(a > c);
108     BOOST_TEST(b > a);
109 
110     // Check assignment
111     a = b;
112     BOOST_TEST(a == b);
113     a = c;
114     BOOST_TEST(a == c);
115 
116     // Check weak order
117     BOOST_TEST(a <= c);
118     BOOST_TEST(a >= c);
119     BOOST_TEST(a <= b);
120     BOOST_TEST(!(a >= b));
121 
122     // Check increment through end
123     a += 255;
124     BOOST_TEST(a != b);
125     ++a;
126     BOOST_TEST(a == b);
127     ++a;
128     BOOST_TEST(a != b);
129 }
130 
131 ///////////////////////////////////////////////////////////////////////////////
132 }
133 
134 typedef unsigned char character_t;
135 typedef file_iterator<character_t,
136     fileiter_impl::std_file_iterator<character_t> > iter;
137 BOOST_CLASS_REQUIRE(iter, boost, RandomAccessIteratorConcept);
138 
139 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
140     typedef file_iterator<character_t,
141         fileiter_impl::mmap_file_iterator<character_t> > iterwin;
142     BOOST_CLASS_REQUIRE(iterwin, boost, RandomAccessIteratorConcept);
143 #endif
144 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
145     typedef file_iterator<character_t,
146         fileiter_impl::mmap_file_iterator<character_t> > iterposix;
147     BOOST_CLASS_REQUIRE(iterposix, boost, RandomAccessIteratorConcept);
148 #endif
149 
main(void)150 int main(void)
151 {
152     if (!CreateTempFile())
153     {
154         cerr << "ERROR: Cannot create temporary file file_iter.tmp" << endl;
155         return 2;
156     }
157 
158     cerr << "Testing standard iterator" << endl;
159     RunTest<iter>();
160 
161 #ifdef BOOST_SPIRIT_FILEITERATOR_WINDOWS
162     cerr << "Testing Windows iterator" << endl;
163     RunTest<iterwin>();
164 #endif
165 
166 #ifdef BOOST_SPIRIT_FILEITERATOR_POSIX
167     cerr << "Testing POSIX iterator" << endl;
168     RunTest<iterposix>();
169 #endif
170 
171     // Check if the file handles were closed correctly
172     BOOST_TEST(remove(TMP_FILE) == 0);
173 
174     return boost::report_errors();
175 }
176 
177 #ifdef BOOST_NO_EXCEPTIONS
178 
179 namespace boost {
throw_exception(std::exception const & e)180     void throw_exception(std::exception const& e)
181     {
182         BOOST_EROR("throw_exception");
183     }
184 }
185 
186 #endif
187