+++ /dev/null
-// deelx.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.26 $
-//
-
-#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 = 0) const;
- 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 != 0) while(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('\n')) || ((chL == RCHART('\r')) && (chR != RCHART('\n')));
- break;
-
- case BOUNDARY_LINE_END:
- bsucc = (npos >= tlen) || (chR == RCHART('\r')) || ((chR == RCHART('\n')) && (chL != RCHART('\r')));
- 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 < 0) return 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 = 0, int 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 misblank(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 = misblank;
- else m_posixfun = 0 ;
-}
-
-template <class CHART> int CPosixElxT <CHART> :: misblank(int c)
-{
- return c == 0x20 || c == '\t';
-}
-
-template <class CHART> int CPosixElxT <CHART> :: Match(CContext * pContext) const
-{
- if(m_posixfun == 0) return 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 = 0, int 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 = 0, int 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 * fixed, int 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 < 0) break;
-
- // 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 = 0, int 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, 0, sizeof(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(0, 1, 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('\b', 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 + 2, 2, 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 + 2, 4, 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 + 3, sizeof(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('\f'), 0, m_nNextPos, delta); break;
- case RCHART('n'): nex2 = CHART_INFO(RCHART('\n'), 0, m_nNextPos, delta); break;
- case RCHART('r'): nex2 = CHART_INFO(RCHART('\r'), 0, m_nNextPos, delta); break;
- case RCHART('t'): nex2 = CHART_INFO(RCHART('\t'), 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' char
- break;
-
- default:
- nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
- break;
- }
- }
- break;
-
- case RCHART('*'):
- case RCHART('+'):
- case RCHART('?'):
- case RCHART('.'):
- case RCHART('{'):
- case RCHART('}'):
- case RCHART(')'):
- case RCHART('|'):
- case RCHART('$'):
- if(m_nCharsetDepth > 0)
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- else
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- break;
-
- case RCHART('-'):
- if(m_nCharsetDepth > 0)
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- else
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- break;
-
- case RCHART('('):
- {
- CHART ch1 = m_pattern[m_nNextPos+1];
- CHART ch2 = m_pattern[m_nNextPos+2];
-
- // skip remark
- if(ch1 == RCHART('?') && ch2 == RCHART('#'))
- {
- m_nNextPos += 2;
- while(m_nNextPos < m_pattern.GetSize())
- {
- if(m_pattern[m_nNextPos] == RCHART(')'))
- break;
-
- m_nNextPos ++;
- }
-
- if(m_pattern[m_nNextPos] == RCHART(')'))
- {
- m_nNextPos ++;
-
- // get next nex2
- return 0;
- }
- }
- else
- {
- if(m_nCharsetDepth > 0)
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- else
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- }
- }
- break;
-
- case RCHART('#'):
- if(m_nFlags & EXTENDED)
- {
- // skip remark
- m_nNextPos ++;
-
- while(m_nNextPos < m_pattern.GetSize())
- {
- if(m_pattern[m_nNextPos] == RCHART('\n') || m_pattern[m_nNextPos] == RCHART('\r'))
- break;
-
- m_nNextPos ++;
- }
-
- // get next nex2
- return 0;
- }
- else
- {
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- }
- break;
-
- case RCHART(' '):
- case RCHART('\f'):
- case RCHART('\n'):
- case RCHART('\r'):
- case RCHART('\t'):
- case RCHART('\v'):
- if(m_nFlags & EXTENDED)
- {
- m_nNextPos ++;
-
- // get next nex2
- return 0;
- }
- else
- {
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- }
- break;
-
- case RCHART('['):
- m_nCharsetDepth ++;
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- break;
-
- case RCHART(']'):
- if(m_nCharsetDepth > 0)
- {
- m_nCharsetDepth --;
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- }
- else
- {
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- }
- break;
-
- case RCHART(':'):
- if(next == CHART_INFO(RCHART('['), 1))
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- else
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- break;
-
- case RCHART('^'):
- if(m_nCharsetDepth == 0 || next == CHART_INFO(RCHART('['), 1) || (curr == CHART_INFO(RCHART('['), 1) && next == CHART_INFO(RCHART(':'), 1)))
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta);
- else
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- break;
-
- case 0:
- if(m_nNextPos >= m_pattern.GetSize())
- nex2 = CHART_INFO(ch, 1, m_nNextPos, delta); // end of string
- else
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta); // common '\0' char
- break;
-
- default:
- nex2 = CHART_INFO(ch, 0, m_nNextPos, delta);
- break;
- }
-
- m_nNextPos += delta;
-
- return 1;
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: GetStockElx(int nStockId)
-{
- ElxInterface ** pStockElxs = m_pStockElxs;
-
- // check
- if(nStockId < 0 || nStockId >= STOCKELX_COUNT)
- return GetStockElx(0);
-
- // create if no
- if(pStockElxs[nStockId] == 0)
- {
- switch(nStockId)
- {
- case STOCKELX_EMPTY:
- pStockElxs[nStockId] = Keep(new CEmptyElx());
- break;
-
- case STOCKELX_WORD:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
-
- pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
- pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
- pRange->m_chars .Push(RCHART('_'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_WORD_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
-
- pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
- pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
- pRange->m_chars .Push(RCHART('_'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DOT_ALL:
- pStockElxs[nStockId] = Keep(new CRangeElxT <CHART> (0, 0));
- break;
-
- case STOCKELX_DOT_NOT_ALL:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
-
- pRange->m_chars .Push(RCHART('\n'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_SPACE:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
-
- pRange->m_chars .Push(RCHART(' '));
- pRange->m_chars .Push(RCHART('\t'));
- pRange->m_chars .Push(RCHART('\r'));
- pRange->m_chars .Push(RCHART('\n'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_SPACE_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
-
- pRange->m_chars .Push(RCHART(' '));
- pRange->m_chars .Push(RCHART('\t'));
- pRange->m_chars .Push(RCHART('\r'));
- pRange->m_chars .Push(RCHART('\n'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DIGITAL:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 1));
-
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DIGITAL_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (0, 0));
-
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_WORD_RIGHTLEFT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
-
- pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
- pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
- pRange->m_chars .Push(RCHART('_'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_WORD_RIGHTLEFT_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
-
- pRange->m_ranges.Push(RCHART('A')); pRange->m_ranges.Push(RCHART('Z'));
- pRange->m_ranges.Push(RCHART('a')); pRange->m_ranges.Push(RCHART('z'));
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
- pRange->m_chars .Push(RCHART('_'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DOT_ALL_RIGHTLEFT:
- pStockElxs[nStockId] = Keep(new CRangeElxT <CHART> (1, 0));
- break;
-
- case STOCKELX_DOT_NOT_ALL_RIGHTLEFT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
-
- pRange->m_chars .Push(RCHART('\n'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_SPACE_RIGHTLEFT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
-
- pRange->m_chars .Push(RCHART(' '));
- pRange->m_chars .Push(RCHART('\t'));
- pRange->m_chars .Push(RCHART('\r'));
- pRange->m_chars .Push(RCHART('\n'));
- pRange->m_chars .Push(RCHART('\f'));
- pRange->m_chars .Push(RCHART('\v'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_SPACE_RIGHTLEFT_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
-
- pRange->m_chars .Push(RCHART(' '));
- pRange->m_chars .Push(RCHART('\t'));
- pRange->m_chars .Push(RCHART('\r'));
- pRange->m_chars .Push(RCHART('\n'));
- pRange->m_chars .Push(RCHART('\f'));
- pRange->m_chars .Push(RCHART('\v'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DIGITAL_RIGHTLEFT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 1));
-
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
-
- case STOCKELX_DIGITAL_RIGHTLEFT_NOT:
- {
- CRangeElxT <CHART> * pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (1, 0));
-
- pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9'));
-
- pStockElxs[nStockId] = pRange;
- }
- break;
- }
- }
-
- // return
- return pStockElxs[nStockId];
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildAlternative(int vaflags)
-{
- if(curr == CHART_INFO(0, 1))
- return GetStockElx(STOCKELX_EMPTY);
-
- // flag instance
- int flags = vaflags;
-
- // first part
- ElxInterface * pAlternativeOne = BuildList(flags);
-
- // check alternative
- if(curr == CHART_INFO(RCHART('|'), 1))
- {
- CAlternativeElx * pAlternative = (CAlternativeElx *)Keep(new CAlternativeElx());
- pAlternative->m_elxlist.Push(pAlternativeOne);
-
- // loop
- while(curr == CHART_INFO(RCHART('|'), 1))
- {
- // skip '|' itself
- MoveNext();
-
- pAlternativeOne = BuildList(flags);
- pAlternative->m_elxlist.Push(pAlternativeOne);
- }
-
- return pAlternative;
- }
-
- return pAlternativeOne;
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildList(int & flags)
-{
- if(curr == CHART_INFO(0, 1) || curr == CHART_INFO(RCHART('|'), 1) || curr == CHART_INFO(RCHART(')'), 1))
- return GetStockElx(STOCKELX_EMPTY);
-
- // first
- ElxInterface * pListOne = BuildRepeat(flags);
-
- if(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1))
- {
- CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
- pList->m_elxlist.Push(pListOne);
-
- while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('|'), 1) && curr != CHART_INFO(RCHART(')'), 1))
- {
- pListOne = BuildRepeat(flags);
-
- // add
- pList->m_elxlist.Push(pListOne);
- }
-
- return pList;
- }
-
- return pListOne;
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildRepeat(int & flags)
-{
- // simple
- ElxInterface * pSimple = BuildSimple(flags);
-
- if(curr.type == 0) return pSimple;
-
- // is quantifier or not
- int bIsQuantifier = 1;
-
- // quantifier range
- unsigned int nMin = 0, nMax = 0;
-
- switch(curr.ch)
- {
- case RCHART('{'):
- {
- CBufferT <char> re;
-
- // skip '{'
- MoveNext();
-
- // copy
- while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART('}'), 1))
- {
- re.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
-
- // skip '}'
- MoveNext();
-
- // read
- int red;
- char * str = re.GetBuffer();
-
- if( ! ReadDec(str, nMin) )
- red = 0;
- else if( *str != ',' )
- red = 1;
- else
- {
- str ++;
-
- if( ! ReadDec(str, nMax) )
- red = 2;
- else
- red = 3;
- }
-
- // check
- if(red <= 1 ) nMax = nMin;
- if(red == 2 ) nMax = INT_MAX;
- if(nMax < nMin) nMax = nMin;
- }
- break;
-
- case RCHART('?'):
- nMin = 0;
- nMax = 1;
-
- // skip '?'
- MoveNext();
- break;
-
- case RCHART('*'):
- nMin = 0;
- nMax = INT_MAX;
-
- // skip '*'
- MoveNext();
- break;
-
- case RCHART('+'):
- nMin = 1;
- nMax = INT_MAX;
-
- // skip '+'
- MoveNext();
- break;
-
- default:
- bIsQuantifier = 0;
- break;
- }
-
- // do quantify
- if(bIsQuantifier)
- {
- // 0 times
- if(nMax == 0)
- return GetStockElx(STOCKELX_EMPTY);
-
- // fixed times
- if(nMin == nMax)
- {
- if(curr == CHART_INFO(RCHART('?'), 1) || curr == CHART_INFO(RCHART('+'), 1))
- MoveNext();
-
- return Keep(new CRepeatElx(pSimple, nMin));
- }
-
- // range times
- if(curr == CHART_INFO(RCHART('?'), 1))
- {
- MoveNext();
- return Keep(new CReluctantElx(pSimple, nMin, nMax));
- }
- else if(curr == CHART_INFO(RCHART('+'), 1))
- {
- MoveNext();
- return Keep(new CPossessiveElx(pSimple, nMin, nMax));
- }
- else
- {
- return Keep(new CGreedyElx(pSimple, nMin, nMax));
- }
- }
-
- return pSimple;
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildSimple(int & flags)
-{
- CBufferT <CHART> fixed;
-
- while(curr != CHART_INFO(0, 1))
- {
- if(curr.type == 0)
- {
- if(next == CHART_INFO(RCHART('{'), 1) || next == CHART_INFO(RCHART('?'), 1) || next == CHART_INFO(RCHART('*'), 1) || next == CHART_INFO(RCHART('+'), 1))
- {
- if(fixed.GetSize() == 0)
- {
- fixed.Append(curr.ch, 1);
- MoveNext();
- }
-
- break;
- }
- else
- {
- fixed.Append(curr.ch, 1);
- MoveNext();
- }
- }
- else if(curr.type == 1)
- {
- CHART vch = curr.ch;
-
- // end of simple
- if(vch == RCHART(')') || vch == RCHART('|'))
- break;
-
- // has fixed already
- if(fixed.GetSize() > 0)
- break;
-
- // left parentheses
- if(vch == RCHART('('))
- {
- return BuildRecursive(flags);
- }
-
- // char set
- if( vch == RCHART('[') || vch == RCHART('.') || vch == RCHART('w') || vch == RCHART('W') ||
- vch == RCHART('s') || vch == RCHART('S') || vch == RCHART('d') || vch == RCHART('D')
- )
- {
- return BuildCharset(flags);
- }
-
- // boundary
- if( vch == RCHART('^') || vch == RCHART('$') || vch == RCHART('A') || vch == RCHART('Z') ||
- vch == RCHART('b') || vch == RCHART('B') || vch == RCHART('G') // vch == RCHART('<') || vch == RCHART('>')
- )
- {
- return BuildBoundary(flags);
- }
-
- // backref
- if(vch == RCHART('\\') || vch == RCHART('k') || vch == RCHART('g'))
- {
- return BuildBackref(flags);
- }
-
- // treat vchar as char
- fixed.Append(curr.ch, 1);
- MoveNext();
- }
- }
-
- if(fixed.GetSize() > 0)
- return Keep(new CStringElxT <CHART> (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE));
- else
- return GetStockElx(STOCKELX_EMPTY);
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildCharset(int & flags)
-{
- // char
- CHART ch = curr.ch;
-
- // skip
- MoveNext();
-
- switch(ch)
- {
- case RCHART('.'):
- return GetStockElx(
- flags & RIGHTTOLEFT ?
- ((flags & SINGLELINE) ? STOCKELX_DOT_ALL_RIGHTLEFT : STOCKELX_DOT_NOT_ALL_RIGHTLEFT) :
- ((flags & SINGLELINE) ? STOCKELX_DOT_ALL : STOCKELX_DOT_NOT_ALL)
- );
-
- case RCHART('w'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT : STOCKELX_WORD);
-
- case RCHART('W'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_WORD_RIGHTLEFT_NOT : STOCKELX_WORD_NOT);
-
- case RCHART('s'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT : STOCKELX_SPACE);
-
- case RCHART('S'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_SPACE_RIGHTLEFT_NOT : STOCKELX_SPACE_NOT);
-
- case RCHART('d'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT : STOCKELX_DIGITAL);
-
- case RCHART('D'):
- return GetStockElx(flags & RIGHTTOLEFT ? STOCKELX_DIGITAL_RIGHTLEFT_NOT : STOCKELX_DIGITAL_NOT);
-
- case RCHART('['):
- {
- CRangeElxT <CHART> * pRange;
-
- // create
- if(curr == CHART_INFO(RCHART(':'), 1))
- {
- CBufferT <char> posix;
-
- do {
- posix.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
- while(curr.ch != RCHART(0) && curr != CHART_INFO(RCHART(']'), 1));
-
- MoveNext(); // skip ']'
-
- // posix
- return Keep(new CPosixElxT <CHART> (posix.GetBuffer(), flags & RIGHTTOLEFT));
- }
- else if(curr == CHART_INFO(RCHART('^'), 1))
- {
- MoveNext(); // skip '^'
- pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 0));
- }
- else
- {
- pRange = (CRangeElxT <CHART> *)Keep(new CRangeElxT <CHART> (flags & RIGHTTOLEFT, 1));
- }
-
- // parse
- while(curr != CHART_INFO(0, 1) && curr != CHART_INFO(RCHART(']'), 1))
- {
- ch = curr.ch;
-
- if(curr.type == 1 && (
- ch == RCHART('.') || ch == RCHART('w') || ch == RCHART('W') || ch == RCHART('s') || ch == RCHART('S') || ch == RCHART('d') || ch == RCHART('D') ||
- (ch == RCHART('[') && next == CHART_INFO(RCHART(':'), 1))
- ))
- {
- pRange->m_embeds.Push(BuildCharset(flags));
- }
- else if(next == CHART_INFO(RCHART('-'), 1) && nex2.type == 0)
- {
- pRange->m_ranges.Push(ch); pRange->m_ranges.Push(nex2.ch);
-
- // next
- MoveNext();
- MoveNext();
- MoveNext();
- }
- else
- {
- pRange->m_chars.Push(ch);
-
- // next
- MoveNext();
- }
- }
-
- // skip ']'
- MoveNext();
-
- return pRange;
- }
- }
-
- return GetStockElx(STOCKELX_EMPTY);
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildRecursive(int & flags)
-{
- // skip '('
- MoveNext();
-
- if(curr == CHART_INFO(RCHART('?'), 1))
- {
- ElxInterface * pElx = 0;
-
- // skip '?'
- MoveNext();
-
- int bNegative = 0;
- CHART named_end = RCHART('>');
-
- switch(curr.ch)
- {
- case RCHART('!'):
- bNegative = 1;
-
- case RCHART('='):
- {
- MoveNext(); // skip '!' or '='
- pElx = Keep(new CAssertElx(BuildAlternative(flags & ~RIGHTTOLEFT), !bNegative));
- }
- break;
-
- case RCHART('<'):
- switch(next.ch)
- {
- case RCHART('!'):
- bNegative = 1;
-
- case RCHART('='):
- MoveNext(); // skip '<'
- MoveNext(); // skip '!' or '='
- {
- pElx = Keep(new CAssertElx(BuildAlternative(flags | RIGHTTOLEFT), !bNegative));
- }
- break;
-
- default: // named group
- break;
- }
- // break if assertion // else named
- if(pElx != 0) break;
-
- case RCHART('P'):
- if(curr.ch == RCHART('P')) MoveNext(); // skip 'P'
-
- case RCHART('\''):
- if (curr.ch == RCHART('<' )) named_end = RCHART('>' );
- else if(curr.ch == RCHART('\'')) named_end = RCHART('\'');
- MoveNext(); // skip '<' or '\''
- {
- // named number
- int nThisBackref = m_nNextNamed ++;
-
- CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
- CBracketElx * pleft = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 1 : 0));
- CBracketElx * pright = (CBracketElx *)Keep(new CBracketElx(-1, flags & RIGHTTOLEFT ? 0 : 1));
-
- // save name
- CBufferT <CHART> & name = pleft->m_szNamed;
- CBufferT <char> num;
-
- while(curr.ch != RCHART(0) && curr.ch != named_end)
- {
- name.Append(curr.ch, 1);
- num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
- MoveNext(); // skip '>' or '\''
-
- // check <num>
- unsigned int number;
- char * str = num.GetBuffer();
-
- if( ReadDec(str, number) ? ( *str == '\0') : 0 )
- {
- pleft ->m_nnumber = number;
- pright->m_nnumber = number;
-
- name.Release();
- }
-
- // left, center, right
- pList->m_elxlist.Push(pleft);
- pList->m_elxlist.Push(BuildAlternative(flags));
- pList->m_elxlist.Push(pright);
-
- // for recursive
- m_namedlist.Prepare(nThisBackref);
- m_namedlist[nThisBackref] = pList;
-
- pElx = pList;
- }
- break;
-
- case RCHART('>'):
- {
- MoveNext(); // skip '>'
- pElx = Keep(new CIndependentElx(BuildAlternative(flags)));
- }
- break;
-
- case RCHART('R'):
- MoveNext(); // skip 'R'
- while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
-
- if(curr.ch == RCHART('<') || curr.ch == RCHART('\''))
- {
- named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\'');
- CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(-3));
-
- MoveNext(); // skip '<' or '\\'
-
- // save name
- CBufferT <CHART> & name = pDelegate->m_szNamed;
- CBufferT <char> num;
-
- while(curr.ch != RCHART(0) && curr.ch != named_end)
- {
- name.Append(curr.ch, 1);
- num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
- MoveNext(); // skip '>' or '\''
-
- // check <num>
- unsigned int number;
- char * str = num.GetBuffer();
-
- if( ReadDec(str, number) ? ( *str == '\0') : 0 )
- {
- pDelegate->m_ndata = number;
- name.Release();
- }
-
- m_recursivelist.Push(pDelegate);
- pElx = pDelegate;
- }
- else
- {
- CBufferT <char> rto;
- while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
- {
- rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
-
- unsigned int rtono = 0;
- char * str = rto.GetBuffer();
- ReadDec(str, rtono);
-
- CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
-
- m_recursivelist.Push(pDelegate);
- pElx = pDelegate;
- }
- break;
-
- case RCHART('('):
- {
- CConditionElx * pConditionElx = (CConditionElx *)Keep(new CConditionElx());
-
- // condition
- ElxInterface * & pCondition = pConditionElx->m_pelxask;
-
- if(next == CHART_INFO(RCHART('?'), 1))
- {
- pCondition = BuildRecursive(flags);
- }
- else // named, assert or number
- {
- MoveNext(); // skip '('
- int pos0 = curr.pos;
-
- // save elx condition
- pCondition = Keep(new CAssertElx(BuildAlternative(flags), 1));
-
- // save name
- pConditionElx->m_szNamed.Append(m_pattern.GetBuffer() + pos0, curr.pos - pos0, 1);
-
- // save number
- CBufferT <char> numstr;
- while(pos0 < curr.pos)
- {
- CHART ch = m_pattern[pos0];
- numstr.Append(((ch & (CHART)0xff) == ch) ? (char)ch : 0, 1);
- pos0 ++;
- }
-
- unsigned int number;
- char * str = numstr.GetBuffer();
-
- // valid group number
- if( ReadDec(str, number) ? ( *str == '\0') : 0 )
- {
- pConditionElx->m_nnumber = number;
- pCondition = 0;
- }
- else // maybe elx, maybe named
- {
- pConditionElx->m_nnumber = -1;
- m_namedconditionlist.Push(pConditionElx);
- }
-
- MoveNext(); // skip ')'
- }
-
- // alternative
- {
- int newflags = flags;
-
- pConditionElx->m_pelxyes = BuildList(newflags);
- }
-
- if(curr.ch == RCHART('|'))
- {
- MoveNext(); // skip '|'
-
- pConditionElx->m_pelxno = BuildAlternative(flags);
- }
- else
- {
- pConditionElx->m_pelxno = 0;
- }
-
- pElx = pConditionElx;
- }
- break;
-
- default:
- while(curr.ch != RCHART(0) && isspace(curr.ch)) MoveNext(); // skip space
-
- if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9')) // recursive (?1) => (?R1)
- {
- CBufferT <char> rto;
- while(curr.ch != RCHART(0) && curr.ch != RCHART(')'))
- {
- rto.Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
-
- unsigned int rtono = 0;
- char * str = rto.GetBuffer();
- ReadDec(str, rtono);
-
- CDelegateElx * pDelegate = (CDelegateElx *)Keep(new CDelegateElx(rtono));
-
- m_recursivelist.Push(pDelegate);
- pElx = pDelegate;
- }
- else
- {
- // flag
- int newflags = flags;
- while(curr != CHART_INFO(0, 1) && curr.ch != RCHART(':') && curr.ch != RCHART(')') && curr != CHART_INFO(RCHART('('), 1))
- {
- int tochange = 0;
-
- switch(curr.ch)
- {
- case RCHART('i'):
- case RCHART('I'):
- tochange = IGNORECASE;
- break;
-
- case RCHART('s'):
- case RCHART('S'):
- tochange = SINGLELINE;
- break;
-
- case RCHART('m'):
- case RCHART('M'):
- tochange = MULTILINE;
- break;
-
- case RCHART('g'):
- case RCHART('G'):
- tochange = GLOBAL;
- break;
-
- case RCHART('-'):
- bNegative = 1;
- break;
- }
-
- if(bNegative)
- newflags &= ~tochange;
- else
- newflags |= tochange;
-
- // move to next char
- MoveNext();
- }
-
- if(curr.ch == RCHART(':') || curr == CHART_INFO(RCHART('('), 1))
- {
- // skip ':'
- if(curr.ch == RCHART(':')) MoveNext();
-
- pElx = BuildAlternative(newflags);
- }
- else
- {
- // change parent flags
- flags = newflags;
-
- pElx = GetStockElx(STOCKELX_EMPTY);
- }
- }
- break;
- }
-
- MoveNext(); // skip ')'
-
- return pElx;
- }
- else
- {
- // group and number
- CListElx * pList = (CListElx *)Keep(new CListElx(flags & RIGHTTOLEFT));
- int nThisBackref = ++ m_nMaxNumber;
-
- // left, center, right
- pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 1 : 0)));
- pList->m_elxlist.Push(BuildAlternative(flags));
- pList->m_elxlist.Push(Keep(new CBracketElx(nThisBackref, flags & RIGHTTOLEFT ? 0 : 1)));
-
- // for recursive
- m_grouplist.Prepare(nThisBackref);
- m_grouplist[nThisBackref] = pList;
-
- // right
- MoveNext(); // skip ')'
-
- return pList;
- }
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildBoundary(int & flags)
-{
- // char
- CHART ch = curr.ch;
-
- // skip
- MoveNext();
-
- switch(ch)
- {
- case RCHART('^'):
- return Keep(new CBoundaryElxT <CHART> ((flags & MULTILINE) ? BOUNDARY_LINE_BEGIN : BOUNDARY_FILE_BEGIN));
-
- case RCHART('$'):
- return Keep(new CBoundaryElxT <CHART> ((flags & MULTILINE) ? BOUNDARY_LINE_END : BOUNDARY_FILE_END));
-
- case RCHART('b'):
- return Keep(new CBoundaryElxT <CHART> (BOUNDARY_WORD_EDGE));
-
- case RCHART('B'):
- return Keep(new CBoundaryElxT <CHART> (BOUNDARY_WORD_EDGE, 0));
-
- case RCHART('A'):
- return Keep(new CBoundaryElxT <CHART> (BOUNDARY_FILE_BEGIN));
-
- case RCHART('Z'):
- return Keep(new CBoundaryElxT <CHART> (BOUNDARY_FILE_END));
-
- case RCHART('G'):
- if(flags & GLOBAL)
- return Keep(new CGlobalElx());
- else
- return GetStockElx(STOCKELX_EMPTY);
-
- default:
- return GetStockElx(STOCKELX_EMPTY);
- }
-}
-
-template <class CHART> ElxInterface * CBuilderT <CHART> :: BuildBackref(int & flags)
-{
- // skip '\\' or '\k' or '\g'
- MoveNext();
-
- if(curr.ch == RCHART('<') || curr.ch == RCHART('\''))
- {
- CHART named_end = curr.ch == RCHART('<') ? RCHART('>') : RCHART('\'');
- CBackrefElxT <CHART> * pbackref = (CBackrefElxT <CHART> *)Keep(new CBackrefElxT <CHART> (-1, flags & RIGHTTOLEFT, flags & IGNORECASE));
-
- MoveNext(); // skip '<' or '\''
-
- // save name
- CBufferT <CHART> & name = pbackref->m_szNamed;
- CBufferT <char> num;
-
- while(curr.ch != RCHART(0) && curr.ch != named_end)
- {
- name.Append(curr.ch, 1);
- num .Append(((curr.ch & (CHART)0xff) == curr.ch) ? (char)curr.ch : 0, 1);
- MoveNext();
- }
- MoveNext(); // skip '>' or '\''
-
- // check <num>
- unsigned int number;
- char * str = num.GetBuffer();
-
- if( ReadDec(str, number) ? ( *str == '\0') : 0 )
- {
- pbackref->m_nnumber = number;
- name.Release();
- }
- else
- {
- m_namedbackreflist.Push(pbackref);
- }
-
- return pbackref;
- }
- else
- {
- unsigned int nbackref = 0;
-
- for(int i=0; i<3; i++)
- {
- if(curr.ch >= RCHART('0') && curr.ch <= RCHART('9'))
- nbackref = nbackref * 10 + (curr.ch - RCHART('0'));
- else
- break;
-
- MoveNext();
- }
-
- return Keep(new CBackrefElxT <CHART> (nbackref, flags & RIGHTTOLEFT, flags & IGNORECASE));
- }
-}
-
-template <class CHART> int CBuilderT <CHART> :: ReadDec(char * & str, unsigned int & dec)
-{
- int s = 0;
- while(str[s] != 0 && isspace(str[s])) s++;
-
- if(str[s] < '0' || str[s] > '9') return 0;
-
- dec = 0;
- unsigned int i;
-
- for(i = s; i<sizeof(CHART)*3 + s; i++)
- {
- if(str[i] >= '0' && str[i] <= '9')
- dec = dec * 10 + (str[i] - '0');
- else
- break;
- }
-
- while(str[i] != 0 && isspace(str[i])) i++;
- str += i;
-
- return 1;
-}
-
-//
-// Regexp
-//
-template <class CHART> class CRegexpT
-{
-public:
- CRegexpT(const CHART * pattern = 0, int flags = 0);
- CRegexpT(const CHART * pattern, int length, int flags);
- void Compile(const CHART * pattern, int flags = 0);
- void Compile(const CHART * pattern, int length, int flags);
-
-public:
- MatchResult MatchExact(const CHART * tstring, CContext * pContext = 0) const;
- MatchResult MatchExact(const CHART * tstring, int length, CContext * pContext = 0) const;
- MatchResult Match(const CHART * tstring, int start = -1, CContext * pContext = 0) const;
- MatchResult Match(const CHART * tstring, int length, int start, CContext * pContext = 0) const;
- MatchResult Match(CContext * pContext) const;
- CContext * PrepareMatch(const CHART * tstring, int start = -1, CContext * pContext = 0) const;
- CContext * PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext = 0) const;
- CHART * Replace(const CHART * tstring, const CHART * replaceto, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const;
- CHART * Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start = -1, int ntimes = -1, MatchResult * result = 0, CContext * pContext = 0) const;
- int GetNamedGroupNumber(const CHART * group_name) const;
-
-public:
- static void ReleaseString (CHART * tstring );
- static void ReleaseContext(CContext * pContext);
-
-public:
- CBuilderT <CHART> m_builder;
-};
-
-//
-// Implementation
-//
-template <class CHART> CRegexpT <CHART> :: CRegexpT(const CHART * pattern, int flags)
-{
- Compile(pattern, CBufferRefT<CHART>(pattern).GetSize(), flags);
-}
-
-template <class CHART> CRegexpT <CHART> :: CRegexpT(const CHART * pattern, int length, int flags)
-{
- Compile(pattern, length, flags);
-}
-
-template <class CHART> inline void CRegexpT <CHART> :: Compile(const CHART * pattern, int flags)
-{
- Compile(pattern, CBufferRefT<CHART>(pattern).GetSize(), flags);
-}
-
-template <class CHART> void CRegexpT <CHART> :: Compile(const CHART * pattern, int length, int flags)
-{
- m_builder.Clear();
- if(pattern != 0) m_builder.Build(CBufferRefT<CHART>(pattern, length), flags);
-}
-
-template <class CHART> inline MatchResult CRegexpT <CHART> :: MatchExact(const CHART * tstring, CContext * pContext) const
-{
- return MatchExact(tstring, CBufferRefT<CHART>(tstring).GetSize(), pContext);
-}
-
-template <class CHART> MatchResult CRegexpT <CHART> :: MatchExact(const CHART * tstring, int length, CContext * pContext) const
-{
- if(m_builder.m_pTopElx == 0)
- return 0;
-
- // info
- int endpos = 0;
-
- CContext context;
- if(pContext == 0) pContext = &context;
-
- pContext->m_stack.Restore(0);
- pContext->m_capturestack.Restore(0);
- pContext->m_captureindex.Restore(0);
-
- pContext->m_nParenZindex = 0;
- pContext->m_nLastBeginPos = -1;
- pContext->m_pMatchString = (void*)tstring;
- pContext->m_pMatchStringLength = length;
-
- if(m_builder.m_nFlags & RIGHTTOLEFT)
- {
- pContext->m_nBeginPos = length;
- pContext->m_nCurrentPos = length;
- endpos = 0;
- }
- else
- {
- pContext->m_nBeginPos = 0;
- pContext->m_nCurrentPos = 0;
- endpos = length;
- }
-
- pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1);
- pContext->m_captureindex[0] = 0;
- pContext->m_capturestack.Push(0);
- pContext->m_capturestack.Push(pContext->m_nCurrentPos);
- pContext->m_capturestack.Push(-1);
- pContext->m_capturestack.Push(-1);
-
- // match
- if( ! m_builder.m_pTopElx->Match( pContext ) )
- return 0;
- else
- {
- while( pContext->m_nCurrentPos != endpos )
- {
- if( ! m_builder.m_pTopElx->MatchNext( pContext ) )
- return 0;
- else
- {
- if( pContext->m_nLastBeginPos == pContext->m_nBeginPos && pContext->m_nBeginPos == pContext->m_nCurrentPos )
- return 0;
- else
- pContext->m_nLastBeginPos = pContext->m_nCurrentPos;
- }
- }
-
- // end pos
- pContext->m_capturestack[2] = pContext->m_nCurrentPos;
-
- return MatchResult( pContext, m_builder.m_nMaxNumber );
- }
-}
-
-template <class CHART> MatchResult CRegexpT <CHART> :: Match(const CHART * tstring, int start, CContext * pContext) const
-{
- return Match(tstring, CBufferRefT<CHART>(tstring).GetSize(), start, pContext);
-}
-
-template <class CHART> MatchResult CRegexpT <CHART> :: Match(const CHART * tstring, int length, int start, CContext * pContext) const
-{
- if(m_builder.m_pTopElx == 0)
- return 0;
-
- CContext context;
- if(pContext == 0) pContext = &context;
-
- pContext->m_nParenZindex = 0;
- pContext->m_nLastBeginPos = -1;
- pContext->m_pMatchString = (void*)tstring;
- pContext->m_pMatchStringLength = length;
-
- if(start < 0)
- {
- if(m_builder.m_nFlags & RIGHTTOLEFT)
- {
- pContext->m_nBeginPos = length;
- pContext->m_nCurrentPos = length;
- }
- else
- {
- pContext->m_nBeginPos = 0;
- pContext->m_nCurrentPos = 0;
- }
- }
- else
- {
- pContext->m_nBeginPos = start;
- pContext->m_nCurrentPos = start;
- }
-
- return Match( pContext );
-}
-
-template <class CHART> MatchResult CRegexpT <CHART> :: Match(CContext * pContext) const
-{
- if(m_builder.m_pTopElx == 0)
- return 0;
-
- int endpos, delta;
-
- if(m_builder.m_nFlags & RIGHTTOLEFT)
- {
- endpos = -1;
- delta = -1;
- }
- else
- {
- endpos = pContext->m_pMatchStringLength + 1;
- delta = 1;
- }
-
- while(pContext->m_nCurrentPos != endpos)
- {
- pContext->m_captureindex.Restore(0);
- pContext->m_stack .Restore(0);
- pContext->m_capturestack.Restore(0);
-
- pContext->m_captureindex.Prepare(m_builder.m_nMaxNumber, -1);
- pContext->m_captureindex[0] = 0;
- pContext->m_capturestack.Push(0);
- pContext->m_capturestack.Push(pContext->m_nCurrentPos);
- pContext->m_capturestack.Push(-1);
- pContext->m_capturestack.Push(-1);
-
- if( m_builder.m_pTopElx->Match( pContext ) )
- {
- // zero width
- if( pContext->m_nLastBeginPos == pContext->m_nBeginPos && pContext->m_nBeginPos == pContext->m_nCurrentPos )
- {
- pContext->m_nCurrentPos += delta;
- continue;
- }
-
- // save pos
- pContext->m_nLastBeginPos = pContext->m_nBeginPos;
- pContext->m_nBeginPos = pContext->m_nCurrentPos;
- pContext->m_capturestack[2] = pContext->m_nCurrentPos;
-
- // return
- return MatchResult( pContext, m_builder.m_nMaxNumber );
- }
- else
- {
- pContext->m_nCurrentPos += delta;
- }
- }
-
- return 0;
-}
-
-template <class CHART> inline CContext * CRegexpT <CHART> :: PrepareMatch(const CHART * tstring, int start, CContext * pContext) const
-{
- return PrepareMatch(tstring, CBufferRefT<CHART>(tstring).GetSize(), start, pContext);
-}
-
-template <class CHART> CContext * CRegexpT <CHART> :: PrepareMatch(const CHART * tstring, int length, int start, CContext * pContext) const
-{
- if(m_builder.m_pTopElx == 0)
- return 0;
-
- if(pContext == 0) pContext = new CContext();
-
- pContext->m_nParenZindex = 0;
- pContext->m_nLastBeginPos = -1;
- pContext->m_pMatchString = (void*)tstring;
- pContext->m_pMatchStringLength = length;
-
- if(start < 0)
- {
- if(m_builder.m_nFlags & RIGHTTOLEFT)
- {
- pContext->m_nBeginPos = length;
- pContext->m_nCurrentPos = length;
- }
- else
- {
- pContext->m_nBeginPos = 0;
- pContext->m_nCurrentPos = 0;
- }
- }
- else
- {
- pContext->m_nBeginPos = start;
- pContext->m_nCurrentPos = start;
- }
-
- return pContext;
-}
-
-template <class CHART> inline int CRegexpT <CHART> :: GetNamedGroupNumber(const CHART * group_name) const
-{
- return m_builder.GetNamedNumber(group_name);
-}
-
-template <class CHART> CHART * CRegexpT <CHART> :: Replace(const CHART * tstring, const CHART * replaceto, int start, int ntimes, MatchResult * result, CContext * pContext) const
-{
- int result_length = 0;
- return Replace(tstring, CBufferRefT<CHART>(tstring).GetSize(), replaceto, CBufferRefT<CHART>(replaceto).GetSize(), result_length, start, ntimes, result, pContext);
-}
-
-template <class CHART> CHART * CRegexpT <CHART> :: Replace(const CHART * tstring, int string_length, const CHART * replaceto, int to_length, int & result_length, int start, int ntimes, MatchResult * remote_result, CContext * oContext) const
-{
- typedef CBufferRefT <CHART> StringRef;
-
- MatchResult local_result(0), * result = remote_result ? remote_result : & local_result;
-
- if(m_builder.m_pTopElx == 0) return 0;
-
- // Prepare
- CContext * pContext = PrepareMatch(tstring, string_length, start, oContext);
-
- int flags = m_builder.m_nFlags;
- int lastIndex = (flags & RIGHTTOLEFT) ? string_length : 0;
- int endpos = (flags & RIGHTTOLEFT) ? 0 : string_length;
- int toIndex = 0, toLastIndex = 0;
- int i, ntime;
-
- CBufferT <StringRef *> buffer, buf;
-
- static const CHART rtoptn[] = { RCHART('\\'), RCHART('$' ), RCHART('('), RCHART('?'), RCHART(':'), RCHART('[' ), RCHART('$' ), RCHART('&' ), RCHART('`' ), RCHART('\''), RCHART('+'), RCHART('_' ), RCHART('\\'), RCHART('d'), RCHART(']'), RCHART('|'), RCHART('\\'), RCHART('{'), RCHART('.'), RCHART('*'), RCHART('?'), RCHART('\\'), RCHART('}'), RCHART(')' ), RCHART('\0') };
- static int rtoptnlen = StringRef(rtoptn).GetSize();
- static CRegexpT <CHART> rtoreg(rtoptn, rtoptnlen, 0);
-
- // Match
- for(ntime = 0; ntimes < 0 || ntime < ntimes; ntime ++)
- {
- (*result) = Match(pContext);
-
- if( ! result->IsMatched() )
- break;
-
- toIndex = toLastIndex;
-
- // before
- if( flags & RIGHTTOLEFT )
- {
- int distance = lastIndex - result->GetEnd();
- if( distance )
- {
- buffer.Push(new StringRef(tstring + result->GetEnd(), distance));
- toIndex -= distance;
- }
- lastIndex = result->GetStart();
- }
- else
- {
- int distance = result->GetStart() - lastIndex;
- if( distance )
- {
- buffer.Push(new StringRef(tstring + lastIndex, distance));
- toIndex += distance;
- }
- lastIndex = result->GetEnd();
- }
-
- toLastIndex = toIndex;
-
- // middle
- CContext * pCtx = rtoreg.PrepareMatch(replaceto, to_length, -1);
- int lastI = 0;
-
- buf.Restore(0);
-
- while(1)
- {
- MatchResult res = rtoreg.Match(pCtx);
-
- if( ! res.IsMatched() )
- break;
-
- // before
- int distance = res.GetStart() - lastI;
- if( distance )
- {
- buf.Push(new StringRef(replaceto + lastI, distance));
- }
- lastI = res.GetStart();
-
- // middle
- int delta = 2, nmatch = 0;
-
- switch(replaceto[res.GetStart() + 1])
- {
- case RCHART('$'):
- buf.Push(new StringRef(rtoptn + 1, 1)); // '$' itself
- break;
-
- case RCHART('&'):
- buf.Push(new StringRef(tstring + result->GetStart(), result->GetEnd() - result->GetStart()));
- break;
-
- case RCHART('`'):
- buf.Push(new StringRef(tstring, result->GetStart()));
- break;
-
- case RCHART('\''):
- buf.Push(new StringRef(tstring + result->GetEnd(), string_length - result->GetEnd()));
- break;
-
- case RCHART('+'):
- for(nmatch = result->MaxGroupNumber(); nmatch >= 0; nmatch --)
- {
- if(result->GetGroupStart(nmatch) >= 0) break;
- }
- buf.Push(new StringRef(tstring + result->GetGroupStart(nmatch), result->GetGroupEnd(nmatch) - result->GetGroupStart(nmatch)));
- break;
-
- case RCHART('_'):
- buf.Push(new StringRef(tstring, string_length));
- break;
-
- case RCHART('{'):
- delta = res.GetEnd() - res.GetStart();
- nmatch = m_builder.GetNamedNumber(StringRef(replaceto + (res.GetStart() + 2), delta - 3));
-
- if(nmatch > 0 && nmatch <= m_builder.m_nMaxNumber)
- buf.Push(new StringRef(tstring + result->GetGroupStart(nmatch), result->GetGroupEnd(nmatch) - result->GetGroupStart(nmatch)));
- else
- buf.Push(new StringRef(replaceto + res.GetStart(), delta));
- break;
-
- default:
- nmatch = 0;
- for(delta=1; delta<=3; delta++)
- {
- CHART ch = replaceto[lastI + delta];
-
- if(ch < RCHART('0') || ch > RCHART('9'))
- break;
-
- nmatch = nmatch * 10 + (ch - RCHART('0'));
- }
-
- if(nmatch > m_builder.m_nMaxNumber)
- {
- while(nmatch > m_builder.m_nMaxNumber)
- {
- nmatch /= 10;
- delta --;
- }
-
- if(nmatch == 0)
- {
- delta = 1;
- }
- }
-
- if(delta == 1)
- buf.Push(new StringRef(rtoptn + 1, 1)); // '$' itself
- else
- buf.Push(new StringRef(tstring + result->GetGroupStart(nmatch), result->GetGroupEnd(nmatch) - result->GetGroupStart(nmatch)));
- break;
- }
-
- lastI += delta;
- }
-
- // after
- if(lastI < to_length)
- buf.Push(new StringRef(replaceto + lastI, to_length - lastI));
-
- // append to buffer
- if(flags & RIGHTTOLEFT)
- {
- for(i=buf.GetSize()-1; i>=0; i--)
- {
- buffer.Push(buf[i]);
- toLastIndex -= buf[i]->GetSize();
- }
- }
- else
- {
- for(i=0; i<buf.GetSize(); i++)
- {
- buffer.Push(buf[i]);
- toLastIndex += buf[i]->GetSize();
- }
- }
-
- rtoreg.ReleaseContext(pCtx);
- }
-
- // after
- if(flags & RIGHTTOLEFT)
- {
- if(endpos < lastIndex) buffer.Push(new StringRef(tstring + endpos, lastIndex - endpos));
- }
- else
- {
- if(lastIndex < endpos) buffer.Push(new StringRef(tstring + lastIndex, endpos - lastIndex));
- }
-
- if(oContext == 0) ReleaseContext(pContext);
-
- // join string
- result_length = 0;
- for(i=0; i<buffer.GetSize(); i++) result_length += buffer[i]->GetSize();
-
- CBufferT <CHART> result_string;
- result_string.Prepare(result_length);
- result_string.Restore(0);
-
- if(flags & RIGHTTOLEFT)
- {
- for(i=buffer.GetSize()-1; i>=0; i--)
- {
- result_string.Append(buffer[i]->GetBuffer(), buffer[i]->GetSize());
- delete buffer[i];
- }
- }
- else
- {
- for(i=0; i<buffer.GetSize(); i++)
- {
- result_string.Append(buffer[i]->GetBuffer(), buffer[i]->GetSize());
- delete buffer[i];
- }
- }
-
- result_string[result_length] = 0;
-
- result->m_result.Append(toIndex < toLastIndex ? toIndex : toLastIndex, 2);
- result->m_result.Append(toIndex > toLastIndex ? toIndex : toLastIndex);
- result->m_result.Append(ntime);
-
- return result_string.Detach();
-}
-
-template <class CHART> inline void CRegexpT <CHART> :: ReleaseString(CHART * tstring)
-{
- if(tstring != 0) delete [] tstring;
-}
-
-template <class CHART> inline void CRegexpT <CHART> :: ReleaseContext(CContext * pContext)
-{
- if(pContext != 0) delete pContext;
-}
-
-//
-// All implementations
-//
-template <int x> CAlternativeElxT <x> :: CAlternativeElxT()
-{
-}
-
-template <int x> int CAlternativeElxT <x> :: Match(CContext * pContext) const
-{
- if(m_elxlist.GetSize() == 0)
- return 1;
-
- // try all
- for(int n = 0; n < m_elxlist.GetSize(); n++)
- {
- if(m_elxlist[n]->Match(pContext))
- {
- pContext->m_stack.Push(n);
- return 1;
- }
- }
-
- return 0;
-}
-
-template <int x> int CAlternativeElxT <x> :: MatchNext(CContext * pContext) const
-{
- if(m_elxlist.GetSize() == 0)
- return 0;
-
- int n = 0;
-
- // recall prev
- pContext->m_stack.Pop(n);
-
- // prev
- if(m_elxlist[n]->MatchNext(pContext))
- {
- pContext->m_stack.Push(n);
- return 1;
- }
- else
- {
- // try rest
- for(n++; n < m_elxlist.GetSize(); n++)
- {
- if(m_elxlist[n]->Match(pContext))
- {
- pContext->m_stack.Push(n);
- return 1;
- }
- }
-
- return 0;
- }
-}
-
-// assertx.cpp: implementation of the CAssertElx class.
-//
-template <int x> CAssertElxT <x> :: CAssertElxT(ElxInterface * pelx, int byes)
-{
- m_pelx = pelx;
- m_byes = byes;
-}
-
-template <int x> int CAssertElxT <x> :: Match(CContext * pContext) const
-{
- int nbegin = pContext->m_nCurrentPos;
- int nsize = pContext->m_stack.GetSize();
- int ncsize = pContext->m_capturestack.GetSize();
- int bsucc;
-
- // match
- if( m_byes )
- bsucc = m_pelx->Match(pContext);
- else
- bsucc = ! m_pelx->Match(pContext);
-
- // status
- pContext->m_stack.Restore(nsize);
- pContext->m_nCurrentPos = nbegin;
-
- if( bsucc )
- pContext->m_stack.Push(ncsize);
- else
- pContext->m_capturestack.Restore(ncsize);
-
- return bsucc;
-}
-
-template <int x> int CAssertElxT <x> :: MatchNext(CContext * pContext) const
-{
- int ncsize = 0;
-
- pContext->m_stack.Pop(ncsize);
- pContext->m_capturestack.Restore(ncsize);
-
- return 0;
-}
-
-// emptyelx.cpp: implementation of the CEmptyElx class.
-//
-template <int x> CEmptyElxT <x> :: CEmptyElxT()
-{
-}
-
-template <int x> int CEmptyElxT <x> :: Match(CContext *) const
-{
- return 1;
-}
-
-template <int x> int CEmptyElxT <x> :: MatchNext(CContext *) const
-{
- return 0;
-}
-
-// globalx.cpp: implementation of the CGlobalElx class.
-//
-template <int x> CGlobalElxT <x> ::CGlobalElxT()
-{
-}
-
-template <int x> int CGlobalElxT <x> :: Match(CContext * pContext) const
-{
- return pContext->m_nCurrentPos == pContext->m_nBeginPos;
-}
-
-template <int x> int CGlobalElxT <x> :: MatchNext(CContext *) const
-{
- return 0;
-}
-
-// greedelx.cpp: implementation of the CGreedyElx class.
-//
-template <int x> CGreedyElxT <x> :: CGreedyElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT <x> (pelx, nmin)
-{
- m_nvart = nmax - nmin;
-}
-
-template <int x> int CGreedyElxT <x> :: Match(CContext * pContext) const
-{
- if( ! CRepeatElxT <x> :: MatchFixed(pContext) )
- return 0;
-
- while( ! MatchVart(pContext) )
- {
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
- }
-
- return 1;
-}
-
-template <int x> int CGreedyElxT <x> :: MatchNext(CContext * pContext) const
-{
- if( MatchNextVart(pContext) )
- return 1;
-
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
-
- while( ! MatchVart(pContext) )
- {
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
- }
-
- return 1;
-}
-
-template <int x> int CGreedyElxT <x> :: MatchVart(CContext * pContext) const
-{
- int n = 0;
- int nbegin = pContext->m_nCurrentPos;
-
- while(n < m_nvart && CRepeatElxT <x> :: m_pelx->Match(pContext))
- {
- while(pContext->m_nCurrentPos == nbegin)
- {
- if( ! CRepeatElxT <x> :: m_pelx->MatchNext(pContext) ) break;
- }
-
- if(pContext->m_nCurrentPos == nbegin) break;
-
- n ++;
- nbegin = pContext->m_nCurrentPos;
- }
-
- pContext->m_stack.Push(n);
-
- return 1;
-}
-
-template <int x> int CGreedyElxT <x> :: MatchNextVart(CContext * pContext) const
-{
- int n = 0;
- pContext->m_stack.Pop(n);
-
- if(n == 0) return 0;
-
- if( ! CRepeatElxT <x> :: m_pelx->MatchNext(pContext) )
- {
- n --;
- }
-
- pContext->m_stack.Push(n);
-
- return 1;
-}
-
-// indepelx.cpp: implementation of the CIndependentElx class.
-//
-template <int x> CIndependentElxT <x> :: CIndependentElxT(ElxInterface * pelx)
-{
- m_pelx = pelx;
-}
-
-template <int x> int CIndependentElxT <x> :: Match(CContext * pContext) const
-{
- int nbegin = pContext->m_nCurrentPos;
- int nsize = pContext->m_stack.GetSize();
- int ncsize = pContext->m_capturestack.GetSize();
-
- // match
- int bsucc = m_pelx->Match(pContext);
-
- // status
- pContext->m_stack.Restore(nsize);
-
- if( bsucc )
- {
- pContext->m_stack.Push(nbegin);
- pContext->m_stack.Push(ncsize);
- }
-
- return bsucc;
-}
-
-template <int x> int CIndependentElxT <x> :: MatchNext(CContext * pContext) const
-{
- int nbegin = 0, ncsize = 0;
-
- pContext->m_stack.Pop(ncsize);
- pContext->m_stack.Pop(nbegin);
-
- pContext->m_capturestack.Restore(ncsize);
- pContext->m_nCurrentPos = nbegin;
-
- return 0;
-}
-
-// listelx.cpp: implementation of the CListElx class.
-//
-template <int x> CListElxT <x> :: CListElxT(int brightleft)
-{
- m_brightleft = brightleft;
-}
-
-template <int x> int CListElxT <x> :: Match(CContext * pContext) const
-{
- if(m_elxlist.GetSize() == 0)
- return 1;
-
- // prepare
- int bol = m_brightleft ? m_elxlist.GetSize() : -1;
- int stp = m_brightleft ? -1 : 1;
- int eol = m_brightleft ? -1 : m_elxlist.GetSize();
-
- // from first
- int n = bol + stp;
-
- // match all
- while(n != eol)
- {
- if(m_elxlist[n]->Match(pContext))
- {
- n += stp;
- }
- else
- {
- n -= stp;
-
- while(n != bol && ! m_elxlist[n]->MatchNext(pContext))
- n -= stp;
-
- if(n != bol)
- n += stp;
- else
- return 0;
- }
- }
-
- return 1;
-}
-
-template <int x> int CListElxT <x> :: MatchNext(CContext * pContext) const
-{
- if(m_elxlist.GetSize() == 0)
- return 0;
-
- // prepare
- int bol = m_brightleft ? m_elxlist.GetSize() : -1;
- int stp = m_brightleft ? -1 : 1;
- int eol = m_brightleft ? -1 : m_elxlist.GetSize();
-
- // from last
- int n = eol - stp;
-
- while(n != bol && ! m_elxlist[n]->MatchNext(pContext))
- n -= stp;
-
- if(n != bol)
- n += stp;
- else
- return 0;
-
- // match rest
- while(n != eol)
- {
- if(m_elxlist[n]->Match(pContext))
- {
- n += stp;
- }
- else
- {
- n -= stp;
-
- while(n != bol && ! m_elxlist[n]->MatchNext(pContext))
- n -= stp;
-
- if(n != bol)
- n += stp;
- else
- return 0;
- }
- }
-
- return 1;
-}
-
-// mresult.cpp: implementation of the MatchResult class.
-//
-template <int x> MatchResultT <x> :: MatchResultT(CContext * pContext, int nMaxNumber)
-{
- if(pContext != 0)
- {
- m_result.Prepare(nMaxNumber * 2 + 3, -1);
-
- // matched
- m_result[0] = 1;
- m_result[1] = nMaxNumber;
-
- for(int n = 0; n <= nMaxNumber; n++)
- {
- int index = pContext->m_captureindex[n];
- if( index < 0 ) continue;
-
- // check enclosed
- int pos1 = pContext->m_capturestack[index + 1];
- int pos2 = pContext->m_capturestack[index + 2];
-
- // info
- m_result[n*2 + 2] = pos1 < pos2 ? pos1 : pos2;
- m_result[n*2 + 3] = pos1 < pos2 ? pos2 : pos1;
- }
- }
-}
-
-template <int x> inline int MatchResultT <x> :: IsMatched() const
-{
- return m_result.At(0, 0);
-}
-
-template <int x> inline int MatchResultT <x> :: MaxGroupNumber() const
-{
- return m_result.At(1, 0);
-}
-
-template <int x> inline int MatchResultT <x> :: GetStart() const
-{
- return m_result.At(2, -1);
-}
-
-template <int x> inline int MatchResultT <x> :: GetEnd() const
-{
- return m_result.At(3, -1);
-}
-
-template <int x> inline int MatchResultT <x> :: GetGroupStart(int nGroupNumber) const
-{
- return m_result.At(2 + nGroupNumber * 2, -1);
-}
-
-template <int x> inline int MatchResultT <x> :: GetGroupEnd(int nGroupNumber) const
-{
- return m_result.At(2 + nGroupNumber * 2 + 1, -1);
-}
-
-template <int x> MatchResultT <x> & MatchResultT <x> :: operator = (const MatchResultT <x> & result)
-{
- m_result.Restore(0);
- if(result.m_result.GetSize() > 0) m_result.Append(result.m_result.GetBuffer(), result.m_result.GetSize());
-
- return *this;
-}
-
-// posselx.cpp: implementation of the CPossessiveElx class.
-//
-template <int x> CPossessiveElxT <x> :: CPossessiveElxT(ElxInterface * pelx, int nmin, int nmax) : CGreedyElxT <x> (pelx, nmin, nmax)
-{
-}
-
-template <int x> int CPossessiveElxT <x> :: Match(CContext * pContext) const
-{
- int nbegin = pContext->m_nCurrentPos;
- int nsize = pContext->m_stack.GetSize();
- int ncsize = pContext->m_capturestack.GetSize();
- int bsucc = 1;
-
- // match
- if( ! CRepeatElxT <x> :: MatchFixed(pContext) )
- {
- bsucc = 0;
- }
- else
- {
- while( ! CGreedyElxT <x> :: MatchVart(pContext) )
- {
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- {
- bsucc = 0;
- break;
- }
- }
- }
-
- // status
- pContext->m_stack.Restore(nsize);
-
- if( bsucc )
- {
- pContext->m_stack.Push(nbegin);
- pContext->m_stack.Push(ncsize);
- }
-
- return bsucc;
-}
-
-template <int x> int CPossessiveElxT <x> :: MatchNext(CContext * pContext) const
-{
- int nbegin = 0, ncsize = 0;
-
- pContext->m_stack.Pop(ncsize);
- pContext->m_stack.Pop(nbegin);
-
- pContext->m_capturestack.Restore(ncsize);
- pContext->m_nCurrentPos = nbegin;
-
- return 0;
-}
-
-// reluctx.cpp: implementation of the CReluctantElx class.
-//
-template <int x> CReluctantElxT <x> :: CReluctantElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT <x> (pelx, nmin)
-{
- m_nvart = nmax - nmin;
-}
-
-template <int x> int CReluctantElxT <x> :: Match(CContext * pContext) const
-{
- if( ! CRepeatElxT <x> :: MatchFixed(pContext) )
- return 0;
-
- while( ! MatchVart(pContext) )
- {
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
- }
-
- return 1;
-}
-
-template <int x> int CReluctantElxT <x> :: MatchNext(CContext * pContext) const
-{
- if( MatchNextVart(pContext) )
- return 1;
-
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
-
- while( ! MatchVart(pContext) )
- {
- if( ! CRepeatElxT <x> :: MatchNextFixed(pContext) )
- return 0;
- }
-
- return 1;
-}
-
-template <int x> int CReluctantElxT <x> :: MatchVart(CContext * pContext) const
-{
- pContext->m_stack.Push(0);
-
- return 1;
-}
-
-template <int x> int CReluctantElxT <x> :: MatchNextVart(CContext * pContext) const
-{
- int n = 0, nbegin = pContext->m_nCurrentPos;
-
- pContext->m_stack.Pop(n);
-
- if(n < m_nvart && CRepeatElxT <x> :: m_pelx->Match(pContext))
- {
- while(pContext->m_nCurrentPos == nbegin)
- {
- if( ! CRepeatElxT <x> :: m_pelx->MatchNext(pContext) ) break;
- }
-
- if(pContext->m_nCurrentPos != nbegin)
- {
- n ++;
-
- pContext->m_stack.Push(nbegin);
- pContext->m_stack.Push(n);
-
- return 1;
- }
- }
-
- while(n > 0)
- {
- pContext->m_stack.Pop(nbegin);
-
- while( CRepeatElxT <x> :: m_pelx->MatchNext(pContext) )
- {
- if(pContext->m_nCurrentPos != nbegin)
- {
- pContext->m_stack.Push(nbegin);
- pContext->m_stack.Push(n);
-
- return 1;
- }
- }
-
- n --;
- }
-
- return 0;
-}
-
-// repeatx.cpp: implementation of the CRepeatElx class.
-//
-template <int x> CRepeatElxT <x> :: CRepeatElxT(ElxInterface * pelx, int ntimes)
-{
- m_pelx = pelx;
- m_nfixed = ntimes;
-}
-
-template <int x> int CRepeatElxT <x> :: Match(CContext * pContext) const
-{
- return MatchFixed(pContext);
-}
-
-template <int x> int CRepeatElxT <x> :: MatchNext(CContext * pContext) const
-{
- return MatchNextFixed(pContext);
-}
-
-template <int x> int CRepeatElxT <x> :: MatchFixed(CContext * pContext) const
-{
- if(m_nfixed == 0)
- return 1;
-
- int n = 0;
-
- while(n < m_nfixed)
- {
- if(m_pelx->Match(pContext))
- {
- n ++;
- }
- else
- {
- n --;
-
- while(n >= 0 && ! m_pelx->MatchNext(pContext))
- n --;
-
- if(n >= 0)
- n ++;
- else
- return 0;
- }
- }
-
- return 1;
-}
-
-template <int x> int CRepeatElxT <x> :: MatchNextFixed(CContext * pContext) const
-{
- if(m_nfixed == 0)
- return 0;
-
- // from last
- int n = m_nfixed - 1;
-
- while(n >= 0 && ! m_pelx->MatchNext(pContext))
- n --;
-
- if(n >= 0)
- n ++;
- else
- return 0;
-
- // match rest
- while(n < m_nfixed)
- {
- if(m_pelx->Match(pContext))
- {
- n ++;
- }
- else
- {
- n --;
-
- while(n >= 0 && ! m_pelx->MatchNext(pContext))
- n --;
-
- if(n >= 0)
- n ++;
- else
- return 0;
- }
- }
-
- return 1;
-}
-
-// Regexp
-typedef CRegexpT <char> CRegexpA;
-typedef CRegexpT <unsigned short> CRegexpW;
-
-#if defined(_UNICODE) || defined(UNICODE)
- typedef CRegexpW CRegexp;
-#else
- typedef CRegexpA CRegexp;
-#endif
-
-#endif//__DEELX_REGEXP__H__