liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
/*=============================================================================
    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 */