]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/xpressive/detail/core/state.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / xpressive / detail / core / state.hpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // state.hpp
3 //
4 // Copyright 2008 Eric Niebler. Distributed under the Boost
5 // Software License, Version 1.0. (See accompanying file
6 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
8 #ifndef BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
9 #define BOOST_XPRESSIVE_DETAIL_CORE_STATE_HPP_EAN_10_04_2005
10
11 // MS compatible compilers support #pragma once
12 #if defined(_MSC_VER)
13 # pragma once
14 #endif
15
16 #include <boost/noncopyable.hpp>
17 #include <boost/xpressive/detail/detail_fwd.hpp>
18 #include <boost/xpressive/detail/core/access.hpp>
19 #include <boost/xpressive/detail/core/action.hpp>
20 #include <boost/xpressive/detail/core/sub_match_vector.hpp>
21 #include <boost/xpressive/detail/utility/sequence_stack.hpp>
22 #include <boost/xpressive/detail/core/regex_impl.hpp>
23 #include <boost/xpressive/regex_constants.hpp>
24
25 namespace boost { namespace xpressive { namespace detail
26 {
27
28 ///////////////////////////////////////////////////////////////////////////////
29 // match_context
30 //
31 template<typename BidiIter>
32 struct match_context
33 {
34 typedef typename iterator_value<BidiIter>::type char_type;
35
36 match_context()
37 : results_ptr_(0)
38 , prev_context_(0)
39 , next_ptr_(0)
40 , traits_(0)
41 {
42 }
43
44 // pointer to the current match results, passed to actions as a parameter.
45 match_results<BidiIter> *results_ptr_;
46
47 // The previous match context, if this match_context corresponds to a nested regex invocation
48 match_context<BidiIter> *prev_context_;
49
50 // If this is a nested match, the "next" sub-expression to execute after the nested match
51 matchable<BidiIter> const *next_ptr_;
52
53 // A pointer to the current traits object
54 detail::traits<char_type> const *traits_;
55 };
56
57 ///////////////////////////////////////////////////////////////////////////////
58 // attr_context
59 //
60 struct attr_context
61 {
62 // Slots for holding type-erased pointers to attributes
63 void const **attr_slots_;
64
65 // The previous attr context, if one exists
66 attr_context *prev_attr_context_;
67 };
68
69 ///////////////////////////////////////////////////////////////////////////////
70 // match_flags
71 //
72 struct match_flags
73 {
74 bool match_all_;
75 bool match_prev_avail_;
76 bool match_bol_;
77 bool match_eol_;
78 bool match_not_bow_;
79 bool match_not_eow_;
80 bool match_not_null_;
81 bool match_continuous_;
82 bool match_partial_;
83
84 explicit match_flags(regex_constants::match_flag_type flags)
85 : match_all_(false)
86 , match_prev_avail_(0 != (flags & regex_constants::match_prev_avail))
87 , match_bol_(match_prev_avail_ || 0 == (flags & regex_constants::match_not_bol))
88 , match_eol_(0 == (flags & regex_constants::match_not_eol))
89 , match_not_bow_(!match_prev_avail_ && 0 != (flags & regex_constants::match_not_bow))
90 , match_not_eow_(0 != (flags & regex_constants::match_not_eow))
91 , match_not_null_(0 != (flags & regex_constants::match_not_null))
92 , match_continuous_(0 != (flags & regex_constants::match_continuous))
93 , match_partial_(0 != (flags & regex_constants::match_partial))
94 {
95 }
96 };
97
98 ///////////////////////////////////////////////////////////////////////////////
99 // match_state
100 //
101 template<typename BidiIter>
102 struct match_state
103 : noncopyable
104 {
105 typedef BidiIter iterator;
106 typedef core_access<BidiIter> access;
107 typedef detail::match_context<BidiIter> match_context;
108 typedef detail::results_extras<BidiIter> results_extras;
109 typedef detail::regex_impl<BidiIter> regex_impl;
110 typedef detail::matchable<BidiIter> matchable;
111 typedef xpressive::match_results<BidiIter> match_results;
112 typedef detail::sub_match_impl<BidiIter> sub_match_impl;
113 typedef detail::actionable actionable;
114
115 BidiIter cur_;
116 sub_match_impl *sub_matches_;
117 std::size_t mark_count_;
118 BidiIter begin_;
119 BidiIter end_;
120
121 match_flags flags_;
122 bool found_partial_match_;
123
124 match_context context_;
125 results_extras *extras_;
126 actionable action_list_;
127 actionable const **action_list_tail_;
128 action_args_type *action_args_;
129 attr_context attr_context_;
130 BidiIter next_search_;
131
132 ///////////////////////////////////////////////////////////////////////////////
133 //
134 match_state
135 (
136 BidiIter begin
137 , BidiIter end
138 , match_results &what
139 , regex_impl const &impl
140 , regex_constants::match_flag_type flags
141 )
142 : cur_(begin)
143 , sub_matches_(0)
144 , mark_count_(0)
145 , begin_(begin)
146 , end_(end)
147 , flags_(flags)
148 , found_partial_match_(false)
149 , context_() // zero-initializes the fields of context_
150 , extras_(&core_access<BidiIter>::get_extras(what))
151 , action_list_()
152 , action_list_tail_(&action_list_.next)
153 , action_args_(&core_access<BidiIter>::get_action_args(what))
154 , attr_context_() // zero-initializes the fields of attr_context_
155 , next_search_(begin)
156 {
157 // reclaim any cached memory in the match_results struct
158 this->extras_->sub_match_stack_.unwind();
159
160 // initialize the context_ struct
161 this->init_(impl, what);
162
163 // move all the nested match_results structs into the match_results cache
164 this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
165 }
166
167 ///////////////////////////////////////////////////////////////////////////////
168 // reset
169 void reset(match_results &what, regex_impl const &impl)
170 {
171 this->extras_ = &core_access<BidiIter>::get_extras(what);
172 this->action_list_.next = 0;
173 this->action_list_tail_ = &action_list_.next;
174 this->action_args_ = &core_access<BidiIter>::get_action_args(what);
175 this->attr_context_ = attr_context();
176 this->context_.prev_context_ = 0;
177 this->found_partial_match_ = false;
178 this->extras_->sub_match_stack_.unwind();
179 this->init_(impl, what);
180 this->extras_->results_cache_.reclaim_all(access::get_nested_results(what));
181 }
182
183 ///////////////////////////////////////////////////////////////////////////////
184 // push_context
185 // called to prepare the state object for a regex match
186 match_context push_context(regex_impl const &impl, matchable const &next, match_context &prev)
187 {
188 // save state
189 match_context context = this->context_;
190
191 // create a new nested match_results for this regex
192 nested_results<BidiIter> &nested = access::get_nested_results(*context.results_ptr_);
193 match_results &what = this->extras_->results_cache_.append_new(nested);
194
195 // (re)initialize the match context
196 this->init_(impl, what);
197
198 // create a linked list of match_context structs
199 this->context_.prev_context_ = &prev;
200 this->context_.next_ptr_ = &next;
201
202 // record the start of the zero-th sub-match
203 this->sub_matches_[0].begin_ = this->cur_;
204
205 return context;
206 }
207
208 ///////////////////////////////////////////////////////////////////////////////
209 // pop_context
210 // called after a nested match failed to restore the context
211 bool pop_context(regex_impl const &impl, bool success)
212 {
213 match_context &context = *this->context_.prev_context_;
214 if(!success)
215 {
216 match_results &what = *context.results_ptr_;
217 this->uninit_(impl, what);
218
219 // send the match_results struct back to the cache
220 nested_results<BidiIter> &nested = access::get_nested_results(what);
221 this->extras_->results_cache_.reclaim_last(nested);
222 }
223
224 // restore the state
225 this->context_ = context;
226 match_results &results = *this->context_.results_ptr_;
227 this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
228 this->mark_count_ = results.size();
229 return success;
230 }
231
232 ///////////////////////////////////////////////////////////////////////////////
233 // swap_context
234 void swap_context(match_context &context)
235 {
236 std::swap(this->context_, context);
237 match_results &results = *this->context_.results_ptr_;
238 this->sub_matches_ = access::get_sub_matches(access::get_sub_match_vector(results));
239 this->mark_count_ = results.size();
240 }
241
242 // beginning of buffer
243 bool bos() const
244 {
245 return this->cur_ == this->begin_;
246 }
247
248 // end of buffer
249 bool eos()
250 {
251 return this->cur_ == this->end_ && this->found_partial_match();
252 }
253
254 // is this the regex that is currently executing?
255 bool is_active_regex(regex_impl const &impl) const
256 {
257 return impl.xpr_.get() == this->context_.results_ptr_->regex_id();
258 }
259
260 // fetch the n-th sub_match
261 sub_match_impl &sub_match(int n)
262 {
263 return this->sub_matches_[n];
264 }
265
266 // called when a partial match has succeeded
267 void set_partial_match()
268 {
269 sub_match_impl &sub0 = this->sub_match(0);
270 sub0.first = sub0.begin_;
271 sub0.second = this->end_;
272 sub0.matched = false;
273 }
274
275 template<typename Traits>
276 Traits const &get_traits() const
277 {
278 return static_cast<traits_holder<Traits> const *>(this->context_.traits_)->traits();
279 }
280
281 private:
282
283 void init_(regex_impl const &impl, match_results &what)
284 {
285 regex_id_type const id = impl.xpr_.get();
286 std::size_t const total_mark_count = impl.mark_count_ + impl.hidden_mark_count_ + 1;
287
288 // initialize the context and the sub_match vector
289 this->context_.results_ptr_ = &what;
290 this->context_.traits_ = impl.traits_.get();
291 this->mark_count_ = impl.mark_count_ + 1;
292 this->sub_matches_ = this->extras_->sub_match_stack_.push_sequence(total_mark_count, sub_match_impl(begin_), detail::fill);
293 this->sub_matches_ += impl.hidden_mark_count_;
294
295 // initialize the match_results struct
296 access::init_match_results(what, id, impl.traits_, this->sub_matches_, this->mark_count_, impl.named_marks_);
297 }
298
299 void uninit_(regex_impl const &impl, match_results &)
300 {
301 extras_->sub_match_stack_.unwind_to(this->sub_matches_ - impl.hidden_mark_count_);
302 }
303
304 bool found_partial_match()
305 {
306 this->found_partial_match_ = true;
307 return true;
308 }
309 };
310
311 ///////////////////////////////////////////////////////////////////////////////
312 // memento
313 //
314 template<typename BidiIter>
315 struct memento
316 {
317 sub_match_impl<BidiIter> *old_sub_matches_;
318 std::size_t nested_results_count_;
319 actionable const *action_list_head_;
320 actionable const **action_list_tail_;
321 attr_context attr_context_;
322 };
323
324 ///////////////////////////////////////////////////////////////////////////////
325 // save_sub_matches
326 //
327 template<typename BidiIter>
328 inline memento<BidiIter> save_sub_matches(match_state<BidiIter> &state)
329 {
330 memento<BidiIter> mem =
331 {
332 state.extras_->sub_match_stack_.push_sequence(state.mark_count_, sub_match_impl<BidiIter>(state.begin_))
333 , state.context_.results_ptr_->nested_results().size()
334 , state.action_list_.next
335 , state.action_list_tail_
336 , state.attr_context_
337 };
338 state.action_list_.next = 0;
339 state.action_list_tail_ = &state.action_list_.next;
340 std::copy(state.sub_matches_, state.sub_matches_ + state.mark_count_, mem.old_sub_matches_);
341 return mem;
342 }
343
344 ///////////////////////////////////////////////////////////////////////////////
345 // restore_action_queue
346 //
347 template<typename BidiIter>
348 inline void restore_action_queue(memento<BidiIter> const &mem, match_state<BidiIter> &state)
349 {
350 state.action_list_.next = mem.action_list_head_;
351 state.action_list_tail_ = mem.action_list_tail_;
352 *state.action_list_tail_ = 0;
353 }
354
355 ///////////////////////////////////////////////////////////////////////////////
356 // restore_sub_matches
357 //
358 template<typename BidiIter>
359 inline void restore_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state)
360 {
361 typedef core_access<BidiIter> access;
362 nested_results<BidiIter> &nested = access::get_nested_results(*state.context_.results_ptr_);
363 std::size_t count = nested.size() - mem.nested_results_count_;
364 state.extras_->results_cache_.reclaim_last_n(nested, count);
365 std::copy(mem.old_sub_matches_, mem.old_sub_matches_ + state.mark_count_, state.sub_matches_);
366 state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
367 state.attr_context_ = mem.attr_context_;
368 }
369
370 ///////////////////////////////////////////////////////////////////////////////
371 // reclaim_sub_matches
372 //
373 template<typename BidiIter>
374 inline void reclaim_sub_matches(memento<BidiIter> const &mem, match_state<BidiIter> &state, bool success)
375 {
376 std::size_t count = state.context_.results_ptr_->nested_results().size() - mem.nested_results_count_;
377 if(count == 0)
378 {
379 state.extras_->sub_match_stack_.unwind_to(mem.old_sub_matches_);
380 }
381 // else we have we must orphan this block of backrefs because we are using the stack
382 // space above it.
383
384 if(!success)
385 {
386 state.attr_context_ = mem.attr_context_;
387 }
388 }
389
390 ///////////////////////////////////////////////////////////////////////////////
391 // traits_cast
392 //
393 template<typename Traits, typename BidiIter>
394 inline Traits const &traits_cast(match_state<BidiIter> const &state)
395 {
396 return state.template get_traits<Traits>();
397 }
398
399 }}} // namespace boost::xpressive::detail
400
401 #endif