[C++] [正则表达式] 一个不错的正则表达式引擎4C++

//  RegEx.cpp : 定义控制台应用程序的入口点。
//
//  本文所使用的“正则表达式解析引擎”来自
//   http://www.regexlab.com/deelx/
//  
#include  " stdafx.h "
#include 
" Regex.h "

/// ===========================================================================
/// 合法的IP
/// A.B.C.D
/// A/B/C/D 为[0-255]间的整数
/// 本规则忽略数字前导0,即 00192 == 192
/// ---------------------------------------------------------------------------

int  is_ip(  const   char *  str )
{
    
static CRegexpT< char > regexp( "0*(1/d{0,2}|2([0-4]/d?|5[0-5]?|/d?)|[3-9]/d?|0)(.0*(1/d{0,2}|2([0-4]/d?|5[0-5]?|/d?)|[3-9]/d?|0)){3}" );
    MatchResult mrRet 
= regexp.MatchExact( str );

    
return mrRet.IsMatched();
}


int  is_email(  const   char *  str )
{
    
static CRegexpT< char > regexp( "^/w+(/./w+)*@/w+(/./w+)+$" );
    MatchResult mrRet 
= regexp.MatchExact( str );

    
return mrRet.IsMatched();
}


int  _tmain( int  argc, _TCHAR *  argv[])
{
    
char* ip1 = "192.168.58.251";
    
char* ip2 = "256.168.58.251";

    printf( 
"%s ==> %s " , ip1 , (is_ip(ip1)?"yes":"no") );
    printf( 
"%s ==> %s " , ip2 , (is_ip(ip2)?"yes":"no") );

    
char* m1 = "hjbcn@126.com";
    
char* m2 = "hjbcn#126.com";

    printf( 
"%s ==> %s " , m1 , (is_email(m1)?"yes":"no") );
    printf( 
"%s ==> %s " , m2 , (is_email(m2)?"yes":"no") );

    getchar();
    
return 0;
}


 

 

//  RegEx.h
//
//  DEELX Regular Expression Engine (v1.2)
//
//  Copyright 2006 (c) RegExLab.com
//  All Rights Reserved.
//
//   http://www.regexlab.com/deelx/
//
//  Author: 史寿伟 (sswater shi)
//  sswater@gmail.com
//
//  $Revision: 1.1.2.27 $
//

#ifndef __DEELX_REGEXP__H__
#define  __DEELX_REGEXP__H__

#include 
< memory.h >
#include 
< ctype.h >
#include 
< limits.h >
#include 
< string .h >
#include 
< stdio.h >

