BufferStreambuf.hh
Go to the documentation of this file.00001
00019 #ifndef avro_BufferStreambuf_hh__
00020 #define avro_BufferStreambuf_HH__
00021
00022 #include "Buffer.hh"
00023
00028 namespace avro {
00029
00039 class ostreambuf : public std::streambuf {
00040
00041 public:
00042
00044 ostreambuf() :
00045 std::streambuf(),
00046 buffer_()
00047 { }
00048
00050 explicit ostreambuf(OutputBuffer &buffer) :
00051 std::streambuf(),
00052 buffer_( buffer )
00053 { }
00054
00056 const OutputBuffer &getBuffer() const {
00057 return buffer_;
00058 }
00059
00060 protected:
00061
00063 virtual int_type overflow(int_type c)
00064 {
00065 buffer_.writeTo(static_cast<OutputBuffer::data_type>(c));
00066 return c;
00067 }
00068
00070 virtual std::streamsize xsputn(const char_type *s, std::streamsize n)
00071 {
00072 return buffer_.writeTo(s, n);
00073 }
00074
00075 private:
00076
00077 OutputBuffer buffer_;
00078 };
00079
00093 class istreambuf : public std::streambuf {
00094
00095 public:
00096
00098 explicit istreambuf(const InputBuffer &buffer) :
00099 std::streambuf(),
00100 buffer_( buffer ),
00101 basePos_(0),
00102 iter_(buffer_.begin())
00103 {
00104 setBuffer();
00105 }
00106
00108 explicit istreambuf(const OutputBuffer &buffer) :
00109 std::streambuf(),
00110 buffer_( buffer, InputBuffer::ShallowCopy()),
00111 basePos_(0),
00112 iter_(buffer_.begin())
00113 {
00114 setBuffer();
00115 }
00116
00118 const InputBuffer &getBuffer() const {
00119 return buffer_;
00120 }
00121
00122 protected:
00123
00125 virtual int_type underflow() {
00126 if(iter_ != buffer_.end()) {
00127 basePos_ += (egptr()-eback());
00128 ++iter_;
00129 }
00130 return setBuffer();
00131 }
00132
00135 virtual std::streamsize xsgetn(char_type *c, std::streamsize len)
00136 {
00137 std::streamsize bytesCopied = 0;
00138
00139 while (bytesCopied < len) {
00140
00141 size_t inBuffer = egptr() - gptr();
00142
00143 if (inBuffer) {
00144 size_t remaining = len - bytesCopied;
00145 size_t toCopy = std::min(inBuffer, remaining);
00146 memcpy(c, gptr(), toCopy);
00147 c += toCopy;
00148 bytesCopied += toCopy;
00149 gbump(toCopy);
00150 }
00151
00152 if(bytesCopied < len) {
00153 underflow();
00154 if(iter_ == buffer_.end()) {
00155 break;
00156 }
00157 }
00158 }
00159
00160 return bytesCopied;
00161 }
00162
00164 virtual pos_type seekoff(off_type off, std::ios::seekdir dir, std::_Ios_Openmode) {
00165
00166 off_type curpos = basePos_ + (gptr() - eback());
00167 off_type newpos = off;
00168
00169 if(dir == std::ios::cur) {
00170 newpos += curpos;
00171 }
00172 else if (dir == std::ios::end) {
00173 newpos += buffer_.size();
00174 }
00175
00176 if(newpos == curpos) {
00177 return curpos;
00178 }
00179
00180 off_type endpos = basePos_ + (egptr() - eback());
00181
00182
00183
00184 if((newpos > endpos) && (newpos > static_cast<off_type>(buffer_.size()) )) {
00185 return pos_type(-1);
00186 }
00187
00188
00189 else if (newpos < basePos_) {
00190 iter_ = buffer_.begin();
00191 basePos_ = 0;
00192 setBuffer();
00193 endpos = (egptr() -eback());
00194 }
00195
00196
00197
00198 while (newpos > endpos) {
00199 istreambuf::underflow();
00200 endpos = basePos_ + (egptr() - eback());
00201 }
00202
00203 setg(eback(), eback() + (newpos - basePos_), egptr());
00204 return newpos;
00205 }
00206
00208 virtual pos_type seekpos(pos_type pos, std::_Ios_Openmode) {
00209 return istreambuf::seekoff(pos, std::ios::beg, std::_Ios_Openmode(0));
00210 }
00211
00214 virtual std::streamsize showmanyc() {
00215
00216
00217
00218
00219
00220 if(egptr() - gptr() == 0) {
00221 istreambuf::underflow();
00222 }
00223 return egptr() - gptr();
00224 }
00225
00226 private:
00227
00231 int_type setBuffer() {
00232 int_type ret = traits_type::eof();
00233
00234 if(iter_ != buffer_.end()) {
00235 char *loc = const_cast <char *> (iter_->data()) ;
00236 setg(loc, loc, loc + iter_->size());
00237 ret = *gptr();
00238 }
00239 else {
00240 setg(0,0,0);
00241 }
00242 return ret;
00243 }
00244
00245 const InputBuffer buffer_;
00246 off_type basePos_;
00247 InputBuffer::const_iterator iter_;
00248 };
00249
00250 }
00251
00252 #endif