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