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