//
//  Data Reference
//
template  < class  ELT >   class  CBufferRefT
{
public:
    CBufferRefT(
const ELT * pcsz, int length);
    CBufferRefT(
const ELT * pcsz);

public:
    
int nCompare      (const ELT * pcsz) const;
    
int nCompareNoCase(const ELT * pcsz) const;
    
int  Compare      (const ELT * pcsz) const;
    
int  CompareNoCase(const ELT * pcsz) const;
    
int  Compare      (const CBufferRefT <ELT> &const;
    
int  CompareNoCase(const CBufferRefT <ELT> &const;

    ELT At          (
int nIndex, ELT def = 0const;
    ELT 
operator [] (int nIndex) const;

    
const ELT * GetBuffer() const;
    
int GetSize() const;

public:
    
virtual ~CBufferRefT();

// Content
protected:
    
const ELT * m_pRef;
    
int         m_nSize;
}
;

//
//  Implemenation
//
template  < class  ELT >  CBufferRefT  < ELT >  :: CBufferRefT( const  ELT  *  pcsz,  int  length)
{
    m_pRef  
= pcsz;
    m_nSize 
= length;
}


template 
< class  ELT >  CBufferRefT  < ELT >  :: CBufferRefT( const  ELT  *  pcsz)
{
    m_pRef  
= pcsz;
    m_nSize 
= 0;

    
if(pcsz != 0while(m_pRef[m_nSize] != 0) m_nSize ++;
}


template 
< class  ELT >   int  CBufferRefT  < ELT >  :: nCompare( const  ELT  *  pcsz)  const
{
    
for(int i=0; i<m_nSize; i++)
    
{
        
if(m_pRef[i] != pcsz[i])
            
return m_pRef[i] - pcsz[i];
    }


    
return 0;
}


template 
< class  ELT >   int  CBufferRefT  < ELT >  :: nCompareNoCase( const  ELT  *  pcsz)  const
{
    
for(int i=0; i<m_nSize; i++)
    
{
        
if(m_pRef[i] != pcsz[i])
        
{
            
if(toupper((int)m_pRef[i]) != toupper((int)pcsz[i]))
                
return m_pRef[i] - pcsz[i];
        }

    }


    
return 0;
}


template 
< class  ELT >  inline  int  CBufferRefT  < ELT >  :: Compare( const  ELT  *  pcsz)  const
{
    
return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize];
}


template 
< class  ELT >  inline  int  CBufferRefT  < ELT >  :: CompareNoCase( const  ELT  *  pcsz)  const
{
    
return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize];
}


template 
< class  ELT >  inline  int  CBufferRefT  < ELT >  :: Compare( const  CBufferRefT  < ELT >   &  cref)  const
{
    
return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1;
}


template 
< class  ELT >  inline  int  CBufferRefT  < ELT >  :: CompareNoCase( const  CBufferRefT  < ELT >   &  cref)  const
{
    
return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1;
}


template 
< class  ELT >  inline ELT CBufferRefT  < ELT >  :: At( int  nIndex, ELT def)  const
{
    
return nIndex >= m_nSize ? def : m_pRef[nIndex];
}


template 
< class  ELT >  inline ELT CBufferRefT  < ELT >  ::  operator  [] ( int  nIndex)  const
{
    
return nIndex >= m_nSize ? 0 : m_pRef[nIndex];
}


template 
< class  ELT >   const  ELT  *  CBufferRefT  < ELT >  :: GetBuffer()  const
{
    
static const ELT _def[] = {0}return m_pRef ? m_pRef : _def;
}


template 
< class  ELT >  inline  int  CBufferRefT  < ELT >  :: GetSize()  const
{
    
return m_nSize;
}


template 
< class  ELT >  CBufferRefT  < ELT >  ::  ~ CBufferRefT()
{
}


//
//  Data Buffer
//
template  < class  ELT >   class  CBufferT :  public  CBufferRefT  < ELT >
{
public:
    CBufferT(
const ELT * pcsz, int length);
    CBufferT(
const ELT * pcsz);
    CBufferT();

public:
    ELT 
& operator [] (int nIndex);
    
const ELT & operator [] (int nIndex) const;
    
void  Append(const ELT * pcsz, int length, int eol = 0);
    
void  Append(ELT el, int eol = 0);

public:
    
void  Push(ELT   el);
    
int   Pop (ELT & el);
    
int   Peek(ELT & el) const;

public:
    
const ELT * GetBuffer() const;
    ELT 
* GetBuffer();
    ELT 
* Detach();
    
void  Release();
    
void  Prepare(int index, int fill = 0);
    
void  Restore(int size);

public:
    
virtual ~CBufferT();

// Content
protected:
    ELT 
* m_pBuffer;
    
int   m_nMaxLength;
}
;

//
//  Implemenation
//
template  < class  ELT >  CBufferT  < ELT >  :: CBufferT( const  ELT  *  pcsz,  int  length) : CBufferRefT  < ELT >  ( 0 , length)
{
    m_nMaxLength 
= CBufferRefT <ELT> :: m_nSize + 1;

    CBufferRefT 
<ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength];
    memcpy(m_pBuffer, pcsz, 
sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
    m_pBuffer[CBufferRefT 
<ELT> :: m_nSize] = 0;
}


template 
< class  ELT >  CBufferT  < ELT >  :: CBufferT( const  ELT  *  pcsz) : CBufferRefT  < ELT >  (pcsz)
{
    m_nMaxLength 
= CBufferRefT <ELT> :: m_nSize + 1;

    CBufferRefT 
<ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength];
    memcpy(m_pBuffer, pcsz, 
sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
    m_pBuffer[CBufferRefT 
<ELT> :: m_nSize] = 0;
}


template 
< class  ELT >  CBufferT  < ELT >  :: CBufferT() : CBufferRefT  < ELT >  ( 0 0 )
{
    m_nMaxLength 
= 0;
    m_pBuffer    
= 0;
}


template 
< class  ELT >  inline ELT  &  CBufferT  < ELT >  ::  operator  [] ( int  nIndex)
{
    
return m_pBuffer[nIndex];
}


template 
< class  ELT >  inline  const  ELT  &  CBufferT  < ELT >  ::  operator  [] ( int  nIndex)  const
{
    
return m_pBuffer[nIndex];
}


template 
< class  ELT >   void  CBufferT  < ELT >  :: Append( const  ELT  *  pcsz,  int  length,  int  eol)
{
    
int nNewLength = m_nMaxLength;

    
// Check length
    if(nNewLength < 8)
        nNewLength 
= 8;

    
if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength)
        nNewLength 
*= 2;

    
if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength)
    
{
        nNewLength  
= CBufferRefT <ELT> :: m_nSize + length + eol + 11;
        nNewLength 
-= nNewLength % 8;
    }


    
// Realloc
    if(nNewLength > m_nMaxLength)
    
{
        ELT 
* pNewBuffer = new ELT[nNewLength];

        
if(m_pBuffer != 0)
        
{
            memcpy(pNewBuffer, m_pBuffer, 
sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
            delete [] m_pBuffer;
        }


        CBufferRefT 
<ELT> :: m_pRef = m_pBuffer = pNewBuffer;
        m_nMaxLength 
= nNewLength;
    }


    
// Append
    memcpy(m_pBuffer + CBufferRefT <ELT> :: m_nSize, pcsz, sizeof(ELT) * length);
    CBufferRefT 
<ELT> :: m_nSize += length;

    
if(eol > 0) m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;
}


template 
< class  ELT >  inline  void  CBufferT  < ELT >  :: Append(ELT el,  int  eol)
{
    Append(
&el, 1, eol);
}


template 
< class  ELT >   void  CBufferT  < ELT >  :: Push(ELT el)
{
    
// Realloc
    if(CBufferRefT <ELT> :: m_nSize >= m_nMaxLength)
    
{
        
int nNewLength = m_nMaxLength * 2;
        
if( nNewLength < 8 ) nNewLength = 8;

        ELT 
* pNewBuffer = new ELT[nNewLength];

        
if(m_pBuffer != 0)
        
{
            memcpy(pNewBuffer, m_pBuffer, 
sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
            delete [] m_pBuffer;
        }


        CBufferRefT 
<ELT> :: m_pRef = m_pBuffer = pNewBuffer;
        m_nMaxLength 
= nNewLength;
    }


    
// Append
    m_pBuffer[CBufferRefT <ELT> :: m_nSize++= el;
}


template 
< class  ELT >  inline  int  CBufferT  < ELT >  :: Pop(ELT  &  el)
{
    
if(CBufferRefT <ELT> :: m_nSize > 0)
    
{
        el 
= m_pBuffer[--CBufferRefT <ELT> :: m_nSize];
        
return 1;
    }

    
else
    
{
        
return 0;
    }

}


template 
< class  ELT >  inline  int  CBufferT  < ELT >  :: Peek(ELT  &  el)  const
{
    
if(CBufferRefT <ELT> :: m_nSize > 0)
    
{
        el 
= m_pBuffer[CBufferRefT <ELT> :: m_nSize - 1];
        
return 1;
    }

    
else
    
{
        
return 0;
    }

}


template 
< class  ELT >   const  ELT  *  CBufferT  < ELT >  :: GetBuffer()  const
{
    
static const ELT _def[] = {0}return m_pBuffer ? m_pBuffer : _def;
}


template 
< class  ELT >  ELT  *  CBufferT  < ELT >  :: GetBuffer()
{
    
static const ELT _def[] = {0}return m_pBuffer ? m_pBuffer : (ELT *)_def;
}


template 
< class  ELT >  ELT  *  CBufferT  < ELT >  :: Detach()
{
    ELT 
* pBuffer = m_pBuffer;

    CBufferRefT 
<ELT> :: m_pRef  = m_pBuffer    = 0;
    CBufferRefT 
<ELT> :: m_nSize = m_nMaxLength = 0;

    
return pBuffer;
}


template 
< class  ELT >   void  CBufferT  < ELT >  :: Release()
{
    ELT 
* pBuffer = Detach();

    
if(pBuffer != 0) delete [] pBuffer;
}


template 
< class  ELT >   void  CBufferT  < ELT >  :: Prepare( int  index,  int  fill)
{
    
int nNewSize = index + 1;

    
// Realloc
    if(nNewSize > m_nMaxLength)
    
{
        
int nNewLength = m_nMaxLength;

        
if( nNewLength < 8 )
            nNewLength 
= 8;

        
if( nNewSize > nNewLength )
            nNewLength 
*= 2;

        
if( nNewSize > nNewLength )
        
{
            nNewLength  
= nNewSize + 11;
            nNewLength 
-= nNewLength % 8;
        }


        ELT 
* pNewBuffer = new ELT[nNewLength];

        
if(m_pBuffer != 0)
        
{
            memcpy(pNewBuffer, m_pBuffer, 
sizeof(ELT) * CBufferRefT <ELT> :: m_nSize);
            delete [] m_pBuffer;
        }


        CBufferRefT 
<ELT> :: m_pRef = m_pBuffer = pNewBuffer;
        m_nMaxLength 
= nNewLength;
    }


    
// size
    if( CBufferRefT <ELT> :: m_nSize < nNewSize )
    
{
        memset(m_pBuffer 
+ CBufferRefT <ELT> :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT <ELT> :: m_nSize));
        CBufferRefT 
<ELT> :: m_nSize = nNewSize;
    }

}


template 
< class  ELT >  inline  void  CBufferT  < ELT >  :: Restore( int  size)
{
    CBufferRefT 
<ELT> :: m_nSize = size;
}


template 
< class  ELT >  CBufferT  < ELT >  ::  ~ CBufferT()
{
    
if(m_pBuffer != 0) delete [] m_pBuffer;
}


//
//  Context
//
class  CContext
{
public:
    CBufferT 
<int> m_stack;
    CBufferT 
<int> m_capturestack, m_captureindex;

public:
    
int    m_nCurrentPos;
    
int    m_nBeginPos;
    
int    m_nLastBeginPos;
    
int    m_nParenZindex;

    
void * m_pMatchString;
    
int    m_pMatchStringLength;
}
;

//
//  Interface
//
class  ElxInterface
{
public:
    
virtual int Match    (CContext * pContext) const = 0;
    
virtual int MatchNext(CContext * pContext) const = 0;

public:
    
virtual ~ElxInterface() {};
}
;

//
//  Alternative
//
template  < int  x >   class  CAlternativeElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CAlternativeElxT();

public:
    CBufferT 
<ElxInterface *> m_elxlist;
}
;

typedef CAlternativeElxT 
< 0 >  CAlternativeElx;

//
//  Assert
//
template  < int  x >   class  CAssertElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CAssertElxT(ElxInterface 
* pelx, int byes = 1);

public:
    ElxInterface 
* m_pelx;
    
int m_byes;
}
;

typedef CAssertElxT 
< 0 >  CAssertElx;

//
//  Back reference elx
//
template  < class  CHART >   class  CBackrefElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CBackrefElxT(
int nnumber, int brightleft, int bignorecase);

public:
    
int m_nnumber;
    
int m_brightleft;
    
int m_bignorecase;

    CBufferT 
<CHART> m_szNamed;
}
;

//
//  Implementation
//
template  < class  CHART >  CBackrefElxT  < CHART >  :: CBackrefElxT( int  nnumber,  int  brightleft,  int  bignorecase)
{
    m_nnumber     
= nnumber;
    m_brightleft  
= brightleft;
    m_bignorecase 
= bignorecase;
}


template 
< class  CHART >   int  CBackrefElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
// check number, for named
    if( m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize() ) return 0;

    
int index = pContext->m_captureindex[m_nnumber];
    
if( index < 0 ) return 0;

    
// check enclosed
    int pos1 = pContext->m_capturestack[index + 1];
    
int pos2 = pContext->m_capturestack[index + 2];

    
if( pos2 < 0 ) pos2 = pContext->m_nCurrentPos;

    
// info
    int lpos = pos1 < pos2 ? pos1 : pos2;
    
int rpos = pos1 < pos2 ? pos2 : pos1;
    
int slen = rpos - lpos;

    
const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
    
int npos = pContext->m_nCurrentPos;
    
int tlen = pContext->m_pMatchStringLength;

    
// compare
    int bsucc;
    CBufferRefT 
<CHART> refstr(pcsz + lpos, slen);

    
if( m_brightleft )
    
{
        
if(npos < slen)
            
return 0;

        
if(m_bignorecase)
            bsucc 
= ! refstr.nCompareNoCase(pcsz + (npos - slen));
        
else
            bsucc 
= ! refstr.nCompare      (pcsz + (npos - slen));

        
if( bsucc )
        
{
            pContext
->m_stack.Push(npos);
            pContext
->m_nCurrentPos -= slen;
        }

    }

    
else
    
{
        
if(npos + slen > tlen)
            
return 0;

        
if(m_bignorecase)
            bsucc 
= ! refstr.nCompareNoCase(pcsz + npos);
        
else
            bsucc 
= ! refstr.nCompare      (pcsz + npos);

        
if( bsucc )
        
{
            pContext
->m_stack.Push(npos);
            pContext
->m_nCurrentPos += slen;
        }

    }


    
return bsucc;
}


template 
< class  CHART >   int  CBackrefElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    
int npos = 0;

    pContext
->m_stack.Pop(npos);
    pContext
->m_nCurrentPos = npos;

    
return 0;
}


//  RCHART
#ifndef RCHART
    
#define  RCHART(ch) ((CHART)ch)
#endif

//  BOUNDARY_TYPE
enum  BOUNDARY_TYPE
{
    BOUNDARY_FILE_BEGIN, 
// begin of whole text
    BOUNDARY_FILE_END  , // end of whole text
    BOUNDARY_LINE_BEGIN, // begin of line
    BOUNDARY_LINE_END  , // end of line
    BOUNDARY_WORD_BEGIN, // begin of word
    BOUNDARY_WORD_END  , // end of word
    BOUNDARY_WORD_EDGE ,
}
;

//
//  Boundary Elx
//
template  < class  CHART >   class  CBoundaryElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CBoundaryElxT(
int ntype, int byes = 1);

protected:
    
static int IsWordChar(CHART ch);

public:
    
int m_ntype;
    
int m_byes;
}
;

//
//  Implementation
//
template  < class  CHART >  CBoundaryElxT  < CHART >  :: CBoundaryElxT( int  ntype,  int  byes)
{
    m_ntype 
= ntype;
    m_byes  
= byes;
}


template 
< class  CHART >   int  CBoundaryElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
const CHART * pcsz  = (const CHART *)pContext->m_pMatchString;
    
int npos = pContext->m_nCurrentPos;
    
int tlen = pContext->m_pMatchStringLength;

    CHART chL 
= npos > 0    ? pcsz[npos - 1] : 0;
    CHART chR 
= npos < tlen ? pcsz[npos    ] : 0;

    
int bsucc = 0;

    
switch(m_ntype)
    
