3
* Copyright (c) 1998-2002
6
* Permission to use, copy, modify, distribute and sell this software
7
* and its documentation for any purpose is hereby granted without fee,
8
* provided that the above copyright notice appear in all copies and
9
* that both that copyright notice and this permission notice appear
10
* in supporting documentation. Dr John Maddock makes no representations
11
* about the suitability of this software for any purpose.
12
* It is provided "as is" without express or implied warranty.
17
* LOCATION: see http://www.boost.org for most recent version.
18
* FILE regex_match.hpp
19
* VERSION see <boost/version.hpp>
20
* DESCRIPTION: Regular expression matching algorithms.
21
* Note this is an internal header file included
22
* by regex.hpp, do not include on its own.
26
#ifndef BOOST_REGEX_MATCH_HPP
27
#define BOOST_REGEX_MATCH_HPP
29
#ifndef BOOST_REGEX_MAX_STATE_COUNT
30
# define BOOST_REGEX_MAX_STATE_COUNT 100000000
33
#include <boost/limits.hpp>
40
#pragma option push -a8 -b -Vx -Ve -pc -w-8026 -w-8027
44
// Unfortunately Rogue Waves standard library appears to have a bug
45
// in std::basic_string::compare that results in eroneous answers
46
// in some cases (tested with Borland C++ 5.1, Rogue Wave lib version
47
// 0x020101) the test case was:
48
// {39135,0} < {0xff,0}
49
// which succeeds when it should not.
52
# define STR_COMP(s,p) s.compare(p)
54
template <class C, class T, class A>
55
inline int string_compare(const std::basic_string<C,T,A>& s, const C* p)
56
{ return s.compare(p); }
57
inline int string_compare(const std::string& s, const char* p)
58
{ return std::strcmp(s.c_str(), p); }
59
# ifndef BOOST_NO_WREGEX
60
inline int string_compare(const std::wstring& s, const wchar_t* p)
61
{ return std::wcscmp(s.c_str(), p); }
63
# define STR_COMP(s,p) string_compare(s,p)
67
inline const charT* re_skip_past_null(const charT* p)
73
template <class iterator, class charT, class traits_type, class Allocator>
74
iterator BOOST_REGEX_CALL re_is_set_member(iterator next,
76
const re_set_long* set_,
77
const reg_expression<charT, traits_type, Allocator>& e)
79
const charT* p = reinterpret_cast<const charT*>(set_+1);
82
bool icase = e.flags() & regbase::icase;
84
if(next == last) return next;
86
typedef typename traits_type::string_type traits_string_type;
87
const traits_type& traits_inst = e.get_traits();
89
// dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never
93
// try and match a single character, could be a multi-character
94
// collating element...
95
for(i = 0; i < set_->csingles; ++i)
100
// treat null string as special case:
101
if(traits_inst.translate(*ptr, icase) != *p)
106
return set_->isnot ? next : (ptr == next) ? ++next : ptr;
110
while(*p && (ptr != last))
112
if(traits_inst.translate(*ptr, icase) != *p)
118
if(*p == 0) // if null we've matched
119
return set_->isnot ? next : (ptr == next) ? ++next : ptr;
121
p = re_skip_past_null(p); // skip null
125
charT col = traits_inst.translate(*next, icase);
128
if(set_->cranges || set_->cequivalents)
130
traits_string_type s2(1, col);
131
traits_string_type s1;
133
// try and match a range, NB only a single character can match
136
if(e.flags() & regbase::nocollate)
139
traits_inst.transform(s1, s2);
140
for(i = 0; i < set_->cranges; ++i)
142
if(STR_COMP(s1, p) <= 0)
146
if(STR_COMP(s1, p) >= 0)
147
return set_->isnot ? next : ++next;
155
// skip second string
161
// try and match an equivalence class, NB only a single character can match
162
if(set_->cequivalents)
164
traits_inst.transform_primary(s1, s2);
165
for(i = 0; i < set_->cequivalents; ++i)
167
if(STR_COMP(s1, p) == 0)
168
return set_->isnot ? next : ++next;
175
if(traits_inst.is_class(col, set_->cclasses) == true)
176
return set_->isnot ? next : ++next;
177
return set_->isnot ? ++next : next;
180
template <class iterator, class Allocator>
181
class _priv_match_data
184
typedef typename boost::detail::rebind_allocator<int, Allocator>::type i_alloc;
185
typedef typename boost::detail::rebind_allocator<iterator, Allocator>::type it_alloc;
186
typedef typename regex_iterator_traits<iterator>::difference_type difference_type;
188
match_results_base<iterator, Allocator> temp_match;
190
jstack<match_results_base<iterator, Allocator>, Allocator> matches;
191
jstack<iterator, Allocator> prev_pos;
192
jstack<const re_syntax_base*, Allocator> prev_record;
193
jstack<int, Allocator> prev_acc;
195
unsigned int caccumulators;
196
difference_type state_count;
197
difference_type max_state_count;
198
iterator* loop_starts;
200
_priv_match_data(const match_results_base<iterator, Allocator>&, iterator, iterator, std::size_t);
207
void set_accumulator_size(unsigned int size);
208
int* get_accumulators()
212
iterator* get_loop_starts()
216
void estimate_max_state_count(iterator a, iterator b, std::size_t states, std::random_access_iterator_tag*)
218
#ifndef BOOST_NO_STD_DISTANCE
219
difference_type dist = std::distance(a,b);
221
difference_type dist = b - a;
224
difference_type lim = std::numeric_limits<difference_type>::max() - 1000 - states;
225
if(dist > (difference_type)(lim / states))
226
max_state_count = lim;
228
max_state_count = 1000 + states * dist;
230
void estimate_max_state_count(iterator a, iterator b, std::size_t states, void*)
232
// we don't know how long the sequence is:
233
max_state_count = BOOST_REGEX_MAX_STATE_COUNT;
237
template <class iterator, class Allocator>
238
_priv_match_data<iterator, Allocator>::_priv_match_data(const match_results_base<iterator, Allocator>& m, iterator a, iterator b, std::size_t states)
239
: temp_match(m), matches(64, m.allocator()), prev_pos(64, m.allocator()), prev_record(64, m.allocator())
241
typedef typename regex_iterator_traits<iterator>::iterator_category category;
247
estimate_max_state_count(a, b, states, static_cast<category*>(0));
250
template <class iterator, class Allocator>
251
void _priv_match_data<iterator, Allocator>::set_accumulator_size(unsigned int size)
253
if(size > caccumulators)
256
caccumulators = size;
257
accumulators = i_alloc(temp_match.allocator()).allocate(caccumulators);
258
BOOST_REGEX_NOEH_ASSERT(accumulators)
259
loop_starts = it_alloc(temp_match.allocator()).allocate(caccumulators);
260
BOOST_REGEX_NOEH_ASSERT(loop_starts)
261
for(unsigned i = 0; i < caccumulators; ++i)
262
new (loop_starts + i) iterator();
266
template <class iterator, class Allocator>
267
void _priv_match_data<iterator, Allocator>::m_free()
271
i_alloc temp1(temp_match.allocator());
272
temp1.deallocate(accumulators, caccumulators);
273
for(unsigned i = 0; i < caccumulators; ++i)
274
::boost::re_detail::pointer_destroy(loop_starts + i);
275
it_alloc temp2(temp_match.allocator());
276
temp2.deallocate(loop_starts, caccumulators);
280
template <class charT, class traits, class Allocator>
281
struct access_t : public reg_expression<charT, traits, Allocator>
283
typedef typename is_byte<charT>::width_type width_type;
284
typedef reg_expression<charT, traits, Allocator> base_type;
285
typedef charT char_type;
286
typedef traits traits_type;
287
typedef Allocator alloc_type;
289
static int repeat_count(const base_type& b)
290
{ return base_type::repeat_count(b); }
291
static unsigned int restart_type(const base_type& b)
292
{ return base_type::restart_type(b); }
293
static const re_syntax_base* first(const base_type& b)
294
{ return base_type::first(b); }
295
static const unsigned char* get_map(const base_type& b)
296
{ return base_type::get_map(b); }
297
static std::size_t leading_length(const base_type& b)
298
{ return base_type::leading_length(b); }
299
static const kmp_info<charT>* get_kmp(const base_type& b)
300
{ return base_type::get_kmp(b); }
301
static bool can_start(char_type c, const unsigned char* _map, unsigned char mask)
303
return reg_expression<char_type, traits_type, alloc_type>::can_start(c, _map, mask, width_type());
308
#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE)
311
// template don't merge if they contain switch statements so declare these
312
// templates in unnamed namespace (ie with internal linkage), each translation
313
// unit then gets its own local copy, it works seemlessly but bloats the app.
317
template <class iterator, class Allocator, class charT, class traits, class Allocator2>
318
bool query_match_aux(iterator first,
320
match_results<iterator, Allocator>& m,
321
const reg_expression<charT, traits, Allocator2>& e,
323
_priv_match_data<iterator, Allocator>& pd,
326
typedef access_t<charT, traits, Allocator2> access;
328
if(e.flags() & regbase::failbit)
331
typedef typename traits::size_type traits_size_type;
332
typedef typename traits::uchar_type traits_uchar_type;
333
typedef typename is_byte<charT>::width_type width_type;
334
typedef typename re_detail::regex_iterator_traits<iterator>::difference_type difference_type;
336
// declare some local aliases to reduce pointer loads
337
// good optimising compilers should make this unnecessary!!
338
jstack<match_results_base<iterator, Allocator>, Allocator>& matches = pd.matches;
339
jstack<iterator, Allocator>& prev_pos = pd.prev_pos;
340
jstack<const re_syntax_base*, Allocator>& prev_record = pd.prev_record;
341
jstack<int, Allocator>& prev_acc = pd.prev_acc;
342
match_results_base<iterator, Allocator>& temp_match = pd.temp_match;
343
temp_match.set_first(first);
344
difference_type& state_count = pd.state_count;
346
const re_syntax_base* ptr = access::first(e);
347
bool match_found = false;
348
bool have_partial_match = false;
349
bool unwind_stack = false;
350
bool need_push_match = (e.mark_count() > 1);
351
int cur_acc = -1; // no active accumulator
352
pd.set_accumulator_size(access::repeat_count(e));
353
int* accumulators = pd.get_accumulators();
354
iterator* start_loop = pd.get_loop_starts();
356
bool icase = e.flags() & regbase::icase;
358
iterator base = first;
359
const traits& traits_inst = e.get_traits();
360
// dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never
364
// prepare m for failure:
366
if((flags & match_init) == 0)
368
m.init_fail(first, last);
379
case syntax_element_match:
382
// match found, save then fallback in case we missed a
384
if((flags & match_not_null) && (first == temp_match[0].first))
386
if((flags & match_all) && (first != last))
388
temp_match.set_second(first);
389
m.maybe_assign(temp_match);
391
if(((flags & match_any) && ((first == last) || !(flags & match_all))) || ((first == last) && (need_push_match == false)))
393
// either we don't care what we match or we've matched
394
// the whole string and can't match anything longer.
395
while(matches.empty() == false)
397
while(prev_pos.empty() == false)
399
while(prev_record.empty() == false)
401
while(prev_acc.empty() == false)
407
case syntax_element_startmark:
409
if(static_cast<const re_brace*>(ptr)->index > 0)
411
temp_match.set_first(first, static_cast<const re_brace*>(ptr)->index);
414
(static_cast<const re_brace*>(ptr)->index == -1)
415
|| (static_cast<const re_brace*>(ptr)->index == -2)
418
matches.push(temp_match);
419
for(k = 0; k <= cur_acc; ++k)
420
prev_pos.push(start_loop[k]);
421
prev_pos.push(first);
422
prev_record.push(ptr);
423
for(k = 0; k <= cur_acc; ++k)
424
prev_acc.push(accumulators[k]);
425
prev_acc.push(cur_acc);
426
prev_acc.push(match_found);
428
// skip next jump and fall through:
433
case syntax_element_endmark:
435
if(static_cast<const re_brace*>(ptr)->index > 0)
437
temp_match.set_second(first, static_cast<const re_brace*>(ptr)->index);
440
(static_cast<const re_brace*>(ptr)->index == -1)
441
|| (static_cast<const re_brace*>(ptr)->index == -2)
450
case syntax_element_literal:
452
unsigned int len = static_cast<const re_literal*>(ptr)->length;
453
const charT* what = reinterpret_cast<const charT*>(static_cast<const re_literal*>(ptr) + 1);
455
// compare string with what we stored in
457
for(unsigned int i = 0; i < len; ++i, ++first)
459
if((first == last) || (traits_inst.translate(*first, icase) != what[i]))
465
case syntax_element_start_line:
467
if(first == temp_match[0].first)
469
// we're at the start of the buffer
470
if(flags & match_prev_avail)
473
// check the previous value even though its before
474
// the start of our "buffer".
477
if(traits::is_separator(*t) && !((*t == '\r') && (*first == '\n')) )
484
if((flags & match_not_bol) == 0)
491
// we're in the middle of the string
492
goto inner_line_check;
493
case syntax_element_end_line:
494
// we're not yet at the end so *first is always valid:
495
if(traits::is_separator(*first))
497
if((first != base) || (flags & match_prev_avail))
499
// check that we're not in the middle of \r\n sequence
502
if((*t == '\r') && (*first == '\n'))
511
case syntax_element_wild:
512
// anything except possibly NULL or \n:
513
if(traits::is_separator(*first))
515
if(flags & match_not_dot_newline)
521
if(*first == charT(0))
523
if(flags & match_not_dot_null)
532
case syntax_element_word_boundary:
534
// prev and this character must be opposites:
535
#if defined(BOOST_REGEX_USE_C_LOCALE) && defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)
536
bool b = traits::is_class(*first, traits::char_class_word);
538
bool b = traits_inst.is_class(*first, traits::char_class_word);
540
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
542
if(flags & match_not_bow)
550
b ^= traits_inst.is_class(*first, traits::char_class_word);
560
case syntax_element_within_word:
561
// both prev and this character must be traits::char_class_word:
562
if(traits_inst.is_class(*first, traits::char_class_word))
565
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
570
b = traits_inst.is_class(*first, traits::char_class_word);
580
case syntax_element_word_start:
581
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
584
if(flags & match_not_bow)
586
if(traits_inst.is_class(*first, traits::char_class_word))
593
// otherwise inside buffer:
594
if(traits_inst.is_class(*first, traits::char_class_word))
598
if(traits_inst.is_class(*t, traits::char_class_word) == false)
604
goto failure; // if we fall through to here then we've failed
605
case syntax_element_word_end:
606
if((first == temp_match[0].first) && ((flags & match_prev_avail) == 0))
607
goto failure; // start of buffer can't be end of word
609
// otherwise inside buffer:
610
if(traits_inst.is_class(*first, traits::char_class_word) == false)
614
if(traits_inst.is_class(*t, traits::char_class_word))
620
goto failure; // if we fall through to here then we've failed
621
case syntax_element_buffer_start:
622
if((first != temp_match[0].first) || (flags & match_not_bob))
627
case syntax_element_buffer_end:
628
if((first != last) || (flags & match_not_eob))
633
case syntax_element_backref:
635
// compare with what we previously matched:
636
iterator i = temp_match[static_cast<const re_brace*>(ptr)->index].first;
637
iterator j = temp_match[static_cast<const re_brace*>(ptr)->index].second;
640
if((first == last) || (traits_inst.translate(*first, icase) != traits_inst.translate(*i, icase)))
648
case syntax_element_long_set:
650
// let the traits class do the work:
651
iterator t = re_is_set_member(first, last, static_cast<const re_set_long*>(ptr), e);
660
case syntax_element_set:
661
// lookup character in table:
662
if(static_cast<const re_set*>(ptr)->_map[(traits_uchar_type)traits_inst.translate(*first, icase)])
669
case syntax_element_jump:
670
ptr = static_cast<const re_jump*>(ptr)->alt.p;
672
case syntax_element_alt:
675
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, (unsigned char)mask_take))
677
// we can take the first alternative,
678
// see if we need to push next alternative:
679
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, mask_skip))
682
matches.push(temp_match);
683
for(k = 0; k <= cur_acc; ++k)
684
prev_pos.push(start_loop[k]);
685
prev_pos.push(first);
686
prev_record.push(ptr);
687
for(k = 0; k <= cur_acc; ++k)
688
prev_acc.push(accumulators[k]);
689
prev_acc.push(cur_acc);
694
if(access::can_start(*first, static_cast<const re_jump*>(ptr)->_map, mask_skip))
696
ptr = static_cast<const re_jump*>(ptr)->alt.p;
699
goto failure; // neither option is possible
701
case syntax_element_rep:
704
// if we're moving to a higher id (nested repeats etc)
705
// zero out our accumualtors:
706
if(cur_acc < static_cast<const re_repeat*>(ptr)->id)
708
cur_acc = static_cast<const re_repeat*>(ptr)->id;
709
accumulators[cur_acc] = 0;
710
start_loop[cur_acc] = first;
713
cur_acc = static_cast<const re_repeat*>(ptr)->id;
715
if(static_cast<const re_repeat*>(ptr)->leading)
718
//charT c = traits_inst.translate(*first);
720
// first of all test for special case where this is last element,
721
// if that is the case then repeat as many times as possible,
722
// as long as the repeat is greedy:
724
if((static_cast<const re_repeat*>(ptr)->alt.p->type == syntax_element_match)
725
&& (static_cast<const re_repeat*>(ptr)->greedy == true))
727
// see if we can take the repeat:
728
if(((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->max)
729
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_take))
731
// push terminating match as fallback:
732
if((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min)
734
if((prev_record.empty() == false) && (prev_record.peek() == static_cast<const re_repeat*>(ptr)->alt.p))
736
// we already have the required fallback
737
// don't add any more, just update this one:
739
matches.peek() = temp_match;
740
prev_pos.peek() = first;
745
matches.push(temp_match);
746
prev_pos.push(first);
747
prev_record.push(static_cast<const re_repeat*>(ptr)->alt.p);
750
// move to next item in list:
751
if((first != start_loop[cur_acc]) || !accumulators[cur_acc])
753
++accumulators[cur_acc];
755
start_loop[cur_acc] = first;
758
else if((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->min)
760
// the repeat was null, and we haven't gone round min times yet,
761
// since all subsequent repeats will be null as well, just update
762
// our repeat count and skip out.
763
accumulators[cur_acc] = static_cast<const re_repeat*>(ptr)->min;
764
ptr = static_cast<const re_repeat*>(ptr)->alt.p;
769
// see if we can skip the repeat:
770
if(((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min)
771
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_skip))
773
ptr = static_cast<const re_repeat*>(ptr)->alt.p;
780
// OK if we get to here then the repeat is either non-terminal or non-greedy,
781
// see if we can skip the repeat:
782
if(((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min)
783
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_skip))
785
// see if we can push failure info:
786
if(((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->max)
787
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_take))
789
// check to see if the last loop matched a NULL string
790
// if so then we really don't want to loop again:
791
if(((unsigned int)accumulators[cur_acc] == static_cast<const re_repeat*>(ptr)->min)
792
|| (first != start_loop[cur_acc]))
795
matches.push(temp_match);
796
prev_pos.push(first);
797
prev_record.push(ptr);
798
for(k = 0; k <= cur_acc; ++k)
799
prev_acc.push(accumulators[k]);
800
// for non-greedy repeats save whether we have a match already:
801
if(static_cast<const re_repeat*>(ptr)->greedy == false)
803
prev_acc.push(match_found);
808
ptr = static_cast<const re_repeat*>(ptr)->alt.p;
812
// otherwise see if we can take the repeat:
813
if(((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->max)
814
&& access::can_start(*first, static_cast<const re_repeat*>(ptr)->_map, mask_take) &&
815
((first != start_loop[cur_acc]) || !accumulators[cur_acc]))
817
// move to next item in list:
818
++accumulators[cur_acc];
820
start_loop[cur_acc] = first;
823
else if((first == start_loop[cur_acc]) && accumulators[cur_acc] && ((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->min))
825
// the repeat was null, and we haven't gone round min times yet,
826
// since all subsequent repeats will be null as well, just update
827
// our repeat count and skip out.
828
accumulators[cur_acc] = static_cast<const re_repeat*>(ptr)->min;
829
ptr = static_cast<const re_repeat*>(ptr)->alt.p;
833
// if we get here then neither option is allowed so fail:
837
case syntax_element_combining:
838
if(traits_inst.is_combining(traits_inst.translate(*first, icase)))
841
while((first != last) && traits_inst.is_combining(traits_inst.translate(*first, icase)))++first;
844
case syntax_element_soft_buffer_end:
846
if(flags & match_not_eob)
849
while((p != last) && traits_inst.is_separator(traits_inst.translate(*p, icase)))++p;
855
case syntax_element_restart_continue:
856
if(first != temp_match[-1].first)
861
jm_assert(0); // should never get to here!!
867
// if we get to here then we've run out of characters to match against,
868
// we could however still have non-character regex items left
869
if((ptr->can_be_null == 0) && ((flags & match_partial) == 0))
877
case syntax_element_match:
879
case syntax_element_startmark:
880
goto start_mark_jump;
881
case syntax_element_endmark:
883
case syntax_element_start_line:
884
goto outer_line_check;
885
case syntax_element_end_line:
886
// we're at the end so *first is never valid:
887
if((flags & match_not_eol) == 0)
893
case syntax_element_word_boundary:
894
case syntax_element_word_end:
895
if(((flags & match_not_eow) == 0) && (first != temp_match[0].first))
899
if(traits_inst.is_class(*t, traits::char_class_word))
906
case syntax_element_buffer_end:
907
case syntax_element_soft_buffer_end:
908
if(flags & match_not_eob)
913
case syntax_element_jump:
914
ptr = static_cast<const re_jump*>(ptr)->alt.p;
916
case syntax_element_alt:
917
if(ptr->can_be_null & mask_take)
919
// we can test the first alternative,
920
// see if we need to push next alternative:
921
if(ptr->can_be_null & mask_skip)
924
matches.push(temp_match);
925
for(k = 0; k <= cur_acc; ++k)
926
prev_pos.push(start_loop[k]);
927
prev_pos.push(first);
928
prev_record.push(ptr);
929
for(k = 0; k <= cur_acc; ++k)
930
prev_acc.push(accumulators[k]);
931
prev_acc.push(cur_acc);
936
if(ptr->can_be_null & mask_skip)
938
ptr = static_cast<const re_jump*>(ptr)->alt.p;
941
goto failure; // neither option is possible
942
case syntax_element_rep:
943
// if we're moving to a higher id (nested repeats etc)
944
// zero out our accumualtors:
945
if(cur_acc < static_cast<const re_repeat*>(ptr)->id)
947
cur_acc = static_cast<const re_repeat*>(ptr)->id;
948
accumulators[cur_acc] = 0;
949
start_loop[cur_acc] = first;
952
cur_acc = static_cast<const re_repeat*>(ptr)->id;
954
// see if we can skip the repeat:
955
if(((unsigned int)accumulators[cur_acc] >= static_cast<const re_repeat*>(ptr)->min)
956
&& ((ptr->can_be_null & mask_skip) || (flags & match_partial)))
958
// don't push failure info, there's no point:
959
ptr = static_cast<const re_repeat*>(ptr)->alt.p;
963
// otherwise see if we can take the repeat:
964
if(((unsigned int)accumulators[cur_acc] < static_cast<const re_repeat*>(ptr)->max)
965
&& (((ptr->can_be_null & (mask_take | mask_skip)) == (mask_take | mask_skip))) || (flags & match_partial))
967
// move to next item in list:
968
++accumulators[cur_acc];
970
start_loop[cur_acc] = first;
974
// if we get here then neither option is allowed so fail:
976
case syntax_element_restart_continue:
977
if(first != temp_match[-1].first)
981
case syntax_element_backref:
982
if(temp_match[static_cast<const re_brace*>(ptr)->index].first
983
!= temp_match[static_cast<const re_brace*>(ptr)->index].second)
995
// check to see if we've been searching too many states:
997
if(state_count >= pd.max_state_count)
999
#ifndef BOOST_NO_EXCEPTIONS
1000
throw std::runtime_error("Max regex search depth exceeded.");
1002
while(matches.empty() == false)
1004
while(prev_pos.empty() == false)
1006
while(prev_record.empty() == false)
1008
while(prev_acc.empty() == false)
1015
// check for possible partial match:
1017
if((flags & match_partial)
1018
&& !match_found // no full match already
1019
&& (base != first) // some charcters have been consumed
1020
&& (first == last)) // end of input has been reached
1022
have_partial_match = true;
1023
temp_match.set_second(first, 0, false);
1024
m.maybe_assign(temp_match);
1027
if(prev_record.empty() == false)
1029
ptr = prev_record.peek();
1032
case syntax_element_alt:
1033
// get next alternative:
1034
ptr = static_cast<const re_jump*>(ptr)->alt.p;
1036
matches.pop(temp_match);
1037
prev_acc.pop(cur_acc);
1038
for(k = cur_acc; k >= 0; --k)
1039
prev_acc.pop(accumulators[k]);
1040
prev_pos.pop(first);
1041
for(k = cur_acc; k >= 0; --k)
1042
prev_pos.pop(start_loop[k]);
1044
if(unwind_stack) goto failure; // unwinding forward assert
1046
case syntax_element_rep:
1048
// we're doing least number of repeats first,
1049
// increment count and repeat again:
1050
bool saved_matched = match_found;
1052
matches.pop(temp_match);
1053
prev_pos.pop(first);
1054
cur_acc = static_cast<const re_repeat*>(ptr)->id;
1055
if(static_cast<const re_repeat*>(ptr)->greedy == false)
1057
saved_matched = prev_acc.peek();
1060
for(k = cur_acc; k >= 0; --k)
1061
prev_acc.pop(accumulators[k]);
1063
if(unwind_stack) goto failure; // unwinding forward assert
1064
if((unsigned int)++accumulators[cur_acc] > static_cast<const re_repeat*>(ptr)->max)
1065
goto failure; // repetions exhausted.
1067
// if the repeat is non-greedy, and we found a match then fail again:
1068
if((static_cast<const re_repeat*>(ptr)->greedy == false) && (match_found == true))
1072
else if (match_found == false)
1073
match_found = saved_matched;
1075
start_loop[cur_acc] = first;
1078
case syntax_element_startmark:
1080
bool saved_matched = match_found;
1081
matches.pop(temp_match);
1082
match_found = prev_acc.peek();
1084
prev_acc.pop(cur_acc);
1085
for(k = cur_acc; k >= 0; --k)
1086
prev_acc.pop(accumulators[k]);
1087
prev_pos.pop(first);
1088
for(k = cur_acc; k >= 0; --k)
1089
prev_pos.pop(start_loop[k]);
1091
unwind_stack = false;
1092
if(static_cast<const re_brace*>(ptr)->index == -1)
1094
if (saved_matched == false)
1096
ptr = static_cast<const re_jump*>(ptr->next.p)->alt.p->next.p;
1099
if(static_cast<const re_brace*>(ptr)->index == -2)
1101
if (saved_matched == true)
1103
ptr = static_cast<const re_jump*>(ptr->next.p)->alt.p->next.p;
1108
case syntax_element_match:
1110
matches.pop(temp_match);
1111
prev_pos.pop(first);
1113
if(unwind_stack) goto failure; // unwinding forward assert
1117
// mustn't get here!!
1121
if(match_found || have_partial_match)
1127
// if we get to here then everything has failed
1128
// and no match was found:
1131
#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE)
1136
template <class iterator>
1137
void _skip_and_inc(unsigned int& clines, iterator& last_line, iterator& first, const iterator last)
1139
while(first != last)
1143
last_line = ++first;
1151
template <class iterator>
1152
void _skip_and_dec(unsigned int& clines, iterator& last_line, iterator& first, iterator base, std::size_t len)
1154
bool need_line = false;
1155
for(std::size_t i = 0; i < len; ++i)
1169
if(last_line != base)
1174
while((last_line != base) && (*last_line != '\n'))
1176
if(*last_line == '\n')
1181
template <class iterator>
1182
inline void _inc_one(unsigned int& clines, iterator& last_line, iterator& first)
1186
last_line = ++first;
1193
template <class iterator, class Allocator>
1194
struct grep_search_predicate
1196
match_results<iterator, Allocator>* pm;
1197
grep_search_predicate(match_results<iterator, Allocator>* p) : pm(p) {}
1198
bool operator()(const match_results<iterator, Allocator>& m)
1200
*pm = static_cast<const match_results_base<iterator, Allocator>&>(m);
1205
#if !defined(BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS) && !defined(BOOST_NO_FUNCTION_TEMPLATE_ORDERING)
1207
template <class iterator, class Allocator>
1208
inline const match_results_base<iterator, Allocator>& grep_out_type(const grep_search_predicate<iterator, Allocator>& o, const Allocator&)
1215
template <class T, class Allocator>
1216
inline const Allocator& grep_out_type(const T&, const Allocator& a)
1221
#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE)
1224
// template don't merge if they contain switch statements so declare these
1225
// templates in unnamed namespace (ie with internal linkage), each translation
1226
// unit then gets its own local copy, it works seemlessly but bloats the app.
1232
// find all non-overlapping matches within the sequence first last:
1234
template <class Predicate, class I, class charT, class traits, class A, class A2>
1235
unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<charT, traits, A>& e, unsigned flags, A2 a)
1237
typedef access_t<charT, traits, A> access;
1239
if(e.flags() & regbase::failbit)
1242
typedef typename traits::size_type traits_size_type;
1243
typedef typename traits::uchar_type traits_uchar_type;
1244
typedef typename is_byte<charT>::width_type width_type;
1246
match_results<I, A2> m(grep_out_type(foo, a));
1248
m.set_size(e.mark_count(), first, last);
1249
m.set_line(1, first);
1252
unsigned int clines = 1;
1253
unsigned int cmatches = 0;
1254
I last_line = first;
1258
bool leading_match = false;
1259
const traits& traits_inst = e.get_traits();
1260
// dwa 9/13/00 suppress incorrect MSVC warning - it claims this is never
1264
flags |= match_init;
1266
_priv_match_data<I, A2> pd(m, first, last, e.size());
1268
const unsigned char* _map = access::get_map(e);
1273
// special case, only test if can_be_null,
1274
// don't dereference any pointers!!
1275
if(access::first(e)->can_be_null)
1277
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1286
// try one time whatever:
1287
if( access::can_start(*first, _map, (unsigned char)mask_any) )
1289
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1292
leading_match = true;
1295
if(m[0].second == last)
1297
// update to end of what matched
1298
// trying to match again with match_not_null set if this
1299
// is a null match...
1301
if(first == m[0].second)
1303
next_base = m[0].second;
1304
pd.temp_match.init_fail(next_base, last);
1305
m.init_fail(next_base, last);
1306
if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
1315
leading_match = false;
1316
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1317
{} // dwa 10/20/2000 - warning suppression for MWCW
1320
_skip_and_inc(clines, last_line, first, restart);
1325
_skip_and_inc(clines, last_line, first, m[0].second);
1326
next_base = m[0].second;
1327
pd.temp_match.init_fail(next_base, last);
1328
m.init_fail(next_base, last);
1333
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1334
{} // dwa 10/20/2000 - warning suppression for MWCW
1337
_skip_and_inc(clines, last_line, first, restart);
1341
_inc_one(clines, last_line, first);
1342
flags |= match_prev_avail | match_not_bob;
1345
// depending on what the first record is we may be able to
1346
// optimise the search:
1347
type = (flags & match_continuous) ?
1348
static_cast<unsigned int>(regbase::restart_continue)
1349
: static_cast<unsigned int>(access::restart_type(e));
1351
if(type == regbase::restart_buf)
1356
case regbase::restart_lit:
1357
case regbase::restart_fixed_lit:
1359
const kmp_info<charT>* info = access::get_kmp(e);
1360
int len = info->len;
1361
const charT* x = info->pstr;
1363
bool icase = e.flags() & regbase::icase;
1364
while (first != last)
1366
while((j > -1) && (x[j] != traits_inst.translate(*first, icase)))
1367
j = info->kmp_next[j];
1368
_inc_one(clines, last_line, first);
1372
if(type == regbase::restart_fixed_lit)
1374
_skip_and_dec(clines, last_line, first, base, j);
1376
std::advance(restart, len);
1378
m.set_second(restart);
1379
m.set_line(clines, last_line);
1383
if(m[0].second == last)
1385
_skip_and_inc(clines, last_line, first, restart);
1386
next_base = m[0].second;
1387
pd.temp_match.init_fail(next_base, last);
1388
m.init_fail(next_base, last);
1394
_skip_and_dec(clines, last_line, first, base, j);
1395
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1398
m.set_line(clines, last_line);
1402
if(m[0].second == last)
1404
// update to end of what matched
1405
_skip_and_inc(clines, last_line, first, m[0].second);
1406
next_base = m[0].second;
1407
pd.temp_match.init_fail(next_base, last);
1408
m.init_fail(next_base, last);
1413
for(int k = 0; (restart != first) && (k < j); ++k, --restart)
1414
{} // dwa 10/20/2000 - warning suppression for MWCW
1417
_skip_and_inc(clines, last_line, first, restart);
1418
j = 0; //we could do better than this...
1425
case regbase::restart_any:
1427
while(first != last)
1429
if( access::can_start(*first, _map, (unsigned char)mask_any) )
1431
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1434
m.set_line(clines, last_line);
1438
if(m[0].second == last)
1440
// update to end of what matched
1441
// trying to match again with match_not_null set if this
1442
// is a null match...
1444
if(first == m[0].second)
1446
next_base = m[0].second;
1447
pd.temp_match.init_fail(next_base, last);
1448
m.init_fail(next_base, last);
1449
if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
1451
m.set_line(clines, last_line);
1459
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1460
{} // dwa 10/20/2000 - warning suppression for MWCW
1463
_skip_and_inc(clines, last_line, first, restart);
1468
_skip_and_inc(clines, last_line, first, m[0].second);
1469
next_base = m[0].second;
1470
pd.temp_match.init_fail(next_base, last);
1471
m.init_fail(next_base, last);
1477
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1478
{} // dwa 10/20/2000 - warning suppression for MWCW
1481
_skip_and_inc(clines, last_line, first, restart);
1485
_inc_one(clines, last_line, first);
1489
case regbase::restart_word:
1491
// do search optimised for word starts:
1492
while(first != last)
1497
// skip the word characters:
1498
while((first != last) && traits_inst.is_class(*first, traits::char_class_word))
1500
// now skip the white space:
1501
while((first != last) && (traits_inst.is_class(*first, traits::char_class_word) == false))
1505
// hack to work around gcc optimisation bug
1506
// just expand the contents of _inc_one here:
1509
last_line = ++first;
1515
_inc_one(clines, last_line, first);
1521
if( access::can_start(*first, _map, (unsigned char)mask_any) )
1523
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1525
m.set_line(clines, last_line);
1529
if(m[0].second == last)
1531
// update to end of what matched
1532
// trying to match again with match_not_null set if this
1533
// is a null match...
1535
if(first == m[0].second)
1537
next_base = m[0].second;
1538
pd.temp_match.init_fail(next_base, last);
1539
m.init_fail(next_base, last);
1540
if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
1542
m.set_line(clines, last_line);
1550
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1551
{} // dwa 10/20/2000 - warning suppression for MWCW
1554
_skip_and_inc(clines, last_line, first, restart);
1559
_skip_and_inc(clines, last_line, first, m[0].second);
1560
next_base = m[0].second;
1561
pd.temp_match.init_fail(next_base, last);
1562
m.init_fail(next_base, last);
1567
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1568
{} // dwa 10/20/2000 - warning suppression for MWCW
1571
_skip_and_inc(clines, last_line, first, restart);
1575
_inc_one(clines, last_line, first);
1579
case regbase::restart_line:
1581
// do search optimised for line starts:
1582
while(first != last)
1584
// find first charcter after a line break:
1588
while((first != last) && (*first != '\n'))
1599
if( access::can_start(*first, _map, (unsigned char)mask_any) )
1601
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1603
m.set_line(clines, last_line);
1607
if(m[0].second == last)
1609
// update to end of what matched
1610
// trying to match again with match_not_null set if this
1611
// is a null match...
1613
if(first == m[0].second)
1615
next_base = m[0].second;
1616
pd.temp_match.init_fail(next_base, last);
1617
m.init_fail(next_base, last);
1618
if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
1620
m.set_line(clines, last_line);
1628
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1629
{} // dwa 10/20/2000 - warning suppression for MWCW
1632
_skip_and_inc(clines, last_line, first, restart);
1637
_skip_and_inc(clines, last_line, first, m[0].second);
1638
next_base = m[0].second;
1639
pd.temp_match.init_fail(next_base, last);
1640
m.init_fail(next_base, last);
1645
for(unsigned int i = 0; (restart != first) && (i < access::leading_length(e)); ++i, --restart)
1646
{} // dwa 10/20/2000 - warning suppression for MWCW
1649
_skip_and_inc(clines, last_line, first, restart);
1653
_inc_one(clines, last_line, first);
1657
case regbase::restart_continue:
1661
while(first != last)
1663
if( access::can_start(*first, _map, (unsigned char)mask_any) )
1665
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1667
m.set_line(clines, last_line);
1671
if(m[0].second == last)
1673
// update to end of what matched
1674
// trying to match again with match_not_null set if this
1675
// is a null match...
1676
if(first == m[0].second)
1678
next_base = m[0].second;
1679
pd.temp_match.init_fail(next_base, last);
1680
m.init_fail(next_base, last);
1681
if(query_match_aux(first, last, m, e, flags | match_not_null, pd, &restart))
1683
m.set_line(clines, last_line);
1689
return cmatches; // can't continue from null match
1691
_skip_and_inc(clines, last_line, first, m[0].second);
1692
next_base = m[0].second;
1693
pd.temp_match.init_fail(next_base, last);
1694
m.init_fail(next_base, last);
1705
// finally check trailing null string:
1706
if(access::first(e)->can_be_null)
1708
if(query_match_aux(first, last, m, e, flags, pd, &restart))
1710
m.set_line(clines, last_line);
1719
#if defined(BOOST_REGEX_NO_TEMPLATE_SWITCH_MERGE)
1720
} // namespace {anon}
1723
} // namespace re_detail
1727
// returns true if the specified regular expression matches
1728
// the whole of the input. Fills in what matched in m.
1730
template <class iterator, class Allocator, class charT, class traits, class Allocator2>
1731
bool regex_match(iterator first, iterator last, match_results<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default)
1733
// prepare m for failure:
1734
if((flags & match_init) == 0)
1736
m.set_size(e.mark_count(), first, last);
1738
m.set_line(1, first);
1740
flags |= match_all; // must match all of input.
1741
re_detail::_priv_match_data<iterator, Allocator> pd(m, first, last, e.size());
1743
bool result = re_detail::query_match_aux(first, last, m, e, flags, pd, &restart);
1746
template <class iterator, class charT, class traits, class Allocator2>
1747
bool regex_match(iterator first, iterator last, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default)
1749
match_results<iterator> m;
1750
return regex_match(first, last, m, e, flags);
1753
// query_match convenience interfaces:
1754
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
1756
// this isn't really a partial specialisation, but template function
1757
// overloading - if the compiler doesn't support partial specialisation
1758
// then it really won't support this either:
1759
template <class charT, class Allocator, class traits, class Allocator2>
1760
inline bool regex_match(const charT* str,
1761
match_results<const charT*, Allocator>& m,
1762
const reg_expression<charT, traits, Allocator2>& e,
1763
unsigned flags = match_default)
1765
return regex_match(str, str + traits::length(str), m, e, flags);
1768
template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2>
1769
inline bool regex_match(const std::basic_string<charT, ST, SA>& s,
1770
match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
1771
const reg_expression<charT, traits, Allocator2>& e,
1772
unsigned flags = match_default)
1774
return regex_match(s.begin(), s.end(), m, e, flags);
1776
template <class charT, class traits, class Allocator2>
1777
inline bool regex_match(const charT* str,
1778
const reg_expression<charT, traits, Allocator2>& e,
1779
unsigned flags = match_default)
1781
match_results<const charT*> m;
1782
return regex_match(str, str + traits::length(str), m, e, flags);
1785
template <class ST, class SA, class charT, class traits, class Allocator2>
1786
inline bool regex_match(const std::basic_string<charT, ST, SA>& s,
1787
const reg_expression<charT, traits, Allocator2>& e,
1788
unsigned flags = match_default)
1790
typedef typename std::basic_string<charT, ST, SA>::const_iterator iterator;
1791
match_results<iterator> m;
1792
return regex_match(s.begin(), s.end(), m, e, flags);
1794
#else // partial ordering
1795
inline bool regex_match(const char* str,
1798
unsigned flags = match_default)
1800
return regex_match(str, str + regex::traits_type::length(str), m, e, flags);
1802
inline bool regex_match(const char* str,
1804
unsigned flags = match_default)
1806
match_results<const char*> m;
1807
return regex_match(str, str + regex::traits_type::length(str), m, e, flags);
1809
#ifndef BOOST_NO_WREGEX
1810
inline bool regex_match(const wchar_t* str,
1813
unsigned flags = match_default)
1815
return regex_match(str, str + wregex::traits_type::length(str), m, e, flags);
1817
inline bool regex_match(const wchar_t* str,
1819
unsigned flags = match_default)
1821
match_results<const wchar_t*> m;
1822
return regex_match(str, str + wregex::traits_type::length(str), m, e, flags);
1825
inline bool regex_match(const std::string& s,
1826
match_results<std::string::const_iterator, regex::allocator_type>& m,
1828
unsigned flags = match_default)
1830
return regex_match(s.begin(), s.end(), m, e, flags);
1832
inline bool regex_match(const std::string& s,
1834
unsigned flags = match_default)
1836
match_results<std::string::const_iterator, regex::allocator_type> m;
1837
return regex_match(s.begin(), s.end(), m, e, flags);
1839
#if !defined(BOOST_NO_WREGEX)
1840
inline bool regex_match(const std::basic_string<wchar_t>& s,
1841
match_results<std::basic_string<wchar_t>::const_iterator, wregex::allocator_type>& m,
1843
unsigned flags = match_default)
1845
return regex_match(s.begin(), s.end(), m, e, flags);
1847
inline bool regex_match(const std::basic_string<wchar_t>& s,
1849
unsigned flags = match_default)
1851
match_results<std::basic_string<wchar_t>::const_iterator, wregex::allocator_type> m;
1852
return regex_match(s.begin(), s.end(), m, e, flags);
1858
template <class iterator, class Allocator, class charT, class traits, class Allocator2>
1859
bool regex_search(iterator first, iterator last, match_results<iterator, Allocator>& m, const reg_expression<charT, traits, Allocator2>& e, unsigned flags = match_default)
1861
if(e.flags() & regbase::failbit)
1864
typedef typename traits::size_type traits_size_type;
1865
typedef typename traits::uchar_type traits_uchar_type;
1867
return re_detail::reg_grep2(re_detail::grep_search_predicate<iterator, Allocator>(&m), first, last, e, flags, m.allocator());
1871
// regex_search convenience interfaces:
1872
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
1874
// this isn't really a partial specialisation, but template function
1875
// overloading - if the compiler doesn't support partial specialisation
1876
// then it really won't support this either:
1877
template <class charT, class Allocator, class traits, class Allocator2>
1878
inline bool regex_search(const charT* str,
1879
match_results<const charT*, Allocator>& m,
1880
const reg_expression<charT, traits, Allocator2>& e,
1881
unsigned flags = match_default)
1883
return regex_search(str, str + traits::length(str), m, e, flags);
1886
template <class ST, class SA, class Allocator, class charT, class traits, class Allocator2>
1887
inline bool regex_search(const std::basic_string<charT, ST, SA>& s,
1888
match_results<typename std::basic_string<charT, ST, SA>::const_iterator, Allocator>& m,
1889
const reg_expression<charT, traits, Allocator2>& e,
1890
unsigned flags = match_default)
1892
return regex_search(s.begin(), s.end(), m, e, flags);
1894
#else // partial specialisation
1895
inline bool regex_search(const char* str,
1898
unsigned flags = match_default)
1900
return regex_search(str, str + regex::traits_type::length(str), m, e, flags);
1902
#ifndef BOOST_NO_WREGEX
1903
inline bool regex_search(const wchar_t* str,
1906
unsigned flags = match_default)
1908
return regex_search(str, str + wregex::traits_type::length(str), m, e, flags);
1911
inline bool regex_search(const std::string& s,
1912
match_results<std::string::const_iterator, regex::allocator_type>& m,
1914
unsigned flags = match_default)
1916
return regex_search(s.begin(), s.end(), m, e, flags);
1918
#if !defined(BOOST_NO_WREGEX)
1919
inline bool regex_search(const std::basic_string<wchar_t>& s,
1920
match_results<std::basic_string<wchar_t>::const_iterator, wregex::allocator_type>& m,
1922
unsigned flags = match_default)
1924
return regex_search(s.begin(), s.end(), m, e, flags);
1933
// find all non-overlapping matches within the sequence first last:
1935
template <class Predicate, class iterator, class charT, class traits, class Allocator>
1936
inline unsigned int regex_grep(Predicate foo, iterator first, iterator last, const reg_expression<charT, traits, Allocator>& e, unsigned flags = match_default)
1938
return re_detail::reg_grep2(foo, first, last, e, flags, e.allocator());
1942
// regex_grep convenience interfaces:
1943
#ifndef BOOST_NO_FUNCTION_TEMPLATE_ORDERING
1945
// this isn't really a partial specialisation, but template function
1946
// overloading - if the compiler doesn't support partial specialisation
1947
// then it really won't support this either:
1948
template <class Predicate, class charT, class Allocator, class traits>
1949
inline unsigned int regex_grep(Predicate foo, const charT* str,
1950
const reg_expression<charT, traits, Allocator>& e,
1951
unsigned flags = match_default)
1953
return regex_grep(foo, str, str + traits::length(str), e, flags);
1956
template <class Predicate, class ST, class SA, class Allocator, class charT, class traits>
1957
inline unsigned int regex_grep(Predicate foo, const std::basic_string<charT, ST, SA>& s,
1958
const reg_expression<charT, traits, Allocator>& e,
1959
unsigned flags = match_default)
1961
return regex_grep(foo, s.begin(), s.end(), e, flags);
1963
#else // partial specialisation
1964
inline unsigned int regex_grep(bool (*foo)(const cmatch&), const char* str,
1966
unsigned flags = match_default)
1968
return regex_grep(foo, str, str + regex::traits_type::length(str), e, flags);
1970
#ifndef BOOST_NO_WREGEX
1971
inline unsigned int regex_grep(bool (*foo)(const wcmatch&), const wchar_t* str,
1973
unsigned flags = match_default)
1975
return regex_grep(foo, str, str + wregex::traits_type::length(str), e, flags);
1978
inline unsigned int regex_grep(bool (*foo)(const match_results<std::string::const_iterator, regex::allocator_type>&), const std::string& s,
1980
unsigned flags = match_default)
1982
return regex_grep(foo, s.begin(), s.end(), e, flags);
1984
#if !defined(BOOST_NO_WREGEX)
1985
inline unsigned int regex_grep(bool (*foo)(const match_results<std::basic_string<wchar_t>::const_iterator, wregex::allocator_type>&),
1986
const std::basic_string<wchar_t>& s,
1988
unsigned flags = match_default)
1990
return regex_grep(foo, s.begin(), s.end(), e, flags);
2001
} // namespace boost
2003
#endif // BOOST_REGEX_MATCH_HPP