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