1 /*=============================================================================
2 Copyright (c) 2003 Giovanni Bajo
3 Copyright (c) 2003 Thomas Witt
4 Copyright (c) 2003 Hartmut Kaiser
5 http://spirit.sourceforge.net/
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 =============================================================================*/
11 ///////////////////////////////////////////////////////////////////////////////
13 // File Iterator structure
15 // The new structure is designed on layers. The top class (used by the user)
16 // is file_iterator, which implements a full random access iterator through
17 // the file, and some specific member functions (constructor that opens
18 // the file, make_end() to generate the end iterator, operator bool to check
19 // if the file was opened correctly).
21 // file_iterator implements the random access iterator interface by the means
22 // of boost::iterator_adaptor, that is inhering an object created with it.
23 // iterator_adaptor gets a low-level file iterator implementation (with just
24 // a few member functions) and a policy (that basically describes to it how
25 // the low-level file iterator interface is). The advantage is that
26 // with boost::iterator_adaptor only 5 functions are needed to implement
27 // a fully conformant random access iterator, instead of dozens of functions
30 // There are two low-level file iterators implemented in this module. The
31 // first (std_file_iterator) uses cstdio stream functions (fopen/fread), which
32 // support full buffering, and is available everywhere (it's standard C++).
33 // The second (mmap_file_iterator) is currently available only on Windows
34 // platforms, and uses memory mapped files, which gives a decent speed boost.
36 ///////////////////////////////////////////////////////////////////////////////
40 // - In the Win32 mmap iterator, we could check if keeping a handle to the
41 // opened file is really required. If it's not, we can just store the file
42 // length (for make_end()) and save performance. Notice that this should be
43 // tested under different Windows versions, the behaviour might change.
44 // - Add some error support (by the means of some exceptions) in case of
45 // low-level I/O failure.
47 ///////////////////////////////////////////////////////////////////////////////
49 #ifndef BOOST_SPIRIT_FILE_ITERATOR_HPP
50 #define BOOST_SPIRIT_FILE_ITERATOR_HPP
53 #include <boost/config.hpp>
54 #include <boost/iterator_adaptors.hpp>
55 #include <boost/spirit/home/classic/namespace.hpp>
56 #include <boost/spirit/home/classic/core/safe_bool.hpp>
58 #include <boost/spirit/home/classic/iterator/file_iterator_fwd.hpp>
60 #if !defined(BOOST_SPIRIT_FILEITERATOR_STD)
61 # if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
62 && !defined(BOOST_DISABLE_WIN32)
63 # define BOOST_SPIRIT_FILEITERATOR_WINDOWS
64 # elif defined(BOOST_HAS_UNISTD_H)
69 # ifdef _POSIX_MAPPED_FILES
70 # define BOOST_SPIRIT_FILEITERATOR_POSIX
71 # endif // _POSIX_MAPPED_FILES
72 # endif // BOOST_HAS_UNISTD_H
74 # if !defined(BOOST_SPIRIT_FILEITERATOR_WINDOWS) && \
75 !defined(BOOST_SPIRIT_FILEITERATOR_POSIX)
76 # define BOOST_SPIRIT_FILEITERATOR_STD
78 #endif // BOOST_SPIRIT_FILEITERATOR_STD
80 ///////////////////////////////////////////////////////////////////////////////
81 namespace boost { namespace spirit {
83 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
86 typename CharT = char,
87 typename BaseIterator =
88 #ifdef BOOST_SPIRIT_FILEITERATOR_STD
89 fileiter_impl::std_file_iterator<CharT>
91 fileiter_impl::mmap_file_iterator<CharT>
93 > class file_iterator;
95 ///////////////////////////////////////////////////////////////////////////////
96 namespace fileiter_impl {
98 /////////////////////////////////////////////////////////////////////////
100 // file_iter_generator
102 // Template meta-function to invoke boost::iterator_adaptor
103 // NOTE: This cannot be moved into the implementation file because of
104 // a bug of MSVC 7.0 and previous versions (base classes types are
105 // looked up at compilation time, not instantion types, and
106 // file_iterator would break).
108 /////////////////////////////////////////////////////////////////////////
110 #if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
111 BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
112 #error "Please use at least Boost V1.31.0 while compiling the file_iterator class!"
113 #else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
115 template <typename CharT, typename BaseIteratorT>
116 struct file_iter_generator
119 typedef BaseIteratorT adapted_t;
120 typedef typename adapted_t::value_type value_type;
122 typedef boost::iterator_adaptor <
123 file_iterator<CharT, BaseIteratorT>,
126 std::random_access_iterator_tag,
132 #endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
134 ///////////////////////////////////////////////////////////////////////////////
135 } /* namespace impl */
138 ///////////////////////////////////////////////////////////////////////////////
142 // Iterates through an opened file.
144 // The main iterator interface is implemented by the iterator_adaptors
145 // library, which wraps a conforming iterator interface around the
146 // impl::BaseIterator class. This class merely derives the iterator_adaptors
147 // generated class to implement the custom constructors and make_end()
150 ///////////////////////////////////////////////////////////////////////////////
152 template<typename CharT, typename BaseIteratorT>
154 : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type,
155 public safe_bool<file_iterator<CharT, BaseIteratorT> >
159 fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type
162 fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::adapted_t
169 file_iterator(std::string const& fileName)
170 : base_t(adapted_t(fileName))
173 file_iterator(const base_t& iter)
177 inline file_iterator& operator=(const base_t& iter);
178 file_iterator make_end(void);
180 // operator bool. This borrows a trick from boost::shared_ptr to avoid
181 // to interfere with arithmetic operations.
182 bool operator_bool(void) const
183 { return this->base(); }
186 friend class ::boost::iterator_core_access;
188 typename base_t::reference dereference() const
190 return this->base_reference().get_cur_char();
195 this->base_reference().next_char();
200 this->base_reference().prev_char();
203 void advance(typename base_t::difference_type n)
205 this->base_reference().advance(n);
209 typename OtherDerivedT, typename OtherIteratorT,
210 typename V, typename C, typename R, typename D
212 typename base_t::difference_type distance_to(
213 iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
216 return x.base().distance(this->base_reference());
220 ///////////////////////////////////////////////////////////////////////////////
221 BOOST_SPIRIT_CLASSIC_NAMESPACE_END
223 }} /* namespace BOOST_SPIRIT_CLASSIC_NS */
225 ///////////////////////////////////////////////////////////////////////////////
226 #include <boost/spirit/home/classic/iterator/impl/file_iterator.ipp> /* implementation */
228 #endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */