]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if !defined(BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM) | |
7 | #define BOOST_SPIRIT_ITERATOR_SPLIT_FUNCTOR_INPUT_POLICY_JAN_17_2008_0103PM | |
8 | ||
9 | #include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp> | |
10 | #include <boost/spirit/home/support/iterators/detail/multi_pass.hpp> | |
11 | #include <boost/assert.hpp> | |
12 | #include <boost/type_traits/is_empty.hpp> | |
13 | ||
14 | namespace boost { namespace spirit { namespace iterator_policies | |
15 | { | |
16 | namespace split_functor_input_is_valid_test_ | |
17 | { | |
18 | template <typename Token> | |
19 | inline bool token_is_valid(Token const&) | |
20 | { | |
21 | return true; | |
22 | } | |
23 | } | |
24 | ||
25 | /////////////////////////////////////////////////////////////////////////// | |
26 | // class split_functor_input | |
27 | // Implementation of the InputPolicy used by multi_pass | |
28 | // split_functor_input gets tokens from a functor | |
29 | // | |
30 | // This policy should be used when the functor holds two parts of data: a | |
31 | // unique part (unique for each instance of the iterator) and a shared | |
32 | // part (to be shared between the different copies of the same iterator). | |
33 | // Using this policy allows to merge the shared part of the functor with | |
34 | // the shared part of the iterator data, saving one pointer and one | |
35 | // allocation per iterator instance. | |
36 | // | |
37 | // The Functor template parameter of this policy is expected to be a | |
38 | // std::pair<unique, shared>, where 'unique' and 'shared' represent the | |
39 | // respective parts of the functor itself. | |
40 | // | |
41 | // Note: the unique part of the functor must have a typedef for result_type | |
42 | // It also must have a static variable of type result_type defined | |
43 | // to represent EOF that is called eof. | |
44 | // | |
45 | /////////////////////////////////////////////////////////////////////////// | |
46 | struct split_functor_input | |
47 | { | |
48 | /////////////////////////////////////////////////////////////////////// | |
49 | template <typename Functor | |
50 | , bool FunctorIsEmpty = is_empty<typename Functor::first_type>::value> | |
51 | class unique; | |
52 | ||
53 | // the unique part of the functor is empty, do not include the functor | |
54 | // as a member at all to avoid unnecessary padding bytes to be included | |
55 | // into the generated structure | |
56 | template <typename Functor> | |
57 | class unique<Functor, true> // : public detail::default_input_policy | |
58 | { | |
59 | protected: | |
60 | typedef typename Functor::first_type functor_type; | |
61 | typedef typename functor_type::result_type result_type; | |
62 | ||
63 | public: | |
64 | typedef result_type value_type; | |
65 | typedef std::ptrdiff_t difference_type; | |
66 | typedef std::ptrdiff_t distance_type; | |
67 | typedef result_type const* pointer; | |
68 | typedef result_type const& reference; | |
69 | ||
70 | protected: | |
71 | unique() {} | |
72 | explicit unique(Functor const&) {} | |
73 | ||
74 | public: | |
75 | void swap(unique&) {} | |
76 | ||
77 | // get the next token | |
78 | template <typename MultiPass> | |
79 | static typename MultiPass::reference get_input(MultiPass& mp) | |
80 | { | |
81 | value_type& curtok = mp.shared()->curtok; | |
82 | using namespace split_functor_input_is_valid_test_; | |
83 | if (!token_is_valid(curtok)) | |
84 | functor_type::get_next(mp, curtok); | |
85 | return curtok; | |
86 | } | |
87 | ||
88 | template <typename MultiPass> | |
89 | static void advance_input(MultiPass& mp) | |
90 | { | |
91 | functor_type::get_next(mp, mp.shared()->curtok); | |
92 | } | |
93 | ||
94 | // test, whether we reached the end of the underlying stream | |
95 | template <typename MultiPass> | |
96 | static bool input_at_eof(MultiPass const& mp) | |
97 | { | |
98 | return mp.shared()->curtok == functor_type::eof; | |
99 | } | |
100 | ||
101 | template <typename MultiPass> | |
102 | static bool input_is_valid(MultiPass const&, value_type const& t) | |
103 | { | |
104 | using namespace split_functor_input_is_valid_test_; | |
105 | return token_is_valid(t); | |
106 | } | |
107 | ||
108 | template <typename MultiPass> | |
109 | static void destroy(MultiPass& mp) | |
110 | { | |
111 | functor_type::destroy(mp); | |
112 | } | |
113 | }; | |
114 | ||
115 | // the unique part of the functor is non-empty | |
116 | template <typename Functor> | |
117 | class unique<Functor, false> : public unique<Functor, true> | |
118 | { | |
119 | protected: | |
120 | typedef typename Functor::first_type functor_type; | |
121 | typedef typename functor_type::result_type result_type; | |
122 | ||
123 | protected: | |
124 | unique() {} | |
125 | explicit unique(Functor const& x) : ftor(x.first) {} | |
126 | ||
127 | void swap(unique& x) | |
128 | { | |
129 | boost::swap(ftor, x.ftor); | |
130 | } | |
131 | ||
132 | public: | |
133 | typedef result_type value_type; | |
134 | typedef std::ptrdiff_t difference_type; | |
135 | typedef std::ptrdiff_t distance_type; | |
136 | typedef result_type const* pointer; | |
137 | typedef result_type const& reference; | |
138 | ||
139 | public: | |
140 | // get the next token | |
141 | template <typename MultiPass> | |
142 | static typename MultiPass::reference get_input(MultiPass& mp) | |
143 | { | |
144 | value_type& curtok = mp.shared()->curtok; | |
145 | using namespace split_functor_input_is_valid_test_; | |
146 | if (!token_is_valid(curtok)) | |
147 | functor_type::get_next(mp, curtok); | |
148 | return curtok; | |
149 | } | |
150 | ||
151 | template <typename MultiPass> | |
152 | static void advance_input(MultiPass& mp) | |
153 | { | |
154 | mp.ftor.get_next(mp, mp.shared()->curtok); | |
155 | } | |
156 | ||
157 | template <typename MultiPass> | |
158 | static bool input_is_valid(MultiPass const&, value_type const& t) | |
159 | { | |
160 | using namespace split_functor_input_is_valid_test_; | |
161 | return token_is_valid(t); | |
162 | } | |
163 | ||
164 | // test, whether we reached the end of the underlying stream | |
165 | template <typename MultiPass> | |
166 | static bool input_at_eof(MultiPass const& mp) | |
167 | { | |
168 | return mp.shared()->curtok == mp.ftor.eof; | |
169 | } | |
170 | ||
171 | typename Functor::first_type& get_functor() const | |
172 | { | |
173 | return ftor; | |
174 | } | |
175 | ||
176 | mutable functor_type ftor; | |
177 | }; | |
178 | ||
179 | /////////////////////////////////////////////////////////////////////// | |
180 | template <typename Functor> | |
181 | struct shared | |
182 | { | |
183 | protected: | |
184 | typedef typename Functor::first_type functor_type; | |
185 | typedef typename functor_type::result_type result_type; | |
186 | ||
187 | public: | |
188 | explicit shared(Functor const& x) : ftor(x.second), curtok(0) {} | |
189 | ||
190 | mutable typename Functor::second_type ftor; | |
191 | result_type curtok; | |
192 | ||
193 | private: | |
194 | // silence MSVC warning C4512: assignment operator could not be generated | |
195 | shared& operator= (shared const&); | |
196 | }; | |
197 | }; | |
198 | ||
199 | }}} | |
200 | ||
201 | #endif |