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