source: NonGTP/Boost/boost/iostreams/filter/aggregate.hpp @ 857

Revision 857, 5.1 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_AGGREGATE_FILTER_HPP_INCLUDED
8#define BOOST_IOSTREAMS_AGGREGATE_FILTER_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 <iterator>                           // back_inserter
17#include <vector>
18#include <boost/iostreams/categories.hpp>
19#include <boost/iostreams/detail/char_traits.hpp>
20#include <boost/iostreams/detail/closer.hpp>
21#include <boost/iostreams/detail/ios.hpp>     // openmode, streamsize.
22#include <boost/iostreams/pipeline.hpp>
23#include <boost/mpl/bool.hpp>
24#include <boost/type_traits/is_convertible.hpp>
25
26// Must come last.
27#include <boost/iostreams/detail/config/disable_warnings.hpp>  // MSVC.
28
29namespace boost { namespace iostreams {
30
31//
32// Template name: aggregate_filter.
33// Template paramters:
34//      Ch - The character type.
35//      Alloc - The allocator type.
36// Description: Utility for defining DualUseFilters which filter an
37//      entire stream at once. To use, override the protected virtual
38//      member do_filter.
39// Note: This filter should not be copied while it is in use.
40//
41template<typename Ch, typename Alloc = std::allocator<Ch> >
42class aggregate_filter  {
43public:
44    typedef Ch char_type;
45    struct category
46        : dual_use,
47          filter_tag,
48          multichar_tag,
49          closable_tag
50        { };
51    aggregate_filter() : ptr_(0), state_(0) { }
52    virtual ~aggregate_filter() { }
53
54    template<typename Source>
55    std::streamsize read(Source& src, char_type* s, std::streamsize n)
56    {
57        using namespace std;
58        assert(!(state_ & f_write));
59        state_ |= f_read;
60        if (!(state_ & f_eof))
61            do_read(src);
62        streamsize amt =
63            (std::min)(n, static_cast<streamsize>(data_.size() - ptr_));
64        if (amt) {
65            BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy(s, &data_[ptr_], amt);
66            ptr_ += amt;
67        }
68        return detail::check_eof(amt);
69    }
70
71    template<typename Sink>
72    std::streamsize write(Sink&, const char_type* s, std::streamsize n)
73    {
74        assert(!(state_ & f_read));
75        state_ |= f_write;
76        data_.insert(data_.end(), s, s + n);
77        return n;
78    }
79   
80    // Give detail::closer permission to call close().
81    typedef aggregate_filter<Ch, Alloc> self;
82    friend struct detail::closer<self>;
83
84    template<typename Sink>
85    void close(Sink& sink, BOOST_IOS::openmode which)
86    {
87        if ((state_ & f_read) && (which & BOOST_IOS::in))
88            close();
89
90        if ((state_ & f_write) && (which & BOOST_IOS::out)) {
91            detail::closer<self> closer(*this);
92            vector_type filtered;
93            do_filter(data_, filtered);
94            do_write(
95                sink, &filtered[0],
96                static_cast<std::streamsize>(filtered.size())
97            );
98        }
99    }
100
101protected:
102    typedef std::vector<Ch, Alloc>           vector_type;
103    typedef typename vector_type::size_type  size_type;
104private:
105    virtual void do_filter(const vector_type& src, vector_type& dest) = 0;
106    virtual void do_close() { }
107
108    template<typename Source>
109    void do_read(Source& src)
110    {
111        using std::streamsize;
112        vector_type data;
113        while (true) {
114            const streamsize  size = default_device_buffer_size;
115            Ch                buf[size];
116            streamsize        amt;
117            if ((amt = boost::iostreams::read(src, buf, size)) == -1)
118                break;
119            data.insert(data.end(), buf, buf + amt);
120        }
121        do_filter(data, data_);
122        state_ |= f_eof;
123    }
124
125    template<typename Sink>
126    void do_write(Sink& sink, const char* s, std::streamsize n)
127    {
128        typedef typename iostreams::category_of<Sink>::type  category;
129        typedef is_convertible<category, output>             can_write;
130        do_write(sink, s, n, can_write());
131    }
132
133    template<typename Sink>
134    void do_write(Sink& sink, const char* s, std::streamsize n, mpl::true_)
135    { iostreams::write(sink, s, n); }
136
137    template<typename Sink>
138    void do_write(Sink&, const char*, std::streamsize, mpl::false_) { }
139
140    void close()
141    {
142        data_.clear();
143        ptr_ = 0;
144        state_ = 0;
145        do_close();
146    }
147
148    enum flag_type {
149        f_read   = 1,
150        f_write  = f_read << 1,
151        f_eof    = f_write << 1
152    };
153
154    // Note: typically will not be copied while vector contains data.
155    vector_type  data_;
156    size_type    ptr_;
157    int          state_;
158};
159BOOST_IOSTREAMS_PIPABLE(aggregate_filter, 1)
160
161} } // End namespaces iostreams, boost.
162
163#include <boost/iostreams/detail/config/enable_warnings.hpp>  // MSVC.
164
165#endif // #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED
Note: See TracBrowser for help on using the repository browser.