source: NonGTP/Boost/boost/regex/v4/perl_matcher_common.hpp @ 857

Revision 857, 27.4 KB checked in by igarcia, 18 years ago (diff)
Line 
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
31namespace boost{
32namespace re_detail{
33
34template <class BidiIterator, class Allocator, class traits>
35perl_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
47template <class BidiIterator, class Allocator, class traits>
48void 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
89template <class BidiIterator, class Allocator, class traits>
90void 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
103template <class BidiIterator, class Allocator, class traits>
104void 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
111template <class BidiIterator, class Allocator, class traits>
112bool 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
135template <class BidiIterator, class Allocator, class traits>
136bool 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
145template <class BidiIterator, class Allocator, class traits>
146bool 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
184template <class BidiIterator, class Allocator, class traits>
185bool 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
194template <class BidiIterator, class Allocator, class traits>
195bool 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
274template <class BidiIterator, class Allocator, class traits>
275bool 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
307template <class BidiIterator, class Allocator, class traits>
308bool 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
326template <class BidiIterator, class Allocator, class traits>
327bool 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
343template <class BidiIterator, class Allocator, class traits>
344bool 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
380template <class BidiIterator, class Allocator, class traits>
381bool 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
412template <class BidiIterator, class Allocator, class traits>
413bool 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
426template <class BidiIterator, class Allocator, class traits>
427bool 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
455template <class BidiIterator, class Allocator, class traits>
456bool 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
493template <class BidiIterator, class Allocator, class traits>
494bool 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
519template <class BidiIterator, class Allocator, class traits>
520bool 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
544template <class BidiIterator, class Allocator, class traits>
545bool 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
569template <class BidiIterator, class Allocator, class traits>
570bool 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
579template <class BidiIterator, class Allocator, class traits>
580bool 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
589template <class BidiIterator, class Allocator, class traits>
590bool 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
606template <class BidiIterator, class Allocator, class traits>
607bool 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
623template <class BidiIterator, class Allocator, class traits>
624bool 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
637template <class BidiIterator, class Allocator, class traits>
638bool perl_matcher<BidiIterator, Allocator, traits>::match_jump()
639{
640   pstate = static_cast<const re_jump*>(pstate)->alt.p;
641   return true;
642}
643
644template <class BidiIterator, class Allocator, class traits>
645bool 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
658template <class BidiIterator, class Allocator, class traits>
659bool 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
671template <class BidiIterator, class Allocator, class traits>
672bool 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
682template <class BidiIterator, class Allocator, class traits>
683bool 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
713template <class BidiIterator, class Allocator, class traits>
714inline 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
722template <class BidiIterator, class Allocator, class traits>
723bool 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
732template <class BidiIterator, class Allocator, class traits>
733bool 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
765template <class BidiIterator, class Allocator, class traits>
766bool 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
801template <class BidiIterator, class Allocator, class traits>
802bool 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
834template <class BidiIterator, class Allocator, class traits>
835bool 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
842template <class BidiIterator, class Allocator, class traits>
843bool 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
Note: See TracBrowser for help on using the repository browser.