Buffer.hh

Go to the documentation of this file.
00001 
00019 #ifndef avro_Buffer_hh__
00020 #define avro_Buffer_hh__
00021 
00022 #include <sys/uio.h>
00023 #include <boost/type_traits.hpp>
00024 #include <vector>
00025 
00026 #include "detail/BufferDetail.hh"
00027 #include "detail/BufferDetailIterator.hh"
00028 
00036 namespace avro {
00037 
00038 class OutputBuffer;
00039 class InputBuffer;
00040 
00041 
00062 class OutputBuffer 
00063 {
00064 
00065   public:
00066 
00067     typedef detail::size_type size_type;
00068     typedef detail::data_type data_type;
00069 
00077     typedef detail::OutputBufferIterator const_iterator;
00078 
00096     OutputBuffer(size_type reserveSize = 0) :
00097         pimpl_(new detail::BufferImpl) 
00098     { 
00099         if(reserveSize) { 
00100             reserve(reserveSize); 
00101         }
00102     }
00103 
00112     void reserve(size_type reserveSize) 
00113     {
00114         pimpl_->reserveFreeSpace(reserveSize);
00115     }
00116 
00122     size_type writeTo(const data_type *data, size_type size) {
00123         return pimpl_->writeTo(data, size);
00124     }
00125 
00133     template<typename T>
00134     void writeTo(T val) {
00135         pimpl_->writeTo(val, boost::is_fundamental<T>());
00136     }
00137 
00150     size_type wroteTo(size_type size) 
00151     {
00152         int wrote = 0;
00153         if(size) {
00154             if(size > freeSpace()) {
00155                 throw std::length_error("Impossible to write more data than free space");
00156             }
00157             wrote = pimpl_->wroteTo(size);
00158         }
00159         return wrote;
00160     }
00161 
00166     bool empty() const {
00167         return  (pimpl_->size()==0);
00168     }
00169 
00174     size_type size() const {
00175         return  pimpl_->size();
00176     }
00177 
00184     size_type freeSpace() const {
00185         return  pimpl_->freeSpace();
00186     }
00187 
00194     template <class BufferType>
00195     void append(const BufferType &buf) {
00196         // don't append an empty buffer
00197         if(buf.size()) {
00198             pimpl_->append(*(buf.pimpl_.get()));
00199         }
00200     }
00201 
00207     const_iterator begin() const {
00208         return const_iterator(pimpl_->beginWrite());
00209     }
00210 
00215     const_iterator end() const {
00216         return const_iterator(pimpl_->endWrite());
00217     }
00218 
00223     void discardData()
00224     {
00225         pimpl_->discardData();
00226     }
00227 
00233     void discardData(size_t bytes)
00234     {
00235         if(bytes > 0) {
00236             if(bytes < pimpl_->size()) {
00237                 pimpl_->discardData(bytes);
00238             }
00239             else if(bytes == pimpl_->size()) {
00240                 pimpl_->discardData();
00241             }
00242             else {
00243                 throw std::out_of_range("trying to discard more data than exists");
00244             }
00245         }
00246     }
00247 
00255     InputBuffer extractData(size_type bytes);
00256 
00262     InputBuffer extractData();
00263 
00268     OutputBuffer clone() const 
00269     {
00270         detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl(*pimpl_));
00271         return OutputBuffer(newImpl);
00272     }
00273 
00280     void appendForeignData(const data_type *data, size_type size, const detail::free_func &func) {
00281         pimpl_->appendForeignData(data, size, func);
00282     }
00283 
00288     int numChunks() const {
00289         return  pimpl_->numFreeChunks();
00290     }
00291 
00296     int numDataChunks() const {
00297         return  pimpl_->numDataChunks();
00298     }
00299 
00300   private:
00301 
00302     friend class InputBuffer;
00303     friend class BufferReader;
00304 
00305     explicit OutputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
00306         pimpl_(pimpl) 
00307     { }
00308 
00309     detail::BufferImpl::SharedPtr pimpl_; 
00310 };
00311 
00326 class InputBuffer 
00327 {
00328 
00329   public:
00330 
00331     typedef detail::size_type size_type;
00332     typedef detail::data_type data_type;
00333 
00334     // needed for asio
00335     typedef detail::InputBufferIterator const_iterator;
00336 
00348     InputBuffer() :
00349         pimpl_(new detail::BufferImpl)
00350     { }
00351 
00364     InputBuffer(const OutputBuffer &src) :
00365         pimpl_(new detail::BufferImpl(*src.pimpl_))
00366     { }
00367 
00372     bool empty() const {
00373         return (pimpl_->size() == 0);
00374     }
00375 
00380     size_type size() const {
00381         return pimpl_->size();
00382     }
00383 
00389     const_iterator begin() const {
00390         return const_iterator(pimpl_->beginRead());
00391     }
00392 
00397     const_iterator end() const {
00398         return const_iterator(pimpl_->endRead());
00399     }
00400 
00405     int numChunks() const {
00406         return pimpl_->numDataChunks();
00407     }
00408 
00409 
00410   private:
00411 
00412     friend class OutputBuffer; // for append function
00413     friend class istreambuf;
00414     friend class BufferReader;
00415 
00416     explicit InputBuffer(const detail::BufferImpl::SharedPtr &pimpl) :
00417         pimpl_(pimpl) 
00418     { }
00419 
00431     class ShallowCopy {};
00432 
00437     InputBuffer(const OutputBuffer &src, const ShallowCopy &) : 
00438         pimpl_(src.pimpl_)
00439     { }
00440 
00448      InputBuffer(const InputBuffer &src, const ShallowCopy &) : 
00449         pimpl_(src.pimpl_)
00450     { }
00451 
00452 
00453     detail::BufferImpl::ConstSharedPtr pimpl_; 
00454 };
00455 
00456 
00457 /* 
00458  * Implementations of some OutputBuffer functions are inlined here
00459  * because InputBuffer definition was required before.
00460  */
00461 
00462 inline InputBuffer OutputBuffer::extractData() 
00463 {
00464     detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
00465     if(pimpl_->size()) {
00466         pimpl_->extractData(*newImpl);
00467     }
00468     return InputBuffer(newImpl);
00469 }
00470 
00471 inline InputBuffer OutputBuffer::extractData(size_type bytes)
00472 {
00473     if(bytes > pimpl_->size()) {
00474         throw std::out_of_range("trying to extract more data than exists");
00475     }
00476 
00477     detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
00478     if(bytes > 0) {
00479         if(bytes < pimpl_->size()) {
00480             pimpl_->extractData(*newImpl, bytes);
00481         }
00482         else {
00483             pimpl_->extractData(*newImpl);
00484         }
00485     }
00486 
00487     return InputBuffer(newImpl);
00488 }
00489 
00507 template<class BufferType>
00508 inline void toIovec(BufferType &buf, std::vector<struct iovec> &iov) 
00509 {
00510     const int chunks = buf.numChunks();
00511     iov.resize(chunks);
00512     typename BufferType::const_iterator iter = buf.begin();
00513     for (int i = 0; i < chunks; ++i) {
00514         iov[i].iov_base = const_cast<typename BufferType::data_type *>(iter->data());
00515         iov[i].iov_len = iter->size();
00516         ++iter;
00517     }
00518 }
00519 
00520 } // namespace
00521 
00522 #endif
Generated on Thu Sep 2 18:40:54 2010 for Avro C++ by  doxygen 1.6.3