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