{
    
case BOUNDARY_FILE_BEGIN:
        bsucc 
= (npos <= 0);
        
break;

    
case BOUNDARY_FILE_END:
        bsucc 
= (npos >= tlen);
        
break;

    
case BOUNDARY_LINE_BEGIN:
        bsucc 
= (npos <= 0   ) || (chL == RCHART(' ')) || ((chL == RCHART(' ')) && (chR != RCHART(' ')));
        
break;

    
case BOUNDARY_LINE_END:
        bsucc 
= (npos >= tlen) || (chR == RCHART(' ')) || ((chR == RCHART(' ')) && (chL != RCHART(' ')));
        
break;

    
case BOUNDARY_WORD_BEGIN:
        bsucc 
= ! IsWordChar(chL) &&   IsWordChar(chR);
        
break;

    
case BOUNDARY_WORD_END:
        bsucc 
=   IsWordChar(chL) && ! IsWordChar(chR);
        
break;

    
case BOUNDARY_WORD_EDGE:
        bsucc 
=   IsWordChar(chL) ?  ! IsWordChar(chR) : IsWordChar(chR);
        
break;
    }


    
return bsucc;
}


template 
< class  CHART >   int  CBoundaryElxT  < CHART >  :: MatchNext(CContext  * const
{
    
return 0;
}


template 
< class  CHART >  inline  int  CBoundaryElxT  < CHART >  :: IsWordChar(CHART ch)
{
    
return (ch >= RCHART('A'&& ch <= RCHART('Z')) || (ch >= RCHART('a'&& ch <= RCHART('z')) || (ch >= RCHART('0'&& ch <= RCHART('9')) || (ch == RCHART('_'));
}


//
//  Bracket
//
template  < class  CHART >   class  CBracketElxT :  public  ElxInterface  
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CBracketElxT(
int nnumber, int bright);

public:
    
int m_nnumber;
    
int m_bright;

    CBufferT 
<CHART> m_szNamed;
}
;

template 
< class  CHART >  CBracketElxT  < CHART >  :: CBracketElxT( int  nnumber,  int  bright)
{
    m_nnumber 
= nnumber;
    m_bright  
= bright;
}


template 
< class  CHART >   int  CBracketElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
// check, for named
    if(m_nnumber < 0return 0;

    
if! m_bright )
    
{
        pContext
->m_captureindex.Prepare(m_nnumber, -1);
        
int index = pContext->m_captureindex[m_nnumber];

        
// check
        if(index > 0 && index < pContext->m_capturestack.GetSize() && pContext->m_capturestack[index+2< 0)
        
{
            pContext
->m_capturestack[index+3--;
            
return 1;
        }


        
// save
        pContext->m_captureindex[m_nnumber] = pContext->m_capturestack.GetSize();

        pContext
->m_capturestack.Push(m_nnumber);
        pContext
->m_capturestack.Push(pContext->m_nCurrentPos);
        pContext
->m_capturestack.Push(-1);
        pContext
->m_capturestack.Push( 0); // z-index
    }

    
else
    
{
        
// check
        int index = pContext->m_captureindex[m_nnumber];

        
if(pContext->m_capturestack[index + 3< 0)
        
{
            pContext
->m_capturestack[index + 3++;
            
return 1;
        }


        
// save
        pContext->m_capturestack[index + 2= pContext->m_nCurrentPos;
        pContext
->m_capturestack[index + 3= pContext->m_nParenZindex ++;
    }


    
return 1;
}


template 
< class  CHART >   int  CBracketElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    
int index = pContext->m_captureindex[m_nnumber];

    
if! m_bright )
    
{
        
if(pContext->m_capturestack[index + 3< 0)
        
{
            pContext
->m_capturestack[index + 3++;
            
return 0;
        }


        pContext
->m_capturestack.Restore(pContext->m_capturestack.GetSize() - 4);

        
// to find
        index = pContext->m_capturestack.GetSize() - 4;
        
while(index >= 0 && pContext->m_capturestack[index] != m_nnumber) index -= 4;

        
// new index
        pContext->m_captureindex[m_nnumber] = index;
    }

    
else
    
{
        
if(pContext->m_capturestack[index + 3< 0)
        
{
            pContext
->m_capturestack[index + 3--;
            
return 0;
        }


        pContext
->m_capturestack[index + 2= -1;
        pContext
->m_capturestack[index + 3=  0;
    }


    
return 0;
}


//
//  Deletage
//
template  < class  CHART >   class  CDelegateElxT :  public  ElxInterface  
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CDelegateElxT(
int ndata = 0);

public:
    ElxInterface 
* m_pelx;
    
int m_ndata; // +0 : recursive to
                 
// -3 : named recursive

    CBufferT 
<CHART> m_szNamed;
}
;

template 
< class  CHART >  CDelegateElxT  < CHART >  :: CDelegateElxT( int  ndata)
{
    m_pelx  
= 0;
    m_ndata 
= ndata;
}


template 
< class  CHART >   int  CDelegateElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
if(m_pelx != 0)
        
return m_pelx->Match(pContext);
    
else
        
return 1;
}


template 
< class  CHART >   int  CDelegateElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    
if(m_pelx != 0)
        
return m_pelx->MatchNext(pContext);
    
else
        
return 0;
}


//
//  Empty
//
template  < int  x >   class  CEmptyElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CEmptyElxT();
}
;

typedef CEmptyElxT 
< 0 >  CEmptyElx;

//
//  Global
//
template  < int  x >   class  CGlobalElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CGlobalElxT();
}
;

typedef CGlobalElxT 
< 0 >  CGlobalElx;

//
//  Repeat
//
template  < int  x >   class  CRepeatElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CRepeatElxT(ElxInterface 
* pelx, int ntimes);

protected:
    
int MatchFixed    (CContext * pContext) const;
    
int MatchNextFixed(CContext * pContext) const;

public:
    ElxInterface 
* m_pelx;
    
int m_nfixed;
}
;

typedef CRepeatElxT 
< 0 >  CRepeatElx;

//
//  Greedy
//
template  < int  x >   class  CGreedyElxT :  public  CRepeatElxT  < x >
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CGreedyElxT(ElxInterface 
* pelx, int nmin = 0int nmax = INT_MAX);

protected:
    
int MatchVart    (CContext * pContext) const;
    
int MatchNextVart(CContext * pContext) const;

public:
    
int m_nvart;
}
;

typedef CGreedyElxT 
< 0 >  CGreedyElx;

//
//  Independent
//
template  < int  x >   class  CIndependentElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CIndependentElxT(ElxInterface 
* pelx);

public:
    ElxInterface 
* m_pelx;
}
;

typedef CIndependentElxT 
< 0 >  CIndependentElx;

//
//  List
//
template  < int  x >   class  CListElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CListElxT(
int brightleft);

public:
    CBufferT 
<ElxInterface *> m_elxlist;
    
int m_brightleft;
}
;

typedef CListElxT 
< 0 >  CListElx;

//
//  Posix Elx
//
template  < class  CHART >   class  CPosixElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CPosixElxT(
const char * posix, int brightleft);

protected:
    
static int m_isblank(int c);

public:
    
int (*m_posixfun)(int);
    
int m_brightleft;
    
int m_byes;
}
;

//
//  Implementation
//
template  < class  CHART >  CPosixElxT  < CHART >  :: CPosixElxT( const   char   *  posix,  int  brightleft)
{
    m_brightleft 
= brightleft;

    
if(posix[1== '^')
    
{
        m_byes 
= 0;
        posix 
+= 2;
    }

    
else
    
{
        m_byes 
= 1;
        posix 
+= 1;
    }


    
if     (!strncmp(posix, "alnum:"6)) m_posixfun = ::isalnum ;
    
else if(!strncmp(posix, "alpha:"6)) m_posixfun = ::isalpha ;
    
else if(!strncmp(posix, "ascii:"6)) m_posixfun = ::isascii ;
    
else if(!strncmp(posix, "cntrl:"6)) m_posixfun = ::iscntrl ;
    
else if(!strncmp(posix, "digit:"6)) m_posixfun = ::isdigit ;
    
else if(!strncmp(posix, "graph:"6)) m_posixfun = ::isgraph ;
    
else if(!strncmp(posix, "lower:"6)) m_posixfun = ::islower ;
    
else if(!strncmp(posix, "print:"6)) m_posixfun = ::isprint ;
    
else if(!strncmp(posix, "punct:"6)) m_posixfun = ::ispunct ;
    
else if(!strncmp(posix, "space:"6)) m_posixfun = ::isspace ;
    
else if(!strncmp(posix, "upper:"6)) m_posixfun = ::isupper ;
    
else if(!strncmp(posix, "xdigit:",7)) m_posixfun = ::isxdigit;
    
else if(!strncmp(posix, "blank:"6)) m_posixfun = m_isblank ;
    
else                                  m_posixfun = 0         ;
}


template 
< class  CHART >   int  CPosixElxT  < CHART >  :: m_isblank( int  c)
{
    
return c == 0x20 || c == ' ';
}


template 
< class  CHART >   int  CPosixElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
if(m_posixfun == 0return 0;

    
int tlen = pContext->m_pMatchStringLength;
    
int npos = pContext->m_nCurrentPos;

    
// check
    int at   = m_brightleft ? npos - 1 : npos;
    
if( at < 0 || at >= tlen )
        
return 0;

    CHART ch 
= ((const CHART *)pContext->m_pMatchString)[at];

    
int bsucc = (*m_posixfun)(ch);

    
if! m_byes )
        bsucc 
= ! bsucc;

    
if( bsucc )
        pContext
->m_nCurrentPos += m_brightleft ? -1 : 1;

    
return bsucc;
}


template 
< class  CHART >   int  CPosixElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    pContext
->m_nCurrentPos -= m_brightleft ? -1 : 1;
    
return 0;
}


//
//  Possessive
//
template  < int  x >   class  CPossessiveElxT :  public  CGreedyElxT  < x >
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CPossessiveElxT(ElxInterface 
* pelx, int nmin = 0int nmax = INT_MAX);
}
;

typedef CPossessiveElxT 
< 0 >  CPossessiveElx;

//
//  Range Elx
//
template  < class  CHART >   class  CRangeElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CRangeElxT(
int brightleft, int byes);

public:
    CBufferT 
<CHART> m_ranges;
    CBufferT 
<CHART> m_chars;
    CBufferT 
<ElxInterface *> m_embeds;

public:
    
int m_brightleft;
    
int m_byes;
}
;

//
//  Implementation
//
template  < class  CHART >  CRangeElxT  < CHART >  :: CRangeElxT( int  brightleft,  int  byes)
{
    m_brightleft 
= brightleft;
    m_byes       
= byes;
}


template 
< class  CHART >   int  CRangeElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
int tlen = pContext->m_pMatchStringLength;
    
int npos = pContext->m_nCurrentPos;

    
// check
    int at   = m_brightleft ? npos - 1 : npos;
    
if( at < 0 || at >= tlen )
        
return 0;

    CHART ch 
= ((const CHART *)pContext->m_pMatchString)[at];
    
int bsucc = 0, i;

    
// compare
    for(i=0!bsucc && i<m_ranges.GetSize(); i+=2)
    
{
        
if(m_ranges[i] <= ch && ch <= m_ranges[i+1]) bsucc = 1;
    }


    
for(i=0!bsucc && i<m_chars.GetSize(); i++)
    
{
        
if(m_chars[i] == ch) bsucc = 1;
    }


    
for(i=0!bsucc && i<m_embeds.GetSize(); i++)
    
{
        
if(m_embeds[i]->Match(pContext))
        
{
            pContext
->m_nCurrentPos = npos;
            bsucc 
= 1;
        }

    }


    
if! m_byes )
        bsucc 
= ! bsucc;

    
if( bsucc )
        pContext
->m_nCurrentPos += m_brightleft ? -1 : 1;

    
return bsucc;
}


template 
< class  CHART >   int  CRangeElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    pContext
->m_nCurrentPos -= m_brightleft ? -1 : 1;
    
return 0;
}


//
//  Reluctant
//
template  < int  x >   class  CReluctantElxT :  public  CRepeatElxT  < x >
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CReluctantElxT(ElxInterface 
* pelx, int nmin = 0int nmax = INT_MAX);

protected:
    
int MatchVart    (CContext * pContext) const;
    
int MatchNextVart(CContext * pContext) const;

public:
    
int m_nvart;
}
;

typedef CReluctantElxT 
< 0 >  CReluctantElx;

//
//  String Elx
//
template  < class  CHART >   class  CStringElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CStringElxT(
const CHART * fixedint nlength, int brightleft, int bignorecase);

public:
    CBufferT 
<CHART> m_szPattern;
    
int m_brightleft;
    
int m_bignorecase;
}
;

//
//  Implementation
//
template  < class  CHART >  CStringElxT  < CHART >  :: CStringElxT( const  CHART  *   fixed int  nlength,  int  brightleft,  int  bignorecase) : m_szPattern( fixed , nlength)
{
    m_brightleft  
= brightleft;
    m_bignorecase 
= bignorecase;
}


template 
< class  CHART >   int  CStringElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
const CHART * pcsz  = (const CHART *)pContext->m_pMatchString;
    
int npos = pContext->m_nCurrentPos;
    
int tlen = pContext->m_pMatchStringLength;
    
int slen = m_szPattern.GetSize();

    
int bsucc;

    
if(m_brightleft)
    
{
        
if(npos < slen)
            
return 0;

        
if(m_bignorecase)
            bsucc 
= ! m_szPattern.nCompareNoCase(pcsz + (npos - slen));
        
else
            bsucc 
= ! m_szPattern.nCompare      (pcsz + (npos - slen));

        
if( bsucc )
            pContext
->m_nCurrentPos -= slen;
    }

    
else
    
{
        
if(npos + slen > tlen)
            
return 0;

        
if(m_bignorecase)
            bsucc 
= ! m_szPattern.nCompareNoCase(pcsz + npos);
        
else
            bsucc 
= ! m_szPattern.nCompare      (pcsz + npos);

        
if( bsucc )
            pContext
->m_nCurrentPos += slen;
    }


    
return bsucc;
}


template 
< class  CHART >   int  CStringElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    
int slen = m_szPattern.GetSize();

    
if(m_brightleft)
        pContext
->m_nCurrentPos += slen;
    
else
        pContext
->m_nCurrentPos -= slen;

    
return 0;
}


//
//  CConditionElx
//
template  < class  CHART >   class  CConditionElxT :  public  ElxInterface
{
public:
    
int Match    (CContext * pContext) const;
    
int MatchNext(CContext * pContext) const;

public:
    CConditionElxT();

public:
    
// backref condition
    int m_nnumber;
    CBufferT 
<CHART> m_szNamed;

    
// elx condition
    ElxInterface * m_pelxask;

    
// selection
    ElxInterface * m_pelxyes, * m_pelxno;
}
;

template 
< class  CHART >  CConditionElxT  < CHART >  :: CConditionElxT()
{
    m_nnumber 
= -1;
}


template 
< class  CHART >   int  CConditionElxT  < CHART >  :: Match(CContext  *  pContext)  const
{
    
// status
    int nbegin = pContext->m_nCurrentPos;
    
int nsize  = pContext->m_stack.GetSize();
    
int ncsize = pContext->m_capturestack.GetSize();

    
// condition result
    int condition_yes = 0;

    
// backref type
    if( m_nnumber >= 0 )
    
{
        
do
        
{
            
if(m_nnumber >= pContext->m_captureindex.GetSize()) break;

            
int index = pContext->m_captureindex[m_nnumber];
            
if( index < 0break;

            
// else valid
            condition_yes = 1;
        }

        
while(0);
    }

    
else
    
{
        
if( m_pelxask == 0 )
            condition_yes 
= 1;
        
else
            condition_yes 
= m_pelxask->Match(pContext);

        pContext
->m_stack.Restore(nsize);
        pContext
->m_nCurrentPos = nbegin;
    }


    
// elx result
    int bsucc;
    
if( condition_yes )
        bsucc 
= m_pelxyes == 0 ? 1 : m_pelxyes->Match(pContext);
    
else
        bsucc 
= m_pelxno  == 0 ? 1 : m_pelxno ->Match(pContext);

    
if( bsucc )
    
{
        pContext
->m_stack.Push(ncsize);
        pContext
->m_stack.Push(condition_yes);
    }

    
else
    
{
        pContext
->m_capturestack.Restore(ncsize);
    }


    
return bsucc;
}


template 
< class  CHART >   int  CConditionElxT  < CHART >  :: MatchNext(CContext  *  pContext)  const
{
    
// pop
    int ncsize, condition_yes;

    pContext
->m_stack.Pop(condition_yes);
    pContext
->m_stack.Pop(ncsize);

    
// elx result
    int bsucc;
    
if( condition_yes )
        bsucc 
= m_pelxyes == 0 ? 0 : m_pelxyes->MatchNext(pContext);
    
else
        bsucc 
= m_pelxno  == 0 ? 0 : m_pelxno ->MatchNext(pContext);

    
if( bsucc )
    
{
        pContext
->m_stack.Push(ncsize);
        pContext
->m_stack.Push(condition_yes);
    }

    
else
    
{
        pContext
->m_capturestack.Restore(ncsize);
    }


    
return bsucc;
}


//
//  MatchResult
//
template  < int  x >   class  MatchResultT
{
public:
    
int IsMatched() const;

public:
    
int GetStart() const;
    
int GetEnd  () const;

public:
    
int MaxGroupNumber() const;
    
int GetGroupStart(int nGroupNumber) const;
    
int GetGroupEnd  (int nGroupNumber) const;

public:
    MatchResultT(CContext 
* pContext, int nMaxNumber = -1);
    MatchResultT 
<x> & operator = (const MatchResultT <x> &);
    inline 
operator int() const return IsMatched(); }

public:
    CBufferT 
<int> m_result;
}
;

typedef MatchResultT 
< 0 >  MatchResult;

//  Stocked Elx IDs
enum  STOCKELX_ID_DEFINES
{
    STOCKELX_EMPTY 
= 0,

    
///

    STOCKELX_DOT_ALL,
    STOCKELX_DOT_NOT_ALL,

    STOCKELX_WORD,
    STOCKELX_WORD_NOT,

    STOCKELX_SPACE,
    STOCKELX_SPACE_NOT,

    STOCKELX_DIGITAL,
    STOCKELX_DIGITAL_NOT,

    
//

    STOCKELX_DOT_ALL_RIGHTLEFT,
    STOCKELX_DOT_NOT_ALL_RIGHTLEFT,

    STOCKELX_WORD_RIGHTLEFT,
    STOCKELX_WORD_RIGHTLEFT_NOT,

    STOCKELX_SPACE_RIGHTLEFT,
    STOCKELX_SPACE_RIGHTLEFT_NOT,

    STOCKELX_DIGITAL_RIGHTLEFT,
    STOCKELX_DIGITAL_RIGHTLEFT_NOT,

    
/

    STOCKELX_COUNT
}
;

//  REGEX_FLAGS
#ifndef _REGEX_FLAGS_DEFINED
    
enum  REGEX_FLAGS
    
{
        NO_FLAG        
= 0,
        SINGLELINE     
= 0x01,
        MULTILINE      
= 0x02,
        GLOBAL         
= 0x04,
        IGNORECASE     
= 0x08,
        RIGHTTOLEFT    
= 0x10,
        EXTENDED       
= 0x20,
    }
;
    
#define  _REGEX_FLAGS_DEFINED
#endif

//
//  Builder T
//
template  < class  CHART >   class  CBuilderT
{
public:
    typedef CDelegateElxT  
<CHART> CDelegateElx;
    typedef CBracketElxT   
<CHART> CBracketElx;
    typedef CBackrefElxT   
<CHART> CBackrefElx;
    typedef CConditionElxT 
<CHART> CConditionElx;

// Methods
public:
    ElxInterface 
* Build(const CBufferRefT <CHART> & pattern, int flags);
    
int GetNamedNumber(const CBufferRefT <CHART> & named) const;
    
void Clear();

public:
     CBuilderT();
    
~CBuilderT();

// Public Attributes
public:
    ElxInterface 
* m_pTopElx;
    
int            m_nFlags;
    
int            m_nMaxNumber;
    
int            m_nNextNamed;
    
int            m_nGroupCount;

    CBufferT 
<ElxInterface  *> m_objlist;
    CBufferT 
<ElxInterface  *> m_grouplist;
    CBufferT 
<CDelegateElx  *> m_recursivelist;
    CBufferT 
<CListElx      *> m_namedlist;
    CBufferT 
<CBackrefElx   *> m_namedbackreflist;
    CBufferT 
<CConditionElx *> m_namedconditionlist;

// CHART_INFO
protected:
    
struct CHART_INFO
    
{
    
public:
        CHART ch;
        
int   type;
        
int   pos;
        
int   len;

    
public:
        CHART_INFO(CHART c, 
int t, int p = 0int l = 0{ ch = c; type = t; pos = p; len = l;    }
        inline 
int operator == (const CHART_INFO & ci)   return ch == ci.ch && type == ci.type; }
        inline 
int operator != (const CHART_INFO & ci)   return ! operator == (ci);             }
    }
;

protected:
    
static unsigned int Hex2Int(const CHART * pcsz, int length, int & used);
    
static int ReadDec(char * & str, unsigned int & dec);
    
void MoveNext();
    
int  GetNext2();

    ElxInterface 
* BuildAlternative(int vaflags);
    ElxInterface 
* BuildList       (int & flags);
    ElxInterface 
* BuildRepeat     (int & flags);
    ElxInterface 
* BuildSimple     (int & flags);
    ElxInterface 
* BuildCharset    (int & flags);
    ElxInterface 
* BuildRecursive  (int & flags);
    ElxInterface 
* BuildBoundary   (int & flags);
    ElxInterface 
* BuildBackref    (int & flags);

    ElxInterface 
* GetStockElx     (int nStockId);
    ElxInterface 
* Keep(ElxInterface * pElx);

// Private Attributes
protected:
    CBufferRefT 
<CHART> m_pattern;
    CHART_INFO prev, curr, next, nex2;
    
int m_nNextPos;
    
int m_nCharsetDepth;
    
int m_bQuoted;
    
int (*m_quote_fun)(int);

    ElxInterface 
* m_pStockElxs[STOCKELX_COUNT];
}
;

//
//  Implementation
//
template  < class  CHART >  CBuilderT  < CHART >  :: CBuilderT() : m_pattern( 0 0 ), prev( 0 0 ), curr( 0 0 ), next( 0 0 ), nex2( 0 0 )
{
    Clear();
}


template 
< class  CHART >  CBuilderT  < CHART >  ::  ~ CBuilderT()
{
    Clear();
}


template 
< class  CHART >   int  CBuilderT  < CHART >  :: GetNamedNumber( const  CBufferRefT  < CHART >   &  named)  const
{
    
for(int i=0; i<m_namedlist.GetSize(); i++)
    
{
        
if! ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_szNamed.CompareNoCase(named) )
            
return ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_nnumber;
    }


    
return -3;
}


