CppCMS
|
00001 00002 // 00003 // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> 00004 // 00005 // See accompanying file COPYING.TXT file for licensing details. 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 rdbuf(&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 } // util 00225 } // cppcms 00226 00227 #endif