File indexing completed on 2025-01-18 09:51:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #ifndef BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
0021 #define BOOST_REGEX_V4_PERL_MATCHER_NON_RECURSIVE_HPP
0022
0023 #include <boost/regex/v4/mem_block_cache.hpp>
0024
0025 #ifdef BOOST_MSVC
0026 #pragma warning(push)
0027 #pragma warning(disable: 4103)
0028 #endif
0029 #ifdef BOOST_HAS_ABI_HEADERS
0030 # include BOOST_ABI_PREFIX
0031 #endif
0032 #ifdef BOOST_MSVC
0033 #pragma warning(pop)
0034 #endif
0035 #ifdef BOOST_MSVC
0036 # pragma warning(push)
0037 # pragma warning(disable: 4706)
0038 #if BOOST_MSVC < 1910
0039 #pragma warning(disable:4800)
0040 #endif
0041 #endif
0042
0043 namespace boost{
0044 namespace BOOST_REGEX_DETAIL_NS{
0045
0046 template <class T>
0047 inline void inplace_destroy(T* p)
0048 {
0049 (void)p;
0050 p->~T();
0051 }
0052
0053 struct saved_state
0054 {
0055 union{
0056 unsigned int state_id;
0057
0058 std::size_t padding1;
0059 std::ptrdiff_t padding2;
0060 void* padding3;
0061 };
0062 saved_state(unsigned i) : state_id(i) {}
0063 };
0064
0065 template <class BidiIterator>
0066 struct saved_matched_paren : public saved_state
0067 {
0068 int index;
0069 sub_match<BidiIterator> sub;
0070 saved_matched_paren(int i, const sub_match<BidiIterator>& s) : saved_state(1), index(i), sub(s){}
0071 };
0072
0073 template <class BidiIterator>
0074 struct saved_position : public saved_state
0075 {
0076 const re_syntax_base* pstate;
0077 BidiIterator position;
0078 saved_position(const re_syntax_base* ps, BidiIterator pos, int i) : saved_state(i), pstate(ps), position(pos){}
0079 };
0080
0081 template <class BidiIterator>
0082 struct saved_assertion : public saved_position<BidiIterator>
0083 {
0084 bool positive;
0085 saved_assertion(bool p, const re_syntax_base* ps, BidiIterator pos)
0086 : saved_position<BidiIterator>(ps, pos, saved_type_assertion), positive(p){}
0087 };
0088
0089 template <class BidiIterator>
0090 struct saved_repeater : public saved_state
0091 {
0092 repeater_count<BidiIterator> count;
0093 saved_repeater(int i, repeater_count<BidiIterator>** s, BidiIterator start, int current_recursion_id)
0094 : saved_state(saved_state_repeater_count), count(i, s, start, current_recursion_id){}
0095 };
0096
0097 struct saved_extra_block : public saved_state
0098 {
0099 saved_state *base, *end;
0100 saved_extra_block(saved_state* b, saved_state* e)
0101 : saved_state(saved_state_extra_block), base(b), end(e) {}
0102 };
0103
0104 struct save_state_init
0105 {
0106 saved_state** stack;
0107 save_state_init(saved_state** base, saved_state** end)
0108 : stack(base)
0109 {
0110 *base = static_cast<saved_state*>(get_mem_block());
0111 *end = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(*base)+BOOST_REGEX_BLOCKSIZE);
0112 --(*end);
0113 (void) new (*end)saved_state(0);
0114 BOOST_REGEX_ASSERT(*end > *base);
0115 }
0116 ~save_state_init()
0117 {
0118 put_mem_block(*stack);
0119 *stack = 0;
0120 }
0121 };
0122
0123 template <class BidiIterator>
0124 struct saved_single_repeat : public saved_state
0125 {
0126 std::size_t count;
0127 const re_repeat* rep;
0128 BidiIterator last_position;
0129 saved_single_repeat(std::size_t c, const re_repeat* r, BidiIterator lp, int arg_id)
0130 : saved_state(arg_id), count(c), rep(r), last_position(lp){}
0131 };
0132
0133 template <class Results>
0134 struct saved_recursion : public saved_state
0135 {
0136 saved_recursion(int idx, const re_syntax_base* p, Results* pr, Results* pr2)
0137 : saved_state(14), recursion_id(idx), preturn_address(p), internal_results(*pr), prior_results(*pr2) {}
0138 int recursion_id;
0139 const re_syntax_base* preturn_address;
0140 Results internal_results, prior_results;
0141 };
0142
0143 struct saved_change_case : public saved_state
0144 {
0145 bool icase;
0146 saved_change_case(bool c) : saved_state(18), icase(c) {}
0147 };
0148
0149 struct incrementer
0150 {
0151 incrementer(unsigned* pu) : m_pu(pu) { ++*m_pu; }
0152 ~incrementer() { --*m_pu; }
0153 bool operator > (unsigned i) { return *m_pu > i; }
0154 private:
0155 unsigned* m_pu;
0156 };
0157
0158 template <class BidiIterator, class Allocator, class traits>
0159 bool perl_matcher<BidiIterator, Allocator, traits>::match_all_states()
0160 {
0161 static matcher_proc_type const s_match_vtable[34] =
0162 {
0163 (&perl_matcher<BidiIterator, Allocator, traits>::match_startmark),
0164 &perl_matcher<BidiIterator, Allocator, traits>::match_endmark,
0165 &perl_matcher<BidiIterator, Allocator, traits>::match_literal,
0166 &perl_matcher<BidiIterator, Allocator, traits>::match_start_line,
0167 &perl_matcher<BidiIterator, Allocator, traits>::match_end_line,
0168 &perl_matcher<BidiIterator, Allocator, traits>::match_wild,
0169 &perl_matcher<BidiIterator, Allocator, traits>::match_match,
0170 &perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary,
0171 &perl_matcher<BidiIterator, Allocator, traits>::match_within_word,
0172 &perl_matcher<BidiIterator, Allocator, traits>::match_word_start,
0173 &perl_matcher<BidiIterator, Allocator, traits>::match_word_end,
0174 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start,
0175 &perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end,
0176 &perl_matcher<BidiIterator, Allocator, traits>::match_backref,
0177 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set,
0178 &perl_matcher<BidiIterator, Allocator, traits>::match_set,
0179 &perl_matcher<BidiIterator, Allocator, traits>::match_jump,
0180 &perl_matcher<BidiIterator, Allocator, traits>::match_alt,
0181 &perl_matcher<BidiIterator, Allocator, traits>::match_rep,
0182 &perl_matcher<BidiIterator, Allocator, traits>::match_combining,
0183 &perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end,
0184 &perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue,
0185
0186
0187
0188
0189 &perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_dispatch,
0190 &perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat,
0191 &perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat,
0192 &perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat,
0193 &perl_matcher<BidiIterator, Allocator, traits>::match_backstep,
0194 &perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref,
0195 &perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case,
0196 &perl_matcher<BidiIterator, Allocator, traits>::match_recursion,
0197 &perl_matcher<BidiIterator, Allocator, traits>::match_fail,
0198 &perl_matcher<BidiIterator, Allocator, traits>::match_accept,
0199 &perl_matcher<BidiIterator, Allocator, traits>::match_commit,
0200 &perl_matcher<BidiIterator, Allocator, traits>::match_then,
0201 };
0202 incrementer inc(&m_recursions);
0203 if(inc > 80)
0204 raise_error(traits_inst, regex_constants::error_complexity);
0205 push_recursion_stopper();
0206 do{
0207 while(pstate)
0208 {
0209 matcher_proc_type proc = s_match_vtable[pstate->type];
0210 ++state_count;
0211 if(!(this->*proc)())
0212 {
0213 if(state_count > max_state_count)
0214 raise_error(traits_inst, regex_constants::error_complexity);
0215 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
0216 m_has_partial_match = true;
0217 bool successful_unwind = unwind(false);
0218 if((m_match_flags & match_partial) && (position == last) && (position != search_base))
0219 m_has_partial_match = true;
0220 if(!successful_unwind)
0221 return m_recursive_result;
0222 }
0223 }
0224 }while(unwind(true));
0225 return m_recursive_result;
0226 }
0227
0228 template <class BidiIterator, class Allocator, class traits>
0229 void perl_matcher<BidiIterator, Allocator, traits>::extend_stack()
0230 {
0231 if(used_block_count)
0232 {
0233 --used_block_count;
0234 saved_state* stack_base;
0235 saved_state* backup_state;
0236 stack_base = static_cast<saved_state*>(get_mem_block());
0237 backup_state = reinterpret_cast<saved_state*>(reinterpret_cast<char*>(stack_base)+BOOST_REGEX_BLOCKSIZE);
0238 saved_extra_block* block = static_cast<saved_extra_block*>(backup_state);
0239 --block;
0240 (void) new (block) saved_extra_block(m_stack_base, m_backup_state);
0241 m_stack_base = stack_base;
0242 m_backup_state = block;
0243 }
0244 else
0245 raise_error(traits_inst, regex_constants::error_stack);
0246 }
0247
0248 template <class BidiIterator, class Allocator, class traits>
0249 inline void perl_matcher<BidiIterator, Allocator, traits>::push_matched_paren(int index, const sub_match<BidiIterator>& sub)
0250 {
0251
0252 saved_matched_paren<BidiIterator>* pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
0253 --pmp;
0254 if(pmp < m_stack_base)
0255 {
0256 extend_stack();
0257 pmp = static_cast<saved_matched_paren<BidiIterator>*>(m_backup_state);
0258 --pmp;
0259 }
0260 (void) new (pmp)saved_matched_paren<BidiIterator>(index, sub);
0261 m_backup_state = pmp;
0262 }
0263
0264 template <class BidiIterator, class Allocator, class traits>
0265 inline void perl_matcher<BidiIterator, Allocator, traits>::push_case_change(bool c)
0266 {
0267
0268 saved_change_case* pmp = static_cast<saved_change_case*>(m_backup_state);
0269 --pmp;
0270 if(pmp < m_stack_base)
0271 {
0272 extend_stack();
0273 pmp = static_cast<saved_change_case*>(m_backup_state);
0274 --pmp;
0275 }
0276 (void) new (pmp)saved_change_case(c);
0277 m_backup_state = pmp;
0278 }
0279
0280 template <class BidiIterator, class Allocator, class traits>
0281 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion_stopper()
0282 {
0283 saved_state* pmp = m_backup_state;
0284 --pmp;
0285 if(pmp < m_stack_base)
0286 {
0287 extend_stack();
0288 pmp = m_backup_state;
0289 --pmp;
0290 }
0291 (void) new (pmp)saved_state(saved_type_recurse);
0292 m_backup_state = pmp;
0293 }
0294
0295 template <class BidiIterator, class Allocator, class traits>
0296 inline void perl_matcher<BidiIterator, Allocator, traits>::push_assertion(const re_syntax_base* ps, bool positive)
0297 {
0298 saved_assertion<BidiIterator>* pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
0299 --pmp;
0300 if(pmp < m_stack_base)
0301 {
0302 extend_stack();
0303 pmp = static_cast<saved_assertion<BidiIterator>*>(m_backup_state);
0304 --pmp;
0305 }
0306 (void) new (pmp)saved_assertion<BidiIterator>(positive, ps, position);
0307 m_backup_state = pmp;
0308 }
0309
0310 template <class BidiIterator, class Allocator, class traits>
0311 inline void perl_matcher<BidiIterator, Allocator, traits>::push_alt(const re_syntax_base* ps)
0312 {
0313 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0314 --pmp;
0315 if(pmp < m_stack_base)
0316 {
0317 extend_stack();
0318 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0319 --pmp;
0320 }
0321 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_alt);
0322 m_backup_state = pmp;
0323 }
0324
0325 template <class BidiIterator, class Allocator, class traits>
0326 inline void perl_matcher<BidiIterator, Allocator, traits>::push_non_greedy_repeat(const re_syntax_base* ps)
0327 {
0328 saved_position<BidiIterator>* pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0329 --pmp;
0330 if(pmp < m_stack_base)
0331 {
0332 extend_stack();
0333 pmp = static_cast<saved_position<BidiIterator>*>(m_backup_state);
0334 --pmp;
0335 }
0336 (void) new (pmp)saved_position<BidiIterator>(ps, position, saved_state_non_greedy_long_repeat);
0337 m_backup_state = pmp;
0338 }
0339
0340 template <class BidiIterator, class Allocator, class traits>
0341 inline void perl_matcher<BidiIterator, Allocator, traits>::push_repeater_count(int i, repeater_count<BidiIterator>** s)
0342 {
0343 saved_repeater<BidiIterator>* pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
0344 --pmp;
0345 if(pmp < m_stack_base)
0346 {
0347 extend_stack();
0348 pmp = static_cast<saved_repeater<BidiIterator>*>(m_backup_state);
0349 --pmp;
0350 }
0351 (void) new (pmp)saved_repeater<BidiIterator>(i, s, position, this->recursion_stack.empty() ? (INT_MIN + 3) : this->recursion_stack.back().idx);
0352 m_backup_state = pmp;
0353 }
0354
0355 template <class BidiIterator, class Allocator, class traits>
0356 inline void perl_matcher<BidiIterator, Allocator, traits>::push_single_repeat(std::size_t c, const re_repeat* r, BidiIterator last_position, int state_id)
0357 {
0358 saved_single_repeat<BidiIterator>* pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
0359 --pmp;
0360 if(pmp < m_stack_base)
0361 {
0362 extend_stack();
0363 pmp = static_cast<saved_single_repeat<BidiIterator>*>(m_backup_state);
0364 --pmp;
0365 }
0366 (void) new (pmp)saved_single_repeat<BidiIterator>(c, r, last_position, state_id);
0367 m_backup_state = pmp;
0368 }
0369
0370 template <class BidiIterator, class Allocator, class traits>
0371 inline void perl_matcher<BidiIterator, Allocator, traits>::push_recursion(int idx, const re_syntax_base* p, results_type* presults, results_type* presults2)
0372 {
0373 saved_recursion<results_type>* pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
0374 --pmp;
0375 if(pmp < m_stack_base)
0376 {
0377 extend_stack();
0378 pmp = static_cast<saved_recursion<results_type>*>(m_backup_state);
0379 --pmp;
0380 }
0381 (void) new (pmp)saved_recursion<results_type>(idx, p, presults, presults2);
0382 m_backup_state = pmp;
0383 }
0384
0385 template <class BidiIterator, class Allocator, class traits>
0386 bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
0387 {
0388
0389 push_case_change(this->icase);
0390 this->icase = static_cast<const re_case*>(pstate)->icase;
0391 pstate = pstate->next.p;
0392 return true;
0393 }
0394
0395 template <class BidiIterator, class Allocator, class traits>
0396 bool perl_matcher<BidiIterator, Allocator, traits>::match_startmark()
0397 {
0398 int index = static_cast<const re_brace*>(pstate)->index;
0399 icase = static_cast<const re_brace*>(pstate)->icase;
0400 switch(index)
0401 {
0402 case 0:
0403 pstate = pstate->next.p;
0404 break;
0405 case -1:
0406 case -2:
0407 {
0408
0409 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0410 pstate = pstate->next.p->next.p;
0411 push_assertion(next_pstate, index == -1);
0412 break;
0413 }
0414 case -3:
0415 {
0416
0417 bool old_independent = m_independent;
0418 m_independent = true;
0419 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0420 pstate = pstate->next.p->next.p;
0421 bool r = false;
0422 #if !defined(BOOST_NO_EXCEPTIONS)
0423 try{
0424 #endif
0425 r = match_all_states();
0426 if(!r && !m_independent)
0427 {
0428
0429
0430 while(unwind(false));
0431 return false;
0432 }
0433 #if !defined(BOOST_NO_EXCEPTIONS)
0434 }
0435 catch(...)
0436 {
0437 pstate = next_pstate;
0438
0439
0440
0441 while(unwind(true)) {}
0442 throw;
0443 }
0444 #endif
0445 pstate = next_pstate;
0446 m_independent = old_independent;
0447 #ifdef BOOST_REGEX_MATCH_EXTRA
0448 if(r && (m_match_flags & match_extra))
0449 {
0450
0451
0452
0453
0454
0455 match_results<BidiIterator, Allocator> temp_match(*m_presult);
0456 unsigned i;
0457 for(i = 0; i < temp_match.size(); ++i)
0458 (*m_presult)[i].get_captures().clear();
0459
0460 #if !defined(BOOST_NO_EXCEPTIONS)
0461 try{
0462 #endif
0463 r = match_all_states();
0464 #if !defined(BOOST_NO_EXCEPTIONS)
0465 }
0466 catch(...)
0467 {
0468 pstate = next_pstate;
0469
0470
0471
0472 while(unwind(true)) {}
0473 throw;
0474 }
0475 #endif
0476
0477 for(i = 0; i < temp_match.size(); ++i)
0478 {
0479 typedef typename sub_match<BidiIterator>::capture_sequence_type seq;
0480 seq& s1 = (*m_presult)[i].get_captures();
0481 const seq& s2 = temp_match[i].captures();
0482 s1.insert(
0483 s1.end(),
0484 s2.begin(),
0485 s2.end());
0486 }
0487 }
0488 #endif
0489 return r;
0490 }
0491 case -4:
0492 {
0493
0494 const re_alt* alt = static_cast<const re_alt*>(pstate->next.p);
0495 BOOST_REGEX_ASSERT(alt->type == syntax_element_alt);
0496 pstate = alt->next.p;
0497 if(pstate->type == syntax_element_assert_backref)
0498 {
0499 if(!match_assert_backref())
0500 pstate = alt->alt.p;
0501 break;
0502 }
0503 else
0504 {
0505
0506 BOOST_REGEX_ASSERT(pstate->type == syntax_element_startmark);
0507 bool negated = static_cast<const re_brace*>(pstate)->index == -2;
0508 BidiIterator saved_position = position;
0509 const re_syntax_base* next_pstate = static_cast<const re_jump*>(pstate->next.p)->alt.p->next.p;
0510 pstate = pstate->next.p->next.p;
0511 #if !defined(BOOST_NO_EXCEPTIONS)
0512 try{
0513 #endif
0514 bool r = match_all_states();
0515 position = saved_position;
0516 if(negated)
0517 r = !r;
0518 if(r)
0519 pstate = next_pstate;
0520 else
0521 pstate = alt->alt.p;
0522 #if !defined(BOOST_NO_EXCEPTIONS)
0523 }
0524 catch(...)
0525 {
0526 pstate = next_pstate;
0527
0528
0529
0530 while(unwind(true)){}
0531 throw;
0532 }
0533 #endif
0534 break;
0535 }
0536 }
0537 case -5:
0538 {
0539 push_matched_paren(0, (*m_presult)[0]);
0540 m_presult->set_first(position, 0, true);
0541 pstate = pstate->next.p;
0542 break;
0543 }
0544 default:
0545 {
0546 BOOST_REGEX_ASSERT(index > 0);
0547 if((m_match_flags & match_nosubs) == 0)
0548 {
0549 push_matched_paren(index, (*m_presult)[index]);
0550 m_presult->set_first(position, index);
0551 }
0552 pstate = pstate->next.p;
0553 break;
0554 }
0555 }
0556 return true;
0557 }
0558
0559 template <class BidiIterator, class Allocator, class traits>
0560 bool perl_matcher<BidiIterator, Allocator, traits>::match_alt()
0561 {
0562 bool take_first, take_second;
0563 const re_alt* jmp = static_cast<const re_alt*>(pstate);
0564
0565
0566 if(position == last)
0567 {
0568 take_first = jmp->can_be_null & mask_take;
0569 take_second = jmp->can_be_null & mask_skip;
0570 }
0571 else
0572 {
0573 take_first = can_start(*position, jmp->_map, (unsigned char)mask_take);
0574 take_second = can_start(*position, jmp->_map, (unsigned char)mask_skip);
0575 }
0576
0577 if(take_first)
0578 {
0579
0580
0581 if(take_second)
0582 {
0583 push_alt(jmp->alt.p);
0584 }
0585 pstate = pstate->next.p;
0586 return true;
0587 }
0588 if(take_second)
0589 {
0590 pstate = jmp->alt.p;
0591 return true;
0592 }
0593 return false;
0594 }
0595
0596 template <class BidiIterator, class Allocator, class traits>
0597 bool perl_matcher<BidiIterator, Allocator, traits>::match_rep()
0598 {
0599 #ifdef BOOST_MSVC
0600 #pragma warning(push)
0601 #pragma warning(disable:4127 4244)
0602 #endif
0603 #ifdef BOOST_BORLANDC
0604 #pragma option push -w-8008 -w-8066 -w-8004
0605 #endif
0606 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0607
0608
0609 bool take_first, take_second;
0610 if(position == last)
0611 {
0612 take_first = rep->can_be_null & mask_take;
0613 take_second = rep->can_be_null & mask_skip;
0614 }
0615 else
0616 {
0617 take_first = can_start(*position, rep->_map, (unsigned char)mask_take);
0618 take_second = can_start(*position, rep->_map, (unsigned char)mask_skip);
0619 }
0620
0621 if((m_backup_state->state_id != saved_state_repeater_count)
0622 || (static_cast<saved_repeater<BidiIterator>*>(m_backup_state)->count.get_id() != rep->state_id)
0623 || (next_count->get_id() != rep->state_id))
0624 {
0625
0626
0627 push_repeater_count(rep->state_id, &next_count);
0628 }
0629
0630
0631
0632
0633
0634 next_count->check_null_repeat(position, rep->max);
0635
0636 if(next_count->get_count() < rep->min)
0637 {
0638
0639 if(take_first)
0640 {
0641
0642 ++(*next_count);
0643 pstate = rep->next.p;
0644 return true;
0645 }
0646 return false;
0647 }
0648
0649 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0650 if(greedy)
0651 {
0652
0653 if((next_count->get_count() < rep->max) && take_first)
0654 {
0655 if(take_second)
0656 {
0657
0658 push_alt(rep->alt.p);
0659 }
0660
0661 ++(*next_count);
0662 pstate = rep->next.p;
0663 return true;
0664 }
0665 else if(take_second)
0666 {
0667 pstate = rep->alt.p;
0668 return true;
0669 }
0670 return false;
0671 }
0672 else
0673 {
0674
0675 if(take_second)
0676 {
0677 if((next_count->get_count() < rep->max) && take_first)
0678 {
0679
0680 push_non_greedy_repeat(rep->next.p);
0681 }
0682 pstate = rep->alt.p;
0683 return true;
0684 }
0685 if((next_count->get_count() < rep->max) && take_first)
0686 {
0687
0688 ++(*next_count);
0689 pstate = rep->next.p;
0690 return true;
0691 }
0692 }
0693 return false;
0694 #ifdef BOOST_BORLANDC
0695 #pragma option pop
0696 #endif
0697 #ifdef BOOST_MSVC
0698 #pragma warning(pop)
0699 #endif
0700 }
0701
0702 template <class BidiIterator, class Allocator, class traits>
0703 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_slow()
0704 {
0705 std::size_t count = 0;
0706 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0707 re_syntax_base* psingle = rep->next.p;
0708
0709 while(count < rep->min)
0710 {
0711 pstate = psingle;
0712 if(!match_wild())
0713 return false;
0714 ++count;
0715 }
0716 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0717 if(greedy)
0718 {
0719
0720 while(count < rep->max)
0721 {
0722 pstate = psingle;
0723 if(!match_wild())
0724 break;
0725 ++count;
0726 }
0727
0728 if((rep->leading) && (count < rep->max))
0729 restart = position;
0730
0731 if(count - rep->min)
0732 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0733
0734 pstate = rep->alt.p;
0735 return true;
0736 }
0737 else
0738 {
0739
0740 if(count < rep->max)
0741 push_single_repeat(count, rep, position, saved_state_rep_slow_dot);
0742 pstate = rep->alt.p;
0743 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0744 }
0745 }
0746
0747 template <class BidiIterator, class Allocator, class traits>
0748 bool perl_matcher<BidiIterator, Allocator, traits>::match_dot_repeat_fast()
0749 {
0750 if(m_match_flags & match_not_dot_null)
0751 return match_dot_repeat_slow();
0752 if((static_cast<const re_dot*>(pstate->next.p)->mask & match_any_mask) == 0)
0753 return match_dot_repeat_slow();
0754
0755 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0756 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0757 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));
0758 if(rep->min > count)
0759 {
0760 position = last;
0761 return false;
0762 }
0763 std::advance(position, count);
0764
0765 if(greedy)
0766 {
0767 if((rep->leading) && (count < rep->max))
0768 restart = position;
0769
0770 if(count - rep->min)
0771 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0772
0773 pstate = rep->alt.p;
0774 return true;
0775 }
0776 else
0777 {
0778
0779 if(count < rep->max)
0780 push_single_repeat(count, rep, position, saved_state_rep_fast_dot);
0781 pstate = rep->alt.p;
0782 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0783 }
0784 }
0785
0786 template <class BidiIterator, class Allocator, class traits>
0787 bool perl_matcher<BidiIterator, Allocator, traits>::match_char_repeat()
0788 {
0789 #ifdef BOOST_MSVC
0790 #pragma warning(push)
0791 #pragma warning(disable:4127)
0792 #endif
0793 #ifdef BOOST_BORLANDC
0794 #pragma option push -w-8008 -w-8066 -w-8004
0795 #endif
0796 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0797 BOOST_REGEX_ASSERT(1 == static_cast<const re_literal*>(rep->next.p)->length);
0798 const char_type what = *reinterpret_cast<const char_type*>(static_cast<const re_literal*>(rep->next.p) + 1);
0799 std::size_t count = 0;
0800
0801
0802
0803 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0804 std::size_t desired = greedy ? rep->max : rep->min;
0805 if(::boost::is_random_access_iterator<BidiIterator>::value)
0806 {
0807 BidiIterator end = position;
0808
0809
0810 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0811 if(desired >= len)
0812 end = last;
0813 else
0814 std::advance(end, desired);
0815 BidiIterator origin(position);
0816 while((position != end) && (traits_inst.translate(*position, icase) == what))
0817 {
0818 ++position;
0819 }
0820 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0821 }
0822 else
0823 {
0824 while((count < desired) && (position != last) && (traits_inst.translate(*position, icase) == what))
0825 {
0826 ++position;
0827 ++count;
0828 }
0829 }
0830
0831 if(count < rep->min)
0832 return false;
0833
0834 if(greedy)
0835 {
0836 if((rep->leading) && (count < rep->max))
0837 restart = position;
0838
0839 if(count - rep->min)
0840 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0841
0842 pstate = rep->alt.p;
0843 return true;
0844 }
0845 else
0846 {
0847
0848 if(count < rep->max)
0849 push_single_repeat(count, rep, position, saved_state_rep_char);
0850 pstate = rep->alt.p;
0851 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0852 }
0853 #ifdef BOOST_BORLANDC
0854 #pragma option pop
0855 #endif
0856 #ifdef BOOST_MSVC
0857 #pragma warning(pop)
0858 #endif
0859 }
0860
0861 template <class BidiIterator, class Allocator, class traits>
0862 bool perl_matcher<BidiIterator, Allocator, traits>::match_set_repeat()
0863 {
0864 #ifdef BOOST_MSVC
0865 #pragma warning(push)
0866 #pragma warning(disable:4127)
0867 #endif
0868 #ifdef BOOST_BORLANDC
0869 #pragma option push -w-8008 -w-8066 -w-8004
0870 #endif
0871 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0872 const unsigned char* map = static_cast<const re_set*>(rep->next.p)->_map;
0873 std::size_t count = 0;
0874
0875
0876
0877 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0878 std::size_t desired = greedy ? rep->max : rep->min;
0879 if(::boost::is_random_access_iterator<BidiIterator>::value)
0880 {
0881 BidiIterator end = position;
0882
0883
0884 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0885 if(desired >= len)
0886 end = last;
0887 else
0888 std::advance(end, desired);
0889 BidiIterator origin(position);
0890 while((position != end) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
0891 {
0892 ++position;
0893 }
0894 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0895 }
0896 else
0897 {
0898 while((count < desired) && (position != last) && map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
0899 {
0900 ++position;
0901 ++count;
0902 }
0903 }
0904
0905 if(count < rep->min)
0906 return false;
0907
0908 if(greedy)
0909 {
0910 if((rep->leading) && (count < rep->max))
0911 restart = position;
0912
0913 if(count - rep->min)
0914 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0915
0916 pstate = rep->alt.p;
0917 return true;
0918 }
0919 else
0920 {
0921
0922 if(count < rep->max)
0923 push_single_repeat(count, rep, position, saved_state_rep_short_set);
0924 pstate = rep->alt.p;
0925 return (position == last) ? (rep->can_be_null & mask_skip) : can_start(*position, rep->_map, mask_skip);
0926 }
0927 #ifdef BOOST_BORLANDC
0928 #pragma option pop
0929 #endif
0930 #ifdef BOOST_MSVC
0931 #pragma warning(pop)
0932 #endif
0933 }
0934
0935 template <class BidiIterator, class Allocator, class traits>
0936 bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set_repeat()
0937 {
0938 #ifdef BOOST_MSVC
0939 #pragma warning(push)
0940 #pragma warning(disable:4127)
0941 #endif
0942 #ifdef BOOST_BORLANDC
0943 #pragma option push -w-8008 -w-8066 -w-8004
0944 #endif
0945 typedef typename traits::char_class_type m_type;
0946 const re_repeat* rep = static_cast<const re_repeat*>(pstate);
0947 const re_set_long<m_type>* set = static_cast<const re_set_long<m_type>*>(pstate->next.p);
0948 std::size_t count = 0;
0949
0950
0951
0952 bool greedy = (rep->greedy) && (!(m_match_flags & regex_constants::match_any) || m_independent);
0953 std::size_t desired = greedy ? rep->max : rep->min;
0954 if(::boost::is_random_access_iterator<BidiIterator>::value)
0955 {
0956 BidiIterator end = position;
0957
0958
0959 std::size_t len = (desired == (std::numeric_limits<std::size_t>::max)()) ? 0u : ::boost::BOOST_REGEX_DETAIL_NS::distance(position, last);
0960 if(desired >= len)
0961 end = last;
0962 else
0963 std::advance(end, desired);
0964 BidiIterator origin(position);
0965 while((position != end) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
0966 {
0967 ++position;
0968 }
0969 count = (unsigned)::boost::BOOST_REGEX_DETAIL_NS::distance(origin, position);
0970 }
0971 else
0972 {
0973 while((count < desired) && (position != last) && (position != re_is_set_member(position, last, set, re.get_data(), icase)))
0974 {
0975 ++position;
0976 ++count;
0977 }
0978 }
0979
0980 if(count < rep->min)
0981 return false;
0982
0983 if(greedy)
0984 {
0985 if((rep->leading) && (count < rep->max))
0986 restart = position;
0987
0988 if(count - rep->min)
0989 push_single_repeat(count, rep, position, saved_state_greedy_single_repeat);
0990
0991 pstate = rep->alt.p;
0992 return true;
0993 }
0994 else
0995 {
0996
0997 if(count < rep->max)
0998 push_single_repeat(count, rep, position, saved_state_rep_long_set);
0999 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
1016
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
1029
1030 push_recursion_pop();
1031
1032
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
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
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
1127
1128
1129
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
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
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
1197
1198 const re_syntax_base* sp = pstate;
1199 match_endmark();
1200 if(!pstate)
1201 {
1202 unwind(true);
1203
1204
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
1228
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
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
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;
1281 return false;
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
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
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
1312 m_backup_state = pmp+1;
1313 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(pmp);
1314 return true;
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;
1322 return false;
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;
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;
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;
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
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
1410 do
1411 {
1412 --position;
1413 --count;
1414 ++state_count;
1415 }while(count && !can_start(*position, rep->_map, mask_skip));
1416
1417
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
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
1459 do
1460 {
1461 if(!match_wild())
1462 {
1463
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
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
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
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
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
1527 if((rep->leading) && (count < rep->max))
1528 restart = position;
1529 if(position == last)
1530 {
1531
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
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
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
1581 do
1582 {
1583 if(traits_inst.translate(*position, icase) != what)
1584 {
1585
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
1596 if((rep->leading) && (count < rep->max))
1597 restart = position;
1598 if(position == last)
1599 {
1600
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
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
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
1650 do
1651 {
1652 if(!map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
1653 {
1654
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
1665 if((rep->leading) && (count < rep->max))
1666 restart = position;
1667 if(position == last)
1668 {
1669
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
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
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
1720 do
1721 {
1722 if(position == re_is_set_member(position, last, set, re.get_data(), icase))
1723 {
1724
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
1735 if((rep->leading) && (count < rep->max))
1736 restart = position;
1737 if(position == last)
1738 {
1739
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
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
1781
1782
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
1802
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
1839
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
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
1862 boost::BOOST_REGEX_DETAIL_NS::inplace_destroy(m_backup_state++);
1863 bool result = false;
1864 while((result = unwind(b)) && !m_unwound_alt){}
1865
1866
1867 if(result && m_unwound_alt)
1868 unwind(b);
1869 return false;
1870 }
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929 }
1930 }
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