/*============================================================================= Copyright (c) 2003 Giovanni Bajo Copyright (c) 2003 Thomas Witt Copyright (c) 2003 Hartmut Kaiser http://spirit.sourceforge.net/ Use, modification and distribution is subject to 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 #include #include #include #include #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 } # 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 { template < typename CharT = char, typename BaseIterator = #ifdef BOOST_SPIRIT_FILEITERATOR_STD fileiter_impl::std_file_iterator #else fileiter_impl::mmap_file_iterator #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 struct file_iter_generator { public: typedef BaseIteratorT adapted_t; typedef typename adapted_t::value_type value_type; typedef boost::iterator_adaptor < file_iterator, 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 class file_iterator : public fileiter_impl::file_iter_generator::type, public safe_bool > { private: typedef typename fileiter_impl::file_iter_generator::type base_t; typedef typename fileiter_impl::file_iter_generator::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 const &x) const { return x.base().distance(this->base_reference()); } }; /////////////////////////////////////////////////////////////////////////////// }} /* namespace boost::spirit */ /////////////////////////////////////////////////////////////////////////////// #include /* implementation */ #endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */