X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/c7f552fd8888da2f0d8cfb228fe0f28d3df3a12c..b4b6f2ea75b9f0f3ca918f5b84016610bf7a4d4f:/interpretor/faust-0.9.47mr3/architecture/osclib/faust/src/lib/deelx.h diff --git a/interpretor/faust-0.9.47mr3/architecture/osclib/faust/src/lib/deelx.h b/interpretor/faust-0.9.47mr3/architecture/osclib/faust/src/lib/deelx.h deleted file mode 100755 index c50ed88..0000000 --- a/interpretor/faust-0.9.47mr3/architecture/osclib/faust/src/lib/deelx.h +++ /dev/null @@ -1,4178 +0,0 @@ -// 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 -#include -#include -#include -#include - -// -// Data Reference -// -template 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 &) const; - int CompareNoCase(const CBufferRefT &) 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 CBufferRefT :: CBufferRefT(const ELT * pcsz, int length) -{ - m_pRef = pcsz; - m_nSize = length; -} - -template CBufferRefT :: CBufferRefT(const ELT * pcsz) -{ - m_pRef = pcsz; - m_nSize = 0; - - if(pcsz != 0) while(m_pRef[m_nSize] != 0) m_nSize ++; -} - -template int CBufferRefT :: nCompare(const ELT * pcsz) const -{ - for(int i=0; i int CBufferRefT :: nCompareNoCase(const ELT * pcsz) const -{ - for(int i=0; i inline int CBufferRefT :: Compare(const ELT * pcsz) const -{ - return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize]; -} - -template inline int CBufferRefT :: CompareNoCase(const ELT * pcsz) const -{ - return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize]; -} - -template inline int CBufferRefT :: Compare(const CBufferRefT & cref) const -{ - return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1; -} - -template inline int CBufferRefT :: CompareNoCase(const CBufferRefT & cref) const -{ - return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1; -} - -template inline ELT CBufferRefT :: At(int nIndex, ELT def) const -{ - return nIndex >= m_nSize ? def : m_pRef[nIndex]; -} - -template inline ELT CBufferRefT :: operator [] (int nIndex) const -{ - return nIndex >= m_nSize ? 0 : m_pRef[nIndex]; -} - -template const ELT * CBufferRefT :: GetBuffer() const -{ - static const ELT _def[] = {0}; return m_pRef ? m_pRef : _def; -} - -template inline int CBufferRefT :: GetSize() const -{ - return m_nSize; -} - -template CBufferRefT :: ~CBufferRefT() -{ -} - -// -// Data Buffer -// -template class CBufferT : public CBufferRefT -{ -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 CBufferT :: CBufferT(const ELT * pcsz, int length) : CBufferRefT (0, length) -{ - m_nMaxLength = CBufferRefT :: m_nSize + 1; - - CBufferRefT :: m_pRef = m_pBuffer = new ELT[m_nMaxLength]; - memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); - m_pBuffer[CBufferRefT :: m_nSize] = 0; -} - -template CBufferT :: CBufferT(const ELT * pcsz) : CBufferRefT (pcsz) -{ - m_nMaxLength = CBufferRefT :: m_nSize + 1; - - CBufferRefT :: m_pRef = m_pBuffer = new ELT[m_nMaxLength]; - memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT :: m_nSize); - m_pBuffer[CBufferRefT :: m_nSize] = 0; -} - -template CBufferT :: CBufferT() : CBufferRefT (0, 0) -{ - m_nMaxLength = 0; - m_pBuffer = 0; -} - -template inline ELT & CBufferT :: operator [] (int nIndex) -{ - return m_pBuffer[nIndex]; -} - -template inline const ELT & CBufferT :: operator [] (int nIndex) const -{ - return m_pBuffer[nIndex]; -} - -template void CBufferT :: Append(const ELT * pcsz, int length, int eol) -{ - int nNewLength = m_nMaxLength; - - // Check length - if(nNewLength < 8) - nNewLength = 8; - - if(CBufferRefT :: m_nSize + length + eol > nNewLength) - nNewLength *= 2; - - if(CBufferRefT :: m_nSize + length + eol > nNewLength) - { - nNewLength = CBufferRefT :: 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 :: m_nSize); - delete [] m_pBuffer; - } - - CBufferRefT :: m_pRef = m_pBuffer = pNewBuffer; - m_nMaxLength = nNewLength; - } - - // Append - memcpy(m_pBuffer + CBufferRefT :: m_nSize, pcsz, sizeof(ELT) * length); - CBufferRefT :: m_nSize += length; - - if(eol > 0) m_pBuffer[CBufferRefT :: m_nSize] = 0; -} - -template inline void CBufferT :: Append(ELT el, int eol) -{ - Append(&el, 1, eol); -} - -template void CBufferT :: Push(ELT el) -{ - // Realloc - if(CBufferRefT :: 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 :: m_nSize); - delete [] m_pBuffer; - } - - CBufferRefT :: m_pRef = m_pBuffer = pNewBuffer; - m_nMaxLength = nNewLength; - } - - // Append - m_pBuffer[CBufferRefT :: m_nSize++] = el; -} - -template inline int CBufferT :: Pop(ELT & el) -{ - if(CBufferRefT :: m_nSize > 0) - { - el = m_pBuffer[--CBufferRefT :: m_nSize]; - return 1; - } - else - { - return 0; - } -} - -template inline int CBufferT :: Peek(ELT & el) const -{ - if(CBufferRefT :: m_nSize > 0) - { - el = m_pBuffer[CBufferRefT :: m_nSize - 1]; - return 1; - } - else - { - return 0; - } -} - -template const ELT * CBufferT :: GetBuffer() const -{ - static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : _def; -} - -template ELT * CBufferT :: GetBuffer() -{ - static const ELT _def[] = {0}; return m_pBuffer ? m_pBuffer : (ELT *)_def; -} - -template ELT * CBufferT :: Detach() -{ - ELT * pBuffer = m_pBuffer; - - CBufferRefT :: m_pRef = m_pBuffer = 0; - CBufferRefT :: m_nSize = m_nMaxLength = 0; - - return pBuffer; -} - -template void CBufferT :: Release() -{ - ELT * pBuffer = Detach(); - - if(pBuffer != 0) delete [] pBuffer; -} - -template void CBufferT :: 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 :: m_nSize); - delete [] m_pBuffer; - } - - CBufferRefT :: m_pRef = m_pBuffer = pNewBuffer; - m_nMaxLength = nNewLength; - } - - // size - if( CBufferRefT :: m_nSize < nNewSize ) - { - memset(m_pBuffer + CBufferRefT :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT :: m_nSize)); - CBufferRefT :: m_nSize = nNewSize; - } -} - -template inline void CBufferT :: Restore(int size) -{ - CBufferRefT :: m_nSize = size; -} - -template CBufferT :: ~CBufferT() -{ - if(m_pBuffer != 0) delete [] m_pBuffer; -} - -// -// Context -// -class CContext -{ -public: - CBufferT m_stack; - CBufferT 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 class CAlternativeElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CAlternativeElxT(); - -public: - CBufferT m_elxlist; -}; - -typedef CAlternativeElxT <0> CAlternativeElx; - -// -// Assert -// -template 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 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 m_szNamed; -}; - -// -// Implementation -// -template CBackrefElxT :: CBackrefElxT(int nnumber, int brightleft, int bignorecase) -{ - m_nnumber = nnumber; - m_brightleft = brightleft; - m_bignorecase = bignorecase; -} - -template int CBackrefElxT :: 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 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 int CBackrefElxT :: 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 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 CBoundaryElxT :: CBoundaryElxT(int ntype, int byes) -{ - m_ntype = ntype; - m_byes = byes; -} - -template int CBoundaryElxT :: 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 int CBoundaryElxT :: MatchNext(CContext *) const -{ - return 0; -} - -template inline int CBoundaryElxT :: 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 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 m_szNamed; -}; - -template CBracketElxT :: CBracketElxT(int nnumber, int bright) -{ - m_nnumber = nnumber; - m_bright = bright; -} - -template int CBracketElxT :: 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 int CBracketElxT :: 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 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 m_szNamed; -}; - -template CDelegateElxT :: CDelegateElxT(int ndata) -{ - m_pelx = 0; - m_ndata = ndata; -} - -template int CDelegateElxT :: Match(CContext * pContext) const -{ - if(m_pelx != 0) - return m_pelx->Match(pContext); - else - return 1; -} - -template int CDelegateElxT :: MatchNext(CContext * pContext) const -{ - if(m_pelx != 0) - return m_pelx->MatchNext(pContext); - else - return 0; -} - -// -// Empty -// -template class CEmptyElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CEmptyElxT(); -}; - -typedef CEmptyElxT <0> CEmptyElx; - -// -// Global -// -template class CGlobalElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CGlobalElxT(); -}; - -typedef CGlobalElxT <0> CGlobalElx; - -// -// Repeat -// -template 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 class CGreedyElxT : public CRepeatElxT -{ -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 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 class CListElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CListElxT(int brightleft); - -public: - CBufferT m_elxlist; - int m_brightleft; -}; - -typedef CListElxT <0> CListElx; - -// -// Posix Elx -// -template 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 CPosixElxT :: 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 int CPosixElxT :: misblank(int c) -{ - return c == 0x20 || c == '\t'; -} - -template int CPosixElxT :: 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 int CPosixElxT :: MatchNext(CContext * pContext) const -{ - pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; - return 0; -} - -// -// Possessive -// -template class CPossessiveElxT : public CGreedyElxT -{ -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 CRangeElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CRangeElxT(int brightleft, int byes); - -public: - CBufferT m_ranges; - CBufferT m_chars; - CBufferT m_embeds; - -public: - int m_brightleft; - int m_byes; -}; - -// -// Implementation -// -template CRangeElxT :: CRangeElxT(int brightleft, int byes) -{ - m_brightleft = brightleft; - m_byes = byes; -} - -template int CRangeElxT :: 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 && iMatch(pContext)) - { - pContext->m_nCurrentPos = npos; - bsucc = 1; - } - } - - if( ! m_byes ) - bsucc = ! bsucc; - - if( bsucc ) - pContext->m_nCurrentPos += m_brightleft ? -1 : 1; - - return bsucc; -} - -template int CRangeElxT :: MatchNext(CContext * pContext) const -{ - pContext->m_nCurrentPos -= m_brightleft ? -1 : 1; - return 0; -} - -// -// Reluctant -// -template class CReluctantElxT : public CRepeatElxT -{ -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 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 m_szPattern; - int m_brightleft; - int m_bignorecase; -}; - -// -// Implementation -// -template CStringElxT :: CStringElxT(const CHART * fixed, int nlength, int brightleft, int bignorecase) : m_szPattern(fixed, nlength) -{ - m_brightleft = brightleft; - m_bignorecase = bignorecase; -} - -template int CStringElxT :: 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 int CStringElxT :: 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 CConditionElxT : public ElxInterface -{ -public: - int Match (CContext * pContext) const; - int MatchNext(CContext * pContext) const; - -public: - CConditionElxT(); - -public: - // backref condition - int m_nnumber; - CBufferT m_szNamed; - - // elx condition - ElxInterface * m_pelxask; - - // selection - ElxInterface * m_pelxyes, * m_pelxno; -}; - -template CConditionElxT :: CConditionElxT() -{ - m_nnumber = -1; -} - -template int CConditionElxT :: 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 int CConditionElxT :: 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 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 & operator = (const MatchResultT &); - inline operator int() const { return IsMatched(); } - -public: - CBufferT 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 CBuilderT -{ -public: - typedef CDelegateElxT CDelegateElx; - typedef CBracketElxT CBracketElx; - typedef CBackrefElxT CBackrefElx; - typedef CConditionElxT CConditionElx; - -// Methods -public: - ElxInterface * Build(const CBufferRefT & pattern, int flags); - int GetNamedNumber(const CBufferRefT & 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 m_objlist; - CBufferT m_grouplist; - CBufferT m_recursivelist; - CBufferT m_namedlist; - CBufferT m_namedbackreflist; - CBufferT 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 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 CBuilderT :: CBuilderT() : m_pattern(0, 0), prev(0, 0), curr(0, 0), next(0, 0), nex2(0, 0) -{ - Clear(); -} - -template CBuilderT :: ~CBuilderT() -{ - Clear(); -} - -template int CBuilderT :: GetNamedNumber(const CBufferRefT & named) const -{ - for(int i=0; im_elxlist[0])->m_szNamed.CompareNoCase(named) ) - return ((CBracketElx *)m_namedlist[i]->m_elxlist[0])->m_nnumber; - } - - return -3; -} - -template ElxInterface * CBuilderT :: Build(const CBufferRefT & 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; im_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; im_elxlist[0]; - - if( pleft->m_nnumber > m_nMaxNumber ) - m_nMaxNumber = pleft->m_nnumber; - } - - // connect recursive - for(i=0; im_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; im_nnumber = GetNamedNumber(m_namedbackreflist[i]->m_szNamed); - } - - // named condition - for(i=0; im_szNamed); - if( nn >= 0 ) - { - m_namedconditionlist[i]->m_nnumber = nn; - m_namedconditionlist[i]->m_pelxask = 0; - } - } - - return m_pTopElx; -} - -template void CBuilderT :: Clear() -{ - for(int i=0; i unsigned int CBuilderT :: Hex2Int(const CHART * pcsz, int length, int & used) -{ - unsigned int result = 0; - int & i = used; - - for(i=0; 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 inline ElxInterface * CBuilderT :: Keep(ElxInterface * pelx) -{ - m_objlist.Push(pelx); - return pelx; -} - -template void CBuilderT :: MoveNext() -{ - // forwards - prev = curr; - curr = next; - next = nex2; - - // get nex2 - while( ! GetNext2() ) {}; -} - -template int CBuilderT :: 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 ElxInterface * CBuilderT :: 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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 (0, 0)); - break; - - case STOCKELX_DOT_NOT_ALL: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); - - pRange->m_chars .Push(RCHART('\n')); - - pStockElxs[nStockId] = pRange; - } - break; - - case STOCKELX_SPACE: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 1)); - - pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); - - pStockElxs[nStockId] = pRange; - } - break; - - case STOCKELX_DIGITAL_NOT: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (0, 0)); - - pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); - - pStockElxs[nStockId] = pRange; - } - break; - - case STOCKELX_WORD_RIGHTLEFT: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 (1, 0)); - break; - - case STOCKELX_DOT_NOT_ALL_RIGHTLEFT: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); - - pRange->m_chars .Push(RCHART('\n')); - - pStockElxs[nStockId] = pRange; - } - break; - - case STOCKELX_SPACE_RIGHTLEFT: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (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 * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 1)); - - pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); - - pStockElxs[nStockId] = pRange; - } - break; - - case STOCKELX_DIGITAL_RIGHTLEFT_NOT: - { - CRangeElxT * pRange = (CRangeElxT *)Keep(new CRangeElxT (1, 0)); - - pRange->m_ranges.Push(RCHART('0')); pRange->m_ranges.Push(RCHART('9')); - - pStockElxs[nStockId] = pRange; - } - break; - } - } - - // return - return pStockElxs[nStockId]; -} - -template ElxInterface * CBuilderT :: 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 ElxInterface * CBuilderT :: 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 ElxInterface * CBuilderT :: 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 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 ElxInterface * CBuilderT :: BuildSimple(int & flags) -{ - CBufferT 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 (fixed.GetBuffer(), fixed.GetSize(), flags & RIGHTTOLEFT, flags & IGNORECASE)); - else - return GetStockElx(STOCKELX_EMPTY); -} - -template ElxInterface * CBuilderT :: 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 * pRange; - - // create - if(curr == CHART_INFO(RCHART(':'), 1)) - { - CBufferT 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 (posix.GetBuffer(), flags & RIGHTTOLEFT)); - } - else if(curr == CHART_INFO(RCHART('^'), 1)) - { - MoveNext(); // skip '^' - pRange = (CRangeElxT *)Keep(new CRangeElxT (flags & RIGHTTOLEFT, 0)); - } - else - { - pRange = (CRangeElxT *)Keep(new CRangeElxT (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 ElxInterface * CBuilderT :: 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 & name = pleft->m_szNamed; - CBufferT 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 - 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 & name = pDelegate->m_szNamed; - CBufferT 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 - 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 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 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 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 ElxInterface * CBuilderT :: BuildBoundary(int & flags) -{ - // char - CHART ch = curr.ch; - - // skip - MoveNext(); - - switch(ch) - { - case RCHART('^'): - return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_BEGIN : BOUNDARY_FILE_BEGIN)); - - case RCHART('$'): - return Keep(new CBoundaryElxT ((flags & MULTILINE) ? BOUNDARY_LINE_END : BOUNDARY_FILE_END)); - - case RCHART('b'): - return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE)); - - case RCHART('B'): - return Keep(new CBoundaryElxT (BOUNDARY_WORD_EDGE, 0)); - - case RCHART('A'): - return Keep(new CBoundaryElxT (BOUNDARY_FILE_BEGIN)); - - case RCHART('Z'): - return Keep(new CBoundaryElxT (BOUNDARY_FILE_END)); - - case RCHART('G'): - if(flags & GLOBAL) - return Keep(new CGlobalElx()); - else - return GetStockElx(STOCKELX_EMPTY); - - default: - return GetStockElx(STOCKELX_EMPTY); - } -} - -template ElxInterface * CBuilderT :: 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 * pbackref = (CBackrefElxT *)Keep(new CBackrefElxT (-1, flags & RIGHTTOLEFT, flags & IGNORECASE)); - - MoveNext(); // skip '<' or '\'' - - // save name - CBufferT & name = pbackref->m_szNamed; - CBufferT 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 - 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 (nbackref, flags & RIGHTTOLEFT, flags & IGNORECASE)); - } -} - -template int CBuilderT :: 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= '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 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 m_builder; -}; - -// -// Implementation -// -template CRegexpT :: CRegexpT(const CHART * pattern, int flags) -{ - Compile(pattern, CBufferRefT(pattern).GetSize(), flags); -} - -template CRegexpT :: CRegexpT(const CHART * pattern, int length, int flags) -{ - Compile(pattern, length, flags); -} - -template inline void CRegexpT :: Compile(const CHART * pattern, int flags) -{ - Compile(pattern, CBufferRefT(pattern).GetSize(), flags); -} - -template void CRegexpT :: Compile(const CHART * pattern, int length, int flags) -{ - m_builder.Clear(); - if(pattern != 0) m_builder.Build(CBufferRefT(pattern, length), flags); -} - -template inline MatchResult CRegexpT :: MatchExact(const CHART * tstring, CContext * pContext) const -{ - return MatchExact(tstring, CBufferRefT(tstring).GetSize(), pContext); -} - -template MatchResult CRegexpT :: 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 MatchResult CRegexpT :: Match(const CHART * tstring, int start, CContext * pContext) const -{ - return Match(tstring, CBufferRefT(tstring).GetSize(), start, pContext); -} - -template MatchResult CRegexpT :: 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 MatchResult CRegexpT :: 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 inline CContext * CRegexpT :: PrepareMatch(const CHART * tstring, int start, CContext * pContext) const -{ - return PrepareMatch(tstring, CBufferRefT(tstring).GetSize(), start, pContext); -} - -template CContext * CRegexpT :: 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 inline int CRegexpT :: GetNamedGroupNumber(const CHART * group_name) const -{ - return m_builder.GetNamedNumber(group_name); -} - -template CHART * CRegexpT :: Replace(const CHART * tstring, const CHART * replaceto, int start, int ntimes, MatchResult * result, CContext * pContext) const -{ - int result_length = 0; - return Replace(tstring, CBufferRefT(tstring).GetSize(), replaceto, CBufferRefT(replaceto).GetSize(), result_length, start, ntimes, result, pContext); -} - -template CHART * CRegexpT :: 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 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 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 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; iGetSize(); - } - } - - 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; iGetSize(); - - CBufferT 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; iGetBuffer(), 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 inline void CRegexpT :: ReleaseString(CHART * tstring) -{ - if(tstring != 0) delete [] tstring; -} - -template inline void CRegexpT :: ReleaseContext(CContext * pContext) -{ - if(pContext != 0) delete pContext; -} - -// -// All implementations -// -template CAlternativeElxT :: CAlternativeElxT() -{ -} - -template int CAlternativeElxT :: 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 CAlternativeElxT :: 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 CAssertElxT :: CAssertElxT(ElxInterface * pelx, int byes) -{ - m_pelx = pelx; - m_byes = byes; -} - -template int CAssertElxT :: 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 CAssertElxT :: 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 CEmptyElxT :: CEmptyElxT() -{ -} - -template int CEmptyElxT :: Match(CContext *) const -{ - return 1; -} - -template int CEmptyElxT :: MatchNext(CContext *) const -{ - return 0; -} - -// globalx.cpp: implementation of the CGlobalElx class. -// -template CGlobalElxT ::CGlobalElxT() -{ -} - -template int CGlobalElxT :: Match(CContext * pContext) const -{ - return pContext->m_nCurrentPos == pContext->m_nBeginPos; -} - -template int CGlobalElxT :: MatchNext(CContext *) const -{ - return 0; -} - -// greedelx.cpp: implementation of the CGreedyElx class. -// -template CGreedyElxT :: CGreedyElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) -{ - m_nvart = nmax - nmin; -} - -template int CGreedyElxT :: Match(CContext * pContext) const -{ - if( ! CRepeatElxT :: MatchFixed(pContext) ) - return 0; - - while( ! MatchVart(pContext) ) - { - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - } - - return 1; -} - -template int CGreedyElxT :: MatchNext(CContext * pContext) const -{ - if( MatchNextVart(pContext) ) - return 1; - - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - - while( ! MatchVart(pContext) ) - { - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - } - - return 1; -} - -template int CGreedyElxT :: MatchVart(CContext * pContext) const -{ - int n = 0; - int nbegin = pContext->m_nCurrentPos; - - while(n < m_nvart && CRepeatElxT :: m_pelx->Match(pContext)) - { - while(pContext->m_nCurrentPos == nbegin) - { - if( ! CRepeatElxT :: 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 CGreedyElxT :: MatchNextVart(CContext * pContext) const -{ - int n = 0; - pContext->m_stack.Pop(n); - - if(n == 0) return 0; - - if( ! CRepeatElxT :: m_pelx->MatchNext(pContext) ) - { - n --; - } - - pContext->m_stack.Push(n); - - return 1; -} - -// indepelx.cpp: implementation of the CIndependentElx class. -// -template CIndependentElxT :: CIndependentElxT(ElxInterface * pelx) -{ - m_pelx = pelx; -} - -template int CIndependentElxT :: 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 CIndependentElxT :: 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 CListElxT :: CListElxT(int brightleft) -{ - m_brightleft = brightleft; -} - -template int CListElxT :: 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 CListElxT :: 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 MatchResultT :: 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 inline int MatchResultT :: IsMatched() const -{ - return m_result.At(0, 0); -} - -template inline int MatchResultT :: MaxGroupNumber() const -{ - return m_result.At(1, 0); -} - -template inline int MatchResultT :: GetStart() const -{ - return m_result.At(2, -1); -} - -template inline int MatchResultT :: GetEnd() const -{ - return m_result.At(3, -1); -} - -template inline int MatchResultT :: GetGroupStart(int nGroupNumber) const -{ - return m_result.At(2 + nGroupNumber * 2, -1); -} - -template inline int MatchResultT :: GetGroupEnd(int nGroupNumber) const -{ - return m_result.At(2 + nGroupNumber * 2 + 1, -1); -} - -template MatchResultT & MatchResultT :: operator = (const MatchResultT & 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 CPossessiveElxT :: CPossessiveElxT(ElxInterface * pelx, int nmin, int nmax) : CGreedyElxT (pelx, nmin, nmax) -{ -} - -template int CPossessiveElxT :: 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 :: MatchFixed(pContext) ) - { - bsucc = 0; - } - else - { - while( ! CGreedyElxT :: MatchVart(pContext) ) - { - if( ! CRepeatElxT :: 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 CPossessiveElxT :: 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 CReluctantElxT :: CReluctantElxT(ElxInterface * pelx, int nmin, int nmax) : CRepeatElxT (pelx, nmin) -{ - m_nvart = nmax - nmin; -} - -template int CReluctantElxT :: Match(CContext * pContext) const -{ - if( ! CRepeatElxT :: MatchFixed(pContext) ) - return 0; - - while( ! MatchVart(pContext) ) - { - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - } - - return 1; -} - -template int CReluctantElxT :: MatchNext(CContext * pContext) const -{ - if( MatchNextVart(pContext) ) - return 1; - - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - - while( ! MatchVart(pContext) ) - { - if( ! CRepeatElxT :: MatchNextFixed(pContext) ) - return 0; - } - - return 1; -} - -template int CReluctantElxT :: MatchVart(CContext * pContext) const -{ - pContext->m_stack.Push(0); - - return 1; -} - -template int CReluctantElxT :: MatchNextVart(CContext * pContext) const -{ - int n = 0, nbegin = pContext->m_nCurrentPos; - - pContext->m_stack.Pop(n); - - if(n < m_nvart && CRepeatElxT :: m_pelx->Match(pContext)) - { - while(pContext->m_nCurrentPos == nbegin) - { - if( ! CRepeatElxT :: 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 :: 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 CRepeatElxT :: CRepeatElxT(ElxInterface * pelx, int ntimes) -{ - m_pelx = pelx; - m_nfixed = ntimes; -} - -template int CRepeatElxT :: Match(CContext * pContext) const -{ - return MatchFixed(pContext); -} - -template int CRepeatElxT :: MatchNext(CContext * pContext) const -{ - return MatchNextFixed(pContext); -} - -template int CRepeatElxT :: 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 CRepeatElxT :: 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 CRegexpA; -typedef CRegexpT CRegexpW; - -#if defined(_UNICODE) || defined(UNICODE) - typedef CRegexpW CRegexp; -#else - typedef CRegexpA CRegexp; -#endif - -#endif//__DEELX_REGEXP__H__