Ticket #1627: grep.hpp

File grep.hpp, 2.8 KB (added by Jonathan Turkanis, 15 years ago)

submission by emreturkay@…

Line 
1#ifndef BOOST_IOSTREAMS_GREP_HPP_INCLUDED
2#define BOOST_IOSTREAMS_GREP_HPP_INCLUDED
3
4#include <string>
5#include <boost/regex.hpp>
6#include <boost/iostreams/categories.hpp>
7#include <boost/iostreams/operations.hpp>
8
9namespace boost { namespace iostreams {
10
11template <typename Ch>
12struct basic_grep_filter
13{
14 typedef Ch char_type;
15 struct category: dual_use, filter_tag { };
16
17 typedef char_traits<char_type> traits_type;
18 typedef std::basic_string<char_type> string_type;
19 typedef boost::basic_regex<char_type> regex_type;
20
21 explicit basic_grep_filter(const char* expr)
22 : expr_(expr), eof_(false), iter_(line_.end())
23 {
24 };
25
26 template <typename Source>
27 typename traits_type::int_type get(Source& src)
28 {
29 if (eof_ && iter_ == line_.end())
30 return EOF;
31
32 if (iter_ != line_.end())
33 return next();
34
35 for (;;)
36 {
37 typename traits_type::int_type c = iostreams::get(src);
38
39 if (c == traits_type::would_block())
40 return c;
41
42 line_ += c;
43
44 if (traits_type::is_eof(c))
45 {
46 eof_ = true;
47 if (boost::regex_search(line_, expr_))
48 {
49 iter_ = line_.begin();
50 return next();
51 }
52
53 iter_ = line_.end();
54 return c;
55 }
56
57 if (c == traits_type::newline())
58 {
59 if (boost::regex_search(line_, expr_))
60 {
61 iter_ = line_.begin();
62 return next();
63 }
64
65 line_.erase();
66 iter_ = line_.end();
67 }
68 }
69 }
70
71 template <typename Sink>
72 bool put(Sink& snk, char_type c)
73 {
74 if (!traits_type::is_eof(c))
75 line_ += c;
76
77 if (traits_type::is_eof(c) || (c == traits_type::newline()))
78 {
79 if (boost::regex_search(line_, expr_))
80 std::for_each(line_.begin(), line_.end(), writer<Sink>(snk));
81
82 if (traits_type::is_eof(c))
83 iostreams::put(snk, c);
84
85 line_.erase();
86 }
87
88 return true;
89 }
90
91private:
92 char_type next()
93 {
94 char_type c = *iter_;
95 ++iter_;
96 if (iter_ == line_.end())
97 {
98 line_.erase();
99 iter_ = line_.end();
100 }
101 return c;
102 }
103
104 template <typename Sink>
105 struct writer
106 {
107 writer(Sink& snk): snk_(snk) { }
108
109 void operator()(const char_type& c)
110 {
111 iostreams::put(snk_, c);
112 }
113
114 private:
115 Sink& snk_;
116 };
117
118private:
119 regex_type expr_;
120 bool eof_;
121 string_type line_;
122 typename string_type::const_iterator iter_;
123};
124
125typedef basic_grep_filter<char> grep_filter;
126typedef basic_grep_filter<wchar_t> wgrep_filter;
127
128} } // End namespaces iostreams, boost.
129
130#endif //#ifndef BOOST_IOSTREAMS_GREP_HPP_INCLUDED