1 /*
2  * Distributed under the Boost Software License, Version 1.0.(See accompanying
3  * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
4  *
5  * See http://www.boost.org/libs/iostreams for documentation.
6  *
7  * Defines a large collection of closable filters and devices that
8  * execute instances of boost::iostreams::test::operation upon
9  * closre(). Used to verify that filters and devices are closed
10  * correctly by the iostreams library
11  *
12  * File:        libs/iostreams/test/detail/closable.hpp
13  * Date:        Sun Dec 09 16:12:23 MST 2007
14  * Copyright:   2007-2008 CodeRage, LLC
15  * Author:      Jonathan Turkanis
16  * Contact:     turkanis at coderage dot com
17  */
18 
19 #ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
20 #define BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
21 
22 #include <boost/iostreams/categories.hpp>
23 #include <boost/iostreams/char_traits.hpp>  // EOF
24 #include <boost/iostreams/concepts.hpp>
25 #include <boost/iostreams/detail/ios.hpp>
26 #include "./operation_sequence.hpp"
27 
28 namespace boost { namespace iostreams { namespace test {
29 
30 template<typename Category>
31 class closable_device { };
32 
33 // Source
34 template<>
35 class closable_device<input> : public source {
36 public:
closable_device(operation close)37     closable_device(operation close) : close_(close) { }
read(char *,std::streamsize)38     std::streamsize read(char*, std::streamsize) { return -1; }
close()39     void close() { close_.execute(); }
40 private:
41     operation close_;
42 };
43 
44 // Sink
45 template<>
46 class closable_device<output> : public sink {
47 public:
closable_device(operation close)48     closable_device(operation close) : close_(close) { }
write(const char *,std::streamsize)49     std::streamsize write(const char*, std::streamsize) { return 0; }
close()50     void close() { close_.execute(); }
51 private:
52     operation close_;
53 };
54 
55 struct borland_output { };
56 
57 // Copy of closable_device<output>, for Borland <= 5.8.2
58 template<>
59 class closable_device<borland_output> : public sink {
60 public:
closable_device(operation close)61     closable_device(operation close) : close_(close) { }
write(const char *,std::streamsize)62     std::streamsize write(const char*, std::streamsize) { return 0; }
close()63     void close() { close_.execute(); }
64 private:
65     operation close_;
66 };
67 
68 // Bidirectional device
69 template<>
70 class closable_device<bidirectional> : public device<bidirectional> {
71 public:
closable_device(operation close_input,operation close_output)72     closable_device(operation close_input, operation close_output)
73         : close_input_(close_input), close_output_(close_output)
74         { }
read(char *,std::streamsize)75     std::streamsize read(char*, std::streamsize) { return -1; }
write(const char *,std::streamsize)76     std::streamsize write(const char*, std::streamsize) { return 0; }
close(BOOST_IOS::openmode which)77     void close(BOOST_IOS::openmode which)
78     {
79         switch (which) {
80         case BOOST_IOS::in:
81             close_input_.execute();
82             break;
83         case BOOST_IOS::out:
84             close_output_.execute();
85             break;
86         default:
87             break;
88         }
89     }
90 private:
91     operation close_input_;
92     operation close_output_;
93 };
94 
95 // Seekable device
96 template<>
97 class closable_device<seekable> : public device<seekable> {
98 public:
closable_device(operation close)99     closable_device(operation close) : close_(close) { }
read(char *,std::streamsize)100     std::streamsize read(char*, std::streamsize) { return -1; }
write(const char *,std::streamsize)101     std::streamsize write(const char*, std::streamsize) { return 0; }
seek(stream_offset,BOOST_IOS::seekdir)102     stream_offset seek(stream_offset, BOOST_IOS::seekdir) { return 0; }
close()103     void close() { close_.execute(); }
104 private:
105     operation close_;
106 };
107 
108 struct direct_input
109     : input, device_tag, closable_tag, direct_tag
110     { };
111 struct direct_output
112     : output, device_tag, closable_tag, direct_tag
113     { };
114 struct direct_bidirectional
115     : bidirectional, device_tag, closable_tag, direct_tag
116     { };
117 struct direct_seekable
118     : seekable, device_tag, closable_tag, direct_tag
119     { };
120 
121 // Direct source
122 template<>
123 class closable_device<direct_input> {
124 public:
125     typedef char          char_type;
126     typedef direct_input  category;
closable_device(operation close)127     closable_device(operation close) : close_(close) { }
input_sequence()128     std::pair<char*, char*> input_sequence()
129     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
close()130     void close() { close_.execute(); }
131 private:
132     operation close_;
133 };
134 
135 // Direct sink
136 template<>
137 class closable_device<direct_output> {
138 public:
139     typedef char           char_type;
140     typedef direct_output  category;
closable_device(operation close)141     closable_device(operation close) : close_(close) { }
output_sequence()142     std::pair<char*, char*> output_sequence()
143     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
close()144     void close() { close_.execute(); }
145 private:
146     operation close_;
147 };
148 
149 // Direct bidirectional device
150 template<>
151 class closable_device<direct_bidirectional> {
152 public:
153     typedef char                  char_type;
154     typedef direct_bidirectional  category;
closable_device(operation close_input,operation close_output)155     closable_device(operation close_input, operation close_output)
156         : close_input_(close_input), close_output_(close_output)
157         { }
input_sequence()158     std::pair<char*, char*> input_sequence()
159     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
output_sequence()160     std::pair<char*, char*> output_sequence()
161     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
close(BOOST_IOS::openmode which)162     void close(BOOST_IOS::openmode which)
163     {
164         switch (which) {
165         case BOOST_IOS::in:
166             close_input_.execute();
167             break;
168         case BOOST_IOS::out:
169             close_output_.execute();
170             break;
171         default:
172             break;
173         }
174     }
175 private:
176     operation close_input_;
177     operation close_output_;
178 };
179 
180 // Direct seekable device
181 template<>
182 class closable_device<direct_seekable> {
183 public:
184     typedef char             char_type;
185     typedef direct_seekable  category;
closable_device(operation close)186     closable_device(operation close) : close_(close) { }
input_sequence()187     std::pair<char*, char*> input_sequence()
188     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
output_sequence()189     std::pair<char*, char*> output_sequence()
190     { return std::pair<char*, char*>(static_cast<char*>(0), static_cast<char*>(0)); }
close()191     void close() { close_.execute(); }
192 private:
193     operation close_;
194 };
195 
196 template<typename Mode>
197 class closable_filter { };
198 
199 // Input filter
200 template<>
201 class closable_filter<input> : public input_filter {
202 public:
closable_filter(operation close)203     closable_filter(operation close) : close_(close) { }
204 
205     template<typename Source>
get(Source &)206     int get(Source&) { return EOF; }
207 
208     template<typename Source>
close(Source &)209     void close(Source&) { close_.execute(); }
210 private:
211     operation close_;
212 };
213 
214 // Output filter
215 template<>
216 class closable_filter<output> : public output_filter {
217 public:
closable_filter(operation close)218     closable_filter(operation close) : close_(close) { }
219 
220     template<typename Sink>
put(Sink &,char)221     bool put(Sink&, char) { return true; }
222 
223     template<typename Sink>
close(Sink &)224     void close(Sink&) { close_.execute(); }
225 private:
226     operation close_;
227 };
228 
229 // Bidirectional filter
230 template<>
231 class closable_filter<bidirectional> : public filter<bidirectional> {
232 public:
closable_filter(operation close_input,operation close_output)233     closable_filter(operation close_input, operation close_output)
234         : close_input_(close_input), close_output_(close_output)
235         { }
236 
237     template<typename Source>
get(Source &)238     int get(Source&) { return EOF; }
239 
240     template<typename Sink>
put(Sink &,char)241     bool put(Sink&, char) { return true; }
242 
243     template<typename Device>
close(Device &,BOOST_IOS::openmode which)244     void close(Device&, BOOST_IOS::openmode which)
245     {
246         switch (which) {
247         case BOOST_IOS::in:
248             close_input_.execute();
249             break;
250         case BOOST_IOS::out:
251             close_output_.execute();
252             break;
253         default:
254             break;
255         }
256     }
257 private:
258     operation close_input_;
259     operation close_output_;
260 };
261 
262 // Seekable filter
263 template<>
264 class closable_filter<seekable> : public filter<seekable> {
265 public:
closable_filter(operation close)266     closable_filter(operation close) : close_(close) { }
read(char *,std::streamsize)267     std::streamsize read(char*, std::streamsize) { return -1; }
268 
269     template<typename Source>
get(Source &)270     int get(Source&) { return EOF; }
271 
272     template<typename Sink>
put(Sink &,char)273     bool put(Sink&, char) { return true; }
274 
275     template<typename Device>
seek(Device &,stream_offset,BOOST_IOS::seekdir)276     stream_offset seek(Device&, stream_offset, BOOST_IOS::seekdir)
277     {
278         return 0;
279     }
280 
281     template<typename Device>
close(Device &)282     void close(Device&) { close_.execute(); }
283 private:
284     operation close_;
285 };
286 
287 // Dual-use filter
288 template<>
289 class closable_filter<dual_use> {
290 public:
291     typedef char char_type;
292     struct category
293         : filter_tag,
294           dual_use,
295           closable_tag
296         { };
closable_filter(operation close_input,operation close_output)297     closable_filter(operation close_input, operation close_output)
298         : close_input_(close_input), close_output_(close_output)
299         { }
300 
301     template<typename Source>
get(Source &)302     int get(Source&) { return EOF; }
303 
304     template<typename Sink>
put(Sink &,char)305     bool put(Sink&, char) { return true; }
306 
307     template<typename Device>
close(Device &,BOOST_IOS::openmode which)308     void close(Device&, BOOST_IOS::openmode which)
309     {
310         switch (which) {
311         case BOOST_IOS::in:
312             close_input_.execute();
313             break;
314         case BOOST_IOS::out:
315             close_output_.execute();
316             break;
317         default:
318             break;
319         }
320     }
321 private:
322     operation close_input_;
323     operation close_output_;
324 };
325 
326 // Symmetric filter
327 class closable_symmetric_filter {
328 public:
329     typedef char char_type;
closable_symmetric_filter(operation close)330     closable_symmetric_filter(operation close) : close_(close) { }
filter(const char * &,const char *,char * &,char *,bool)331     bool filter( const char*&, const char*,
332                  char*&, char*, bool )
333     {
334         return false;
335     }
close()336     void close() { close_.execute(); }
337 private:
338     operation close_;
339 };
340 
341 } } } // End namespaces test, iostreams, boost.
342 
343 #endif // #ifndef BOOST_IOSTREAMS_TEST_CLOSABLE_HPP_INCLUDED
344