blob: 5d5fed002d5a65521154751cfa0c07e505a7a1ba [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 * common to both the recursive and non-recursive versions.
18 */
19
20#ifndef NDNBOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP
21#define NDNBOOST_REGEX_V4_PERL_MATCHER_COMMON_HPP
22
23#ifdef NDNBOOST_MSVC
24#pragma warning(push)
25#pragma warning(disable: 4103)
26#endif
27#ifdef NDNBOOST_HAS_ABI_HEADERS
28# include NDNBOOST_ABI_PREFIX
29#endif
30#ifdef NDNBOOST_MSVC
31#pragma warning(pop)
32#endif
33
34#ifdef __BORLANDC__
35# pragma option push -w-8008 -w-8066
36#endif
37#ifdef NDNBOOST_MSVC
38# pragma warning(push)
39# pragma warning(disable: 4800)
40#endif
41
42namespace ndnboost{
43namespace re_detail{
44
45template <class BidiIterator, class Allocator, class traits>
46void perl_matcher<BidiIterator, Allocator, traits>::construct_init(const basic_regex<char_type, traits>& e, match_flag_type f)
47{
48 typedef typename regex_iterator_traits<BidiIterator>::iterator_category category;
49 typedef typename basic_regex<char_type, traits>::flag_type expression_flag_type;
50
51 if(e.empty())
52 {
53 // precondition failure: e is not a valid regex.
54 std::invalid_argument ex("Invalid regular expression object");
55 ndnboost::throw_exception(ex);
56 }
57 pstate = 0;
58 m_match_flags = f;
59 estimate_max_state_count(static_cast<category*>(0));
60 expression_flag_type re_f = re.flags();
61 icase = re_f & regex_constants::icase;
62 if(!(m_match_flags & (match_perl|match_posix)))
63 {
64 if((re_f & (regbase::main_option_type|regbase::no_perl_ex)) == 0)
65 m_match_flags |= match_perl;
66 else if((re_f & (regbase::main_option_type|regbase::emacs_ex)) == (regbase::basic_syntax_group|regbase::emacs_ex))
67 m_match_flags |= match_perl;
68 else if((re_f & (regbase::main_option_type|regbase::literal)) == (regbase::literal))
69 m_match_flags |= match_perl;
70 else
71 m_match_flags |= match_posix;
72 }
73 if(m_match_flags & match_posix)
74 {
75 m_temp_match.reset(new match_results<BidiIterator, Allocator>());
76 m_presult = m_temp_match.get();
77 }
78 else
79 m_presult = &m_result;
80#ifdef NDNBOOST_REGEX_NON_RECURSIVE
81 m_stack_base = 0;
82 m_backup_state = 0;
83#endif
84 // find the value to use for matching word boundaries:
85 m_word_mask = re.get_data().m_word_mask;
86 // find bitmask to use for matching '.':
87 match_any_mask = static_cast<unsigned char>((f & match_not_dot_newline) ? re_detail::test_not_newline : re_detail::test_newline);
88}
89
90template <class BidiIterator, class Allocator, class traits>
91void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(std::random_access_iterator_tag*)
92{
93 //
94 // How many states should we allow our machine to visit before giving up?
95 // This is a heuristic: it takes the greater of O(N^2) and O(NS^2)
96 // where N is the length of the string, and S is the number of states
97 // in the machine. It's tempting to up this to O(N^2S) or even O(N^2S^2)
98 // but these take unreasonably amounts of time to bale out in pathological
99 // cases.
100 //
101 // Calculate NS^2 first:
102 //
103 static const std::ptrdiff_t k = 100000;
104 std::ptrdiff_t dist = ndnboost::re_detail::distance(base, last);
105 if(dist == 0)
106 dist = 1;
107 std::ptrdiff_t states = re.size();
108 if(states == 0)
109 states = 1;
110 states *= states;
111 if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
112 {
113 max_state_count = (std::min)((std::ptrdiff_t)NDNBOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
114 return;
115 }
116 states *= dist;
117 if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
118 {
119 max_state_count = (std::min)((std::ptrdiff_t)NDNBOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
120 return;
121 }
122 states += k;
123
124 max_state_count = states;
125
126 //
127 // Now calculate N^2:
128 //
129 states = dist;
130 if((std::numeric_limits<std::ptrdiff_t>::max)() / dist < states)
131 {
132 max_state_count = (std::min)((std::ptrdiff_t)NDNBOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
133 return;
134 }
135 states *= dist;
136 if((std::numeric_limits<std::ptrdiff_t>::max)() - k < states)
137 {
138 max_state_count = (std::min)((std::ptrdiff_t)NDNBOOST_REGEX_MAX_STATE_COUNT, (std::numeric_limits<std::ptrdiff_t>::max)() - 2);
139 return;
140 }
141 states += k;
142 //
143 // N^2 can be a very large number indeed, to prevent things getting out
144 // of control, cap the max states:
145 //
146 if(states > NDNBOOST_REGEX_MAX_STATE_COUNT)
147 states = NDNBOOST_REGEX_MAX_STATE_COUNT;
148 //
149 // If (the possibly capped) N^2 is larger than our first estimate,
150 // use this instead:
151 //
152 if(states > max_state_count)
153 max_state_count = states;
154}
155
156template <class BidiIterator, class Allocator, class traits>
157inline void perl_matcher<BidiIterator, Allocator, traits>::estimate_max_state_count(void*)
158{
159 // we don't know how long the sequence is:
160 max_state_count = NDNBOOST_REGEX_MAX_STATE_COUNT;
161}
162
163#ifdef NDNBOOST_REGEX_HAS_MS_STACK_GUARD
164template <class BidiIterator, class Allocator, class traits>
165inline bool perl_matcher<BidiIterator, Allocator, traits>::protected_call(
166 protected_proc_type proc)
167{
168 ::ndnboost::re_detail::concrete_protected_call
169 <perl_matcher<BidiIterator, Allocator, traits> >
170 obj(this, proc);
171 return obj.execute();
172
173}
174#endif
175
176template <class BidiIterator, class Allocator, class traits>
177inline bool perl_matcher<BidiIterator, Allocator, traits>::match()
178{
179#ifdef NDNBOOST_REGEX_HAS_MS_STACK_GUARD
180 return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::match_imp);
181#else
182 return match_imp();
183#endif
184}
185
186template <class BidiIterator, class Allocator, class traits>
187bool perl_matcher<BidiIterator, Allocator, traits>::match_imp()
188{
189 // initialise our stack if we are non-recursive:
190#ifdef NDNBOOST_REGEX_NON_RECURSIVE
191 save_state_init init(&m_stack_base, &m_backup_state);
192 used_block_count = NDNBOOST_REGEX_MAX_BLOCKS;
193#if !defined(NDNBOOST_NO_EXCEPTIONS)
194 try{
195#endif
196#endif
197
198 // reset our state machine:
199 position = base;
200 search_base = base;
201 state_count = 0;
202 m_match_flags |= regex_constants::match_all;
203 m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last);
204 m_presult->set_base(base);
205 m_presult->set_named_subs(this->re.get_named_subs());
206 if(m_match_flags & match_posix)
207 m_result = *m_presult;
208 verify_options(re.flags(), m_match_flags);
209 if(0 == match_prefix())
210 return false;
211 return (m_result[0].second == last) && (m_result[0].first == base);
212
213#if defined(NDNBOOST_REGEX_NON_RECURSIVE) && !defined(NDNBOOST_NO_EXCEPTIONS)
214 }
215 catch(...)
216 {
217 // unwind all pushed states, apart from anything else this
218 // ensures that all the states are correctly destructed
219 // not just the memory freed.
220 while(unwind(true)){}
221 throw;
222 }
223#endif
224}
225
226template <class BidiIterator, class Allocator, class traits>
227inline bool perl_matcher<BidiIterator, Allocator, traits>::find()
228{
229#ifdef NDNBOOST_REGEX_HAS_MS_STACK_GUARD
230 return protected_call(&perl_matcher<BidiIterator, Allocator, traits>::find_imp);
231#else
232 return find_imp();
233#endif
234}
235
236template <class BidiIterator, class Allocator, class traits>
237bool perl_matcher<BidiIterator, Allocator, traits>::find_imp()
238{
239 static matcher_proc_type const s_find_vtable[7] =
240 {
241 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_any,
242 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_word,
243 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_line,
244 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf,
245 &perl_matcher<BidiIterator, Allocator, traits>::match_prefix,
246 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
247 &perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit,
248 };
249
250 // initialise our stack if we are non-recursive:
251#ifdef NDNBOOST_REGEX_NON_RECURSIVE
252 save_state_init init(&m_stack_base, &m_backup_state);
253 used_block_count = NDNBOOST_REGEX_MAX_BLOCKS;
254#if !defined(NDNBOOST_NO_EXCEPTIONS)
255 try{
256#endif
257#endif
258
259 state_count = 0;
260 if((m_match_flags & regex_constants::match_init) == 0)
261 {
262 // reset our state machine:
263 search_base = position = base;
264 pstate = re.get_first_state();
265 m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), base, last);
266 m_presult->set_base(base);
267 m_presult->set_named_subs(this->re.get_named_subs());
268 m_match_flags |= regex_constants::match_init;
269 }
270 else
271 {
272 // start again:
273 search_base = position = m_result[0].second;
274 // If last match was null and match_not_null was not set then increment
275 // our start position, otherwise we go into an infinite loop:
276 if(((m_match_flags & match_not_null) == 0) && (m_result.length() == 0))
277 {
278 if(position == last)
279 return false;
280 else
281 ++position;
282 }
283 // reset $` start:
284 m_presult->set_size((m_match_flags & match_nosubs) ? 1 : re.mark_count(), search_base, last);
285 //if((base != search_base) && (base == backstop))
286 // m_match_flags |= match_prev_avail;
287 }
288 if(m_match_flags & match_posix)
289 {
290 m_result.set_size(re.mark_count(), base, last);
291 m_result.set_base(base);
292 }
293
294 verify_options(re.flags(), m_match_flags);
295 // find out what kind of expression we have:
296 unsigned type = (m_match_flags & match_continuous) ?
297 static_cast<unsigned int>(regbase::restart_continue)
298 : static_cast<unsigned int>(re.get_restart_type());
299
300 // call the appropriate search routine:
301 matcher_proc_type proc = s_find_vtable[type];
302 return (this->*proc)();
303
304#if defined(NDNBOOST_REGEX_NON_RECURSIVE) && !defined(NDNBOOST_NO_EXCEPTIONS)
305 }
306 catch(...)
307 {
308 // unwind all pushed states, apart from anything else this
309 // ensures that all the states are correctly destructed
310 // not just the memory freed.
311 while(unwind(true)){}
312 throw;
313 }
314#endif
315}
316
317template <class BidiIterator, class Allocator, class traits>
318bool perl_matcher<BidiIterator, Allocator, traits>::match_prefix()
319{
320 m_has_partial_match = false;
321 m_has_found_match = false;
322 pstate = re.get_first_state();
323 m_presult->set_first(position);
324 restart = position;
325 match_all_states();
326 if(!m_has_found_match && m_has_partial_match && (m_match_flags & match_partial))
327 {
328 m_has_found_match = true;
329 m_presult->set_second(last, 0, false);
330 position = last;
331 if((m_match_flags & match_posix) == match_posix)
332 {
333 m_result.maybe_assign(*m_presult);
334 }
335 }
336#ifdef NDNBOOST_REGEX_MATCH_EXTRA
337 if(m_has_found_match && (match_extra & m_match_flags))
338 {
339 //
340 // we have a match, reverse the capture information:
341 //
342 for(unsigned i = 0; i < m_presult->size(); ++i)
343 {
344 typename sub_match<BidiIterator>::capture_sequence_type & seq = ((*m_presult)[i]).get_captures();
345 std::reverse(seq.begin(), seq.end());
346 }
347 }
348#endif
349 if(!m_has_found_match)
350 position = restart; // reset search postion
351 return m_has_found_match;
352}
353
354template <class BidiIterator, class Allocator, class traits>
355bool perl_matcher<BidiIterator, Allocator, traits>::match_literal()
356{
357 unsigned int len = static_cast<const re_literal*>(pstate)->length;
358 const char_type* what = reinterpret_cast<const char_type*>(static_cast<const re_literal*>(pstate) + 1);
359 //
360 // compare string with what we stored in
361 // our records:
362 for(unsigned int i = 0; i < len; ++i, ++position)
363 {
364 if((position == last) || (traits_inst.translate(*position, icase) != what[i]))
365 return false;
366 }
367 pstate = pstate->next.p;
368 return true;
369}
370
371template <class BidiIterator, class Allocator, class traits>
372bool perl_matcher<BidiIterator, Allocator, traits>::match_start_line()
373{
374 if(position == backstop)
375 {
376 if((m_match_flags & match_prev_avail) == 0)
377 {
378 if((m_match_flags & match_not_bol) == 0)
379 {
380 pstate = pstate->next.p;
381 return true;
382 }
383 return false;
384 }
385 }
386 else if(m_match_flags & match_single_line)
387 return false;
388
389 // check the previous value character:
390 BidiIterator t(position);
391 --t;
392 if(position != last)
393 {
394 if(is_separator(*t) && !((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n'))) )
395 {
396 pstate = pstate->next.p;
397 return true;
398 }
399 }
400 else if(is_separator(*t))
401 {
402 pstate = pstate->next.p;
403 return true;
404 }
405 return false;
406}
407
408template <class BidiIterator, class Allocator, class traits>
409bool perl_matcher<BidiIterator, Allocator, traits>::match_end_line()
410{
411 if(position != last)
412 {
413 if(m_match_flags & match_single_line)
414 return false;
415 // we're not yet at the end so *first is always valid:
416 if(is_separator(*position))
417 {
418 if((position != backstop) || (m_match_flags & match_prev_avail))
419 {
420 // check that we're not in the middle of \r\n sequence
421 BidiIterator t(position);
422 --t;
423 if((*t == static_cast<char_type>('\r')) && (*position == static_cast<char_type>('\n')))
424 {
425 return false;
426 }
427 }
428 pstate = pstate->next.p;
429 return true;
430 }
431 }
432 else if((m_match_flags & match_not_eol) == 0)
433 {
434 pstate = pstate->next.p;
435 return true;
436 }
437 return false;
438}
439
440template <class BidiIterator, class Allocator, class traits>
441bool perl_matcher<BidiIterator, Allocator, traits>::match_wild()
442{
443 if(position == last)
444 return false;
445 if(is_separator(*position) && ((match_any_mask & static_cast<const re_dot*>(pstate)->mask) == 0))
446 return false;
447 if((*position == char_type(0)) && (m_match_flags & match_not_dot_null))
448 return false;
449 pstate = pstate->next.p;
450 ++position;
451 return true;
452}
453
454template <class BidiIterator, class Allocator, class traits>
455bool perl_matcher<BidiIterator, Allocator, traits>::match_word_boundary()
456{
457 bool b; // indcates whether next character is a word character
458 if(position != last)
459 {
460 // prev and this character must be opposites:
461 #if defined(NDNBOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
462 b = traits::isctype(*position, m_word_mask);
463 #else
464 b = traits_inst.isctype(*position, m_word_mask);
465 #endif
466 }
467 else
468 {
469 b = (m_match_flags & match_not_eow) ? true : false;
470 }
471 if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
472 {
473 if(m_match_flags & match_not_bow)
474 b ^= true;
475 else
476 b ^= false;
477 }
478 else
479 {
480 --position;
481 b ^= traits_inst.isctype(*position, m_word_mask);
482 ++position;
483 }
484 if(b)
485 {
486 pstate = pstate->next.p;
487 return true;
488 }
489 return false; // no match if we get to here...
490}
491
492template <class BidiIterator, class Allocator, class traits>
493bool perl_matcher<BidiIterator, Allocator, traits>::match_within_word()
494{
495 if(position == last)
496 return false;
497 // both prev and this character must be m_word_mask:
498 bool prev = traits_inst.isctype(*position, m_word_mask);
499 {
500 bool b;
501 if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
502 return false;
503 else
504 {
505 --position;
506 b = traits_inst.isctype(*position, m_word_mask);
507 ++position;
508 }
509 if(b == prev)
510 {
511 pstate = pstate->next.p;
512 return true;
513 }
514 }
515 return false;
516}
517
518template <class BidiIterator, class Allocator, class traits>
519bool perl_matcher<BidiIterator, Allocator, traits>::match_word_start()
520{
521 if(position == last)
522 return false; // can't be starting a word if we're already at the end of input
523 if(!traits_inst.isctype(*position, m_word_mask))
524 return false; // next character isn't a word character
525 if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
526 {
527 if(m_match_flags & match_not_bow)
528 return false; // no previous input
529 }
530 else
531 {
532 // otherwise inside buffer:
533 BidiIterator t(position);
534 --t;
535 if(traits_inst.isctype(*t, m_word_mask))
536 return false; // previous character not non-word
537 }
538 // OK we have a match:
539 pstate = pstate->next.p;
540 return true;
541}
542
543template <class BidiIterator, class Allocator, class traits>
544bool perl_matcher<BidiIterator, Allocator, traits>::match_word_end()
545{
546 if((position == backstop) && ((m_match_flags & match_prev_avail) == 0))
547 return false; // start of buffer can't be end of word
548 BidiIterator t(position);
549 --t;
550 if(traits_inst.isctype(*t, m_word_mask) == false)
551 return false; // previous character wasn't a word character
552
553 if(position == last)
554 {
555 if(m_match_flags & match_not_eow)
556 return false; // end of buffer but not end of word
557 }
558 else
559 {
560 // otherwise inside buffer:
561 if(traits_inst.isctype(*position, m_word_mask))
562 return false; // next character is a word character
563 }
564 pstate = pstate->next.p;
565 return true; // if we fall through to here then we've succeeded
566}
567
568template <class BidiIterator, class Allocator, class traits>
569bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_start()
570{
571 if((position != backstop) || (m_match_flags & match_not_bob))
572 return false;
573 // OK match:
574 pstate = pstate->next.p;
575 return true;
576}
577
578template <class BidiIterator, class Allocator, class traits>
579bool perl_matcher<BidiIterator, Allocator, traits>::match_buffer_end()
580{
581 if((position != last) || (m_match_flags & match_not_eob))
582 return false;
583 // OK match:
584 pstate = pstate->next.p;
585 return true;
586}
587
588template <class BidiIterator, class Allocator, class traits>
589bool perl_matcher<BidiIterator, Allocator, traits>::match_backref()
590{
591 //
592 // Compare with what we previously matched.
593 // Note that this succeeds if the backref did not partisipate
594 // in the match, this is in line with ECMAScript, but not Perl
595 // or PCRE.
596 //
597 int index = static_cast<const re_brace*>(pstate)->index;
598 if(index >= 10000)
599 {
600 named_subexpressions::range_type r = re.get_data().equal_range(index);
601 NDNBOOST_ASSERT(r.first != r.second);
602 do
603 {
604 index = r.first->index;
605 ++r.first;
606 }while((r.first != r.second) && ((*m_presult)[index].matched != true));
607 }
608
609 if((m_match_flags & match_perl) && !(*m_presult)[index].matched)
610 return false;
611
612 BidiIterator i = (*m_presult)[index].first;
613 BidiIterator j = (*m_presult)[index].second;
614 while(i != j)
615 {
616 if((position == last) || (traits_inst.translate(*position, icase) != traits_inst.translate(*i, icase)))
617 return false;
618 ++i;
619 ++position;
620 }
621 pstate = pstate->next.p;
622 return true;
623}
624
625template <class BidiIterator, class Allocator, class traits>
626bool perl_matcher<BidiIterator, Allocator, traits>::match_long_set()
627{
628 typedef typename traits::char_class_type char_class_type;
629 // let the traits class do the work:
630 if(position == last)
631 return false;
632 BidiIterator t = re_is_set_member(position, last, static_cast<const re_set_long<char_class_type>*>(pstate), re.get_data(), icase);
633 if(t != position)
634 {
635 pstate = pstate->next.p;
636 position = t;
637 return true;
638 }
639 return false;
640}
641
642template <class BidiIterator, class Allocator, class traits>
643bool perl_matcher<BidiIterator, Allocator, traits>::match_set()
644{
645 if(position == last)
646 return false;
647 if(static_cast<const re_set*>(pstate)->_map[static_cast<unsigned char>(traits_inst.translate(*position, icase))])
648 {
649 pstate = pstate->next.p;
650 ++position;
651 return true;
652 }
653 return false;
654}
655
656template <class BidiIterator, class Allocator, class traits>
657bool perl_matcher<BidiIterator, Allocator, traits>::match_jump()
658{
659 pstate = static_cast<const re_jump*>(pstate)->alt.p;
660 return true;
661}
662
663template <class BidiIterator, class Allocator, class traits>
664bool perl_matcher<BidiIterator, Allocator, traits>::match_combining()
665{
666 if(position == last)
667 return false;
668 if(is_combining(traits_inst.translate(*position, icase)))
669 return false;
670 ++position;
671 while((position != last) && is_combining(traits_inst.translate(*position, icase)))
672 ++position;
673 pstate = pstate->next.p;
674 return true;
675}
676
677template <class BidiIterator, class Allocator, class traits>
678bool perl_matcher<BidiIterator, Allocator, traits>::match_soft_buffer_end()
679{
680 if(m_match_flags & match_not_eob)
681 return false;
682 BidiIterator p(position);
683 while((p != last) && is_separator(traits_inst.translate(*p, icase)))++p;
684 if(p != last)
685 return false;
686 pstate = pstate->next.p;
687 return true;
688}
689
690template <class BidiIterator, class Allocator, class traits>
691bool perl_matcher<BidiIterator, Allocator, traits>::match_restart_continue()
692{
693 if(position == search_base)
694 {
695 pstate = pstate->next.p;
696 return true;
697 }
698 return false;
699}
700
701template <class BidiIterator, class Allocator, class traits>
702bool perl_matcher<BidiIterator, Allocator, traits>::match_backstep()
703{
704#ifdef NDNBOOST_MSVC
705#pragma warning(push)
706#pragma warning(disable:4127)
707#endif
708 if( ::ndnboost::is_random_access_iterator<BidiIterator>::value)
709 {
710 std::ptrdiff_t maxlen = ::ndnboost::re_detail::distance(backstop, position);
711 if(maxlen < static_cast<const re_brace*>(pstate)->index)
712 return false;
713 std::advance(position, -static_cast<const re_brace*>(pstate)->index);
714 }
715 else
716 {
717 int c = static_cast<const re_brace*>(pstate)->index;
718 while(c--)
719 {
720 if(position == backstop)
721 return false;
722 --position;
723 }
724 }
725 pstate = pstate->next.p;
726 return true;
727#ifdef NDNBOOST_MSVC
728#pragma warning(pop)
729#endif
730}
731
732template <class BidiIterator, class Allocator, class traits>
733inline bool perl_matcher<BidiIterator, Allocator, traits>::match_assert_backref()
734{
735 // return true if marked sub-expression N has been matched:
736 int index = static_cast<const re_brace*>(pstate)->index;
737 bool result = false;
738 if(index == 9999)
739 {
740 // Magic value for a (DEFINE) block:
741 return false;
742 }
743 else if(index > 0)
744 {
745 // Have we matched subexpression "index"?
746 // Check if index is a hash value:
747 if(index >= 10000)
748 {
749 named_subexpressions::range_type r = re.get_data().equal_range(index);
750 while(r.first != r.second)
751 {
752 if((*m_presult)[r.first->index].matched)
753 {
754 result = true;
755 break;
756 }
757 ++r.first;
758 }
759 }
760 else
761 {
762 result = (*m_presult)[index].matched;
763 }
764 pstate = pstate->next.p;
765 }
766 else
767 {
768 // Have we recursed into subexpression "index"?
769 // If index == 0 then check for any recursion at all, otherwise for recursion to -index-1.
770 int idx = -index-1;
771 if(idx >= 10000)
772 {
773 named_subexpressions::range_type r = re.get_data().equal_range(idx);
774 int stack_index = recursion_stack.empty() ? -1 : recursion_stack.back().idx;
775 while(r.first != r.second)
776 {
777 result |= (stack_index == r.first->index);
778 if(result)break;
779 ++r.first;
780 }
781 }
782 else
783 {
784 result = !recursion_stack.empty() && ((recursion_stack.back().idx == idx) || (index == 0));
785 }
786 pstate = pstate->next.p;
787 }
788 return result;
789}
790
791template <class BidiIterator, class Allocator, class traits>
792bool perl_matcher<BidiIterator, Allocator, traits>::match_toggle_case()
793{
794 // change our case sensitivity:
795 this->icase = static_cast<const re_case*>(pstate)->icase;
796 pstate = pstate->next.p;
797 return true;
798}
799
800
801template <class BidiIterator, class Allocator, class traits>
802bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_any()
803{
804#ifdef NDNBOOST_MSVC
805#pragma warning(push)
806#pragma warning(disable:4127)
807#endif
808 const unsigned char* _map = re.get_map();
809 while(true)
810 {
811 // skip everything we can't match:
812 while((position != last) && !can_start(*position, _map, (unsigned char)mask_any) )
813 ++position;
814 if(position == last)
815 {
816 // run out of characters, try a null match if possible:
817 if(re.can_be_null())
818 return match_prefix();
819 break;
820 }
821 // now try and obtain a match:
822 if(match_prefix())
823 return true;
824 if(position == last)
825 return false;
826 ++position;
827 }
828 return false;
829#ifdef NDNBOOST_MSVC
830#pragma warning(pop)
831#endif
832}
833
834template <class BidiIterator, class Allocator, class traits>
835bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_word()
836{
837#ifdef NDNBOOST_MSVC
838#pragma warning(push)
839#pragma warning(disable:4127)
840#endif
841 // do search optimised for word starts:
842 const unsigned char* _map = re.get_map();
843 if((m_match_flags & match_prev_avail) || (position != base))
844 --position;
845 else if(match_prefix())
846 return true;
847 do
848 {
849 while((position != last) && traits_inst.isctype(*position, m_word_mask))
850 ++position;
851 while((position != last) && !traits_inst.isctype(*position, m_word_mask))
852 ++position;
853 if(position == last)
854 break;
855
856 if(can_start(*position, _map, (unsigned char)mask_any) )
857 {
858 if(match_prefix())
859 return true;
860 }
861 if(position == last)
862 break;
863 } while(true);
864 return false;
865#ifdef NDNBOOST_MSVC
866#pragma warning(pop)
867#endif
868}
869
870template <class BidiIterator, class Allocator, class traits>
871bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_line()
872{
873 // do search optimised for line starts:
874 const unsigned char* _map = re.get_map();
875 if(match_prefix())
876 return true;
877 while(position != last)
878 {
879 while((position != last) && !is_separator(*position))
880 ++position;
881 if(position == last)
882 return false;
883 ++position;
884 if(position == last)
885 {
886 if(re.can_be_null() && match_prefix())
887 return true;
888 return false;
889 }
890
891 if( can_start(*position, _map, (unsigned char)mask_any) )
892 {
893 if(match_prefix())
894 return true;
895 }
896 if(position == last)
897 return false;
898 //++position;
899 }
900 return false;
901}
902
903template <class BidiIterator, class Allocator, class traits>
904bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_buf()
905{
906 if((position == base) && ((m_match_flags & match_not_bob) == 0))
907 return match_prefix();
908 return false;
909}
910
911template <class BidiIterator, class Allocator, class traits>
912bool perl_matcher<BidiIterator, Allocator, traits>::find_restart_lit()
913{
914#if 0
915 if(position == last)
916 return false; // can't possibly match if we're at the end already
917
918 unsigned type = (m_match_flags & match_continuous) ?
919 static_cast<unsigned int>(regbase::restart_continue)
920 : static_cast<unsigned int>(re.get_restart_type());
921
922 const kmp_info<char_type>* info = access::get_kmp(re);
923 int len = info->len;
924 const char_type* x = info->pstr;
925 int j = 0;
926 while (position != last)
927 {
928 while((j > -1) && (x[j] != traits_inst.translate(*position, icase)))
929 j = info->kmp_next[j];
930 ++position;
931 ++j;
932 if(j >= len)
933 {
934 if(type == regbase::restart_fixed_lit)
935 {
936 std::advance(position, -j);
937 restart = position;
938 std::advance(restart, len);
939 m_result.set_first(position);
940 m_result.set_second(restart);
941 position = restart;
942 return true;
943 }
944 else
945 {
946 restart = position;
947 std::advance(position, -j);
948 if(match_prefix())
949 return true;
950 else
951 {
952 for(int k = 0; (restart != position) && (k < j); ++k, --restart)
953 {} // dwa 10/20/2000 - warning suppression for MWCW
954 if(restart != last)
955 ++restart;
956 position = restart;
957 j = 0; //we could do better than this...
958 }
959 }
960 }
961 }
962 if((m_match_flags & match_partial) && (position == last) && j)
963 {
964 // we need to check for a partial match:
965 restart = position;
966 std::advance(position, -j);
967 return match_prefix();
968 }
969#endif
970 return false;
971}
972
973} // namespace re_detail
974
975} // namespace ndnboost
976
977#ifdef NDNBOOST_MSVC
978# pragma warning(pop)
979#endif
980
981#ifdef __BORLANDC__
982# pragma option pop
983#endif
984#ifdef NDNBOOST_MSVC
985#pragma warning(push)
986#pragma warning(disable: 4103)
987#endif
988#ifdef NDNBOOST_HAS_ABI_HEADERS
989# include NDNBOOST_ABI_SUFFIX
990#endif
991#ifdef NDNBOOST_MSVC
992#pragma warning(pop)
993#endif
994
995#endif
996