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
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
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;
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
00459
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 }
00521
00522 #endif