⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reimpl2.h

📁 代理服务器原代码
💻 H
📖 第 1 页 / 共 3 页
字号:
        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 + -