📄 reimpl2.h
字号:
m_pat( new string_type( pat ) ),
m_subst( new string_type( subst ) ),
m_subst_list(),
m_pfirst( NULL ),
m_invisible_groups()
{
}
virtual ~basic_rpattern_base_impl();
regex_arena m_arena; // The sub_expr arena
bool m_fuses_backrefs; // true if the substitution uses backrefs
bool m_floop; // false if m_pfirst->recursive_match_all_ only needs to be called once
bool m_fok_to_recurse; // false if the pattern would recurse too deeply
size_t m_cgroups; // number of groups ( always at least one )
size_t m_cgroups_visible; // number of visible groups
REGEX_FLAGS m_flags; // flags used to customize search/replace
REGEX_MODE m_mode; // Used to pick the fast or safe algorithm
width_type m_nwidth; // width of the pattern
std::auto_ptr<string_type> m_pat; // contains the unparsed pattern
std::auto_ptr<string_type> m_subst; // contains the unparsed substitution
subst_list_type m_subst_list; // used to speed up substitution
std::auto_ptr<sub_expr_base<CI> const> m_pfirst; // first subexpression in pattern
std::list<size_t> m_invisible_groups; // groups w/o backrefs
size_t _cgroups_total() const //throw()
{
return m_cgroups;
}
bool _loops() const //throw()
{
return m_floop;
}
size_t _get_next_group_nbr()
{
return m_cgroups++;
}
void _normalize_string( string_type & str ) const //throw()
{
if( NORMALIZE & flags() )
process_escapes( str, true );
}
bool _save_backrefs() const //throw()
{
return m_fuses_backrefs || ! ( flags() & NOBACKREFS );
}
sub_expr_base<CI> const * _get_first_subexpression() const //throw()
{
return m_pfirst.get();
}
bool _ok_to_recurse() const //throw()
{
switch( m_mode )
{
case MODE_FAST:
return true;
case MODE_SAFE:
return false;
case MODE_MIXED:
return m_fok_to_recurse;
default:
return false;
}
}
// These are virtual so that when the instantiator object implicitly
// instantiates this template, these functions still get external linkage.
virtual bool _do_match( match_param<CI> & param, bool use_null ) const;
virtual bool _do_match( match_param<CI> & param, char_type const * szbegin ) const;
virtual size_t _do_count( match_param<CI> & param, bool use_null ) const;
virtual size_t _do_count( match_param<CI> & param, char_type const * szbegin ) const;
friend struct matcher_helper<CI>;
REGEX_FLAGS flags() const //throw()
{
return m_flags;
}
REGEX_MODE mode() const // throw()
{
return m_mode;
}
width_type get_width() const //throw()
{
return m_nwidth;
}
size_t cgroups() const //throw()
{
return m_cgroups_visible;
}
string_type const & get_pat() const //throw()
{
return *m_pat;
}
string_type const & get_subst() const //throw()
{
return *m_subst;
}
void swap( basic_rpattern_base_impl<CI> & that ) // throw()
{
std::swap( m_fuses_backrefs, that.m_fuses_backrefs );
std::swap( m_floop, that.m_floop );
std::swap( m_fok_to_recurse, that.m_fok_to_recurse );
std::swap( m_cgroups, that.m_cgroups );
std::swap( m_cgroups_visible, that.m_cgroups_visible );
std::swap( m_flags, that.m_flags );
std::swap( m_mode, that.m_mode );
std::swap( m_nwidth, that.m_nwidth );
swap_auto_ptr( m_pat, that.m_pat );
swap_auto_ptr( m_subst, that.m_subst );
swap_auto_ptr( m_pfirst, that.m_pfirst );
m_subst_list.swap( that.m_subst_list );
m_invisible_groups.swap( m_invisible_groups );
m_arena.swap( that.m_arena );
}
static size_t const npos;
};
template< typename CI >
size_t const basic_rpattern_base_impl<CI>::npos = size_t( -1 );
template< typename CI >
struct matcher_helper
{
typedef basic_rpattern_base_impl<CI> rpattern_type;
typedef typename rpattern_type::size_type size_type;
typedef typename rpattern_type::char_type char_type;
typedef typename rpattern_type::traits_type traits_type;
typedef typename rpattern_type::backref_type backref_type;
typedef typename rpattern_type::backref_vector backref_vector;
static match_param<CI> init_param( CI ibegin, CI iend, basic_match_results<CI> & results )
{
results.ibegin = ibegin;
return match_param<CI>( ibegin, iend, & results.m_rgbackrefs );
}
// Here is the main dispatch loop. It is responsible for calling
// match on the current sub-expression and repeating for the next
// sub-expression. It also backtracks the match when it needs to.
template< typename CSTRINGS >
static bool _Do_match_iterative( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur, CSTRINGS )
{
unsafe_stack & s = *param.pstack;
void * jump_ptr = s.set_jump(); // the bottom of the stack
param.icur = icur;
if( ! expr->iterative_match_this_( param, CSTRINGS() ) )
{
return false;
}
for( ;; )
{
do
{
if( param.next == NULL ) // This means we're done
if( param.no0len && param.istart == param.icur )
goto keep_looking;
else
return s.long_jump( jump_ptr ), true;
s.push( expr );
expr = param.next;
}
while( expr->iterative_match_this_( param, CSTRINGS() ) );
do
{
if( jump_ptr == s.set_jump() ) // No more posibilities to try
return false;
s.pop( expr );
keep_looking:;
}
while( ! expr->iterative_rematch_this_( param, CSTRINGS() ) );
}
}
static bool _Do_match_iterative_helper( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur )
{
return _Do_match_iterative( expr, param, icur, false_t() );
}
static bool _Do_match_iterative_helper_c( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur )
{
return _Do_match_iterative( expr, param, icur, true_t() );
}
static bool _Do_match_recursive( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur )
{
return expr->recursive_match_all_( param, icur );
}
static bool _Do_match_recursive_c( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur )
{
return expr->recursive_match_all_c( param, icur );
}
static bool _Do_match_impl( rpattern_type const & pat, match_param<CI> & param, bool const use_null )
{
typedef std::list<size_t>::const_iterator LCI;
typedef bool ( *pfndomatch_t )( sub_expr_base<CI> const * expr, match_param<CI> & param, CI icur );
bool floop = pat._loops();
unsigned flags = pat.flags();
width_type nwidth = pat.get_width();
// If the pstack parameter is not NULL, we should do a safe, iterative match.
// Otherwise, we should do a fast, recursive match.
pfndomatch_t pfndomatch;
if( NULL != param.pstack )
if( use_null )
pfndomatch = &_Do_match_iterative_helper_c;
else
pfndomatch = &_Do_match_iterative_helper;
else
if( use_null )
pfndomatch = &_Do_match_recursive_c;
else
pfndomatch = &_Do_match_recursive;
sub_expr_base<CI> const * pfirst = pat._get_first_subexpression();
param.first = pfirst;
assert( NULL != param.prgbackrefs );
param.prgbackrefs->resize( pat._cgroups_total() );
std::fill( param.prgbackrefs->begin(), param.prgbackrefs->end(), backref_type() );
#ifdef _MSC_VER
__try
{
#endif
if( ! use_null )
{
// If the minimum width of the pattern exceeds the width of the
// string, a succesful match is impossible
if( nwidth.m_min <= ( size_t )std::distance( param.istart, param.istop ) )
{
CI local_istop = param.istop;
std::advance( local_istop, -int( nwidth.m_min ) );
if( RIGHTMOST & flags )
{
// begin trying to match after the last character.
// Continue to the beginning
for( CI icur = local_istop; icur >= param.istart; --icur, param.no0len = false )
if( ( *pfndomatch )( pfirst, param, icur ) )
break; // m_floop not used for rightmost matches
}
else
{
// begin trying to match before the first character.
// Continue to the end
for( CI icur = param.istart; icur <= local_istop; ++icur, param.no0len = false )
if( ( *pfndomatch )( pfirst, param, icur ) || ! floop )
break;
}
}
}
else
{
assert( 0 == ( RIGHTMOST & flags ) );
// begin trying to match before the first character.
// Continue to the end
for( CI icur = param.istart; ; ++icur, param.no0len = false )
{
if( ( *pfndomatch )( pfirst, param, icur ) || ! floop )
break;
if( traits_type::eq( REGEX_CHAR(char_type,'\0'), *icur ) )
break;
}
}
#ifdef _MSC_VER
}
__except( REGEX_STACK_OVERFLOW == _exception_code() )
{
// we have overflowed the stack. reset the guard page.
_resetstkoflw();
// This match fails silently.
std::fill( param.prgbackrefs->begin(), param.prgbackrefs->end(), backref_tag<CI>() );
}
#endif
// Remove information about the "invisible" groups
if( ( *param.prgbackrefs )[0].matched )
{
size_t dropped = 0;
std::list<size_t> const & l = pat.m_invisible_groups;
for( LCI curr = l.begin(), next = l.begin(); curr != l.end(); curr = next, ++dropped )
{
if( ++next == l.end() )
{
std::copy(
param.prgbackrefs->begin() + *curr + 1,
param.prgbackrefs->end(),
param.prgbackrefs->begin() + *curr - dropped );
}
else
{
std::copy(
param.prgbackrefs->begin() + *curr + 1,
param.prgbackrefs->begin() + *next,
param.prgbackrefs->begin() + *curr - dropped );
}
}
param.prgbackrefs->resize( param.prgbackrefs->size() - dropped );
}
else
{
param.prgbackrefs->resize( param.prgbackrefs->size() - pat.m_invisible_groups.size() );
}
return ( *param.prgbackrefs )[0].matched;
}
static bool _Do_match_with_stack( rpattern_type const & pat, match_param<CI> & param, bool const use_null );
static bool _Do_match( rpattern_type const & pat, match_param<CI> & param, bool const use_null )
{
if( pat._ok_to_recurse() )
return _Do_match_impl( pat, param, use_null );
return _Do_match_with_stack( pat, param, use_null );
}
template< typename CH, typename TR, typename AL >
static size_t _Do_subst_internal(
std::basic_string<CH, TR, AL> & str,
basic_subst_results<CH, TR, AL> const & results,
rpattern_type const & pat,
size_type strpos,
size_type strlen )
{
typedef subst_list_type::const_iterator LCI;
enum { UPPER = -1, NIL, LOWER } next = NIL, rest = NIL;
bool first = true;
size_t old_strpos = strpos;
typename std::basic_string<CH, TR, AL>::iterator itstrlen = str.begin();
std::advance( itstrlen, strpos + strlen );
std::basic_string<char_type> const & subst = pat.get_subst();
for( LCI isubst = pat.m_subst_list.begin(); isubst != pat.m_subst_list.end(); ++isubst )
{
size_t sublen;
typename std::basic_string<CH, TR, AL>::const_iterator itsubpos1; // iter into str
typename std::basic_string<CH, TR, AL>::const_iterator itsublen1;
typename std::basic_string<char_type>::const_iterator itsubpos2; // iter into subst string
typename std::basic_string<char_type>::const_iterator itsublen2;
typename std::basic_string<CH, TR, AL>::iterator itstrpos = str.begin();
std::advance( itstrpos, strpos );
switch( isubst->stype )
{
case subst_node::SUBST_STRING:
itsubpos2 = subst.begin();
std::advance( itsubpos2, isubst->subst_string.rstart );
itsublen2 = itsubpos2;
std::advance( itsublen2, isubst->subst_string.rlength );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -