00001
00002
00003
00004
00005
00006
00008 #ifndef CPPCMS_STEAL_BUF_H
00009 #define CPPCMS_STEAL_BUF_H
00010
00011 #include <streambuf>
00012 #include <ostream>
00013 #include <stdio.h>
00014 #include <string>
00015 #include <string.h>
00016 #include <stdlib.h>
00017
00018 namespace cppcms {
00019 namespace util {
00020
00031 template<size_t OnStackSize = 128>
00032 class stackbuf : public std::streambuf {
00033 stackbuf(stackbuf const &);
00034 void operator=(stackbuf const &);
00035 public:
00039 char *begin()
00040 {
00041 return pbase();
00042 }
00046 char *end()
00047 {
00048 return pptr();
00049 }
00053 char *c_str()
00054 {
00055 *pptr() = 0;
00056 return begin();
00057 }
00061 std::string str()
00062 {
00063 return std::string(begin(),size_t(end()-begin()));
00064 }
00065 stackbuf()
00066 {
00067 init();
00068 }
00069 ~stackbuf()
00070 {
00071 free(on_heap_);
00072 }
00073 protected:
00074
00075 int overflow(int c)
00076 {
00077 size_t current_size;
00078 size_t new_size;
00079 if(pbase() == on_stack_) {
00080 current_size = OnStackSize;
00081 new_size = OnStackSize * 2;
00082 on_heap_ = (char *)malloc(new_size + 1);
00083 if(!on_heap_)
00084 throw std::bad_alloc();
00085 memcpy(on_heap_,on_stack_,current_size);
00086 }
00087 else {
00088 current_size = pptr() - pbase();
00089 new_size = current_size * 2;
00090 char *new_ptr = (char *)realloc(on_heap_,new_size + 1);
00091 if(!new_ptr)
00092 throw std::bad_alloc();
00093 on_heap_ = new_ptr;
00094
00095 }
00096 setp(on_heap_,on_heap_ + new_size);
00097 pbump(current_size);
00098 if(c!=EOF)
00099 sputc(c);
00100 return 0;
00101 }
00102 private:
00103 void init()
00104 {
00105 on_heap_ = 0;
00106 setp(on_stack_,on_stack_+OnStackSize);
00107 }
00108 char *on_heap_;
00109 char on_stack_[OnStackSize + 1];
00110 };
00111
00112
00125 template<size_t Size = 128>
00126 class steal_buffer : public stackbuf<Size> {
00127 public:
00131 steal_buffer(std::ostream &out)
00132 {
00133 stolen_ = 0;
00134 stream_ = 0;
00135 steal(out);
00136 }
00140 steal_buffer()
00141 {
00142 stolen_ = 0;
00143 stream_ = 0;
00144 }
00148 void steal(std::ostream &out)
00149 {
00150 release();
00151 stolen_ = out.rdbuf(this);
00152 stream_ = &out;
00153 }
00158 void release()
00159 {
00160 if(stream_ && stolen_) {
00161 stream_->rdbuf(stolen_);
00162 }
00163 stream_ = 0;
00164 stolen_ = 0;
00165 }
00166 ~steal_buffer()
00167 {
00168 release();
00169 }
00170 private:
00171 std::streambuf *stolen_;
00172 std::ostream *stream_;
00173 };
00174
00182 template<size_t Size = 128>
00183 class stackstream : public std::ostream {
00184 public:
00188 stackstream() : std::ostream(0)
00189 {
00190 rbbuf(&buf_);
00191 }
00195 char *begin()
00196 {
00197 return buf_->begin();
00198 }
00202 char *end()
00203 {
00204 return buf_->end();
00205 }
00209 char *c_str()
00210 {
00211 return buf_.c_str();
00212 }
00216 std::string str()
00217 {
00218 return buf_.str();
00219 }
00220 private:
00221 stackbuf<Size> buf_;
00222 };
00223
00224 }
00225 }
00226
00227 #endif