// 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_TYPEenum 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 IDsenum 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 '