1/*=============================================================================
2 Copyright (c) 2003 Giovanni Bajo
3 Copyright (c) 2003 Thomas Witt
4 Copyright (c) 2003 Hartmut Kaiser
5 http://spirit.sourceforge.net/
6
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=============================================================================*/
10
11///////////////////////////////////////////////////////////////////////////////
12//
13// File Iterator structure
14//
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).
20//
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
28// and operators.
29//
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.
35//
36///////////////////////////////////////////////////////////////////////////////
37//
38// TODO LIST:
39//
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.
46//
47///////////////////////////////////////////////////////////////////////////////
48
49#ifndef BOOST_SPIRIT_FILE_ITERATOR_HPP
50#define BOOST_SPIRIT_FILE_ITERATOR_HPP
51
52#include <string>
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>
57
58#include <boost/spirit/home/classic/iterator/file_iterator_fwd.hpp>
59
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)
65extern "C"
66{
67# include <unistd.h>
68}
69# ifdef _POSIX_MAPPED_FILES
70# define BOOST_SPIRIT_FILEITERATOR_POSIX
71# endif // _POSIX_MAPPED_FILES
72# endif // BOOST_HAS_UNISTD_H
73
74# if !defined(BOOST_SPIRIT_FILEITERATOR_WINDOWS) && \
75 !defined(BOOST_SPIRIT_FILEITERATOR_POSIX)
76# define BOOST_SPIRIT_FILEITERATOR_STD
77# endif
78#endif // BOOST_SPIRIT_FILEITERATOR_STD
79
80///////////////////////////////////////////////////////////////////////////////
81namespace boost { namespace spirit {
82
83BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
84
85template <
86 typename CharT = char,
87 typename BaseIterator =
88#ifdef BOOST_SPIRIT_FILEITERATOR_STD
89 fileiter_impl::std_file_iterator<CharT>
90#else
91 fileiter_impl::mmap_file_iterator<CharT>
92#endif
93> class file_iterator;
94
95///////////////////////////////////////////////////////////////////////////////
96namespace fileiter_impl {
97
98 /////////////////////////////////////////////////////////////////////////
99 //
100 // file_iter_generator
101 //
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).
107 //
108 /////////////////////////////////////////////////////////////////////////
109
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
114
115 template <typename CharT, typename BaseIteratorT>
116 struct file_iter_generator
117 {
118 public:
119 typedef BaseIteratorT adapted_t;
120 typedef typename adapted_t::value_type value_type;
121
122 typedef boost::iterator_adaptor <
123 file_iterator<CharT, BaseIteratorT>,
124 adapted_t,
125 value_type const,
126 std::random_access_iterator_tag,
127 boost::use_default,
128 std::ptrdiff_t
129 > type;
130 };
131
132#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
133
134///////////////////////////////////////////////////////////////////////////////
135} /* namespace impl */
136
137
138///////////////////////////////////////////////////////////////////////////////
139//
140// file_iterator
141//
142// Iterates through an opened file.
143//
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()
148// member function.
149//
150///////////////////////////////////////////////////////////////////////////////
151
152template<typename CharT, typename BaseIteratorT>
153class file_iterator
154 : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type,
155 public safe_bool<file_iterator<CharT, BaseIteratorT> >
156{
157private:
158 typedef typename
159 fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type
160 base_t;
161 typedef typename
162 fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::adapted_t
163 adapted_t;
164
165public:
166 file_iterator()
167 {}
168
169 file_iterator(std::string const& fileName)
170 : base_t(adapted_t(fileName))
171 {}
172
173 file_iterator(const base_t& iter)
174 : base_t(iter)
175 {}
176
177 inline file_iterator& operator=(const base_t& iter);
178 file_iterator make_end(void);
179
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(); }
184
185private:
186 friend class ::boost::iterator_core_access;
187
188 typename base_t::reference dereference() const
189 {
190 return this->base_reference().get_cur_char();
191 }
192
193 void increment()
194 {
195 this->base_reference().next_char();
196 }
197
198 void decrement()
199 {
200 this->base_reference().prev_char();
201 }
202
203 void advance(typename base_t::difference_type n)
204 {
205 this->base_reference().advance(n);
206 }
207
208 template <
209 typename OtherDerivedT, typename OtherIteratorT,
210 typename V, typename C, typename R, typename D
211 >
212 typename base_t::difference_type distance_to(
213 iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
214 const &x) const
215 {
216 return x.base().distance(this->base_reference());
217 }
218};
219
220///////////////////////////////////////////////////////////////////////////////
221BOOST_SPIRIT_CLASSIC_NAMESPACE_END
222
223}} /* namespace BOOST_SPIRIT_CLASSIC_NS */
224
225///////////////////////////////////////////////////////////////////////////////
226#include <boost/spirit/home/classic/iterator/impl/file_iterator.ipp> /* implementation */
227
228#endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */
229
230

source code of boost/libs/spirit/include/boost/spirit/home/classic/iterator/file_iterator.hpp