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         // short circuit for tell()  
00176         if(newpos == curpos) {
00177             return curpos;
00178         }
00179 
00180         off_type endpos = basePos_ + (egptr() - eback());
00181 
00182         // if the position is after our current buffer make
00183         // sure it's not past the end of the buffer
00184         if((newpos > endpos) && (newpos > static_cast<off_type>(buffer_.size()) )) {
00185             return pos_type(-1);
00186         }
00187         // if the new position is before our current iterator
00188         // reset the iterator to the beginning
00189         else if (newpos < basePos_) {
00190             iter_ = buffer_.begin();
00191             basePos_ = 0;
00192             setBuffer();
00193             endpos = (egptr() -eback());
00194         }
00195 
00196         // now if the new position is after the end of the buffer
00197         // increase the buffer until it is not
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         // this function only gets called when the current buffer has been
00217         // completely read, verify this is the case, and if so, underflow to
00218         // fetch the next buffer
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 } // namespace
00251 
00252 #endif 
Generated on Thu Sep 2 18:40:54 2010 for Avro C++ by  doxygen 1.6.3