123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- /*=============================================================================
- 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 const& 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 */
|