Joshua
open source statistical hierarchical phrase-based machine translation system
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
src/kenlm/util/stream/stream.hh
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     // The following are pointers to raw memory
00060     // current_ is the current record
00061     // end_ is the end of the block (so we know when to move to the next block)
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 } // namespace stream
00076 } // namespace util
00077 #endif // UTIL_STREAM_STREAM_H