CppCMS
steal_buf.h
1 //
3 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
4 //
5 // See accompanying file COPYING.TXT file for licensing details.
6 //
8 #ifndef CPPCMS_STEAL_BUF_H
9 #define CPPCMS_STEAL_BUF_H
10 
11 #include <streambuf>
12 #include <ostream>
13 #include <istream>
14 #include <stdio.h>
15 #include <string>
16 #include <string.h>
17 #include <stdlib.h>
18 
19 namespace cppcms {
20 namespace util {
21 
26 
27  class const_char_buf : public std::streambuf {
28  public:
33  {
34  range(0,0);
35  }
39  const_char_buf(char const *begin,char const *end)
40  {
41  range(begin,end);
42  }
46  void range(char const *cbegin,char const *cend)
47  {
48  char *begin = const_cast<char*>(cbegin);
49  char *end = const_cast<char*>(cend);
50  setg(begin,begin,end);
51  }
55  char const *begin() const
56  {
57  return eback();
58  }
62  char const *end() const
63  {
64  return egptr();
65  }
66  };
67 
72  class const_char_istream : public std::istream {
73  public:
77  const_char_istream() : std::istream(0)
78  {
79  init(&buf_);
80  }
84  const_char_istream(char const *begin,char const *end) : std::istream(0)
85  {
86  buf_.range(begin,end);
87  init(&buf_);
88  }
92  char const *begin() const
93  {
94  return buf_.begin();
95  }
99  char const *end() const
100  {
101  return buf_.end();
102  }
106  void range(char const *begin,char const *end)
107  {
108  buf_.range(begin,end);
109  clear();
110  }
111  private:
112  const_char_buf buf_;
113  };
114 
125  template<size_t OnStackSize = 128>
126  class stackbuf : public std::streambuf {
127  stackbuf(stackbuf const &);
128  void operator=(stackbuf const &);
129  public:
133  char *begin()
134  {
135  return pbase();
136  }
140  char *end()
141  {
142  return pptr();
143  }
147  char *c_str()
148  {
149  *pptr() = 0;
150  return begin();
151  }
155  std::string str()
156  {
157  return std::string(begin(),size_t(end()-begin()));
158  }
159  stackbuf()
160  {
161  init();
162  }
163  ~stackbuf()
164  {
165  free(on_heap_);
166  }
167  protected:
168 
169  int overflow(int c)
170  {
171  size_t current_size;
172  size_t new_size;
173  if(pbase() == on_stack_) {
174  current_size = OnStackSize;
175  new_size = OnStackSize * 2;
176  on_heap_ = (char *)malloc(new_size + 1);
177  if(!on_heap_)
178  throw std::bad_alloc();
179  memcpy(on_heap_,on_stack_,current_size);
180  }
181  else {
182  current_size = pptr() - pbase();
183  new_size = current_size * 2;
184  char *new_ptr = (char *)realloc(on_heap_,new_size + 1);
185  if(!new_ptr)
186  throw std::bad_alloc();
187  on_heap_ = new_ptr;
188 
189  }
190  setp(on_heap_,on_heap_ + new_size);
191  pbump(current_size);
192  if(c!=EOF)
193  sputc(c);
194  return 0;
195  }
196  private:
197  void init()
198  {
199  on_heap_ = 0;
200  setp(on_stack_,on_stack_+OnStackSize);
201  }
202  char *on_heap_;
203  char on_stack_[OnStackSize + 1];
204  };
205 
206 
219  template<size_t Size = 128>
220  class steal_buffer : public stackbuf<Size> {
221  public:
225  steal_buffer(std::ostream &out)
226  {
227  stolen_ = 0;
228  stream_ = 0;
229  steal(out);
230  }
235  {
236  stolen_ = 0;
237  stream_ = 0;
238  }
242  void steal(std::ostream &out)
243  {
244  release();
245  stolen_ = out.rdbuf(this);
246  stream_ = &out;
247  }
252  void release()
253  {
254  if(stream_ && stolen_) {
255  stream_->rdbuf(stolen_);
256  }
257  stream_ = 0;
258  stolen_ = 0;
259  }
260  ~steal_buffer()
261  {
262  release();
263  }
264  private:
265  std::streambuf *stolen_;
266  std::ostream *stream_;
267  };
268 
276  template<size_t Size = 128>
277  class stackstream : public std::ostream {
278  public:
282  stackstream() : std::ostream(0)
283  {
284  rdbuf(&buf_);
285  }
289  char *begin()
290  {
291  return buf_.begin();
292  }
296  char *end()
297  {
298  return buf_.end();
299  }
303  char *c_str()
304  {
305  return buf_.c_str();
306  }
310  std::string str()
311  {
312  return buf_.str();
313  }
314  private:
315  stackbuf<Size> buf_;
316  };
317 
318  template<typename Filter,int BufferSize=128>
319  class filterbuf : public std::streambuf {
320  public:
321  filterbuf() : output_(0), output_stream_(0)
322  {
323  setp(buffer_,buffer_+BufferSize);
324  }
325  filterbuf(std::ostream &out) : output_(0), output_stream_(0)
326  {
327  setp(buffer_,buffer_+BufferSize);
328  steal(out);
329  }
330  ~filterbuf()
331  {
332  try {
333  release();
334  }
335  catch(...) {}
336  }
337  void steal(std::ostream &out)
338  {
339  release();
340  output_stream_ = &out;
341  output_ = out.rdbuf(this);
342  }
343  int release()
344  {
345  int r=0;
346  if(output_stream_) {
347  if(write()!=0)
348  r=-1;
349  output_stream_->rdbuf(output_);
350  output_=0;
351  output_stream_=0;
352  }
353  return r;
354  }
355  protected:
356  int overflow(int c)
357  {
358  if(write()!=0)
359  return -1;
360  if(c!=EOF) {
361  *pptr()=c;
362  pbump(1);
363  }
364  return 0;
365  }
366  private:
367  int write()
368  {
369  if(static_cast<Filter*>(this)->convert(pbase(),pptr(),output_)!=0) {
370  output_stream_->setstate(std::ios_base::failbit);
371  return -1;
372  }
373  setp(buffer_,buffer_ + BufferSize);
374  return 0;
375  }
376  char buffer_[BufferSize];
377  std::streambuf *output_;
378  std::ostream *output_stream_;
379  };
380 
381  template<typename Filter>
382  class filterbuf<Filter,0> : public std::streambuf {
383  public:
384  filterbuf() : output_(0), output_stream_(0)
385  {
386  }
387  filterbuf(std::ostream &out) : output_(0), output_stream_(0)
388  {
389  steal(out);
390  }
391  ~filterbuf()
392  {
393  release();
394  }
395  void steal(std::ostream &out)
396  {
397  release();
398  output_stream_ = &out;
399  output_ = out.rdbuf(this);
400  }
401  int release()
402  {
403  int r=0;
404  if(output_stream_) {
405  output_stream_->rdbuf(output_);
406  output_=0;
407  output_stream_=0;
408  }
409  return r;
410  }
411  protected:
412  int overflow(int c)
413  {
414  if(c!=EOF) {
415  char tmp=c;
416  if(write(&tmp,&tmp+1)!=0)
417  return -1;
418  }
419  return 0;
420  }
421  std::streamsize xsputn(char const *s,std::streamsize size)
422  {
423  if(write(s,s+size)!=0)
424  return -1;
425  return size;
426  }
427  private:
428  int write(char const *begin,char const *end)
429  {
430  if(static_cast<Filter*>(this)->convert(begin,end,output_)!=0) {
431  output_stream_->setstate(std::ios_base::failbit);
432  return -1;
433  }
434  return 0;
435  }
436  std::streambuf *output_;
437  std::ostream *output_stream_;
438  };
439 
440 } // util
441 } // cppcms
442 
443 #endif
void range(char const *begin, char const *end)
Definition: steal_buf.h:106
char * end()
Definition: steal_buf.h:140
char const * end() const
Definition: steal_buf.h:99
Definition: steal_buf.h:72
char * begin()
Definition: steal_buf.h:133
char * begin()
Definition: steal_buf.h:289
void steal(std::ostream &out)
Definition: steal_buf.h:242
This is the namespace where all CppCMS functionality is placed.
Definition: application.h:19
const_char_buf()
Definition: steal_buf.h:32
char * c_str()
Definition: steal_buf.h:303
const_char_istream()
Definition: steal_buf.h:77
std::string str()
Definition: steal_buf.h:155
char const * end() const
Definition: steal_buf.h:62
char * end()
Definition: steal_buf.h:296
stackstream()
Definition: steal_buf.h:282
void range(char const *cbegin, char const *cend)
Definition: steal_buf.h:46
Fast output stream object.
Definition: steal_buf.h:277
const_char_istream(char const *begin, char const *end)
Definition: steal_buf.h:84
Definition: steal_buf.h:27
Definition: steal_buf.h:319
This is a special buffer that allows to "steal" some chunk of text from the output stream...
Definition: steal_buf.h:220
char * c_str()
Definition: steal_buf.h:147
std::string str()
Definition: steal_buf.h:310
char const * begin() const
Definition: steal_buf.h:55
steal_buffer(std::ostream &out)
Definition: steal_buf.h:225
Very simple output stream buffer that uses stack for small chunks of text and then allocates memory o...
Definition: steal_buf.h:126
char const * begin() const
Definition: steal_buf.h:92
void release()
Definition: steal_buf.h:252
const_char_buf(char const *begin, char const *end)
Definition: steal_buf.h:39
steal_buffer()
Definition: steal_buf.h:234