1 | // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com) |
2 | // (C) Copyright 2004-2007 Jonathan Turkanis |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) |
5 | |
6 | // See http://www.boost.org/libs/iostreams for documentation. |
7 | |
8 | |
9 | #ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED |
10 | #define BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED |
11 | |
12 | #include <iostream> |
13 | #include <exception> |
14 | #include <string> |
15 | #include <string.h> |
16 | #include <fstream> |
17 | #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES |
18 | # include <istream> |
19 | # include <ostream> |
20 | #else |
21 | # include <iostream.h> |
22 | #endif |
23 | |
24 | #include <boost/config.hpp> |
25 | #include <boost/detail/workaround.hpp> |
26 | #include <boost/iostreams/detail/char_traits.hpp> |
27 | #include <boost/iostreams/detail/config/wide_streams.hpp> |
28 | #include "./constants.hpp" |
29 | |
30 | // Must come last. |
31 | #include <boost/iostreams/detail/config/disable_warnings.hpp> |
32 | |
33 | // Code generation bugs cause tests to fail with global optimization. |
34 | #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
35 | # pragma optimize("g", off) |
36 | #endif |
37 | |
38 | // Included only by tests; no need to #undef. |
39 | #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES |
40 | # define BOOST_TEMPLATE_DECL template<typename Ch, typename Tr> |
41 | # define BOOST_CHAR Ch |
42 | # define BOOST_ISTREAM std::basic_istream<Ch, Tr> |
43 | # define BOOST_OSTREAM std::basic_ostream<Ch, Tr> |
44 | #else |
45 | # define BOOST_TEMPLATE_DECL |
46 | # define BOOST_CHAR char |
47 | # define BOOST_ISTREAM std::istream |
48 | # define BOOST_OSTREAM std::ostream |
49 | #endif |
50 | |
51 | namespace boost { namespace iostreams { namespace test { |
52 | |
53 | BOOST_TEMPLATE_DECL |
54 | bool compare_streams_in_chars(BOOST_ISTREAM& first, BOOST_ISTREAM& second) |
55 | { |
56 | for (int z = 0; z < data_reps; ++z) |
57 | for (int w = 0; w < data_length(); ++w) |
58 | if (first.eof() != second.eof() || first.get() != second.get()) |
59 | return false; |
60 | return true; |
61 | } |
62 | |
63 | BOOST_TEMPLATE_DECL |
64 | bool compare_streams_in_chunks(BOOST_ISTREAM& first, BOOST_ISTREAM& second) |
65 | { |
66 | int i = 0; |
67 | do { |
68 | BOOST_CHAR buf_one[chunk_size]; |
69 | BOOST_CHAR buf_two[chunk_size]; |
70 | first.read(buf_one, chunk_size); |
71 | second.read(buf_two, chunk_size); |
72 | std::streamsize amt = first.gcount(); |
73 | if ( amt != static_cast<std::streamsize>(second.gcount()) || |
74 | BOOST_IOSTREAMS_CHAR_TRAITS(BOOST_CHAR):: |
75 | compare(buf_one, buf_two, static_cast<std::size_t>(amt)) != 0 ) |
76 | return false; |
77 | ++i; |
78 | } while (!first.eof()); |
79 | return true; |
80 | } |
81 | |
82 | bool compare_files(const std::string& first, const std::string& second) |
83 | { |
84 | using namespace std; |
85 | ifstream one(first.c_str(), BOOST_IOS::in | BOOST_IOS::binary); |
86 | ifstream two(second.c_str(), BOOST_IOS::in | BOOST_IOS::binary); |
87 | return compare_streams_in_chunks(first&: one, second&: two); |
88 | } |
89 | |
90 | #ifndef BOOST_IOSTREAMS_NO_STREAM_TEMPLATES |
91 | template<typename Container, typename Ch, typename Tr> |
92 | #else |
93 | template<typename Container> |
94 | #endif |
95 | bool compare_container_and_stream(Container& cnt, BOOST_ISTREAM& is) |
96 | { |
97 | typename Container::iterator first = cnt.begin(); |
98 | typename Container::iterator last = cnt.end(); |
99 | do { |
100 | if ((first == last) != is.eof()) return false; |
101 | if (first != last && *first++ != is.get()) return false; |
102 | } while (first != last); |
103 | return true; |
104 | } |
105 | |
106 | template<typename Container> |
107 | bool compare_container_and_file(Container& cnt, const std::string& file) |
108 | { |
109 | std::ifstream fstrm(file.c_str(), BOOST_IOS::in | BOOST_IOS::binary); |
110 | return compare_container_and_stream(cnt, fstrm); |
111 | } |
112 | |
113 | BOOST_TEMPLATE_DECL |
114 | void write_data_in_chars(BOOST_OSTREAM& os) |
115 | { |
116 | for (int z = 0; z < data_reps; ++z) |
117 | for (int w = 0; w < data_length(); ++w) |
118 | os.put(detail::data((BOOST_CHAR*)0)[w]); |
119 | os.flush(); |
120 | } |
121 | |
122 | BOOST_TEMPLATE_DECL |
123 | void write_data_in_chunks(BOOST_OSTREAM& os) |
124 | { |
125 | const BOOST_CHAR* buf = detail::data((BOOST_CHAR*)0); |
126 | for (int z = 0; z < data_reps; ++z) |
127 | os.write(buf, data_length()); |
128 | os.flush(); |
129 | } |
130 | |
131 | bool test_seekable_in_chars(std::iostream& io) |
132 | { |
133 | int i; // old 'for' scope workaround. |
134 | |
135 | // Test seeking with ios::cur |
136 | for (i = 0; i < data_reps; ++i) { |
137 | int j; |
138 | for (j = 0; j < chunk_size; ++j) |
139 | io.put(c: narrow_data()[j]); |
140 | io.seekp(-chunk_size, BOOST_IOS::cur); |
141 | for (j = 0; j < chunk_size; ++j) |
142 | if (io.get() != narrow_data()[j]) |
143 | return false; |
144 | io.seekg(-chunk_size, BOOST_IOS::cur); |
145 | for (j = 0; j < chunk_size; ++j) |
146 | io.put(c: narrow_data()[j]); |
147 | } |
148 | |
149 | // Test seeking with ios::beg |
150 | std::streamoff off = 0; |
151 | io.seekp(0, BOOST_IOS::beg); |
152 | for (i = 0; i < data_reps; ++i, off += chunk_size) { |
153 | int j; |
154 | for (j = 0; j < chunk_size; ++j) |
155 | io.put(c: narrow_data()[j]); |
156 | io.seekp(off, BOOST_IOS::beg); |
157 | for (j = 0; j < chunk_size; ++j) |
158 | if (io.get() != narrow_data()[j]) |
159 | return false; |
160 | io.seekg(off, BOOST_IOS::beg); |
161 | for (j = 0; j < chunk_size; ++j) |
162 | io.put(c: narrow_data()[j]); |
163 | } |
164 | |
165 | // Test seeking with ios::end |
166 | io.seekp(0, BOOST_IOS::end); |
167 | off = io.tellp(); |
168 | io.seekp(-off, BOOST_IOS::end); |
169 | for (i = 0; i < data_reps; ++i, off -= chunk_size) { |
170 | int j; |
171 | for (j = 0; j < chunk_size; ++j) |
172 | io.put(c: narrow_data()[j]); |
173 | io.seekp(-off, BOOST_IOS::end); |
174 | for (j = 0; j < chunk_size; ++j) |
175 | if (io.get() != narrow_data()[j]) |
176 | return false; |
177 | io.seekg(-off, BOOST_IOS::end); |
178 | for (j = 0; j < chunk_size; ++j) |
179 | io.put(c: narrow_data()[j]); |
180 | } |
181 | return true; |
182 | } |
183 | |
184 | bool test_seekable_in_chunks(std::iostream& io) |
185 | { |
186 | int i; // old 'for' scope workaround. |
187 | |
188 | // Test seeking with ios::cur |
189 | for (i = 0; i < data_reps; ++i) { |
190 | io.write(s: narrow_data(), n: chunk_size); |
191 | io.seekp(-chunk_size, BOOST_IOS::cur); |
192 | char buf[chunk_size]; |
193 | io.read(s: buf, n: chunk_size); |
194 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
195 | return false; |
196 | io.seekg(-chunk_size, BOOST_IOS::cur); |
197 | io.write(s: narrow_data(), n: chunk_size); |
198 | } |
199 | |
200 | // Test seeking with ios::beg |
201 | std::streamoff off = 0; |
202 | io.seekp(0, BOOST_IOS::beg); |
203 | for (i = 0; i < data_reps; ++i, off += chunk_size) { |
204 | io.write(s: narrow_data(), n: chunk_size); |
205 | io.seekp(off, BOOST_IOS::beg); |
206 | char buf[chunk_size]; |
207 | io.read(s: buf, n: chunk_size); |
208 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
209 | return false; |
210 | io.seekg(off, BOOST_IOS::beg); |
211 | io.write(s: narrow_data(), n: chunk_size); |
212 | } |
213 | |
214 | // Test seeking with ios::end |
215 | io.seekp(0, BOOST_IOS::end); |
216 | off = io.tellp(); |
217 | io.seekp(-off, BOOST_IOS::end); |
218 | for (i = 0; i < data_reps; ++i, off -= chunk_size) { |
219 | io.write(s: narrow_data(), n: chunk_size); |
220 | io.seekp(-off, BOOST_IOS::end); |
221 | char buf[chunk_size]; |
222 | io.read(s: buf, n: chunk_size); |
223 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
224 | return false; |
225 | io.seekg(-off, BOOST_IOS::end); |
226 | io.write(s: narrow_data(), n: chunk_size); |
227 | } |
228 | return true; |
229 | } |
230 | |
231 | bool test_input_seekable(std::istream& io) |
232 | { |
233 | int i; // old 'for' scope workaround. |
234 | |
235 | // Test seeking with ios::cur |
236 | for (i = 0; i < data_reps; ++i) { |
237 | for (int j = 0; j < chunk_size; ++j) |
238 | if (io.get() != narrow_data()[j]) |
239 | return false; |
240 | io.seekg(-chunk_size, BOOST_IOS::cur); |
241 | char buf[chunk_size]; |
242 | io.read(s: buf, n: chunk_size); |
243 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
244 | return false; |
245 | } |
246 | |
247 | // Test seeking with ios::beg |
248 | std::streamoff off = 0; |
249 | io.seekg(0, BOOST_IOS::beg); |
250 | for (i = 0; i < data_reps; ++i, off += chunk_size) { |
251 | for (int j = 0; j < chunk_size; ++j) |
252 | if (io.get() != narrow_data()[j]) |
253 | return false; |
254 | io.seekg(off, BOOST_IOS::beg); |
255 | char buf[chunk_size]; |
256 | io.read(s: buf, n: chunk_size); |
257 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
258 | return false; |
259 | } |
260 | |
261 | // Test seeking with ios::end |
262 | io.seekg(0, BOOST_IOS::end); |
263 | off = io.tellg(); |
264 | io.seekg(-off, BOOST_IOS::end); |
265 | for (i = 0; i < data_reps; ++i, off -= chunk_size) { |
266 | for (int j = 0; j < chunk_size; ++j) |
267 | if (io.get() != narrow_data()[j]) |
268 | return false; |
269 | io.seekg(-off, BOOST_IOS::end); |
270 | char buf[chunk_size]; |
271 | io.read(s: buf, n: chunk_size); |
272 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
273 | return false; |
274 | } |
275 | return true; |
276 | } |
277 | |
278 | bool test_output_seekable(std::ostream& io) |
279 | { |
280 | int i; // old 'for' scope workaround. |
281 | |
282 | // Test seeking with ios::cur |
283 | for (i = 0; i < data_reps; ++i) { |
284 | for (int j = 0; j < chunk_size; ++j) |
285 | io.put(c: narrow_data()[j]); |
286 | io.seekp(-chunk_size, BOOST_IOS::cur); |
287 | io.write(s: narrow_data(), n: chunk_size); |
288 | } |
289 | |
290 | // Test seeking with ios::beg |
291 | std::streamoff off = 0; |
292 | io.seekp(0, BOOST_IOS::beg); |
293 | for (i = 0; i < data_reps; ++i, off += chunk_size) { |
294 | for (int j = 0; j < chunk_size; ++j) |
295 | io.put(c: narrow_data()[j]); |
296 | io.seekp(off, BOOST_IOS::beg); |
297 | io.write(s: narrow_data(), n: chunk_size); |
298 | } |
299 | |
300 | // Test seeking with ios::end |
301 | io.seekp(0, BOOST_IOS::end); |
302 | off = io.tellp(); |
303 | io.seekp(-off, BOOST_IOS::end); |
304 | for (i = 0; i < data_reps; ++i, off -= chunk_size) { |
305 | for (int j = 0; j < chunk_size; ++j) |
306 | io.put(c: narrow_data()[j]); |
307 | io.seekp(-off, BOOST_IOS::end); |
308 | io.write(s: narrow_data(), n: chunk_size); |
309 | } |
310 | return true; |
311 | } |
312 | |
313 | bool test_dual_seekable(std::iostream& io) |
314 | { |
315 | int i; // old 'for' scope workaround. |
316 | |
317 | // Test seeking with ios::cur |
318 | for (i = 0; i < data_reps; ++i) { |
319 | for (int j = 0; j < chunk_size; ++j) |
320 | io.put(c: narrow_data()[j]); |
321 | io.seekp(-chunk_size, BOOST_IOS::cur); |
322 | for (int j = 0; j < chunk_size; ++j) |
323 | if (io.get() != narrow_data()[j]) |
324 | return false; |
325 | io.seekg(-chunk_size, BOOST_IOS::cur); |
326 | io.write(s: narrow_data(), n: chunk_size); |
327 | char buf[chunk_size]; |
328 | io.read(s: buf, n: chunk_size); |
329 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
330 | return false; |
331 | } |
332 | |
333 | // Test seeking with ios::beg |
334 | std::streamoff off = 0; |
335 | io.seekp(0, BOOST_IOS::beg); |
336 | io.seekg(0, BOOST_IOS::beg); |
337 | for (i = 0; i < data_reps; ++i, off += chunk_size) { |
338 | for (int j = 0; j < chunk_size; ++j) |
339 | io.put(c: narrow_data()[j]); |
340 | io.seekp(off, BOOST_IOS::beg); |
341 | for (int j = 0; j < chunk_size; ++j) |
342 | if (io.get() != narrow_data()[j]) |
343 | return false; |
344 | io.seekg(off, BOOST_IOS::beg); |
345 | io.write(s: narrow_data(), n: chunk_size); |
346 | char buf[chunk_size]; |
347 | io.read(s: buf, n: chunk_size); |
348 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
349 | return false; |
350 | } |
351 | |
352 | // Test seeking with ios::end |
353 | io.seekp(0, BOOST_IOS::end); |
354 | io.seekg(0, BOOST_IOS::end); |
355 | off = io.tellp(); |
356 | io.seekp(-off, BOOST_IOS::end); |
357 | io.seekg(-off, BOOST_IOS::end); |
358 | for (i = 0; i < data_reps; ++i, off -= chunk_size) { |
359 | for (int j = 0; j < chunk_size; ++j) |
360 | io.put(c: narrow_data()[j]); |
361 | io.seekp(-off, BOOST_IOS::end); |
362 | for (int j = 0; j < chunk_size; ++j) |
363 | if (io.get() != narrow_data()[j]) |
364 | return false; |
365 | io.seekg(-off, BOOST_IOS::end); |
366 | io.write(s: narrow_data(), n: chunk_size); |
367 | char buf[chunk_size]; |
368 | io.read(s: buf, n: chunk_size); |
369 | if (strncmp(s1: buf, s2: narrow_data(), n: chunk_size) != 0) |
370 | return false; |
371 | } |
372 | return true; |
373 | } |
374 | |
375 | } } } // End namespaces test, iostreams, boost. |
376 | |
377 | #include <boost/iostreams/detail/config/enable_warnings.hpp> |
378 | |
379 | #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) |
380 | # pragma optimize("", on) |
381 | #endif |
382 | |
383 | #endif // #ifndef BOOST_IOSTREAMS_TEST_VERIFICATION_HPP_INCLUDED |
384 | |