source: NonGTP/Boost/boost/spirit/iterator/file_iterator.hpp @ 857

Revision 857, 8.2 KB checked in by igarcia, 18 years ago (diff)
Line 
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    Use, modification and distribution is subject to the Boost Software
8    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9    http://www.boost.org/LICENSE_1_0.txt)
10=============================================================================*/
11
12///////////////////////////////////////////////////////////////////////////////
13//
14//  File Iterator structure
15//
16//  The new structure is designed on layers. The top class (used by the user)
17//  is file_iterator, which implements a full random access iterator through
18//  the file, and some specific member functions (constructor that opens
19//  the file, make_end() to generate the end iterator, operator bool to check
20//  if the file was opened correctly).
21//
22//  file_iterator implements the random access iterator interface by the means
23//  of boost::iterator_adaptor, that is inhering an object created with it.
24//  iterator_adaptor gets a low-level file iterator implementation (with just
25//  a few member functions) and a policy (that basically describes to it how
26//  the low-level file iterator interface is). The advantage is that
27//  with boost::iterator_adaptor only 5 functions are needed to implement
28//  a fully conformant random access iterator, instead of dozens of functions
29//  and operators.
30//
31//  There are two low-level file iterators implemented in this module. The
32//  first (std_file_iterator) uses cstdio stream functions (fopen/fread), which
33//  support full buffering, and is available everywhere (it's standard C++).
34//  The second (mmap_file_iterator) is currently available only on Windows
35//  platforms, and uses memory mapped files, which gives a decent speed boost.
36//
37///////////////////////////////////////////////////////////////////////////////
38//
39//  TODO LIST:
40//
41//  - In the Win32 mmap iterator, we could check if keeping a handle to the
42//    opened file is really required. If it's not, we can just store the file
43//    length (for make_end()) and save performance. Notice that this should be
44//    tested under different Windows versions, the behaviour might change.
45//  - Add some error support (by the means of some exceptions) in case of
46//    low-level I/O failure.
47//
48///////////////////////////////////////////////////////////////////////////////
49
50#ifndef BOOST_SPIRIT_FILE_ITERATOR_HPP
51#define BOOST_SPIRIT_FILE_ITERATOR_HPP
52
53#include <string>
54#include <boost/config.hpp>
55#include <boost/iterator_adaptors.hpp>
56#include <boost/spirit/core/safe_bool.hpp>
57
58#if !defined(BOOST_SPIRIT_FILEITERATOR_STD)
59#  if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \
60      && !defined(BOOST_DISABLE_WIN32)
61#    define BOOST_SPIRIT_FILEITERATOR_WINDOWS
62#  elif defined(BOOST_HAS_UNISTD_H)
63extern "C"
64{
65#    include <unistd.h>
66}
67#    ifdef _POSIX_MAPPED_FILES
68#      define BOOST_SPIRIT_FILEITERATOR_POSIX
69#    endif // _POSIX_MAPPED_FILES
70#  endif // BOOST_HAS_UNISTD_H
71
72#  if !defined(BOOST_SPIRIT_FILEITERATOR_WINDOWS) && \
73      !defined(BOOST_SPIRIT_FILEITERATOR_POSIX)
74#    define BOOST_SPIRIT_FILEITERATOR_STD
75#  endif
76#endif // BOOST_SPIRIT_FILEITERATOR_STD
77
78///////////////////////////////////////////////////////////////////////////////
79namespace boost { namespace spirit {
80
81///////////////////////////////////////////////////////////////////////////////
82namespace fileiter_impl {
83
84    // Forward declarations
85    template <typename CharT = char>
86    class std_file_iterator;
87
88#if !defined(BOOST_SPIRIT_FILEITERATOR_STD)
89    template <typename CharT = char>
90    class mmap_file_iterator;
91#endif
92
93///////////////////////////////////////////////////////////////////////////////
94}   // namespace fileiter_impl
95
96template <
97    typename CharT = char,
98    typename BaseIterator =
99#ifdef BOOST_SPIRIT_FILEITERATOR_STD
100        fileiter_impl::std_file_iterator<CharT>
101#else
102        fileiter_impl::mmap_file_iterator<CharT>
103#endif
104> class file_iterator;
105
106///////////////////////////////////////////////////////////////////////////////
107namespace fileiter_impl {
108
109    /////////////////////////////////////////////////////////////////////////
110    //
111    //  file_iter_generator
112    //
113    //  Template meta-function to invoke boost::iterator_adaptor
114    //  NOTE: This cannot be moved into the implementation file because of
115    //  a bug of MSVC 7.0 and previous versions (base classes types are
116    //  looked up at compilation time, not instantion types, and
117    //  file_iterator would break).
118    //
119    /////////////////////////////////////////////////////////////////////////
120
121#if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
122     BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
123#error "Please use at least Boost V1.31.0 while compiling the file_iterator class!"
124#else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
125
126    template <typename CharT, typename BaseIteratorT>
127    struct file_iter_generator
128    {
129    public:
130        typedef BaseIteratorT adapted_t;
131        typedef typename adapted_t::value_type value_type;
132
133        typedef boost::iterator_adaptor <
134            file_iterator<CharT, BaseIteratorT>,
135            adapted_t,
136            value_type const,
137            std::random_access_iterator_tag,
138            boost::use_default,
139            signed long
140        > type;
141    };
142
143#endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
144
145///////////////////////////////////////////////////////////////////////////////
146} /* namespace impl */
147
148
149///////////////////////////////////////////////////////////////////////////////
150//
151//  file_iterator
152//
153//  Iterates through an opened file.
154//
155//  The main iterator interface is implemented by the iterator_adaptors
156//  library, which wraps a conforming iterator interface around the
157//  impl::BaseIterator class. This class merely derives the iterator_adaptors
158//  generated class to implement the custom constructors and make_end()
159//  member function.
160//
161///////////////////////////////////////////////////////////////////////////////
162
163template<typename CharT, typename BaseIteratorT>
164class file_iterator
165    : public fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type,
166      public safe_bool<file_iterator<CharT, BaseIteratorT> >
167{
168private:
169    typedef typename
170        fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::type
171        base_t;
172    typedef typename
173        fileiter_impl::file_iter_generator<CharT, BaseIteratorT>::adapted_t
174        adapted_t;
175
176public:
177    file_iterator()
178    {}
179
180    file_iterator(std::string fileName)
181    :   base_t(adapted_t(fileName))
182    {}
183
184    file_iterator(const base_t& iter)
185    :   base_t(iter)
186    {}
187
188    inline file_iterator& operator=(const base_t& iter);
189    file_iterator make_end(void);
190
191    // operator bool. This borrows a trick from boost::shared_ptr to avoid
192    //   to interfere with arithmetic operations.
193    bool operator_bool(void) const
194    { return this->base(); }
195
196private:
197    friend class ::boost::iterator_core_access;
198
199    typename base_t::reference dereference() const
200    {
201        return this->base_reference().get_cur_char();
202    }
203
204    void increment()
205    {
206        this->base_reference().next_char();
207    }
208
209    void decrement()
210    {
211        this->base_reference().prev_char();
212    }
213
214    void advance(typename base_t::difference_type n)
215    {
216        this->base_reference().advance(n);
217    }
218
219    template <
220        typename OtherDerivedT, typename OtherIteratorT,
221        typename V, typename C, typename R, typename D
222    >
223    typename base_t::difference_type distance_to(
224        iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
225        const &x) const
226    {
227        return x.base().distance(this->base_reference());
228    }
229};
230
231///////////////////////////////////////////////////////////////////////////////
232}} /* namespace boost::spirit */
233
234///////////////////////////////////////////////////////////////////////////////
235#include <boost/spirit/iterator/impl/file_iterator.ipp> /* implementation */
236
237#endif /* BOOST_SPIRIT_FILE_ITERATOR_HPP */
238
Note: See TracBrowser for help on using the repository browser.