BufferReader.hh
Go to the documentation of this file.00001
00019 #ifndef avro_BufferReader_hh__
00020 #define avro_BufferReader_hh__
00021
00022 #include "Buffer.hh"
00023
00032 namespace avro {
00033
00039 class BufferReader : private boost::noncopyable
00040 {
00041
00042 public:
00043
00044 typedef detail::data_type data_type;
00045 typedef detail::size_type size_type;
00046
00047 private:
00048
00049 size_type chunkRemaining() const {
00050 return iter_->dataSize() - chunkPos_;
00051 }
00052
00053 void incrementChunk(size_type howmuch) {
00054 bytesRemaining_ -= howmuch;
00055 chunkPos_ += howmuch;
00056 if(chunkPos_ == iter_->dataSize()) {
00057 chunkPos_ = 0;
00058 ++iter_;
00059 }
00060 }
00061
00062 void rewind() {
00063 iter_ = bufferImpl_->beginRead();
00064 bytesRemaining_ = bytes_;
00065 chunkPos_ = 0;
00066 }
00067
00068 const data_type *addr() const {
00069 return iter_->tellReadPos() + chunkPos_;
00070 }
00071
00072 public:
00073
00074 BufferReader(const InputBuffer &buf) :
00075 bufferImpl_(buf.pimpl_),
00076 iter_(bufferImpl_->beginRead()),
00077 bytes_(bufferImpl_->size()),
00078 bytesRemaining_(bytes_),
00079 chunkPos_(0)
00080 { }
00081
00082 BufferReader(const OutputBuffer &buf) :
00083 bufferImpl_(buf.pimpl_),
00084 iter_(bufferImpl_->beginRead()),
00085 bytes_(bufferImpl_->size()),
00086 bytesRemaining_(bytes_),
00087 chunkPos_(0)
00088 { }
00089
00094 size_type bytesRemaining() const {
00095 return bytesRemaining_;
00096 }
00097
00102 size_type bytesRead() const {
00103 return bytes_ - bytesRemaining_;
00104 }
00105
00110 size_type read(data_type *data, size_type size) {
00111
00112 if(size > bytesRemaining_) {
00113 size = bytesRemaining_;
00114 }
00115 size_type sizeToRead = size;
00116
00117 while(sizeToRead) {
00118 const size_type toRead = std::min(sizeToRead, chunkRemaining());
00119 memcpy(data, addr(), toRead);
00120 sizeToRead -= toRead;
00121 data += toRead;
00122 incrementChunk(toRead);
00123 }
00124
00125 return size;
00126 }
00127
00132 bool read(std::string &str, size_type size) {
00133 if(size > bytesRemaining_) {
00134 return false;
00135 }
00136
00137 if(size <= chunkRemaining()) {
00138 fastStringRead(str, size);
00139 }
00140 else {
00141 slowStringRead(str, size);
00142 }
00143
00144 return true;
00145 }
00146
00147
00154 template<typename T>
00155 bool read(T &val) {
00156 return read(val, boost::is_fundamental<T>());
00157 }
00158
00163 bool skip(size_type bytes) {
00164 bool skipped = false;
00165 if(bytes <= bytesRemaining_) {
00166 doSkip(bytes);
00167 skipped = true;
00168 }
00169 return skipped;
00170 }
00171
00176 bool seek(size_type pos) {
00177 if(pos > bytes_) {
00178 return false;
00179 }
00180
00181 size_type toSkip = pos;
00182 size_type curPos = bytesRead();
00183
00184 if(pos >= curPos) {
00185 toSkip -= curPos;
00186 }
00187
00188
00189 else if(pos >= (curPos - chunkPos_)) {
00190 curPos -= chunkPos_;
00191 bytesRemaining_ += chunkPos_;
00192 chunkPos_ = 0;
00193 toSkip -= curPos;
00194 }
00195 else {
00196 rewind();
00197 }
00198 doSkip(toSkip);
00199 return true;
00200 }
00201
00202 bool peek(char &val) {
00203 bool ret = (bytesRemaining_ > 0);
00204 if(ret) {
00205 val = *(addr());
00206 }
00207 return ret;
00208 }
00209
00210 InputBuffer copyData(size_type bytes) {
00211 if(bytes > bytesRemaining_) {
00212
00213 bytes = 0;
00214 }
00215 detail::BufferImpl::SharedPtr newImpl(new detail::BufferImpl);
00216 if(bytes) {
00217 bufferImpl_->copyData(*newImpl, iter_, chunkPos_, bytes);
00218 doSkip(bytes);
00219 }
00220 return InputBuffer(newImpl);
00221 }
00222
00223 private:
00224
00225 void doSkip(size_type sizeToSkip) {
00226
00227 while(sizeToSkip) {
00228 const size_type toSkip = std::min(sizeToSkip, chunkRemaining());
00229 sizeToSkip -= toSkip;
00230 incrementChunk(toSkip);
00231 }
00232 }
00233
00234 template<typename T>
00235 bool read(T &val, const boost::true_type&)
00236 {
00237 if(sizeof(T) > bytesRemaining_) {
00238 return false;
00239 }
00240
00241 if (sizeof(T) <= chunkRemaining()) {
00242 val = *(reinterpret_cast<const T*> (addr()));
00243 incrementChunk(sizeof(T));
00244 }
00245 else {
00246 read(reinterpret_cast<data_type *>(&val), sizeof(T));
00247 }
00248 return true;
00249 }
00250
00252 template<typename T>
00253 bool read(T &val, const boost::false_type&)
00254 {
00255 BOOST_STATIC_ASSERT(sizeof(T)==0);
00256 return false;
00257 }
00258
00259 void fastStringRead(std::string &str, size_type sizeToCopy) {
00260 str.assign(addr(), sizeToCopy);
00261 incrementChunk(sizeToCopy);
00262 }
00263
00264 void slowStringRead(std::string &str, size_type sizeToCopy) {
00265 str.clear();
00266 str.reserve(sizeToCopy);
00267 while(sizeToCopy) {
00268 const size_type toCopy = std::min(sizeToCopy, chunkRemaining());
00269 str.append(addr(), toCopy);
00270 sizeToCopy -= toCopy;
00271 incrementChunk(toCopy);
00272 }
00273 }
00274
00275 detail::BufferImpl::ConstSharedPtr bufferImpl_;
00276 detail::BufferImpl::ChunkList::const_iterator iter_;
00277 size_type bytes_;
00278 size_type bytesRemaining_;
00279 size_type chunkPos_;
00280 };
00281
00282
00283 }
00284
00285 #endif