]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/xpressive/include/boost/xpressive/detail/core/state.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / xpressive / include / boost / xpressive / detail / core / state.hpp
CommitLineData
7c673cae
FG
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
25namespace boost { namespace xpressive { namespace detail
26{
27
28///////////////////////////////////////////////////////////////////////////////
29// match_context
30//
31template<typename BidiIter>
32struct 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//
60struct 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//
72struct 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//
101template<typename BidiIter>
102struct 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
281private:
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//
314template<typename BidiIter>
315struct 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//
327template<typename BidiIter>
328inline 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//
347template<typename BidiIter>
348inline 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//
358template<typename BidiIter>
359inline 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//
373template<typename BidiIter>
374inline 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//
393template<typename Traits, typename BidiIter>
394inline 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