// RegEx.cpp : 定义控制台应用程序的入口点。 // // 本文所使用的“正则表达式解析引擎”来自 // http://www.regexlab.com/deelx/ // #include " stdafx.h " #include " Regex.h " /**/ /// ===========================================================================/// 合法的IP/// A.B.C.D/// A/B/C/D 为[0-255]间的整数/// 本规则忽略数字前导0,即 00192 == 192/// --------------------------------------------------------------------------- int is_ip( const char * str ) ... { static CRegexpT< char > regexp( "0*(1/d{0,2}|2([0-4]/d?|5[0-5]?|/d?)|[3-9]/d?|0)(.0*(1/d{0,2}|2([0-4]/d?|5[0-5]?|/d?)|[3-9]/d?|0)){3}" ); MatchResult mrRet = regexp.MatchExact( str ); return mrRet.IsMatched();} int is_email( const char * str ) ... { static CRegexpT< char > regexp( "^/w+(/./w+)*@/w+(/./w+)+$" ); MatchResult mrRet = regexp.MatchExact( str ); return mrRet.IsMatched();} int _tmain( int argc, _TCHAR * argv[]) ... { char* ip1 = "192.168.58.251"; char* ip2 = "256.168.58.251"; printf( "%s ==> %s " , ip1 , (is_ip(ip1)?"yes":"no") ); printf( "%s ==> %s " , ip2 , (is_ip(ip2)?"yes":"no") ); char* m1 = "hjbcn@126.com"; char* m2 = "hjbcn#126.com"; printf( "%s ==> %s " , m1 , (is_email(m1)?"yes":"no") ); printf( "%s ==> %s " , m2 , (is_email(m2)?"yes":"no") ); getchar(); return 0;} // RegEx.h // // DEELX Regular Expression Engine (v1.2) // // Copyright 2006 (c) RegExLab.com // All Rights Reserved. // // http://www.regexlab.com/deelx/ // // Author: 史寿伟 (sswater shi) // sswater@gmail.com // // $Revision: 1.1.2.27 $ // #ifndef __DEELX_REGEXP__H__ #define __DEELX_REGEXP__H__ #include < memory.h > #include < ctype.h > #include < limits.h > #include < string .h > #include < stdio.h > // // Data Reference // template < class ELT > class CBufferRefT ... {public: CBufferRefT(const ELT * pcsz, int length); CBufferRefT(const ELT * pcsz);public: int nCompare (const ELT * pcsz) const; int nCompareNoCase(const ELT * pcsz) const; int Compare (const ELT * pcsz) const; int CompareNoCase(const ELT * pcsz) const; int Compare (const CBufferRefT <ELT> &) const; int CompareNoCase(const CBufferRefT <ELT> &) const; ELT At (int nIndex, ELT def = 0) const; ELT operator [] (int nIndex) const; const ELT * GetBuffer() const; int GetSize() const;public: virtual ~CBufferRefT();// Contentprotected: 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();// Contentprotected: ELT * m_pBuffer; int m_nMaxLength;} ; // // Implemenation // template < class ELT > CBufferT < ELT > :: CBufferT( const ELT * pcsz, int length) : CBufferRefT < ELT > ( 0 , length) ... { m_nMaxLength = CBufferRefT <ELT> :: m_nSize + 1; CBufferRefT <ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength]; memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize); m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;} template < class ELT > CBufferT < ELT > :: CBufferT( const ELT * pcsz) : CBufferRefT < ELT > (pcsz) ... { m_nMaxLength = CBufferRefT <ELT> :: m_nSize + 1; CBufferRefT <ELT> :: m_pRef = m_pBuffer = new ELT[m_nMaxLength]; memcpy(m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize); m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;} template < class ELT > CBufferT < ELT > :: CBufferT() : CBufferRefT < ELT > ( 0 , 0 ) ... { m_nMaxLength = 0; m_pBuffer = 0;} template < class ELT > inline ELT & CBufferT < ELT > :: operator [] ( int nIndex) ... { return m_pBuffer[nIndex];} template < class ELT > inline const ELT & CBufferT < ELT > :: operator [] ( int nIndex) const ... { return m_pBuffer[nIndex];} template < class ELT > void CBufferT < ELT > :: Append( const ELT * pcsz, int length, int eol) ... { int nNewLength = m_nMaxLength; // Check length if(nNewLength < 8) nNewLength = 8; if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength) nNewLength *= 2; if(CBufferRefT <ELT> :: m_nSize + length + eol > nNewLength) ...{ nNewLength = CBufferRefT <ELT> :: m_nSize + length + eol + 11; nNewLength -= nNewLength % 8; } // Realloc if(nNewLength > m_nMaxLength) ...{ ELT * pNewBuffer = new ELT[nNewLength]; if(m_pBuffer != 0) ...{ memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize); delete [] m_pBuffer; } CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer; m_nMaxLength = nNewLength; } // Append memcpy(m_pBuffer + CBufferRefT <ELT> :: m_nSize, pcsz, sizeof(ELT) * length); CBufferRefT <ELT> :: m_nSize += length; if(eol > 0) m_pBuffer[CBufferRefT <ELT> :: m_nSize] = 0;} template < class ELT > inline void CBufferT < ELT > :: Append(ELT el, int eol) ... { Append(&el, 1, eol);} template < class ELT > void CBufferT < ELT > :: Push(ELT el) ... { // Realloc if(CBufferRefT <ELT> :: m_nSize >= m_nMaxLength) ...{ int nNewLength = m_nMaxLength * 2; if( nNewLength < 8 ) nNewLength = 8; ELT * pNewBuffer = new ELT[nNewLength]; if(m_pBuffer != 0) ...{ memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize); delete [] m_pBuffer; } CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer; m_nMaxLength = nNewLength; } // Append m_pBuffer[CBufferRefT <ELT> :: m_nSize++] = el;} template < class ELT > inline int CBufferT < ELT > :: Pop(ELT & el) ... { if(CBufferRefT <ELT> :: m_nSize > 0) ...{ el = m_pBuffer[--CBufferRefT <ELT> :: m_nSize]; return 1; } else ...{ return 0; }} template < class ELT > inline int CBufferT < ELT > :: Peek(ELT & el) const ... { if(CBufferRefT <ELT> :: m_nSize > 0) ...{ el = m_pBuffer[CBufferRefT <ELT> :: m_nSize - 1]; return 1; } else ...{ return 0; }} template < class ELT > const ELT * CBufferT < ELT > :: GetBuffer() const ... { static const ELT _def[] = ...{0}; return m_pBuffer ? m_pBuffer : _def;} template < class ELT > ELT * CBufferT < ELT > :: GetBuffer() ... { static const ELT _def[] = ...{0}; return m_pBuffer ? m_pBuffer : (ELT *)_def;} template < class ELT > ELT * CBufferT < ELT > :: Detach() ... { ELT * pBuffer = m_pBuffer; CBufferRefT <ELT> :: m_pRef = m_pBuffer = 0; CBufferRefT <ELT> :: m_nSize = m_nMaxLength = 0; return pBuffer;} template < class ELT > void CBufferT < ELT > :: Release() ... { ELT * pBuffer = Detach(); if(pBuffer != 0) delete [] pBuffer;} template < class ELT > void CBufferT < ELT > :: Prepare( int index, int fill) ... { int nNewSize = index + 1; // Realloc if(nNewSize > m_nMaxLength) ...{ int nNewLength = m_nMaxLength; if( nNewLength < 8 ) nNewLength = 8; if( nNewSize > nNewLength ) nNewLength *= 2; if( nNewSize > nNewLength ) ...{ nNewLength = nNewSize + 11; nNewLength -= nNewLength % 8; } ELT * pNewBuffer = new ELT[nNewLength]; if(m_pBuffer != 0) ...{ memcpy(pNewBuffer, m_pBuffer, sizeof(ELT) * CBufferRefT <ELT> :: m_nSize); delete [] m_pBuffer; } CBufferRefT <ELT> :: m_pRef = m_pBuffer = pNewBuffer; m_nMaxLength = nNewLength; } // size if( CBufferRefT <ELT> :: m_nSize < nNewSize ) ...{ memset(m_pBuffer + CBufferRefT <ELT> :: m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT <ELT> :: m_nSize)); CBufferRefT <ELT> :: m_nSize = nNewSize; }} template < class ELT > inline void CBufferT < ELT > :: Restore( int size) ... { CBufferRefT <ELT> :: m_nSize = size;} template < class ELT > CBufferT < ELT > :: ~ CBufferT() ... { if(m_pBuffer != 0) delete [] m_pBuffer;} // // Context // class CContext ... {public: CBufferT <int> m_stack; CBufferT <int> m_capturestack, m_captureindex;public: int m_nCurrentPos; int m_nBeginPos; int m_nLastBeginPos; int m_nParenZindex; void * m_pMatchString; int m_pMatchStringLength;} ; // // Interface // class ElxInterface ... {public: virtual int Match (CContext * pContext) const = 0; virtual int MatchNext(CContext * pContext) const = 0;public: virtual ~ElxInterface() ...{};} ; // // Alternative // template < int x > class CAlternativeElxT : public ElxInterface ... {public: int Match (CContext * pContext) const; int MatchNext(CContext * pContext) const;public: CAlternativeElxT();public: CBufferT <ElxInterface *> m_elxlist;} ;typedef CAlternativeElxT < 0 > CAlternativeElx; // // Assert // template < int x > class CAssertElxT : public ElxInterface ... {public: int Match (CContext * pContext) const; int MatchNext(CContext * pContext) const;public: CAssertElxT(ElxInterface * pelx, int byes = 1);public: ElxInterface * m_pelx; int m_byes;} ;typedef CAssertElxT < 0 > CAssertElx; // // Back reference elx // template < class CHART > class CBackrefElxT : public ElxInterface ... {public: int Match (CContext * pContext) const; int MatchNext(CContext * pContext) const;public: CBackrefElxT(int nnumber, int brightleft, int bignorecase);public: int m_nnumber; int m_brightleft; int m_bignorecase; CBufferT <CHART> m_szNamed;} ; // // Implementation // template < class CHART > CBackrefElxT < CHART > :: CBackrefElxT( int nnumber, int brightleft, int bignorecase) ... { m_nnumber = nnumber; m_brightleft = brightleft; m_bignorecase = bignorecase;} template < class CHART > int CBackrefElxT < CHART > :: Match(CContext * pContext) const ... { // check number, for named if( m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize() ) return 0; int index = pContext->m_captureindex[m_nnumber]; if( index < 0 ) return 0; // check enclosed int pos1 = pContext->m_capturestack[index + 1]; int pos2 = pContext->m_capturestack[index + 2]; if( pos2 < 0 ) pos2 = pContext->m_nCurrentPos; // info int lpos = pos1 < pos2 ? pos1 : pos2; int rpos = pos1 < pos2 ? pos2 : pos1; int slen = rpos - lpos; const CHART * pcsz = (const CHART *)pContext->m_pMatchString; int npos = pContext->m_nCurrentPos; int tlen = pContext->m_pMatchStringLength; // compare int bsucc; CBufferRefT <CHART> refstr(pcsz + lpos, slen); if( m_brightleft ) ...{ if(npos < slen) return 0; if(m_bignorecase) bsucc = ! refstr.nCompareNoCase(pcsz + (npos - slen)); else bsucc = ! refstr.nCompare (pcsz + (npos - slen)); if( bsucc ) ...{ pContext->m_stack.Push(npos); pContext->m_nCurrentPos -= slen; } } else ...{ if(npos + slen > tlen) return 0; if(m_bignorecase) bsucc = ! refstr.nCompareNoCase(pcsz + npos); else bsucc = ! refstr.nCompare (pcsz + npos); if( bsucc ) ...{ pContext->m_stack.Push(npos); pContext->m_nCurrentPos += slen; } } return bsucc;} template < class CHART > int CBackrefElxT < CHART > :: MatchNext(CContext * pContext) const ... { int npos = 0; pContext->m_stack.Pop(npos); pContext->m_nCurrentPos = npos; return 0;} // RCHART #ifndef RCHART #define RCHART(ch) ((CHART)ch) #endif // BOUNDARY_TYPE enum BOUNDARY_TYPE ... { BOUNDARY_FILE_BEGIN, // begin of whole text BOUNDARY_FILE_END , // end of whole text BOUNDARY_LINE_BEGIN, // begin of line BOUNDARY_LINE_END , // end of line BOUNDARY_WORD_BEGIN, // begin of word BOUNDARY_WORD_END , // end of word BOUNDARY_WORD_EDGE ,} ; // // Boundary Elx // template < class CHART > class CBoundaryElxT : public ElxInterface ... {public: int Match (CContext * pContext) const; int MatchNext(CContext * pContext) const;public: CBoundaryElxT(int ntype, int byes = 1);protected: static int IsWordChar(CHART ch);public: int m_ntype; int m_byes;} ; // // Implementation // template < class CHART > CBoundaryElxT < CHART > :: CBoundaryElxT( int ntype, int byes) ... { m_ntype = ntype; m_byes = byes;} template < class CHART > int CBoundaryElxT < CHART > :: Match(CContext * pContext) const ... { const CHART * pcsz = (const CHART *)pContext->m_pMatchString; int npos = pContext->m_nCurrentPos; int tlen = pContext->m_pMatchStringLength; CHART chL = npos > 0 ? pcsz[npos - 1] : 0; CHART chR = npos < tlen ? pcsz[npos ] : 0; int bsucc = 0; switch(m_ntype) ...{ case BOUNDARY_FILE_BEGIN: bsucc = (npos <= 0); break; case BOUNDARY_FILE_END: bsucc = (npos >= tlen); break; case BOUNDARY_LINE_BEGIN: bsucc = (npos <= 0 ) || (chL == RCHART(' ')) || ((chL == RCHART(' ')) && (chR != RCHART(' '))); break; case BOUNDARY_LINE_END: bsucc = (npos >= tlen) || (chR == RCHART(' ')) || ((chR == RCHART(' ')) && (chL != RCHART(' '))); break; case BOUNDARY_WORD_BEGIN: bsucc = ! IsWordChar(chL) && IsWordChar(chR); break; case BOUNDARY_WORD_END: bsucc = IsWordChar(chL) && ! IsWordChar(chR); break; case BOUNDARY_WORD_EDGE: bsucc = IsWordChar(chL) ? ! IsWordChar(chR) : IsWordChar(chR); break; } return bsucc;} template < class CHART > int CBoundaryElxT < CHART > :: MatchNext(CContext * ) const ... { return 0;} template < class CHART > inline int CBoundaryElxT < CHART > :: IsWordChar(CHART ch) ... { return (ch >= RCHART('A') && ch <= RCHART('Z')) || (ch >= RCHART('a') && ch <= RCHART('z')) || (ch >= RCHART('0') && ch <= RCHART('9')) || (ch == RCHART('_'));} // // Bracket // template < class CHART > class CBracketElxT : public ElxInterface ... {public: int Match (CContext * pContext) const; int MatchNext(CContext * pContext) const;public: CBracketElxT(int nnumber, int bright);public: int m_nnumber; int m_bright; CBufferT <CHART> m_szNamed;} ;template < class CHART > CBracketElxT < CHART > :: CBracketElxT( int nnumber, int bright) ... { m_nnumber = nnumber; m_bright = bright;} template < class CHART > int CBracketElxT < CHART > :: Match(CContext * pContext) const ... { // check, for named if(m_nnumber < 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 m_isblank(int c);public: int (*m_posixfun)(int); int m_brightleft; int m_byes;} ; // // Implementation // template < class CHART > CPosixElxT < CHART > :: CPosixElxT( const char * posix, int brightleft) ... { m_brightleft = brightleft; if(posix[1] == '^') ...{ m_byes = 0; posix += 2; } else ...{ m_byes = 1; posix += 1; } if (!strncmp(posix, "alnum:", 6)) m_posixfun = ::isalnum ; else if(!strncmp(posix, "alpha:", 6)) m_posixfun = ::isalpha ; else if(!strncmp(posix, "ascii:", 6)) m_posixfun = ::isascii ; else if(!strncmp(posix, "cntrl:", 6)) m_posixfun = ::iscntrl ; else if(!strncmp(posix, "digit:", 6)) m_posixfun = ::isdigit ; else if(!strncmp(posix, "graph:", 6)) m_posixfun = ::isgraph ; else if(!strncmp(posix, "lower:", 6)) m_posixfun = ::islower ; else if(!strncmp(posix, "print:", 6)) m_posixfun = ::isprint ; else if(!strncmp(posix, "punct:", 6)) m_posixfun = ::ispunct ; else if(!strncmp(posix, "space:", 6)) m_posixfun = ::isspace ; else if(!strncmp(posix, "upper:", 6)) m_posixfun = ::isupper ; else if(!strncmp(posix, "xdigit:",7)) m_posixfun = ::isxdigit; else if(!strncmp(posix, "blank:", 6)) m_posixfun = m_isblank ; else m_posixfun = 0 ;} template < class CHART > int CPosixElxT < CHART > :: m_isblank( int c) ... { return c == 0x20 || c == ' ';} template < class CHART > int CPosixElxT < CHART > :: Match(CContext * pContext) const ... { if(m_posixfun == 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;// Methodspublic: ElxInterface * Build(const CBufferRefT <CHART> & pattern, int flags); int GetNamedNumber(const CBufferRefT <CHART> & named) const; void Clear();public: CBuilderT(); ~CBuilderT();// Public Attributespublic: 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_INFOprotected: 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 Attributesprotected: 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('', 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(' '), 0, m_nNextPos, delta); break; case RCHART('n'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break; case RCHART('r'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break; case RCHART('t'): nex2 = CHART_INFO(RCHART(' '), 0, m_nNextPos, delta); break; case RCHART('v'): nex2 = CHART_INFO(RCHART('v'), 0, m_nNextPos, delta); break; case RCHART('e'): nex2 = CHART_INFO(RCHART( 27 ), 0, m_nNextPos, delta); break; case RCHART('G'): // skip 'G' if(m_nCharsetDepth > 0) ...{ m_nNextPos += 2; return 0; } else ...{ nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta); break; } case RCHART('L'): if( ! m_quote_fun ) m_quote_fun = ::tolower; case RCHART('U'): if( ! m_quote_fun ) m_quote_fun = ::toupper; case RCHART('Q'): ...{ m_bQuoted = 1; m_nNextPos += 2; return 0; } case RCHART('E'): ...{ m_quote_fun = 0; m_bQuoted = 0; m_nNextPos += 2; return 0; } case 0: if(m_nNextPos+1 >= m_pattern.GetSize()) ...{ delta = 1; nex2 = CHART_INFO(ch , 0, m_nNextPos, delta); } else nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta); // common '