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