summaryrefslogtreecommitdiffstats
blob: 2b355bfa6dbe53a5181bfb813c7586632bde5e4c (plain)
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
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//  Copyright (c) 2001, Daniel C. Nuffer
//  Copyright (c) 2001-2011 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)

#if !defined(BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM)
#define BOOST_SPIRIT_ITERATOR_MULTI_PASS_MAR_16_2007_1124AM

#include <boost/config.hpp>
#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
#include <boost/spirit/home/support/iterators/detail/combine_policies.hpp>
#include <boost/limits.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/utility/base_from_member.hpp>

namespace boost { namespace spirit
{
    ///////////////////////////////////////////////////////////////////////////
    // The default multi_pass instantiation uses a ref-counted std_deque scheme.
    ///////////////////////////////////////////////////////////////////////////
    template<typename T, typename Policies>
    class multi_pass
      : private boost::base_from_member<
            typename Policies::BOOST_NESTED_TEMPLATE shared<T>*>
      , public Policies::BOOST_NESTED_TEMPLATE unique<T>
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
      , typename iterator_base_creator<T, typename Policies::input_policy>::type
#endif
    {
    private:
        // unique and shared data types
        typedef typename Policies::BOOST_NESTED_TEMPLATE unique<T>
            policies_base_type;
        typedef typename Policies::BOOST_NESTED_TEMPLATE shared<T>
            shared_data_type;

        typedef boost::base_from_member<shared_data_type*> member_base;

        // define the types the standard embedded iterator typedefs are taken
        // from
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
        typedef typename iterator_base_creator<Input, T>::type iterator_type;
#else
        typedef typename policies_base_type::input_policy iterator_type;
#endif

    public:
        // standard iterator typedefs
        typedef std::forward_iterator_tag iterator_category;
        typedef typename iterator_type::value_type value_type;
        typedef typename iterator_type::difference_type difference_type;
        typedef typename iterator_type::distance_type distance_type;
        typedef typename iterator_type::reference reference;
        typedef typename iterator_type::pointer pointer;

        multi_pass() : member_base(static_cast<shared_data_type*>(0)) {}

        explicit multi_pass(T& input)
          : member_base(new shared_data_type(input)), policies_base_type(input) {}

        explicit multi_pass(T const& input)
          : member_base(new shared_data_type(input)), policies_base_type(input) {}

        multi_pass(multi_pass const& x)
          : member_base(x.member), policies_base_type(x)
        {
            policies_base_type::clone(*this);
        }

#if BOOST_WORKAROUND(__GLIBCPP__, == 20020514)
        // The standard library shipped with gcc-3.1 has a bug in
        // bits/basic_string.tcc. It tries to use iter::iter(0) to
        // construct an iterator. Ironically, this  happens in sanity
        // checking code that isn't required by the standard.
        // The workaround is to provide an additional constructor that
        // ignores its int argument and behaves like the default constructor.
        multi_pass(int) : member_base(static_cast<shared_data_type*>(0)) {}
#endif // BOOST_WORKAROUND(__GLIBCPP__, == 20020514)

        ~multi_pass()
        {
            if (policies_base_type::release(*this)) {
                policies_base_type::destroy(*this);
                delete this->member;
            }
        }

        multi_pass& operator=(multi_pass const& x)
        {
            if (this != &x) {
                multi_pass temp(x);
                temp.swap(*this);
            }
            return *this;
        }

        void swap(multi_pass& x)
        {
            boost::swap(this->member, x.member);
            this->policies_base_type::swap(x);
        }

        reference operator*() const
        {
            policies_base_type::docheck(*this);
            return policies_base_type::dereference(*this);
        }
        pointer operator->() const
        {
            return &(operator*());
        }

        multi_pass& operator++()
        {
            policies_base_type::docheck(*this);
            policies_base_type::increment(*this);
            return *this;
        }
        multi_pass operator++(int)
        {
            multi_pass tmp(*this);
            ++*this;
            return tmp;
        }

        void clear_queue(BOOST_SCOPED_ENUM(traits::clear_mode) mode =
            traits::clear_mode::clear_if_enabled)
        {
            if (mode == traits::clear_mode::clear_always || !inhibit_clear_queue())
                policies_base_type::clear_queue(*this);
        }
        bool inhibit_clear_queue() const
        {
            return this->member->inhibit_clear_queue_;
        }
        void inhibit_clear_queue(bool flag)
        {
            this->member->inhibit_clear_queue_ = flag;
        }

        bool operator==(multi_pass const& y) const
        {
            if (is_eof())
                return y.is_eof();
            if (y.is_eof())
                return false;

            return policies_base_type::equal_to(*this, y);
        }
        bool operator<(multi_pass const& y) const
        {
            return policies_base_type::less_than(*this, y);
        }

        bool operator!=(multi_pass const& y)
        {
            return !(*this == y);
        }
        bool operator>(multi_pass const& y)
        {
            return y < *this;
        }
        bool operator>=(multi_pass const& y)
        {
            return !(*this < y);
        }
        bool operator<=(multi_pass const& y)
        {
            return !(y < *this);
        }

        // allow access to base member
        shared_data_type* shared() const { return this->member; }

    private: // helper functions
        bool is_eof() const
        {
            return (0 == this->member) || policies_base_type::is_eof(*this);
        }
    };

    ///////////////////////////////////////////////////////////////////////////
    //  Generator function
    ///////////////////////////////////////////////////////////////////////////
    template <typename Policies, typename T>
    inline multi_pass<T, Policies>
    make_multi_pass(T& i)
    {
        return multi_pass<T, Policies>(i);
    }
    template <typename Policies, typename T>
    inline multi_pass<T, Policies>
    make_multi_pass(T const& i)
    {
        return multi_pass<T, Policies>(i);
    }

    ///////////////////////////////////////////////////////////////////////////
    template <typename T>
    inline multi_pass<T>
    make_default_multi_pass(T& i)
    {
        return multi_pass<T>(i);
    }
    template <typename T>
    inline multi_pass<T>
    make_default_multi_pass(T const& i)
    {
        return multi_pass<T>(i);
    }

    ///////////////////////////////////////////////////////////////////////////
    template <typename T, typename Policies>
    inline void
    swap(multi_pass<T, Policies> &x, multi_pass<T, Policies> &y)
    {
        x.swap(y);
    }

    ///////////////////////////////////////////////////////////////////////////
    // define special functions allowing to integrate any multi_pass iterator
    // with expectation points
    namespace traits
    {
        template <typename T, typename Policies>
        void clear_queue(multi_pass<T, Policies>& mp
          , BOOST_SCOPED_ENUM(traits::clear_mode) mode)
        {
            mp.clear_queue(mode);
        }

        template <typename T, typename Policies>
        void inhibit_clear_queue(multi_pass<T, Policies>& mp, bool flag)
        {
            mp.inhibit_clear_queue(flag);
        }

        template <typename T, typename Policies>
        bool inhibit_clear_queue(multi_pass<T, Policies>& mp)
        {
            return mp.inhibit_clear_queue();
        }
    }

}} // namespace boost::spirit

#endif