]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/regex/include/boost/regex/v4/perl_matcher_non_recursive.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / regex / include / boost / regex / v4 / perl_matcher_non_recursive.hpp
1 /*
2 *
3 * Copyright (c) 2002
4 * John Maddock
5 *
6 * Use, modification and distribution are subject to the
7 * Boost Software License, Version 1.0. (See accompanying file
8 * LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 *
10 */
11
12 /*
13 * LOCATION: see http://www.boost.org for most recent version.
14 * FILE perl_matcher_common.cpp
15 * VERSION see <boost/version.hpp>
16 * DESCRIPTION: Definitions of perl_matcher member functions that are
17 * specific to the non-recursive implementation.
18 */
19
20 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
21 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
22
23 #include <new>
24
25 #ifdef BOOST_MSVC
26 #pragma warning(push)
27 #pragma warning(disable: 4103)
28 #endif
29 #ifdef BOOST_HAS_ABI_HEADERS
30 # include BOOST_ABI_PREFIX
31 #endif
32 #ifdef BOOST_MSVC
33 #pragma warning(pop)
34 #endif
35 #ifdef BOOST_MSVC
36 # pragma warning(push)
37 # pragma warning(disable: 4800 4706)
38 #endif
39
40 namespace boost{
41 namespace BOOST_REGEX_DETAIL_NS{
42
43 template <class T>
44 inline void inplace_destroy(T* p)
45 {
46 (void)p; // warning suppression
47 p->~T();
48 }
49
50 struct saved_state
51 {
52 union{
53 unsigned int state_id;
54 // this padding ensures correct alignment on 64-bit platforms:
55 std::size_t padding1;
56 std::ptrdiff_t padding2;
57 void* padding3;
58 };
59 saved_state(unsigned i) : state_id(i) {}
60 };
61
62 template <class BidiIterator>
63 struct saved_matched_paren : public saved_state
64 {
65 int index;
66 sub_match<BidiIterator> sub;
67 saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){};
68 };
69
70 template <class BidiIterator>
71 struct saved_position : public saved_state
72 {
73 const re_syntax_base* pstate;
74 BidiIterator position;
75 saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){};
76 };
77
78 template <class BidiIterator>
79 struct saved_assertion : public saved_position<BidiIterator>
80 {
81 bool positive;
82 saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
83 : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){};
84 };
85
86 template <class BidiIterator>
87 struct saved_repeater : public saved_state
88 {
89 repeater_count<BidiIterator> count;
90 saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
91 : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
92 };
93
94 struct saved_extra_block : public saved_state
95 {
96 saved_state *base, *end;
97 saved_extra_block(saved_state* b, saved_state* e)
98 : saved_state(saved_state_extra_block), base(b), end(e) {}
99 };
100
101 struct save_state_init
102 {
103 saved_state** stack;
104 save_state_init(saved_state** base, saved_state** end)
105 : stack(base)
106 {
107 *base = static_cast<saved_state*>(get_mem_block());
108 *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
109 --(*end);
110 (void) new (*end)saved_state(0);
111 BOOST_ASSERT(*end > *base);
112 }
113 ~save_state_init()
114 {
115 put_mem_block(*stack);
116 *stack = 0;
117 }
118 };
119
120 template <class BidiIterator>
121 struct saved_single_repeat : public saved_state
122 {
123 std::size_t count;
124 const re_repeat* rep;
125 BidiIterator last_position;
126 saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
127 : saved_state(arg_id), count(c), rep(r), last_position(lp){}
128 };
129
130 template <class Results>
131 struct saved_recursion : public saved_state
132 {
133 saved_recursion(int idx, const re_syntax_base* p, Results* pr)
134 : saved_state(14), recursion_id(idx), preturn_address(p), results(*pr)
135 {}
136 int recursion_id;
137 const re_syntax_base* preturn_address;
138 Results results;
139 };
140
141 struct saved_change_case : public saved_state
142 {
143 bool icase;
144 saved_change_case(bool c) : saved_state(18), icase(c) {}
145 };
146
147 template <class BidiIterator, class Allocator, class traits>
148 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
149 {
150 static matcher_proc_type const s_match_vtable[34] =
151 {
152 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
153 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
154 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
155 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
156 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
157 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
158 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
159 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
160 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
161 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
162 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
163 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
164 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
165 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
166 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
167 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
168 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
169 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
170 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
171 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
172 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
173 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
174 // Although this next line *should* be evaluated at compile time, in practice
175 // some compilers (VC++) emit run-time initialisation which breaks thread
176 // safety, so use a dispatch function instead:
177 //(::boost::is_random_access_iterator<BidiIterator>::value ? &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast : &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow),
178 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
179 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
180 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
181 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
182 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
183 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
184 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
185 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
186 &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
187 &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
188 &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
189 &perl_matcher<BidiIterator, Allocator, traits>::match_then,
190 };
191
192 push_recursion_stopper();
193 do{
194 while(pstate)
195 {
196 matcher_proc_type proc = s_match_vtable[pstate->type];
197 ++state_count;
198 if(!(this->*proc)())
199 {
200 if(state_count > max_state_count)
201 raise_error(traits_inst, regex_constants::error_complexity);
202 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
203 m_has_partial_match = true;
204 bool successful_unwind = unwind(false);
205 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
206 m_has_partial_match = true;
207 if(false == successful_unwind)
208 return m_recursive_result;
209 }
210 }
211 }while(unwind(true));
212 return m_recursive_result;
213 }
214
215 template <class BidiIterator, class Allocator, class traits>
216 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
217 {
218 if(used_block_count)
219 {
220 --used_block_count;
221 saved_state* stack_base;
222 saved_state* backup_state;
223 stack_base = static_cast<saved_state*>(get_mem_block());
224 backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
225 saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
226 --block;
227 (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
228 m_stack_base = stack_base;
229 m_backup_state = block;
230 }
231 else
232 raise_error(traits_inst, regex_constants::error_stack);
233 }
234
235 template <class BidiIterator, class Allocator, class traits>
236 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
237 {
238 //BOOST_ASSERT(index);
239 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
240 --pmp;
241 if(pmp < m_stack_base)
242 {
243 extend_stack();
244 pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
245 --pmp;
246 }
247 (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
248 m_backup_state = pmp;
249 }
250
251 template <class BidiIterator, class Allocator, class traits>
252 inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
253 {
254 //BOOST_ASSERT(index);
255 saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
256 --pmp;
257 if(pmp < m_stack_base)
258 {
259 extend_stack();
260 pmp = static_cast<saved_change_case*>(m_backup_state);
261 --pmp;
262 }
263 (void) new (pmp)saved_change_case(c);
264 m_backup_state = pmp;
265 }
266
267 template <class BidiIterator, class Allocator, class traits>
268 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
269 {
270 saved_state* pmp = m_backup_state;
271 --pmp;
272 if(pmp < m_stack_base)
273 {
274 extend_stack();
275 pmp = m_backup_state;
276 --pmp;
277 }
278 (void) new (pmp)saved_state(saved_type_recurse);
279 m_backup_state = pmp;
280 }
281
282 template <class BidiIterator, class Allocator, class traits>
283 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
284 {
285 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
286 --pmp;
287 if(pmp < m_stack_base)
288 {
289 extend_stack();
290 pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
291 --pmp;
292 }
293 (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
294 m_backup_state = pmp;
295 }
296
297 template <class BidiIterator, class Allocator, class traits>
298 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
299 {
300 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
301 --pmp;
302 if(pmp < m_stack_base)
303 {
304 extend_stack();
305 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
306 --pmp;
307 }
308 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
309 m_backup_state = pmp;
310 }
311
312 template <class BidiIterator, class Allocator, class traits>
313 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
314 {
315 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
316 --pmp;
317 if(pmp < m_stack_base)
318 {
319 extend_stack();
320 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
321 --pmp;
322 }
323 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
324 m_backup_state = pmp;
325 }
326
327 template <class BidiIterator, class Allocator, class traits>
328 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
329 {
330 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
331 --pmp;
332 if(pmp < m_stack_base)
333 {
334 extend_stack();
335 pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
336 --pmp;
337 }
338 (void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.size() ? this->recursion_stack.back().idx : (INT_MIN + 3));
339 m_backup_state = pmp;
340 }
341
342 template <class BidiIterator, class Allocator, class traits>
343 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
344 {
345 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
346 --pmp;
347 if(pmp < m_stack_base)
348 {
349 extend_stack();
350 pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
351 --pmp;
352 }
353 (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
354 m_backup_state = pmp;
355 }
356
357 template <class BidiIterator, class Allocator, class traits>
358 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults)
359 {
360 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
361 --pmp;
362 if(pmp < m_stack_base)
363 {
364 extend_stack();
365 pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
366 --pmp;
367 }
368 (void) new (pmp)saved_recursion<results_type>(idx, p, presults);
369 m_backup_state = pmp;
370 }
371
372 template <class BidiIterator, class Allocator, class traits>
373 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
374 {
375 // change our case sensitivity:
376 push_case_change(this->icase);
377 this->icase = static_cast<const re_case*>(pstate)->icase;
378 pstate = pstate->next.p;
379 return true;
380 }
381
382 template <class BidiIterator, class Allocator, class traits>
383 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
384 {
385 int index = static_cast<const re_brace*>(pstate)->index;
386 icase = static_cast<const re_brace*>(pstate)->icase;
387 switch(index)
388 {
389 case 0:
390 pstate = pstate->next.p;
391 break;
392 case -1:
393 case -2:
394 {
395 // forward lookahead assert:
396 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
397 pstate = pstate->next.p->next.p;
398 push_assertion(next_pstate, index == -1);
399 break;
400 }
401 case -3:
402 {
403 // independent sub-expression, currently this is always recursive:
404 bool old_independent = m_independent;
405 m_independent = true;
406 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
407 pstate = pstate->next.p->next.p;
408 bool r = match_all_states();
409 if(!r && !m_independent)
410 {
411 // Must be unwinding from a COMMIT/SKIP/PRUNE and the independent
412 // sub failed, need to unwind everything else:
413 while(unwind(false));
414 return false;
415 }
416 pstate = next_pstate;
417 m_independent = old_independent;
418 #ifdef BOOST_REGEX_MATCH_EXTRA
419 if(r && (m_match_flags & match_extra))
420 {
421 //
422 // our captures have been stored in *m_presult
423 // we need to unpack them, and insert them
424 // back in the right order when we unwind the stack:
425 //
426 match_results<BidiIterator, Allocator> temp_match(*m_presult);
427 unsigned i;
428 for(i = 0; i < temp_match.size(); ++i)
429 (*m_presult)[i].get_captures().clear();
430 // match everything else:
431 r = match_all_states();
432 // now place the stored captures back:
433 for(i = 0; i < temp_match.size(); ++i)
434 {
435 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
436 seq& s1 = (*m_presult)[i].get_captures();
437 const seq& s2 = temp_match[i].captures();
438 s1.insert(
439 s1.end(),
440 s2.begin(),
441 s2.end());
442 }
443 }
444 #endif
445 return r;
446 }
447 case -4:
448 {
449 // conditional expression:
450 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
451 BOOST_ASSERT(alt->type == syntax_element_alt);
452 pstate = alt->next.p;
453 if(pstate->type == syntax_element_assert_backref)
454 {
455 if(!match_assert_backref())
456 pstate = alt->alt.p;
457 break;
458 }
459 else
460 {
461 // zero width assertion, have to match this recursively:
462 BOOST_ASSERT(pstate->type == syntax_element_startmark);
463 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
464 BidiIterator saved_position = position;
465 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
466 pstate = pstate->next.p->next.p;
467 bool r = match_all_states();
468 position = saved_position;
469 if(negated)
470 r = !r;
471 if(r)
472 pstate = next_pstate;
473 else
474 pstate = alt->alt.p;
475 break;
476 }
477 }
478 case -5:
479 {
480 push_matched_paren(0, (*m_presult)[0]);
481 m_presult->set_first(position, 0, true);
482 pstate = pstate->next.p;
483 break;
484 }
485 default:
486 {
487 BOOST_ASSERT(index > 0);
488 if((m_match_flags & match_nosubs) == 0)
489 {
490 push_matched_paren(index, (*m_presult)[index]);
491 m_presult->set_first(position, index);
492 }
493 pstate = pstate->next.p;
494 break;
495 }
496 }
497 return true;
498 }
499
500 template <class BidiIterator, class Allocator, class traits>
501 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
502 {
503 bool take_first, take_second;
504 const re_alt* jmp = static_cast<const re_alt*>(pstate);
505
506 // find out which of these two alternatives we need to take:
507 if(position == last)
508 {
509 take_first = jmp->can_be_null & mask_take;
510 take_second = jmp->can_be_null & mask_skip;
511 }
512 else
513 {
514 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
515 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
516 }
517
518 if(take_first)
519 {
520 // we can take the first alternative,
521 // see if we need to push next alternative:
522 if(take_second)
523 {
524 push_alt(jmp->alt.p);
525 }
526 pstate = pstate->next.p;
527 return true;
528 }
529 if(take_second)
530 {
531 pstate = jmp->alt.p;
532 return true;
533 }
534 return false; // neither option is possible
535 }
536
537 template <class BidiIterator, class Allocator, class traits>
538 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
539 {
540 #ifdef BOOST_MSVC
541 #pragma warning(push)
542 #pragma warning(disable:4127 4244)
543 #endif
544 #ifdef __BORLANDC__
545 #pragma option push -w-8008 -w-8066 -w-8004
546 #endif
547 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
548
549 // find out which of these two alternatives we need to take:
550 bool take_first, take_second;
551 if(position == last)
552 {
553 take_first = rep->can_be_null & mask_take;
554 take_second = rep->can_be_null & mask_skip;
555 }
556 else
557 {
558 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
559 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
560 }
561
562 if((m_backup_state->state_id != saved_state_repeater_count)
563 || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
564 || (next_count->get_id() != rep->state_id))
565 {
566 // we're moving to a different repeat from the last
567 // one, so set up a counter object:
568 push_repeater_count(rep->state_id, &next_count);
569 }
570 //
571 // If we've had at least one repeat already, and the last one
572 // matched the NULL string then set the repeat count to
573 // maximum:
574 //
575 next_count->check_null_repeat(position, rep->max);
576
577 if(next_count->get_count() < rep->min)
578 {
579 // we must take the repeat:
580 if(take_first)
581 {
582 // increase the counter:
583 ++(*next_count);
584 pstate = rep->next.p;
585 return true;
586 }
587 return false;
588 }
589
590 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
591 if(greedy)
592 {
593 // try and take the repeat if we can:
594 if((next_count->get_count() < rep->max) && take_first)
595 {
596 if(take_second)
597 {
598 // store position in case we fail:
599 push_alt(rep->alt.p);
600 }
601 // increase the counter:
602 ++(*next_count);
603 pstate = rep->next.p;
604 return true;
605 }
606 else if(take_second)
607 {
608 pstate = rep->alt.p;
609 return true;
610 }
611 return false; // can't take anything, fail...
612 }
613 else // non-greedy
614 {
615 // try and skip the repeat if we can:
616 if(take_second)
617 {
618 if((next_count->get_count() < rep->max) && take_first)
619 {
620 // store position in case we fail:
621 push_non_greedy_repeat(rep->next.p);
622 }
623 pstate = rep->alt.p;
624 return true;
625 }
626 if((next_count->get_count() < rep->max) && take_first)
627 {
628 // increase the counter:
629 ++(*next_count);
630 pstate = rep->next.p;
631 return true;
632 }
633 }
634 return false;
635 #ifdef __BORLANDC__
636 #pragma option pop
637 #endif
638 #ifdef BOOST_MSVC
639 #pragma warning(pop)
640 #endif
641 }
642
643 template <class BidiIterator, class Allocator, class traits>
644 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
645 {
646 unsigned count = 0;
647 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
648 re_syntax_base* psingle = rep->next.p;
649 // match compulsary repeats first:
650 while(count < rep->min)
651 {
652 pstate = psingle;
653 if(!match_wild())
654 return false;
655 ++count;
656 }
657 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
658 if(greedy)
659 {
660 // repeat for as long as we can:
661 while(count < rep->max)
662 {
663 pstate = psingle;
664 if(!match_wild())
665 break;
666 ++count;
667 }
668 // remember where we got to if this is a leading repeat:
669 if((rep->leading) && (count < rep->max))
670 restart = position;
671 // push backtrack info if available:
672 if(count - rep->min)
673 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
674 // jump to next state:
675 pstate = rep->alt.p;
676 return true;
677 }
678 else
679 {
680 // non-greedy, push state and return true if we can skip:
681 if(count < rep->max)
682 push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
683 pstate = rep->alt.p;
684 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
685 }
686 }
687
688 template <class BidiIterator, class Allocator, class traits>
689 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
690 {
691 if(m_match_flags & match_not_dot_null)
692 return match_dot_repeat_slow();
693 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
694 return match_dot_repeat_slow();
695
696 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
697 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
698 unsigned count = static_cast<unsigned>((std::min)(static_cast<unsigned>(::boost::BOOST_REGEX_DETAIL_NS::distance(position, last)), static_cast<unsigned>(greedy ? rep->max : rep->min)));
699 if(rep->min > count)
700 {
701 position = last;
702 return false; // not enough text left to match
703 }
704 std::advance(position, count);
705
706 if(greedy)
707 {
708 if((rep->leading) && (count < rep->max))
709 restart = position;
710 // push backtrack info if available:
711 if(count - rep->min)
712 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
713 // jump to next state:
714 pstate = rep->alt.p;
715 return true;
716 }
717 else
718 {
719 // non-greedy, push state and return true if we can skip:
720 if(count < rep->max)
721 push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
722 pstate = rep->alt.p;
723 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
724 }
725 }
726
727 template <class BidiIterator, class Allocator, class traits>
728 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
729 {
730 #ifdef BOOST_MSVC
731 #pragma warning(push)
732 #pragma warning(disable:4127)
733 #endif
734 #ifdef __BORLANDC__
735 #pragma option push -w-8008 -w-8066 -w-8004
736 #endif
737 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
738 BOOST_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
739 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
740 std::size_t count = 0;
741 //
742 // start by working out how much we can skip:
743 //
744 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
745 std::size_t desired = greedy ? rep->max : rep->min;
746 if(::boost::is_random_access_iterator<BidiIterator>::value)
747 {
748 BidiIterator end = position;
749 // Move end forward by "desired", preferably without using distance or advance if we can
750 // as these can be slow for some iterator types.
751 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
752 if(desired >= len)
753 end = last;
754 else
755 std::advance(end, desired);
756 BidiIterator origin(position);
757 while((position != end) && (traits_inst.translate(*position, icase) == what))
758 {
759 ++position;
760 }
761 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
762 }
763 else
764 {
765 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
766 {
767 ++position;
768 ++count;
769 }
770 }
771
772 if(count < rep->min)
773 return false;
774
775 if(greedy)
776 {
777 if((rep->leading) && (count < rep->max))
778 restart = position;
779 // push backtrack info if available:
780 if(count - rep->min)
781 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
782 // jump to next state:
783 pstate = rep->alt.p;
784 return true;
785 }
786 else
787 {
788 // non-greedy, push state and return true if we can skip:
789 if(count < rep->max)
790 push_single_repeat(count, rep, position, saved_state_rep_char);
791 pstate = rep->alt.p;
792 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
793 }
794 #ifdef __BORLANDC__
795 #pragma option pop
796 #endif
797 #ifdef BOOST_MSVC
798 #pragma warning(pop)
799 #endif
800 }
801
802 template <class BidiIterator, class Allocator, class traits>
803 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
804 {
805 #ifdef BOOST_MSVC
806 #pragma warning(push)
807 #pragma warning(disable:4127)
808 #endif
809 #ifdef __BORLANDC__
810 #pragma option push -w-8008 -w-8066 -w-8004
811 #endif
812 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
813 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
814 std::size_t count = 0;
815 //
816 // start by working out how much we can skip:
817 //
818 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
819 std::size_t desired = greedy ? rep->max : rep->min;
820 if(::boost::is_random_access_iterator<BidiIterator>::value)
821 {
822 BidiIterator end = position;
823 // Move end forward by "desired", preferably without using distance or advance if we can
824 // as these can be slow for some iterator types.
825 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
826 if(desired >= len)
827 end = last;
828 else
829 std::advance(end, desired);
830 BidiIterator origin(position);
831 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
832 {
833 ++position;
834 }
835 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
836 }
837 else
838 {
839 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
840 {
841 ++position;
842 ++count;
843 }
844 }
845
846 if(count < rep->min)
847 return false;
848
849 if(greedy)
850 {
851 if((rep->leading) && (count < rep->max))
852 restart = position;
853 // push backtrack info if available:
854 if(count - rep->min)
855 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
856 // jump to next state:
857 pstate = rep->alt.p;
858 return true;
859 }
860 else
861 {
862 // non-greedy, push state and return true if we can skip:
863 if(count < rep->max)
864 push_single_repeat(count, rep, position, saved_state_rep_short_set);
865 pstate = rep->alt.p;
866 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
867 }
868 #ifdef __BORLANDC__
869 #pragma option pop
870 #endif
871 #ifdef BOOST_MSVC
872 #pragma warning(pop)
873 #endif
874 }
875
876 template <class BidiIterator, class Allocator, class traits>
877 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
878 {
879 #ifdef BOOST_MSVC
880 #pragma warning(push)
881 #pragma warning(disable:4127)
882 #endif
883 #ifdef __BORLANDC__
884 #pragma option push -w-8008 -w-8066 -w-8004
885 #endif
886 typedef typename traits::char_class_type m_type;
887 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
888 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
889 std::size_t count = 0;
890 //
891 // start by working out how much we can skip:
892 //
893 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
894 std::size_t desired = greedy ? rep->max : rep->min;
895 if(::boost::is_random_access_iterator<BidiIterator>::value)
896 {
897 BidiIterator end = position;
898 // Move end forward by "desired", preferably without using distance or advance if we can
899 // as these can be slow for some iterator types.
900 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
901 if(desired >= len)
902 end = last;
903 else
904 std::advance(end, desired);
905 BidiIterator origin(position);
906 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
907 {
908 ++position;
909 }
910 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
911 }
912 else
913 {
914 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
915 {
916 ++position;
917 ++count;
918 }
919 }
920
921 if(count < rep->min)
922 return false;
923
924 if(greedy)
925 {
926 if((rep->leading) && (count < rep->max))
927 restart = position;
928 // push backtrack info if available:
929 if(count - rep->min)
930 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
931 // jump to next state:
932 pstate = rep->alt.p;
933 return true;
934 }
935 else
936 {
937 // non-greedy, push state and return true if we can skip:
938 if(count < rep->max)
939 push_single_repeat(count, rep, position, saved_state_rep_long_set);
940 pstate = rep->alt.p;
941 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
942 }
943 #ifdef __BORLANDC__
944 #pragma option pop
945 #endif
946 #ifdef BOOST_MSVC
947 #pragma warning(pop)
948 #endif
949 }
950
951 template <class BidiIterator, class Allocator, class traits>
952 bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
953 {
954 BOOST_ASSERT(pstate->type == syntax_element_recurse);
955 //
956 // Backup call stack:
957 //
958 push_recursion_pop();
959 //
960 // Set new call stack:
961 //
962 if(recursion_stack.capacity() == 0)
963 {
964 recursion_stack.reserve(50);
965 }
966 recursion_stack.push_back(recursion_info<results_type>());
967 recursion_stack.back().preturn_address = pstate->next.p;
968 recursion_stack.back().results = *m_presult;
969 pstate = static_cast<const re_jump*>(pstate)->alt.p;
970 recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
971 //if(static_cast<const re_recurse*>(pstate)->state_id > 0)
972 {
973 push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);
974 }
975
976 return true;
977 }
978
979 template <class BidiIterator, class Allocator, class traits>
980 bool perl_matcher<BidiIterator, Allocator, traits>::match_endmark()
981 {
982 int index = static_cast<const re_brace*>(pstate)->index;
983 icase = static_cast<const re_brace*>(pstate)->icase;
984 if(index > 0)
985 {
986 if((m_match_flags & match_nosubs) == 0)
987 {
988 m_presult->set_second(position, index);
989 }
990 if(!recursion_stack.empty())
991 {
992 if(index == recursion_stack.back().idx)
993 {
994 pstate = recursion_stack.back().preturn_address;
995 *m_presult = recursion_stack.back().results;
996 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
997 recursion_stack.pop_back();
998 push_repeater_count(-(2 + index), &next_count);
999 }
1000 }
1001 }
1002 else if((index < 0) && (index != -4))
1003 {
1004 // matched forward lookahead:
1005 pstate = 0;
1006 return true;
1007 }
1008 pstate = pstate->next.p;
1009 return true;
1010 }
1011
1012 template <class BidiIterator, class Allocator, class traits>
1013 bool perl_matcher<BidiIterator, Allocator, traits>::match_match()
1014 {
1015 if(!recursion_stack.empty())
1016 {
1017 BOOST_ASSERT(0 == recursion_stack.back().idx);
1018 pstate = recursion_stack.back().preturn_address;
1019 *m_presult = recursion_stack.back().results;
1020 push_recursion(recursion_stack.back().idx, recursion_stack.back().preturn_address, &recursion_stack.back().results);
1021 recursion_stack.pop_back();
1022 return true;
1023 }
1024 if((m_match_flags & match_not_null) && (position == (*m_presult)[0].first))
1025 return false;
1026 if((m_match_flags & match_all) && (position != last))
1027 return false;
1028 if((m_match_flags & regex_constants::match_not_initial_null) && (position == search_base))
1029 return false;
1030 m_presult->set_second(position);
1031 pstate = 0;
1032 m_has_found_match = true;
1033 if((m_match_flags & match_posix) == match_posix)
1034 {
1035 m_result.maybe_assign(*m_presult);
1036 if((m_match_flags & match_any) == 0)
1037 return false;
1038 }
1039 #ifdef BOOST_REGEX_MATCH_EXTRA
1040 if(match_extra & m_match_flags)
1041 {
1042 for(unsigned i = 0; i < m_presult->size(); ++i)
1043 if((*m_presult)[i].matched)
1044 ((*m_presult)[i]).get_captures().push_back((*m_presult)[i]);
1045 }
1046 #endif
1047 return true;
1048 }
1049
1050 template <class BidiIterator, class Allocator, class traits>
1051 bool perl_matcher<BidiIterator, Allocator, traits>::match_commit()
1052 {
1053 // Ideally we would just junk all the states that are on the stack,
1054 // however we might not unwind correctly in that case, so for now,
1055 // just mark that we don't backtrack into whatever is left (or rather
1056 // we'll unwind it unconditionally without pausing to try other matches).
1057
1058 switch(static_cast<const re_commit*>(pstate)->action)
1059 {
1060 case commit_commit:
1061 restart = last;
1062 break;
1063 case commit_skip:
1064 if(base != position)
1065 {
1066 restart = position;
1067 // Have to decrement restart since it will get incremented again later:
1068 --restart;
1069 }
1070 break;
1071 case commit_prune:
1072 break;
1073 }
1074
1075 saved_state* pmp = m_backup_state;
1076 --pmp;
1077 if(pmp < m_stack_base)
1078 {
1079 extend_stack();
1080 pmp = m_backup_state;
1081 --pmp;
1082 }
1083 (void) new (pmp)saved_state(16);
1084 m_backup_state = pmp;
1085 pstate = pstate->next.p;
1086 return true;
1087 }
1088
1089 template <class BidiIterator, class Allocator, class traits>
1090 bool perl_matcher<BidiIterator, Allocator, traits>::match_then()
1091 {
1092 // Just leave a mark that we need to skip to next alternative:
1093 saved_state* pmp = m_backup_state;
1094 --pmp;
1095 if(pmp < m_stack_base)
1096 {
1097 extend_stack();
1098 pmp = m_backup_state;
1099 --pmp;
1100 }
1101 (void) new (pmp)saved_state(17);
1102 m_backup_state = pmp;
1103 pstate = pstate->next.p;
1104 return true;
1105 }
1106
1107 template <class BidiIterator, class Allocator, class traits>
1108 bool perl_matcher<BidiIterator, Allocator, traits>::skip_until_paren(int index, bool have_match)
1109 {
1110 while(pstate)
1111 {
1112 if(pstate->type == syntax_element_endmark)
1113 {
1114 if(static_cast<const re_brace*>(pstate)->index == index)
1115 {
1116 if(have_match)
1117 return this->match_endmark();
1118 pstate = pstate->next.p;
1119 return true;
1120 }
1121 else
1122 {
1123 // Unenclosed closing ), occurs when (*ACCEPT) is inside some other
1124 // parenthesis which may or may not have other side effects associated with it.
1125 match_endmark();
1126 if(!pstate)
1127 {
1128 unwind(true);
1129 }
1130 }
1131 continue;
1132 }
1133 else if(pstate->type == syntax_element_match)
1134 return true;
1135 else if(pstate->type == syntax_element_startmark)
1136 {
1137 int idx = static_cast<const re_brace*>(pstate)->index;
1138 pstate = pstate->next.p;
1139 skip_until_paren(idx, false);
1140 continue;
1141 }
1142 pstate = pstate->next.p;
1143 }
1144 return true;
1145 }
1146
1147 /****************************************************************************
1148
1149 Unwind and associated proceedures follow, these perform what normal stack
1150 unwinding does in the recursive implementation.
1151
1152 ****************************************************************************/
1153
1154 template <class BidiIterator, class Allocator, class traits>
1155 bool perl_matcher<BidiIterator, Allocator, traits>::unwind(bool have_match)
1156 {
1157 static unwind_proc_type const s_unwind_table[19] =
1158 {
1159 &perl_matcher<BidiIterator, Allocator, traits>::unwind_end,
1160 &perl_matcher<BidiIterator, Allocator, traits>::unwind_paren,
1161 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper,
1162 &perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion,
1163 &perl_matcher<BidiIterator, Allocator, traits>::unwind_alt,
1164 &perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter,
1165 &perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block,
1166 &perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat,
1167 &perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat,
1168 &perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat,
1169 &perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat,
1170 &perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat,
1171 &perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat,
1172 &perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat,
1173 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion,
1174 &perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop,
1175 &perl_matcher<BidiIterator, Allocator, traits>::unwind_commit,
1176 &perl_matcher<BidiIterator, Allocator, traits>::unwind_then,
1177 &perl_matcher<BidiIterator, Allocator, traits>::unwind_case,
1178 };
1179
1180 m_recursive_result = have_match;
1181 m_unwound_lookahead = false;
1182 m_unwound_alt = false;
1183 unwind_proc_type unwinder;
1184 bool cont;
1185 //
1186 // keep unwinding our stack until we have something to do:
1187 //
1188 do
1189 {
1190 unwinder = s_unwind_table[m_backup_state->state_id];
1191 cont = (this->*unwinder)(m_recursive_result);
1192 }while(cont);
1193 //
1194 // return true if we have more states to try:
1195 //
1196 return pstate ? true : false;
1197 }
1198
1199 template <class BidiIterator, class Allocator, class traits>
1200 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_end(bool)
1201 {
1202 pstate = 0; // nothing left to search
1203 return false; // end of stack nothing more to search
1204 }
1205
1206 template <class BidiIterator, class Allocator, class traits>
1207 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_case(bool)
1208 {
1209 saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
1210 icase = pmp->icase;
1211 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1212 m_backup_state = pmp;
1213 return true;
1214 }
1215
1216 template <class BidiIterator, class Allocator, class traits>
1217 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_paren(bool have_match)
1218 {
1219 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
1220 // restore previous values if no match was found:
1221 if(have_match == false)
1222 {
1223 m_presult->set_first(pmp->sub.first, pmp->index, pmp->index == 0);
1224 m_presult->set_second(pmp->sub.second, pmp->index, pmp->sub.matched, pmp->index == 0);
1225 }
1226 #ifdef BOOST_REGEX_MATCH_EXTRA
1227 //
1228 // we have a match, push the capture information onto the stack:
1229 //
1230 else if(pmp->sub.matched && (match_extra & m_match_flags))
1231 ((*m_presult)[pmp->index]).get_captures().push_back(pmp->sub);
1232 #endif
1233 // unwind stack:
1234 m_backup_state = pmp+1;
1235 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1236 return true; // keep looking
1237 }
1238
1239 template <class BidiIterator, class Allocator, class traits>
1240 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_stopper(bool)
1241 {
1242 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1243 pstate = 0; // nothing left to search
1244 return false; // end of stack nothing more to search
1245 }
1246
1247 template <class BidiIterator, class Allocator, class traits>
1248 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_assertion(bool r)
1249 {
1250 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
1251 pstate = pmp->pstate;
1252 position = pmp->position;
1253 bool result = (r == pmp->positive);
1254 m_recursive_result = pmp->positive ? r : !r;
1255 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1256 m_backup_state = pmp;
1257 m_unwound_lookahead = true;
1258 return !result; // return false if the assertion was matched to stop search.
1259 }
1260
1261 template <class BidiIterator, class Allocator, class traits>
1262 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_alt(bool r)
1263 {
1264 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1265 if(!r)
1266 {
1267 pstate = pmp->pstate;
1268 position = pmp->position;
1269 }
1270 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1271 m_backup_state = pmp;
1272 m_unwound_alt = !r;
1273 return r;
1274 }
1275
1276 template <class BidiIterator, class Allocator, class traits>
1277 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_repeater_counter(bool)
1278 {
1279 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
1280 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1281 m_backup_state = pmp;
1282 return true; // keep looking
1283 }
1284
1285 template <class BidiIterator, class Allocator, class traits>
1286 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_extra_block(bool)
1287 {
1288 saved_extra_block* pmp = static_cast<saved_extra_block*>(m_backup_state);
1289 void* condemmed = m_stack_base;
1290 m_stack_base = pmp->base;
1291 m_backup_state = pmp->end;
1292 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1293 put_mem_block(condemmed);
1294 return true; // keep looking
1295 }
1296
1297 template <class BidiIterator, class Allocator, class traits>
1298 inline void perl_matcher<BidiIterator, Allocator, traits>::destroy_single_repeat()
1299 {
1300 saved_single_repeat<BidiIterator>* p = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1301 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(p++);
1302 m_backup_state = p;
1303 }
1304
1305 template <class BidiIterator, class Allocator, class traits>
1306 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_greedy_single_repeat(bool r)
1307 {
1308 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1309
1310 // if we have a match, just discard this state:
1311 if(r)
1312 {
1313 destroy_single_repeat();
1314 return true;
1315 }
1316
1317 const re_repeat* rep = pmp->rep;
1318 std::size_t count = pmp->count;
1319 BOOST_ASSERT(rep->next.p != 0);
1320 BOOST_ASSERT(rep->alt.p != 0);
1321
1322 count -= rep->min;
1323
1324 if((m_match_flags & match_partial) && (position == last))
1325 m_has_partial_match = true;
1326
1327 BOOST_ASSERT(count);
1328 position = pmp->last_position;
1329
1330 // backtrack till we can skip out:
1331 do
1332 {
1333 --position;
1334 --count;
1335 ++state_count;
1336 }while(count && !can_start(*position, rep->_map, mask_skip));
1337
1338 // if we've hit base, destroy this state:
1339 if(count == 0)
1340 {
1341 destroy_single_repeat();
1342 if(!can_start(*position, rep->_map, mask_skip))
1343 return true;
1344 }
1345 else
1346 {
1347 pmp->count = count + rep->min;
1348 pmp->last_position = position;
1349 }
1350 pstate = rep->alt.p;
1351 return false;
1352 }
1353
1354 template <class BidiIterator, class Allocator, class traits>
1355 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_slow_dot_repeat(bool r)
1356 {
1357 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1358
1359 // if we have a match, just discard this state:
1360 if(r)
1361 {
1362 destroy_single_repeat();
1363 return true;
1364 }
1365
1366 const re_repeat* rep = pmp->rep;
1367 std::size_t count = pmp->count;
1368 BOOST_ASSERT(rep->type == syntax_element_dot_rep);
1369 BOOST_ASSERT(rep->next.p != 0);
1370 BOOST_ASSERT(rep->alt.p != 0);
1371 BOOST_ASSERT(rep->next.p->type == syntax_element_wild);
1372
1373 BOOST_ASSERT(count < rep->max);
1374 pstate = rep->next.p;
1375 position = pmp->last_position;
1376
1377 if(position != last)
1378 {
1379 // wind forward until we can skip out of the repeat:
1380 do
1381 {
1382 if(!match_wild())
1383 {
1384 // failed repeat match, discard this state and look for another:
1385 destroy_single_repeat();
1386 return true;
1387 }
1388 ++count;
1389 ++state_count;
1390 pstate = rep->next.p;
1391 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1392 }
1393 if(position == last)
1394 {
1395 // can't repeat any more, remove the pushed state:
1396 destroy_single_repeat();
1397 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1398 m_has_partial_match = true;
1399 if(0 == (rep->can_be_null & mask_skip))
1400 return true;
1401 }
1402 else if(count == rep->max)
1403 {
1404 // can't repeat any more, remove the pushed state:
1405 destroy_single_repeat();
1406 if(!can_start(*position, rep->_map, mask_skip))
1407 return true;
1408 }
1409 else
1410 {
1411 pmp->count = count;
1412 pmp->last_position = position;
1413 }
1414 pstate = rep->alt.p;
1415 return false;
1416 }
1417
1418 template <class BidiIterator, class Allocator, class traits>
1419 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_fast_dot_repeat(bool r)
1420 {
1421 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1422
1423 // if we have a match, just discard this state:
1424 if(r)
1425 {
1426 destroy_single_repeat();
1427 return true;
1428 }
1429
1430 const re_repeat* rep = pmp->rep;
1431 std::size_t count = pmp->count;
1432
1433 BOOST_ASSERT(count < rep->max);
1434 position = pmp->last_position;
1435 if(position != last)
1436 {
1437
1438 // wind forward until we can skip out of the repeat:
1439 do
1440 {
1441 ++position;
1442 ++count;
1443 ++state_count;
1444 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1445 }
1446
1447 // remember where we got to if this is a leading repeat:
1448 if((rep->leading) && (count < rep->max))
1449 restart = position;
1450 if(position == last)
1451 {
1452 // can't repeat any more, remove the pushed state:
1453 destroy_single_repeat();
1454 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1455 m_has_partial_match = true;
1456 if(0 == (rep->can_be_null & mask_skip))
1457 return true;
1458 }
1459 else if(count == rep->max)
1460 {
1461 // can't repeat any more, remove the pushed state:
1462 destroy_single_repeat();
1463 if(!can_start(*position, rep->_map, mask_skip))
1464 return true;
1465 }
1466 else
1467 {
1468 pmp->count = count;
1469 pmp->last_position = position;
1470 }
1471 pstate = rep->alt.p;
1472 return false;
1473 }
1474
1475 template <class BidiIterator, class Allocator, class traits>
1476 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_char_repeat(bool r)
1477 {
1478 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1479
1480 // if we have a match, just discard this state:
1481 if(r)
1482 {
1483 destroy_single_repeat();
1484 return true;
1485 }
1486
1487 const re_repeat* rep = pmp->rep;
1488 std::size_t count = pmp->count;
1489 pstate = rep->next.p;
1490 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
1491 position = pmp->last_position;
1492
1493 BOOST_ASSERT(rep->type == syntax_element_char_rep);
1494 BOOST_ASSERT(rep->next.p != 0);
1495 BOOST_ASSERT(rep->alt.p != 0);
1496 BOOST_ASSERT(rep->next.p->type == syntax_element_literal);
1497 BOOST_ASSERT(count < rep->max);
1498
1499 if(position != last)
1500 {
1501 // wind forward until we can skip out of the repeat:
1502 do
1503 {
1504 if(traits_inst.translate(*position, icase) != what)
1505 {
1506 // failed repeat match, discard this state and look for another:
1507 destroy_single_repeat();
1508 return true;
1509 }
1510 ++count;
1511 ++ position;
1512 ++state_count;
1513 pstate = rep->next.p;
1514 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1515 }
1516 // remember where we got to if this is a leading repeat:
1517 if((rep->leading) && (count < rep->max))
1518 restart = position;
1519 if(position == last)
1520 {
1521 // can't repeat any more, remove the pushed state:
1522 destroy_single_repeat();
1523 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1524 m_has_partial_match = true;
1525 if(0 == (rep->can_be_null & mask_skip))
1526 return true;
1527 }
1528 else if(count == rep->max)
1529 {
1530 // can't repeat any more, remove the pushed state:
1531 destroy_single_repeat();
1532 if(!can_start(*position, rep->_map, mask_skip))
1533 return true;
1534 }
1535 else
1536 {
1537 pmp->count = count;
1538 pmp->last_position = position;
1539 }
1540 pstate = rep->alt.p;
1541 return false;
1542 }
1543
1544 template <class BidiIterator, class Allocator, class traits>
1545 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_short_set_repeat(bool r)
1546 {
1547 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1548
1549 // if we have a match, just discard this state:
1550 if(r)
1551 {
1552 destroy_single_repeat();
1553 return true;
1554 }
1555
1556 const re_repeat* rep = pmp->rep;
1557 std::size_t count = pmp->count;
1558 pstate = rep->next.p;
1559 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
1560 position = pmp->last_position;
1561
1562 BOOST_ASSERT(rep->type == syntax_element_short_set_rep);
1563 BOOST_ASSERT(rep->next.p != 0);
1564 BOOST_ASSERT(rep->alt.p != 0);
1565 BOOST_ASSERT(rep->next.p->type == syntax_element_set);
1566 BOOST_ASSERT(count < rep->max);
1567
1568 if(position != last)
1569 {
1570 // wind forward until we can skip out of the repeat:
1571 do
1572 {
1573 if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
1574 {
1575 // failed repeat match, discard this state and look for another:
1576 destroy_single_repeat();
1577 return true;
1578 }
1579 ++count;
1580 ++ position;
1581 ++state_count;
1582 pstate = rep->next.p;
1583 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1584 }
1585 // remember where we got to if this is a leading repeat:
1586 if((rep->leading) && (count < rep->max))
1587 restart = position;
1588 if(position == last)
1589 {
1590 // can't repeat any more, remove the pushed state:
1591 destroy_single_repeat();
1592 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1593 m_has_partial_match = true;
1594 if(0 == (rep->can_be_null & mask_skip))
1595 return true;
1596 }
1597 else if(count == rep->max)
1598 {
1599 // can't repeat any more, remove the pushed state:
1600 destroy_single_repeat();
1601 if(!can_start(*position, rep->_map, mask_skip))
1602 return true;
1603 }
1604 else
1605 {
1606 pmp->count = count;
1607 pmp->last_position = position;
1608 }
1609 pstate = rep->alt.p;
1610 return false;
1611 }
1612
1613 template <class BidiIterator, class Allocator, class traits>
1614 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_long_set_repeat(bool r)
1615 {
1616 typedef typename traits::char_class_type m_type;
1617 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
1618
1619 // if we have a match, just discard this state:
1620 if(r)
1621 {
1622 destroy_single_repeat();
1623 return true;
1624 }
1625
1626 const re_repeat* rep = pmp->rep;
1627 std::size_t count = pmp->count;
1628 pstate = rep->next.p;
1629 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate);
1630 position = pmp->last_position;
1631
1632 BOOST_ASSERT(rep->type == syntax_element_long_set_rep);
1633 BOOST_ASSERT(rep->next.p != 0);
1634 BOOST_ASSERT(rep->alt.p != 0);
1635 BOOST_ASSERT(rep->next.p->type == syntax_element_long_set);
1636 BOOST_ASSERT(count < rep->max);
1637
1638 if(position != last)
1639 {
1640 // wind forward until we can skip out of the repeat:
1641 do
1642 {
1643 if(position == re_is_set_member(position, last, set, re.get_data(), icase))
1644 {
1645 // failed repeat match, discard this state and look for another:
1646 destroy_single_repeat();
1647 return true;
1648 }
1649 ++position;
1650 ++count;
1651 ++state_count;
1652 pstate = rep->next.p;
1653 }while((count < rep->max) && (position != last) && !can_start(*position, rep->_map, mask_skip));
1654 }
1655 // remember where we got to if this is a leading repeat:
1656 if((rep->leading) && (count < rep->max))
1657 restart = position;
1658 if(position == last)
1659 {
1660 // can't repeat any more, remove the pushed state:
1661 destroy_single_repeat();
1662 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
1663 m_has_partial_match = true;
1664 if(0 == (rep->can_be_null & mask_skip))
1665 return true;
1666 }
1667 else if(count == rep->max)
1668 {
1669 // can't repeat any more, remove the pushed state:
1670 destroy_single_repeat();
1671 if(!can_start(*position, rep->_map, mask_skip))
1672 return true;
1673 }
1674 else
1675 {
1676 pmp->count = count;
1677 pmp->last_position = position;
1678 }
1679 pstate = rep->alt.p;
1680 return false;
1681 }
1682
1683 template <class BidiIterator, class Allocator, class traits>
1684 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_non_greedy_repeat(bool r)
1685 {
1686 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1687 if(!r)
1688 {
1689 position = pmp->position;
1690 pstate = pmp->pstate;
1691 ++(*next_count);
1692 }
1693 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1694 m_backup_state = pmp;
1695 return r;
1696 }
1697
1698 template <class BidiIterator, class Allocator, class traits>
1699 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion(bool r)
1700 {
1701 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
1702 if(!r)
1703 {
1704 recursion_stack.push_back(recursion_info<results_type>());
1705 recursion_stack.back().idx = pmp->recursion_id;
1706 recursion_stack.back().preturn_address = pmp->preturn_address;
1707 recursion_stack.back().results = pmp->results;
1708 }
1709 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1710 m_backup_state = pmp;
1711 return true;
1712 }
1713
1714 template <class BidiIterator, class Allocator, class traits>
1715 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_recursion_pop(bool r)
1716 {
1717 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1718 if(!r)
1719 {
1720 recursion_stack.pop_back();
1721 }
1722 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1723 m_backup_state = pmp;
1724 return true;
1725 }
1726
1727 template <class BidiIterator, class Allocator, class traits>
1728 void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_pop()
1729 {
1730 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1731 --pmp;
1732 if(pmp < m_stack_base)
1733 {
1734 extend_stack();
1735 pmp = static_cast<saved_state*>(m_backup_state);
1736 --pmp;
1737 }
1738 (void) new (pmp)saved_state(15);
1739 m_backup_state = pmp;
1740 }
1741
1742 template <class BidiIterator, class Allocator, class traits>
1743 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_commit(bool b)
1744 {
1745 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1746 while(unwind(b) && !m_unwound_lookahead){}
1747 if(m_unwound_lookahead && pstate)
1748 {
1749 //
1750 // If we stop because we just unwound an assertion, put the
1751 // commit state back on the stack again:
1752 //
1753 saved_state* pmp = m_backup_state;
1754 --pmp;
1755 if(pmp < m_stack_base)
1756 {
1757 extend_stack();
1758 pmp = m_backup_state;
1759 --pmp;
1760 }
1761 (void) new (pmp)saved_state(16);
1762 m_backup_state = pmp;
1763 }
1764 // This prevents us from stopping when we exit from an independent sub-expression:
1765 m_independent = false;
1766 return false;
1767 }
1768
1769 template <class BidiIterator, class Allocator, class traits>
1770 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_then(bool b)
1771 {
1772 // Unwind everything till we hit an alternative:
1773 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1774 bool result = false;
1775 while((result = unwind(b)) && !m_unwound_alt){}
1776 // We're now pointing at the next alternative, need one more backtrack
1777 // since *all* the other alternatives must fail once we've reached a THEN clause:
1778 if(result && m_unwound_alt)
1779 unwind(b);
1780 return false;
1781 }
1782
1783 /*
1784 template <class BidiIterator, class Allocator, class traits>
1785 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_pop(bool r)
1786 {
1787 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1788 if(!r)
1789 {
1790 --parenthesis_stack_position;
1791 }
1792 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1793 m_backup_state = pmp;
1794 return true;
1795 }
1796
1797 template <class BidiIterator, class Allocator, class traits>
1798 void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_pop()
1799 {
1800 saved_state* pmp = static_cast<saved_state*>(m_backup_state);
1801 --pmp;
1802 if(pmp < m_stack_base)
1803 {
1804 extend_stack();
1805 pmp = static_cast<saved_state*>(m_backup_state);
1806 --pmp;
1807 }
1808 (void) new (pmp)saved_state(16);
1809 m_backup_state = pmp;
1810 }
1811
1812 template <class BidiIterator, class Allocator, class traits>
1813 bool perl_matcher<BidiIterator, Allocator, traits>::unwind_parenthesis_push(bool r)
1814 {
1815 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1816 if(!r)
1817 {
1818 parenthesis_stack[parenthesis_stack_position++] = pmp->position;
1819 }
1820 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp++);
1821 m_backup_state = pmp;
1822 return true;
1823 }
1824
1825 template <class BidiIterator, class Allocator, class traits>
1826 inline void perl_matcher<BidiIterator, Allocator, traits>::push_parenthesis_push(BidiIterator p)
1827 {
1828 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1829 --pmp;
1830 if(pmp < m_stack_base)
1831 {
1832 extend_stack();
1833 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
1834 --pmp;
1835 }
1836 (void) new (pmp)saved_position<BidiIterator>(0, p, 17);
1837 m_backup_state = pmp;
1838 }
1839 */
1840 } // namespace BOOST_REGEX_DETAIL_NS
1841 } // namespace boost
1842
1843 #ifdef BOOST_MSVC
1844 # pragma warning(pop)
1845 #endif
1846
1847 #ifdef BOOST_MSVC
1848 #pragma warning(push)
1849 #pragma warning(disable: 4103)
1850 #endif
1851 #ifdef BOOST_HAS_ABI_HEADERS
1852 # include BOOST_ABI_SUFFIX
1853 #endif
1854 #ifdef BOOST_MSVC
1855 #pragma warning(pop)
1856 #endif
1857
1858 #endif
1859
1860