summaryrefslogtreecommitdiffstats
blob: 711ae903946f16a9b2f6d26cbb041450e33f3489 (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
//  Copyright (c) 2001-2011 Hartmut Kaiser
// 
//  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_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM)
#define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM

#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_empty.hpp>

namespace boost { namespace spirit { namespace iterator_policies
{
    namespace split_functor_input_is_valid_test_
    {
        template <typename Token>
        inline bool token_is_valid(Token const&)
        {
            return true;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    //  class split_functor_input
    //  Implementation of the InputPolicy used by multi_pass
    //  split_functor_input gets tokens from a functor
    // 
    //  This policy should be used when the functor holds two parts of data: a
    //  unique part (unique for each instance of the iterator) and a shared 
    //  part (to be shared between the different copies of the same iterator).
    //  Using this policy allows to merge the shared part of the functor with 
    //  the shared part of the iterator data, saving one pointer and one 
    //  allocation per iterator instance.
    //
    //  The Functor template parameter of this policy is expected to be a 
    //  std::pair<unique, shared>, where 'unique' and 'shared' represent the
    //  respective parts of the functor itself.
    //
    //  Note: the unique part of the functor must have a typedef for result_type
    //        It also must have a static variable of type result_type defined 
    //        to represent EOF that is called eof.
    //
    ///////////////////////////////////////////////////////////////////////////
    struct split_functor_input
    {
        ///////////////////////////////////////////////////////////////////////
        template <typename Functor
          , bool FunctorIsEmpty = is_empty<typename Functor::first_type>::value>
        class unique;

        // the unique part of the functor is empty, do not include the functor 
        // as a member at all to avoid unnecessary padding bytes to be included 
        // into the generated structure
        template <typename Functor>
        class unique<Functor, true> // : public detail::default_input_policy
        {
        protected:
            typedef typename Functor::first_type functor_type;
            typedef typename functor_type::result_type result_type;

        public:
            typedef result_type value_type;
            typedef std::ptrdiff_t difference_type;
            typedef std::ptrdiff_t distance_type;
            typedef result_type const* pointer;
            typedef result_type const& reference;

        protected:
            unique() {}
            explicit unique(Functor const&) {}

        public:
            void swap(unique&) {}

            // get the next token
            template <typename MultiPass>
            static typename MultiPass::reference get_input(MultiPass& mp)
            {
                value_type& curtok = mp.shared()->curtok;
                using namespace split_functor_input_is_valid_test_;
                if (!token_is_valid(curtok))
                    functor_type::get_next(mp, curtok);
                return curtok;
            }

            template <typename MultiPass>
            static void advance_input(MultiPass& mp)
            {
                functor_type::get_next(mp, mp.shared()->curtok);
            }

            // test, whether we reached the end of the underlying stream
            template <typename MultiPass>
            static bool input_at_eof(MultiPass const& mp) 
            {
                return mp.shared()->curtok == functor_type::eof;
            }

            template <typename MultiPass>
            static bool input_is_valid(MultiPass const&, value_type const& t) 
            {
                using namespace split_functor_input_is_valid_test_;
                return token_is_valid(t);
            }

            template <typename MultiPass>
            static void destroy(MultiPass& mp) 
            {
                functor_type::destroy(mp);
            }
        };

        // the unique part of the functor is non-empty
        template <typename Functor>
        class unique<Functor, false> : public unique<Functor, true>
        {
        protected:
            typedef typename Functor::first_type functor_type;
            typedef typename functor_type::result_type result_type;

        protected:
            unique() {}
            explicit unique(Functor const& x) : ftor(x.first) {}

            void swap(unique& x)
            {
                boost::swap(ftor, x.ftor);
            }

        public:
            typedef result_type value_type;
            typedef std::ptrdiff_t difference_type;
            typedef std::ptrdiff_t distance_type;
            typedef result_type const* pointer;
            typedef result_type const& reference;

        public:
            // get the next token
            template <typename MultiPass>
            static typename MultiPass::reference get_input(MultiPass& mp)
            {
                value_type& curtok = mp.shared()->curtok;
                using namespace split_functor_input_is_valid_test_;
                if (!token_is_valid(curtok))
                    functor_type::get_next(mp, curtok);
                return curtok;
            }

            template <typename MultiPass>
            static void advance_input(MultiPass& mp)
            {
                mp.ftor.get_next(mp, mp.shared()->curtok);
            }

            template <typename MultiPass>
            static bool input_is_valid(MultiPass const&, value_type const& t) 
            {
                using namespace split_functor_input_is_valid_test_;
                return token_is_valid(t);
            }

            // test, whether we reached the end of the underlying stream
            template <typename MultiPass>
            static bool input_at_eof(MultiPass const& mp) 
            {
                return mp.shared()->curtok == mp.ftor.eof;
            }

            typename Functor::first_type& get_functor() const
            {
                return ftor;
            }

            mutable functor_type ftor;
        };

        ///////////////////////////////////////////////////////////////////////
        template <typename Functor>
        struct shared
        {
        protected:
            typedef typename Functor::first_type functor_type;
            typedef typename functor_type::result_type result_type;

        public:
            explicit shared(Functor const& x) : ftor(x.second), curtok(0) {}

            mutable typename Functor::second_type ftor;
            result_type curtok;

        private:
            // silence MSVC warning C4512: assignment operator could not be generated
            shared& operator= (shared const&);
        };
    };

}}}

#endif