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