• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
65 extern "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 ///////////////////////////////////////////////////////////////////////////////
81 namespace boost { namespace spirit {
82 
83 BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
84 
85 template <
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 ///////////////////////////////////////////////////////////////////////////////
96 namespace 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 
152 template<typename CharT, typename BaseIteratorT>
153 class file_iterator
154     : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type,
155       public safe_bool<file_iterator<CharT, BaseIteratorT> >
156 {
157 private:
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 
165 public:
file_iterator()166     file_iterator()
167     {}
168 
file_iterator(std::string const & fileName)169     file_iterator(std::string const& fileName)
170     :   base_t(adapted_t(fileName))
171     {}
172 
file_iterator(const base_t & iter)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.
operator_bool(void) const182     bool operator_bool(void) const
183     { return this->base(); }
184 
185 private:
186     friend class ::boost::iterator_core_access;
187 
dereference() const188     typename base_t::reference dereference() const
189     {
190         return this->base_reference().get_cur_char();
191     }
192 
increment()193     void increment()
194     {
195         this->base_reference().next_char();
196     }
197 
decrement()198     void decrement()
199     {
200         this->base_reference().prev_char();
201     }
202 
advance(typename base_t::difference_type n)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     >
distance_to(iterator_adaptor<OtherDerivedT,OtherIteratorT,V,C,R,D> const & x) const212     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 ///////////////////////////////////////////////////////////////////////////////
221 BOOST_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