]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/iostreams/include/boost/iostreams/filter/line.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / iostreams / include / boost / iostreams / filter / line.hpp
1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2005-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_LINE_FILTER_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED
10
11 #if defined(_MSC_VER)
12 # pragma once
13 #endif
14
15 #include <algorithm> // min.
16 #include <boost/assert.hpp>
17 #include <memory> // allocator.
18 #include <string>
19 #include <boost/config.hpp> // BOOST_STATIC_CONSTANT.
20 #include <boost/iostreams/categories.hpp>
21 #include <boost/iostreams/checked_operations.hpp>
22 #include <boost/iostreams/detail/ios.hpp> // openmode, streamsize.
23 #include <boost/iostreams/read.hpp> // check_eof
24 #include <boost/iostreams/pipeline.hpp>
25 #include <boost/iostreams/write.hpp>
26
27 // Must come last.
28 #include <boost/iostreams/detail/config/disable_warnings.hpp> // VC7.1 C4244.
29
30 namespace boost { namespace iostreams {
31
32 //
33 // Template name: line_filter.
34 // Template parameters:
35 // Ch - The character type.
36 // Alloc - The allocator type.
37 // Description: Filter which processes data one line at a time.
38 //
39 template< typename Ch,
40 typename Alloc = std::allocator<Ch> >
41 class basic_line_filter {
42 private:
43 typedef typename std::basic_string<Ch>::traits_type string_traits;
44 public:
45 typedef Ch char_type;
46 typedef char_traits<char_type> traits_type;
47 typedef std::basic_string<
48 Ch,
49 string_traits,
50 Alloc
51 > string_type;
52 struct category
53 : dual_use,
54 filter_tag,
55 multichar_tag,
56 closable_tag
57 { };
58 protected:
59 basic_line_filter(bool suppress_newlines = false)
60 : pos_(string_type::npos),
61 flags_(suppress_newlines ? f_suppress : 0)
62 { }
63 public:
64 virtual ~basic_line_filter() { }
65
66 template<typename Source>
67 std::streamsize read(Source& src, char_type* s, std::streamsize n)
68 {
69 using namespace std;
70 BOOST_ASSERT(!(flags_ & f_write));
71 flags_ |= f_read;
72
73 // Handle unfinished business.
74 std::streamsize result = 0;
75 if (!cur_line_.empty() && (result = read_line(s, n)) == n)
76 return n;
77
78 typename traits_type::int_type status = traits_type::good();
79 while (result < n && !traits_type::is_eof(status)) {
80
81 // Call next_line() to retrieve a line of filtered text, and
82 // read_line() to copy it into buffer s.
83 if (traits_type::would_block(status = next_line(src)))
84 return result;
85 result += read_line(s + result, n - result);
86 }
87
88 return detail::check_eof(result);
89 }
90
91 template<typename Sink>
92 std::streamsize write(Sink& snk, const char_type* s, std::streamsize n)
93 {
94 using namespace std;
95 BOOST_ASSERT(!(flags_ & f_read));
96 flags_ |= f_write;
97
98 // Handle unfinished business.
99 if (pos_ != string_type::npos && !write_line(snk))
100 return 0;
101
102 const char_type *cur = s, *next;
103 while (true) {
104
105 // Search for the next full line in [cur, s + n), filter it
106 // and write it to snk.
107 typename string_type::size_type rest = n - (cur - s);
108 if ((next = traits_type::find(cur, rest, traits_type::newline()))) {
109 cur_line_.append(cur, next - cur);
110 cur = next + 1;
111 if (!write_line(snk))
112 return static_cast<std::streamsize>(cur - s);
113 } else {
114 cur_line_.append(cur, rest);
115 return n;
116 }
117 }
118 }
119
120 template<typename Sink>
121 void close(Sink& snk, BOOST_IOS::openmode which)
122 {
123 if ((flags_ & f_read) && which == BOOST_IOS::in)
124 close_impl();
125
126 if ((flags_ & f_write) && which == BOOST_IOS::out) {
127 try {
128 if (!cur_line_.empty())
129 write_line(snk);
130 } catch (...) {
131 try {
132 close_impl();
133 } catch (...) { }
134 throw;
135 }
136 close_impl();
137 }
138 }
139 private:
140 virtual string_type do_filter(const string_type& line) = 0;
141
142 // Copies filtered characters fron the current line into
143 // the given buffer.
144 std::streamsize read_line(char_type* s, std::streamsize n)
145 {
146 using namespace std;
147 std::streamsize result =
148 (std::min) (n, static_cast<std::streamsize>(cur_line_.size()));
149 traits_type::copy(s, cur_line_.data(), result);
150 cur_line_.erase(0, result);
151 return result;
152 }
153
154 // Attempts to retrieve a line of text from the given source; returns
155 // an int_type as a good/eof/would_block status code.
156 template<typename Source>
157 typename traits_type::int_type next_line(Source& src)
158 {
159 using namespace std;
160 typename traits_type::int_type c;
161 while ( traits_type::is_good(c = iostreams::get(src)) &&
162 c != traits_type::newline() )
163 {
164 cur_line_ += traits_type::to_int_type(c);
165 }
166 if (!traits_type::would_block(c)) {
167 if (!cur_line_.empty() || c == traits_type::newline())
168 cur_line_ = do_filter(cur_line_);
169 if (c == traits_type::newline() && (flags_ & f_suppress) == 0)
170 cur_line_ += c;
171 }
172 return c; // status indicator.
173 }
174
175 // Filters the current line and attemps to write it to the given sink.
176 // Returns true for success.
177 template<typename Sink>
178 bool write_line(Sink& snk)
179 {
180 string_type line = do_filter(cur_line_);
181 if ((flags_ & f_suppress) == 0)
182 line += traits_type::newline();
183 std::streamsize amt = static_cast<std::streamsize>(line.size());
184 bool result = iostreams::write_if(snk, line.data(), amt) == amt;
185 if (result)
186 clear();
187 return result;
188 }
189
190 void close_impl()
191 {
192 clear();
193 flags_ &= f_suppress;
194 }
195
196 void clear()
197 {
198 cur_line_.erase();
199 pos_ = string_type::npos;
200 }
201
202 enum flag_type {
203 f_read = 1,
204 f_write = f_read << 1,
205 f_suppress = f_write << 1
206 };
207
208 string_type cur_line_;
209 typename string_type::size_type pos_;
210 int flags_;
211 };
212 BOOST_IOSTREAMS_PIPABLE(basic_line_filter, 2)
213
214 typedef basic_line_filter<char> line_filter;
215 typedef basic_line_filter<wchar_t> wline_filter;
216
217 } } // End namespaces iostreams, boost.
218
219 #include <boost/iostreams/detail/config/enable_warnings.hpp>
220
221 #endif // #ifndef BOOST_IOSTREAMS_LINE_FILTER_HPP_INCLUDED