limitstream.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27  */
28 
29 #ifndef CXXTOOLS_LIMITSTREAM_H
30 #define CXXTOOLS_LIMITSTREAM_H
31 
32 #include <iostream>
33 #include <algorithm>
34 
35 namespace cxxtools
36 {
48  template <typename char_type>
49  class BasicLimitStreambuf : public std::basic_streambuf<char_type>
50  {
51  std::basic_streambuf<char_type>* _sb;
52  unsigned _icount;
53  unsigned _ocount;
54  unsigned _ibufsize;
55  char_type* _ibuffer;
56 
57  typedef typename std::basic_streambuf<char_type>::traits_type traits_type;
58  typedef typename std::basic_streambuf<char_type>::int_type int_type;
59 
60  public:
62  BasicLimitStreambuf(std::basic_streambuf<char_type>* sb,
63  unsigned icount, unsigned ocount, unsigned ibufsize = 8192)
64  : _sb(sb),
65  _icount(icount),
66  _ocount(ocount),
67  _ibufsize(ibufsize),
68  _ibuffer(0)
69  { }
70 
72  { delete[] _ibuffer; }
73 
75  unsigned icount() const
76  { return _icount + (this->egptr() - this->gptr()); }
77 
82  void icount(unsigned c)
83  { _icount = c; }
84 
86  unsigned ocount() const
87  { return _ocount; }
88 
90  void ocount(unsigned c)
91  { _ocount = c; }
92 
94  std::basic_streambuf<char_type>* streambuf()
95  { return _sb; }
96 
98  void attach(std::basic_streambuf<char_type>* s)
99  { _sb = s; }
100 
101  protected:
102  char_type* ibuffer()
103  {
104  if (_ibuffer == 0)
105  _ibuffer = new char_type[_ibufsize];
106  return _ibuffer;
107  }
108 
109  std::streamsize showmanyc()
110  {
111  if (this->gptr() == this->egptr() && _icount > 0)
112  {
113  std::streamsize n = _sb->in_avail();
114 
115  if (n > 0)
116  {
117  n = _sb->sgetn(ibuffer(), std::min(static_cast<std::streamsize>(_icount), n));
118  this->setg(_ibuffer, _ibuffer, _ibuffer + n);
119 
120  _icount -= n;
121  }
122  }
123 
124  return this->egptr() - this->gptr();
125  }
126 
127  int_type overflow(int_type ch)
128  {
129  if (ch != traits_type::eof() && _ocount > 0)
130  {
131  int r = _sb->sputc(traits_type::to_char_type(ch));
132  if (r == traits_type::eof())
133  return traits_type::eof();
134  --_ocount;
135  return traits_type::not_eof(ch);
136  }
137 
138  return traits_type::eof();
139  }
140 
141  int_type underflow()
142  {
143  if (_icount == 0)
144  return traits_type::eof();
145 
146  std::streamsize c = _sb->sgetn(ibuffer(), std::min(_icount, _ibufsize));
147  if (c == 0)
148  return traits_type::eof();
149 
150  _icount -= c;
151 
152  this->setg(_ibuffer, _ibuffer, _ibuffer + c);
153 
154  return this->sgetc();
155  }
156 
157  int sync()
158  {
159  return 0;
160  }
161  };
162 
168  template <typename char_type>
169  class BasicLimitIStream : public std::basic_istream<char_type>
170  {
172 
173  public:
176  explicit BasicLimitIStream(std::basic_istream<char_type>& source, unsigned count = 0)
177  : std::basic_istream<char_type>(0),
178  _streambuf(source.rdbuf(), count, 0)
179  {
180  std::basic_istream<char_type>::init(&_streambuf);
181  }
182 
185  BasicLimitIStream(std::basic_streambuf<char_type>* source, unsigned count = 0)
186  : std::basic_istream<char_type>(0),
187  _streambuf(source, count, 0)
188  {
189  std::basic_istream<char_type>::init(&_streambuf);
190  }
191 
193  unsigned icount() const
194  { return _streambuf.icount(); }
195 
197  void icount(unsigned c)
198  { _streambuf.icount(c); }
199 
201  void attach(std::basic_istream<char_type>& s)
202  { _streambuf.attach(s.rdbuf()); }
203 
205  void attach(std::basic_streambuf<char_type>* s)
206  { _streambuf.attach(s); }
207 
208  };
209 
215  template <typename char_type>
216  class BasicLimitOStream : public std::basic_ostream<char_type>
217  {
219 
220  public:
223  explicit BasicLimitOStream(std::basic_ostream<char_type>& sink, unsigned count = 0)
224  : std::basic_ostream<char_type>(0),
225  _streambuf(sink.rdbuf(), 0, count)
226  {
227  std::basic_ostream<char_type>::init(&_streambuf);
228  }
229 
232  explicit BasicLimitOStream(std::basic_streambuf<char_type>* sink, unsigned count = 0)
233  : std::basic_ostream<char_type>(0),
234  _streambuf(sink, 0, count)
235  {
236  std::basic_ostream<char_type>::init(&_streambuf);
237  }
238 
240  unsigned ocount() const
241  { return _streambuf.ocount(); }
242 
244  void ocount(unsigned c)
245  { _streambuf.ocount(c); }
246 
248  void attach(std::basic_ostream<char_type>& s)
249  { _streambuf.attach(s.rdbuf()); }
250 
252  void attach(std::basic_streambuf<char_type>* s)
253  { _streambuf.attach(s); }
254 
255  };
256 
260  template <typename char_type>
261  class BasicLimitIOStream : public std::basic_iostream<char_type>
262  {
264 
265  public:
268  BasicLimitIOStream(std::basic_iostream<char_type>& sinksource, unsigned icount, unsigned ocount)
269  : std::basic_iostream<char_type>(0),
270  _streambuf(sinksource.rdbuf(), icount, ocount)
271  {
272  std::basic_iostream<char_type>::init(&_streambuf);
273  }
274 
277  BasicLimitIOStream(std::basic_iostream<char_type>& sinksource)
278  : std::basic_iostream<char_type>(0),
279  _streambuf(sinksource.rdbuf(), 0, 0)
280  {
281  std::basic_iostream<char_type>::init(&_streambuf);
282  }
283 
286  BasicLimitIOStream(std::basic_streambuf<char_type>* sinksource, unsigned icount, unsigned ocount)
287  : std::basic_iostream<char_type>(0),
288  _streambuf(sinksource, icount, ocount)
289  {
290  std::basic_iostream<char_type>::init(&_streambuf);
291  }
292 
295  BasicLimitIOStream(std::basic_streambuf<char_type>* sinksource)
296  : std::basic_iostream<char_type>(0),
297  _streambuf(sinksource, 0, 0)
298  {
299  std::basic_iostream<char_type>::init(&_streambuf);
300  }
301 
303  unsigned icount() const
304  { return _streambuf.icount(); }
305 
307  void icount(unsigned c)
308  { _streambuf.icount(c); }
309 
311  unsigned ocount() const
312  { return _streambuf.ocount(); }
313 
315  void ocount(unsigned c)
316  { _streambuf.ocount(c); }
317 
319  void attach(std::basic_iostream<char_type>& s)
320  { _streambuf.attach(s.rdbuf()); }
321 
323  void attach(std::basic_streambuf<char_type>* s)
324  { _streambuf.attach(s); }
325 
326  };
327 
332 }
333 
334 #endif // CXXTOOLS_LIMITSTREAM_H
335