00001 #ifndef UTIL_STREAM_STREAM_H
00002 #define UTIL_STREAM_STREAM_H
00003
00004 #include "util/stream/chain.hh"
00005
00006 #include <boost/noncopyable.hpp>
00007
00008 #include <cassert>
00009 #include <stdint.h>
00010
00011 namespace util {
00012 namespace stream {
00013
00014 class Stream : boost::noncopyable {
00015 public:
00016 Stream() : current_(NULL), end_(NULL) {}
00017
00018 void Init(const ChainPosition &position) {
00019 entry_size_ = position.GetChain().EntrySize();
00020 block_size_ = position.GetChain().BlockSize();
00021 block_it_.Init(position);
00022 StartBlock();
00023 }
00024
00025 explicit Stream(const ChainPosition &position) {
00026 Init(position);
00027 }
00028
00029 operator bool() const { return current_ != NULL; }
00030 bool operator!() const { return current_ == NULL; }
00031
00032 const void *Get() const { return current_; }
00033 void *Get() { return current_; }
00034
00035 void Poison() {
00036 block_it_->SetValidSize(current_ - static_cast<uint8_t*>(block_it_->Get()));
00037 ++block_it_;
00038 block_it_.Poison();
00039 }
00040
00041 Stream &operator++() {
00042 assert(*this);
00043 assert(current_ < end_);
00044 current_ += entry_size_;
00045 if (current_ == end_) {
00046 ++block_it_;
00047 StartBlock();
00048 }
00049 return *this;
00050 }
00051
00052 private:
00053 void StartBlock() {
00054 for (; block_it_ && !block_it_->ValidSize(); ++block_it_) {}
00055 current_ = static_cast<uint8_t*>(block_it_->Get());
00056 end_ = current_ + block_it_->ValidSize();
00057 }
00058
00059
00060
00061
00062 uint8_t *current_, *end_;
00063
00064 std::size_t entry_size_;
00065 std::size_t block_size_;
00066
00067 Link block_it_;
00068 };
00069
00070 inline Chain &operator>>(Chain &chain, Stream &stream) {
00071 stream.Init(chain.Add());
00072 return chain;
00073 }
00074
00075 }
00076 }
00077 #endif // UTIL_STREAM_STREAM_H