Chris@16: // Copyright Vladimir Prus 2004. Chris@16: // Distributed under the Boost Software License, Version 1.0. Chris@16: // (See accompanying file LICENSE_1_0.txt Chris@16: // or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_EOF_ITERATOR_VP_2004_03_12 Chris@16: #define BOOST_EOF_ITERATOR_VP_2004_03_12 Chris@16: Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: Chris@16: /** The 'eof_iterator' class is useful for constructing forward iterators Chris@16: in cases where iterator extract data from some source and it's easy Chris@16: to detect 'eof' -- i.e. the situation where there's no data. One Chris@16: apparent example is reading lines from a file. Chris@16: Chris@16: Implementing such iterators using 'iterator_facade' directly would Chris@16: require to create class with three core operation, a couple of Chris@16: constructors. When using 'eof_iterator', the derived class should define Chris@16: only one method to get new value, plus a couple of constructors. Chris@16: Chris@16: The basic idea is that iterator has 'eof' bit. Two iterators are equal Chris@16: only if both have their 'eof' bits set. The 'get' method either obtains Chris@16: the new value or sets the 'eof' bit. Chris@16: Chris@16: Specifically, derived class should define: Chris@16: Chris@16: 1. A default constructor, which creates iterator with 'eof' bit set. The Chris@16: constructor body should call 'found_eof' method defined here. Chris@16: 2. Some other constructor. It should initialize some 'data pointer' used Chris@16: in iterator operation and then call 'get'. Chris@16: 3. The 'get' method. It should operate this way: Chris@16: - look at some 'data pointer' to see if new element is available; Chris@16: if not, it should call 'found_eof'. Chris@16: - extract new element and store it at location returned by the 'value' Chris@16: method. Chris@16: - advance the data pointer. Chris@16: Chris@16: Essentially, the 'get' method has the functionality of both 'increment' Chris@16: and 'dereference'. It's very good for the cases where data extraction Chris@16: implicitly moves data pointer, like for stream operation. Chris@16: */ Chris@16: template Chris@16: class eof_iterator : public iterator_facade Chris@16: { Chris@16: public: Chris@16: eof_iterator() Chris@16: : m_at_eof(false) Chris@16: {} Chris@16: Chris@16: protected: // interface for derived Chris@16: Chris@16: /** Returns the reference which should be used by derived Chris@16: class to store the next value. */ Chris@16: ValueType& value() Chris@16: { Chris@16: return m_value; Chris@16: } Chris@16: Chris@16: /** Should be called by derived class to indicate that it can't Chris@16: produce next element. */ Chris@16: void found_eof() Chris@16: { Chris@16: m_at_eof = true; Chris@16: } Chris@16: Chris@16: Chris@16: private: // iterator core operations Chris@16: friend class iterator_core_access; Chris@16: Chris@16: void increment() Chris@16: { Chris@16: static_cast(*this).get(); Chris@16: } Chris@16: Chris@16: bool equal(const eof_iterator& other) const Chris@16: { Chris@16: if (m_at_eof && other.m_at_eof) Chris@16: return true; Chris@16: else Chris@16: return false; Chris@16: } Chris@16: Chris@16: const ValueType& dereference() const Chris@16: { Chris@16: return m_value; Chris@16: } Chris@16: Chris@16: bool m_at_eof; Chris@16: ValueType m_value; Chris@16: }; Chris@16: } Chris@16: Chris@16: #endif Chris@16: