source: NonGTP/Boost/boost/iostreams/invert.hpp @ 857

Revision 857, 5.3 KB checked in by igarcia, 18 years ago (diff)
Line 
1// (C) Copyright Jonathan Turkanis 2003.
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#ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
8#define BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
9
10#if defined(_MSC_VER) && (_MSC_VER >= 1020)
11# pragma once
12#endif             
13
14#include <algorithm>                             // copy, min. 
15#include <cassert>
16#include <boost/config.hpp>                      // BOOST_DEDUCED_TYPENAME.       
17#include <boost/detail/workaround.hpp>           // default_filter_buffer_size.
18#include <boost/iostreams/char_traits.hpp>
19#include <boost/iostreams/compose.hpp>
20#include <boost/iostreams/constants.hpp>
21#include <boost/iostreams/device/array.hpp>
22#include <boost/iostreams/detail/buffer.hpp>
23#include <boost/iostreams/detail/counted_array.hpp>
24#include <boost/mpl/if.hpp>
25#include <boost/ref.hpp>
26#include <boost/shared_ptr.hpp>
27#include <boost/type_traits/is_convertible.hpp>
28
29// Must come last.
30#include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
31
32namespace boost { namespace iostreams {
33
34//
35// Template name: inverse.
36// Template paramters:
37//      Filter - A filter adapter which
38// Description: Returns an instance of an appropriate specialization of inverse.
39//
40template<typename Filter>
41class inverse {
42private:
43    typedef typename category_of<Filter>::type   base_category;
44    typedef reference_wrapper<Filter>            filter_ref;
45public:
46    typedef typename char_type_of<Filter>::type  char_type;
47    typedef typename int_type_of<Filter>::type   int_type;
48    typedef char_traits<char_type>               traits_type;
49    typedef typename
50            mpl::if_<
51                is_convertible<
52                    base_category,
53                    input
54                >,
55                output,
56                input
57            >::type                              mode;
58    struct category
59        : mode,
60          filter_tag,
61          multichar_tag,
62          closable_tag
63        { };
64    explicit inverse( const Filter& filter,
65                      std::streamsize buffer_size =
66                          default_filter_buffer_size)
67        : pimpl_(new impl(filter, buffer_size))
68        { }
69
70    template<typename Source>
71    std::streamsize read(Source& src, char* s, std::streamsize n)
72    {
73        typedef detail::counted_array_sink<char_type>  array_sink;
74        typedef composite<filter_ref, array_sink>      filtered_array_sink;
75
76        assert((flags() & f_write) == 0);
77        if (flags() == 0) {
78            flags() = f_read;
79            buf().set(0, 0);
80        }
81
82        filtered_array_sink snk(filter(), array_sink(s, n));
83        int_type status;
84        for ( status = traits_type::good();
85              snk.second().count() < n && status == traits_type::good(); )
86        {
87            status = buf().fill(src);
88            buf().flush(snk);
89        }
90        return snk.second().count() == 0 &&
91               status == traits_type::eof()
92                   ?
93               -1
94                   :
95               snk.second().count();
96    }
97
98    template<typename Sink>
99    std::streamsize write(Sink& dest, const char* s, std::streamsize n)
100    {
101        typedef detail::counted_array_source<char_type>  array_source;
102        typedef composite<filter_ref, array_source>      filtered_array_source;
103
104        assert((flags() & f_read) == 0);
105        if (flags() == 0) {
106            flags() = f_write;
107            buf().set(0, 0);
108        }
109       
110        filtered_array_source src(filter(), array_source(s, n));
111        for (bool good = true; src.second().count() < n && good; ) {
112            buf().fill(src);
113            good = buf().flush(dest);
114        }
115        return src.second().count();
116    }
117
118    template<typename Device>
119    void close( Device& dev,
120                BOOST_IOS::openmode which =
121                    BOOST_IOS::in | BOOST_IOS::out )
122    {
123        if ((which & BOOST_IOS::out) != 0 && (flags() & f_write) != 0)
124            buf().flush(dev);
125        flags() = 0;
126    }
127private:
128    filter_ref filter() { return boost::ref(pimpl_->filter_); }
129    detail::buffer<char_type>& buf() { return pimpl_->buf_; }
130    int& flags() { return pimpl_->flags_; }
131   
132    enum flags_ {
133        f_read = 1, f_write = 2
134    };
135
136    struct impl {
137        impl(const Filter& filter, std::streamsize n)
138            : filter_(filter), buf_(n), flags_(0)
139        { buf_.set(0, 0); }
140        Filter                     filter_;
141        detail::buffer<char_type>  buf_;
142        int                        flags_;
143    };
144    shared_ptr<impl> pimpl_;
145};
146
147//
148// Template name: invert.
149// Template paramters:
150//      Filter - A model of InputFilter or OutputFilter.
151// Description: Returns an instance of an appropriate specialization of inverse.
152//
153template<typename Filter>
154inverse<Filter> invert(const Filter& f) { return inverse<Filter>(f); }
155                   
156//----------------------------------------------------------------------------//
157
158} } // End namespaces iostreams, boost.
159
160#include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
161
162#endif // #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.