| /*============================================================================= |
| Copyright (c) 2003 Giovanni Bajo |
| Copyright (c) 2003 Thomas Witt |
| Copyright (c) 2003 Hartmut Kaiser |
| http://spirit.sourceforge.net/ |
| |
| Distributed under the Boost Software License, Version 1.0. (See accompanying |
| file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| =============================================================================*/ |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // File Iterator structure |
| // |
| // The new structure is designed on layers. The top class (used by the user) |
| // is file_iterator, which implements a full random access iterator through |
| // the file, and some specific member functions (constructor that opens |
| // the file, make_end() to generate the end iterator, operator bool to check |
| // if the file was opened correctly). |
| // |
| // file_iterator implements the random access iterator interface by the means |
| // of boost::iterator_adaptor, that is inhering an object created with it. |
| // iterator_adaptor gets a low-level file iterator implementation (with just |
| // a few member functions) and a policy (that basically describes to it how |
| // the low-level file iterator interface is). The advantage is that |
| // with boost::iterator_adaptor only 5 functions are needed to implement |
| // a fully conformant random access iterator, instead of dozens of functions |
| // and operators. |
| // |
| // There are two low-level file iterators implemented in this module. The |
| // first (std_file_iterator) uses cstdio stream functions (fopen/fread), which |
| // support full buffering, and is available everywhere (it's standard C++). |
| // The second (mmap_file_iterator) is currently available only on Windows |
| // platforms, and uses memory mapped files, which gives a decent speed boost. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // TODO LIST: |
| // |
| // - In the Win32 mmap iterator, we could check if keeping a handle to the |
| // opened file is really required. If it's not, we can just store the file |
| // length (for make_end()) and save performance. Notice that this should be |
| // tested under different Windows versions, the behaviour might change. |
| // - Add some error support (by the means of some exceptions) in case of |
| // low-level I/O failure. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #ifndef BOOST_SPIRIT_FILE_ITERATOR_HPP |
| #define BOOST_SPIRIT_FILE_ITERATOR_HPP |
| |
| #include <string> |
| #include <boost/config.hpp> |
| #include <boost/iterator_adaptors.hpp> |
| #include <boost/spirit/home/classic/namespace.hpp> |
| #include <boost/spirit/home/classic/core/safe_bool.hpp> |
| |
| #include <boost/spirit/home/classic/iterator/file_iterator_fwd.hpp> |
| |
| #if !defined(BOOST_SPIRIT_FILEITERATOR_STD) |
| # if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ |
| && !defined(BOOST_DISABLE_WIN32) |
| # define BOOST_SPIRIT_FILEITERATOR_WINDOWS |
| # elif defined(BOOST_HAS_UNISTD_H) |
| extern "C" |
| { |
| # include <unistd.h> |
| } |
| # ifdef _POSIX_MAPPED_FILES |
| # define BOOST_SPIRIT_FILEITERATOR_POSIX |
| # endif // _POSIX_MAPPED_FILES |
| # endif // BOOST_HAS_UNISTD_H |
| |
| # if !defined(BOOST_SPIRIT_FILEITERATOR_WINDOWS) && \ |
| !defined(BOOST_SPIRIT_FILEITERATOR_POSIX) |
| # define BOOST_SPIRIT_FILEITERATOR_STD |
| # endif |
| #endif // BOOST_SPIRIT_FILEITERATOR_STD |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace boost { namespace spirit { |
| |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN |
| |
| template < |
| typename CharT = char, |
| typename BaseIterator = |
| #ifdef BOOST_SPIRIT_FILEITERATOR_STD |
| fileiter_impl::std_file_iterator<CharT> |
| #else |
| fileiter_impl::mmap_file_iterator<CharT> |
| #endif |
| > class file_iterator; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| namespace fileiter_impl { |
| |
| ///////////////////////////////////////////////////////////////////////// |
| // |
| // file_iter_generator |
| // |
| // Template meta-function to invoke boost::iterator_adaptor |
| // NOTE: This cannot be moved into the implementation file because of |
| // a bug of MSVC 7.0 and previous versions (base classes types are |
| // looked up at compilation time, not instantion types, and |
| // file_iterator would break). |
| // |
| ///////////////////////////////////////////////////////////////////////// |
| |
| #if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \ |
| BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| #error "Please use at least Boost V1.31.0 while compiling the file_iterator class!" |
| #else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| |
| template <typename CharT, typename BaseIteratorT> |
| struct file_iter_generator |
| { |
| public: |
| typedef BaseIteratorT adapted_t; |
| typedef typename adapted_t::value_type value_type; |
| |
| typedef boost::iterator_adaptor < |
| file_iterator<CharT, BaseIteratorT>, |
| adapted_t, |
| value_type const, |
| std::random_access_iterator_tag, |
| boost::use_default, |
| std::ptrdiff_t |
| > type; |
| }; |
| |
| #endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200 |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| } /* namespace impl */ |
| |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| // |
| // file_iterator |
| // |
| // Iterates through an opened file. |
| // |
| // The main iterator interface is implemented by the iterator_adaptors |
| // library, which wraps a conforming iterator interface around the |
| // impl::BaseIterator class. This class merely derives the iterator_adaptors |
| // generated class to implement the custom constructors and make_end() |
| // member function. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| template<typename CharT, typename BaseIteratorT> |
| class file_iterator |
| : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type, |
| public safe_bool<file_iterator<CharT, BaseIteratorT> > |
| { |
| private: |
| typedef typename |
| fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type |
| base_t; |
| typedef typename |
| fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::adapted_t |
| adapted_t; |
| |
| public: |
| file_iterator() |
| {} |
| |
| file_iterator(std::string fileName) |
| : base_t(adapted_t(fileName)) |
| {} |
| |
| file_iterator(const base_t& iter) |
| : base_t(iter) |
| {} |
| |
| inline file_iterator& operator=(const base_t& iter); |
| file_iterator make_end(void); |
| |
| // operator bool. This borrows a trick from boost::shared_ptr to avoid |
| // to interfere with arithmetic operations. |
| bool operator_bool(void) const |
| { return this->base(); } |
| |
| private: |
| friend class ::boost::iterator_core_access; |
| |
| typename base_t::reference dereference() const |
| { |
| return this->base_reference().get_cur_char(); |
| } |
| |
| void increment() |
| { |
| this->base_reference().next_char(); |
| } |
| |
| void decrement() |
| { |
| this->base_reference().prev_char(); |
| } |
| |
| void advance(typename base_t::difference_type n) |
| { |
| this->base_reference().advance(n); |
| } |
| |
| template < |
| typename OtherDerivedT, typename OtherIteratorT, |
| typename V, typename C, typename R, typename D |
| > |
| typename base_t::difference_type distance_to( |
| iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D> |
| const &x) const |
| { |
| return x.base().distance(this->base_reference()); |
| } |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| BOOST_SPIRIT_CLASSIC_NAMESPACE_END |
| |
| }} /* namespace BOOST_SPIRIT_CLASSIC_NS */ |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| #include <boost/spirit/home/classic/iterator/impl/file_iterator.ipp> /* implementation */ |
| |
| #endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */ |
| |