template 
< class  CHART >  ElxInterface  *  CBuilderT  < CHART >  :: Build( const  CBufferRefT  < CHART >   &  pattern,  int  flags)
{
    
// init
    m_pattern       = pattern;
    m_nNextPos      
= 0;
    m_nCharsetDepth 
= 0;
    m_nMaxNumber    
= 0;
    m_nNextNamed    
= 0;
    m_nFlags        
= flags;
    m_bQuoted       
= 0;
    m_quote_fun     
= 0;

    m_grouplist         .Restore(
0);
    m_recursivelist     .Restore(
0);
    m_namedlist         .Restore(
0);
    m_namedbackreflist  .Restore(
0);
    m_namedconditionlist.Restore(
0);

    
int i;
    
for(i=0; i<3; i++) MoveNext();

    
// build
    m_pTopElx = BuildAlternative(flags);

    
// group 0
    m_grouplist.Prepare(0);
    m_grouplist[
0= m_pTopElx;

    
// append named to unnamed
    m_nGroupCount = m_grouplist.GetSize();

    m_grouplist.Prepare(m_nMaxNumber 
+ m_namedlist.GetSize());

    
for(i=0; i<m_namedlist.GetSize(); i++)
    
{
        CBracketElx 
* pleft  = (CBracketElx *)m_namedlist[i]->m_elxlist[0];
        CBracketElx 
* pright = (CBracketElx *)m_namedlist[i]->m_elxlist[2];

        
// append
        m_grouplist[m_nGroupCount ++= m_namedlist[i];

        
if( pleft->m_nnumber > 0 )
            
continue;

        
// same name
        int find_same_name = GetNamedNumber(pleft->m_szNamed);
        
if( find_same_name >= 0 )
        
{
            pleft 
->m_nnumber = find_same_name;
            pright
->m_nnumber = find_same_name;
        }

        
else
        
{
            m_nMaxNumber 
++;

            pleft 
->m_nnumber = m_nMaxNumber;
            pright
->m_nnumber = m_nMaxNumber;
        }

    }


    
for(i=1; i<m_nGroupCount; i++)
    
{
        CBracketElx 
* pleft = (CBracketElx *)((CListElx*)m_grouplist[i])->m_elxlist[0];

        
if( pleft->m_nnumber > m_nMaxNumber )
            m_nMaxNumber 
= pleft->m_nnumber;
    }


    
// connect recursive
    for(i=0; i<m_recursivelist.GetSize(); i++)
    
{
        
if( m_recursivelist[i]->m_ndata == -3 )
            m_recursivelist[i]
->m_ndata = GetNamedNumber(m_recursivelist[i]->m_szNamed);

        
if( m_recursivelist[i]->m_ndata >= 0 && m_recursivelist[i]->m_ndata < m_grouplist.GetSize() )
            m_recursivelist[i]
->m_pelx = m_grouplist[m_recursivelist[i]->m_ndata];
    }


    
// named backref
    for(i=0; i<m_namedbackreflist.GetSize(); i++)
    
{
        m_namedbackreflist[i]
->m_nnumber = GetNamedNumber(m_namedbackreflist[i]->m_szNamed);
    }


    
// named condition
    for(i=0; i<m_namedconditionlist.GetSize(); i++)
    
{
        
int nn = GetNamedNumber(m_namedconditionlist[i]->m_szNamed);
        
if( nn >= 0 )
        
{
            m_namedconditionlist[i]
->m_nnumber = nn;
            m_namedconditionlist[i]
->m_pelxask = 0;
        }

    }


    
return m_pTopElx;
}


template 
< class  CHART >   void  CBuilderT  < CHART >  :: Clear()
{
    
for(int i=0; i<m_objlist.GetSize(); i++)
    
{
        delete m_objlist[i];
    }


    m_objlist.Restore(
0);
    m_pTopElx 
= 0;

    memset(m_pStockElxs, 
0sizeof(m_pStockElxs));
}


//
//  hex to int
//
template  < class  CHART >  unsigned  int  CBuilderT  < CHART >  :: Hex2Int( const  CHART  *  pcsz,  int  length,  int   &  used)
{
    unsigned 
int result = 0;
    
int & i = used;

    
for(i=0; i<length; i++)
    
{
        
if(pcsz[i] >= RCHART('0'&& pcsz[i] <= RCHART('9'))
            result 
= (result << 4+ (pcsz[i] - RCHART('0'));
        
else if(pcsz[i] >= RCHART('A'&& pcsz[i] <= RCHART('F'))
            result 
= (result << 4+ (0x0A + (pcsz[i] - RCHART('A')));
        
else if(pcsz[i] >= RCHART('a'&& pcsz[i] <= RCHART('f'))
            result 
= (result << 4+ (0x0A + (pcsz[i] - RCHART('a')));
        
else
            
break;
    }


    
return result;
}


template 
< class  CHART >  inline ElxInterface  *  CBuilderT  < CHART >  :: Keep(ElxInterface  *  pelx)
{
    m_objlist.Push(pelx);
    
return pelx;
}


template 
< class  CHART >   void  CBuilderT  < CHART >  :: MoveNext()
{
    
// forwards
    prev = curr;
    curr 
= next;
    next 
= nex2;

    
// get nex2
    while! GetNext2() ) {};
}


template 
< class  CHART >   int  CBuilderT  < CHART >  :: GetNext2()
{
    
// check length
    if(m_nNextPos >= m_pattern.GetSize())
    
{
        nex2 
= CHART_INFO(01, m_nNextPos, 0);
        
return 1;
    }


    
int   delta = 1;
    CHART ch    
= m_pattern[m_nNextPos];

    
// if quoted
    if(m_bQuoted)
    
{
        
if(ch == RCHART('/'))
        
{
            
if(m_pattern[m_nNextPos + 1== RCHART('E'))
            
{
                m_quote_fun 
= 0;
                m_bQuoted   
= 0;
                m_nNextPos 
+= 2;
                
return 0;
            }

        }


        
if(m_quote_fun != 0)
            nex2 
= CHART_INFO((CHART)(*m_quote_fun)((int)ch), 0, m_nNextPos, delta);
        
else
            nex2 
= CHART_INFO(ch, 0, m_nNextPos, delta);

        m_nNextPos 
+= delta;

        
return 1;
    }


    
// common
    switch(ch)
    
{
    
case RCHART('/'):
        
{
            CHART ch1 
= m_pattern[m_nNextPos+1];

            
// backref
            if(ch1 >= RCHART('0'&& ch1 <= RCHART('9'))
            
{
                nex2 
= CHART_INFO(ch, 1, m_nNextPos, delta);
                
break;
            }


            
// escape
            delta     = 2;

            
switch(ch1)
            
{
            
case RCHART('A'):
            
case RCHART('Z'):
            
case RCHART('w'):
            
case RCHART('W'):
            
case RCHART('s'):
            
case RCHART('S'):
            
case RCHART('B'):
            
case RCHART('d'):
            
case RCHART('D'):
            
case RCHART('k'):
            
case RCHART('g'):
                nex2 
= CHART_INFO(ch1, 1, m_nNextPos, delta);
                
break;

            
case RCHART('b'):
                
if(m_nCharsetDepth > 0)
                    nex2 
= CHART_INFO(''0, m_nNextPos, delta);
                
else
                    nex2 
= CHART_INFO(ch1, 1, m_nNextPos, delta);
                
break;

            
/*
            case RCHART('<'):
            case RCHART('>'):
                if(m_nCharsetDepth > 0)
                    nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
                else
                    nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
                break;
            
*/


            
case RCHART('x'):
                
if(m_pattern[m_nNextPos+2!= '{')
                
{
                    
int red = 0;
                    unsigned 
int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 22, red);

                    delta 
+= red;

                    
if(red > 0)
                        nex2 
= CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
                    
else
                        nex2 
= CHART_INFO(ch1, 0, m_nNextPos, delta);

                
break;
                }


            
case RCHART('u'):
                
if(m_pattern[m_nNextPos+2!= '{')
                
{
                    
int red = 0;
                    unsigned 
int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 24, red);

                    delta 
+= red;

                    
if(red > 0)
                        nex2 
= CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
                    
else
                        nex2 
= CHART_INFO(ch1, 0, m_nNextPos, delta);
                }

                
else
                
{
                    
int red = 0;
                    unsigned 
int ch2 = Hex2Int(m_pattern.GetBuffer() + m_nNextPos + 3sizeof(int* 2, red);

                    delta 
+= red;

                    
while(m_nNextPos + delta < m_pattern.GetSize() && m_pattern.At(m_nNextPos + delta) != RCHART('}'))
                        delta 
++;

                    delta 
++// skip '}'

                    nex2 
= CHART_INFO(RCHART(ch2), 0, m_nNextPos, delta);
                }

                
break;

            
case RCHART('a'): nex2 = CHART_INFO(RCHART('a'), 0, m_nNextPos, delta); break;
            
case RCHART('f'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break;
            
case RCHART('n'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break;
            
case RCHART('r'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break;
            
case RCHART('t'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break;
            
case RCHART('v'): nex2 = CHART_INFO(RCHART('v'), 0, m_nNextPos, delta); break;
            
case RCHART('e'): nex2 = CHART_INFO(RCHART( 27 ), 0, m_nNextPos, delta); break;

            
case RCHART('G'):  // skip 'G'
                if(m_nCharsetDepth > 0)
                
{
                    m_nNextPos 
+= 2;
                    
return 0;
                }

                
else
                
{
                    nex2 
= CHART_INFO(ch1, 1, m_nNextPos, delta);
                    
break;
                }


            
case RCHART('L'):
                
if! m_quote_fun ) m_quote_fun = ::tolower;

            
case RCHART('U'):
                
if! m_quote_fun ) m_quote_fun = ::toupper;

            
case RCHART('Q'):
                
{
                    m_bQuoted   
= 1;
                    m_nNextPos 
+= 2;
                    
return 0;
                }


            
case RCHART('E'):
                
{
                    m_quote_fun 
= 0;
                    m_bQuoted   
= 0;
                    m_nNextPos 
+= 2;
                    
return 0;
                }


            
case 0:
                
if(m_nNextPos+1 >= m_pattern.GetSize())
                
{
                    delta 
= 1;
                    nex2 
= CHART_INFO(ch , 0, m_nNextPos, delta);
                }

                
else
                    nex2 
= CHART_INFO(ch1, 0, m_nNextPos, delta); // common '
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值