3 // DEELX Regular Expression Engine (v1.2)
5 // Copyright 2006 (c) RegExLab.com
6 // All Rights Reserved.
8 // http://www.regexlab.com/deelx/
10 // Author: Ê·ÊÙΰ (sswater shi)
13 // $Revision: 1.1.2.26 $
16 #ifndef __DEELX_REGEXP__H__
17 #define __DEELX_REGEXP__H__
28 template <class ELT
> class CBufferRefT
31 CBufferRefT(const ELT
* pcsz
, int length
);
32 CBufferRefT(const ELT
* pcsz
);
35 int nCompare (const ELT
* pcsz
) const;
36 int nCompareNoCase(const ELT
* pcsz
) const;
37 int Compare (const ELT
* pcsz
) const;
38 int CompareNoCase(const ELT
* pcsz
) const;
39 int Compare (const CBufferRefT
<ELT
> &) const;
40 int CompareNoCase(const CBufferRefT
<ELT
> &) const;
42 ELT
At (int nIndex
, ELT def
= 0) const;
43 ELT
operator [] (int nIndex
) const;
45 const ELT
* GetBuffer() const;
49 virtual ~CBufferRefT();
60 template <class ELT
> CBufferRefT
<ELT
> :: CBufferRefT(const ELT
* pcsz
, int length
)
66 template <class ELT
> CBufferRefT
<ELT
> :: CBufferRefT(const ELT
* pcsz
)
71 if(pcsz
!= 0) while(m_pRef
[m_nSize
] != 0) m_nSize
++;
74 template <class ELT
> int CBufferRefT
<ELT
> :: nCompare(const ELT
* pcsz
) const
76 for(int i
=0; i
<m_nSize
; i
++)
78 if(m_pRef
[i
] != pcsz
[i
])
79 return m_pRef
[i
] - pcsz
[i
];
85 template <class ELT
> int CBufferRefT
<ELT
> :: nCompareNoCase(const ELT
* pcsz
) const
87 for(int i
=0; i
<m_nSize
; i
++)
89 if(m_pRef
[i
] != pcsz
[i
])
91 if(toupper((int)m_pRef
[i
]) != toupper((int)pcsz
[i
]))
92 return m_pRef
[i
] - pcsz
[i
];
99 template <class ELT
> inline int CBufferRefT
<ELT
> :: Compare(const ELT
* pcsz
) const
101 return nCompare(pcsz
) ? 1 : (int)pcsz
[m_nSize
];
104 template <class ELT
> inline int CBufferRefT
<ELT
> :: CompareNoCase(const ELT
* pcsz
) const
106 return nCompareNoCase(pcsz
) ? 1 : (int)pcsz
[m_nSize
];
109 template <class ELT
> inline int CBufferRefT
<ELT
> :: Compare(const CBufferRefT
<ELT
> & cref
) const
111 return m_nSize
== cref
.m_nSize
? nCompare(cref
.GetBuffer()) : 1;
114 template <class ELT
> inline int CBufferRefT
<ELT
> :: CompareNoCase(const CBufferRefT
<ELT
> & cref
) const
116 return m_nSize
== cref
.m_nSize
? nCompareNoCase(cref
.GetBuffer()) : 1;
119 template <class ELT
> inline ELT CBufferRefT
<ELT
> :: At(int nIndex
, ELT def
) const
121 return nIndex
>= m_nSize
? def
: m_pRef
[nIndex
];
124 template <class ELT
> inline ELT CBufferRefT
<ELT
> :: operator [] (int nIndex
) const
126 return nIndex
>= m_nSize
? 0 : m_pRef
[nIndex
];
129 template <class ELT
> const ELT
* CBufferRefT
<ELT
> :: GetBuffer() const
131 static const ELT _def
[] = {0}; return m_pRef
? m_pRef
: _def
;
134 template <class ELT
> inline int CBufferRefT
<ELT
> :: GetSize() const
139 template <class ELT
> CBufferRefT
<ELT
> :: ~CBufferRefT()
146 template <class ELT
> class CBufferT
: public CBufferRefT
<ELT
>
149 CBufferT(const ELT
* pcsz
, int length
);
150 CBufferT(const ELT
* pcsz
);
154 ELT
& operator [] (int nIndex
);
155 const ELT
& operator [] (int nIndex
) const;
156 void Append(const ELT
* pcsz
, int length
, int eol
= 0);
157 void Append(ELT el
, int eol
= 0);
162 int Peek(ELT
& el
) const;
165 const ELT
* GetBuffer() const;
169 void Prepare(int index
, int fill
= 0);
170 void Restore(int size
);
184 template <class ELT
> CBufferT
<ELT
> :: CBufferT(const ELT
* pcsz
, int length
) : CBufferRefT
<ELT
> (0, length
)
186 m_nMaxLength
= CBufferRefT
<ELT
> :: m_nSize
+ 1;
188 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= new ELT
[m_nMaxLength
];
189 memcpy(m_pBuffer
, pcsz
, sizeof(ELT
) * CBufferRefT
<ELT
> :: m_nSize
);
190 m_pBuffer
[CBufferRefT
<ELT
> :: m_nSize
] = 0;
193 template <class ELT
> CBufferT
<ELT
> :: CBufferT(const ELT
* pcsz
) : CBufferRefT
<ELT
> (pcsz
)
195 m_nMaxLength
= CBufferRefT
<ELT
> :: m_nSize
+ 1;
197 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= new ELT
[m_nMaxLength
];
198 memcpy(m_pBuffer
, pcsz
, sizeof(ELT
) * CBufferRefT
<ELT
> :: m_nSize
);
199 m_pBuffer
[CBufferRefT
<ELT
> :: m_nSize
] = 0;
202 template <class ELT
> CBufferT
<ELT
> :: CBufferT() : CBufferRefT
<ELT
> (0, 0)
208 template <class ELT
> inline ELT
& CBufferT
<ELT
> :: operator [] (int nIndex
)
210 return m_pBuffer
[nIndex
];
213 template <class ELT
> inline const ELT
& CBufferT
<ELT
> :: operator [] (int nIndex
) const
215 return m_pBuffer
[nIndex
];
218 template <class ELT
> void CBufferT
<ELT
> :: Append(const ELT
* pcsz
, int length
, int eol
)
220 int nNewLength
= m_nMaxLength
;
226 if(CBufferRefT
<ELT
> :: m_nSize
+ length
+ eol
> nNewLength
)
229 if(CBufferRefT
<ELT
> :: m_nSize
+ length
+ eol
> nNewLength
)
231 nNewLength
= CBufferRefT
<ELT
> :: m_nSize
+ length
+ eol
+ 11;
232 nNewLength
-= nNewLength
% 8;
236 if(nNewLength
> m_nMaxLength
)
238 ELT
* pNewBuffer
= new ELT
[nNewLength
];
242 memcpy(pNewBuffer
, m_pBuffer
, sizeof(ELT
) * CBufferRefT
<ELT
> :: m_nSize
);
246 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= pNewBuffer
;
247 m_nMaxLength
= nNewLength
;
251 memcpy(m_pBuffer
+ CBufferRefT
<ELT
> :: m_nSize
, pcsz
, sizeof(ELT
) * length
);
252 CBufferRefT
<ELT
> :: m_nSize
+= length
;
254 if(eol
> 0) m_pBuffer
[CBufferRefT
<ELT
> :: m_nSize
] = 0;
257 template <class ELT
> inline void CBufferT
<ELT
> :: Append(ELT el
, int eol
)
262 template <class ELT
> void CBufferT
<ELT
> :: Push(ELT el
)
265 if(CBufferRefT
<ELT
> :: m_nSize
>= m_nMaxLength
)
267 int nNewLength
= m_nMaxLength
* 2;
268 if( nNewLength
< 8 ) nNewLength
= 8;
270 ELT
* pNewBuffer
= new ELT
[nNewLength
];
274 memcpy(pNewBuffer
, m_pBuffer
, sizeof(ELT
) * CBufferRefT
<ELT
> :: m_nSize
);
278 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= pNewBuffer
;
279 m_nMaxLength
= nNewLength
;
283 m_pBuffer
[CBufferRefT
<ELT
> :: m_nSize
++] = el
;
286 template <class ELT
> inline int CBufferT
<ELT
> :: Pop(ELT
& el
)
288 if(CBufferRefT
<ELT
> :: m_nSize
> 0)
290 el
= m_pBuffer
[--CBufferRefT
<ELT
> :: m_nSize
];
299 template <class ELT
> inline int CBufferT
<ELT
> :: Peek(ELT
& el
) const
301 if(CBufferRefT
<ELT
> :: m_nSize
> 0)
303 el
= m_pBuffer
[CBufferRefT
<ELT
> :: m_nSize
- 1];
312 template <class ELT
> const ELT
* CBufferT
<ELT
> :: GetBuffer() const
314 static const ELT _def
[] = {0}; return m_pBuffer
? m_pBuffer
: _def
;
317 template <class ELT
> ELT
* CBufferT
<ELT
> :: GetBuffer()
319 static const ELT _def
[] = {0}; return m_pBuffer
? m_pBuffer
: (ELT
*)_def
;
322 template <class ELT
> ELT
* CBufferT
<ELT
> :: Detach()
324 ELT
* pBuffer
= m_pBuffer
;
326 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= 0;
327 CBufferRefT
<ELT
> :: m_nSize
= m_nMaxLength
= 0;
332 template <class ELT
> void CBufferT
<ELT
> :: Release()
334 ELT
* pBuffer
= Detach();
336 if(pBuffer
!= 0) delete [] pBuffer
;
339 template <class ELT
> void CBufferT
<ELT
> :: Prepare(int index
, int fill
)
341 int nNewSize
= index
+ 1;
344 if(nNewSize
> m_nMaxLength
)
346 int nNewLength
= m_nMaxLength
;
351 if( nNewSize
> nNewLength
)
354 if( nNewSize
> nNewLength
)
356 nNewLength
= nNewSize
+ 11;
357 nNewLength
-= nNewLength
% 8;
360 ELT
* pNewBuffer
= new ELT
[nNewLength
];
364 memcpy(pNewBuffer
, m_pBuffer
, sizeof(ELT
) * CBufferRefT
<ELT
> :: m_nSize
);
368 CBufferRefT
<ELT
> :: m_pRef
= m_pBuffer
= pNewBuffer
;
369 m_nMaxLength
= nNewLength
;
373 if( CBufferRefT
<ELT
> :: m_nSize
< nNewSize
)
375 memset(m_pBuffer
+ CBufferRefT
<ELT
> :: m_nSize
, fill
, sizeof(ELT
) * (nNewSize
- CBufferRefT
<ELT
> :: m_nSize
));
376 CBufferRefT
<ELT
> :: m_nSize
= nNewSize
;
380 template <class ELT
> inline void CBufferT
<ELT
> :: Restore(int size
)
382 CBufferRefT
<ELT
> :: m_nSize
= size
;
385 template <class ELT
> CBufferT
<ELT
> :: ~CBufferT()
387 if(m_pBuffer
!= 0) delete [] m_pBuffer
;
396 CBufferT
<int> m_stack
;
397 CBufferT
<int> m_capturestack
, m_captureindex
;
405 void * m_pMatchString
;
406 int m_pMatchStringLength
;
415 virtual int Match (CContext
* pContext
) const = 0;
416 virtual int MatchNext(CContext
* pContext
) const = 0;
419 virtual ~ElxInterface() {};
425 template <int x
> class CAlternativeElxT
: public ElxInterface
428 int Match (CContext
* pContext
) const;
429 int MatchNext(CContext
* pContext
) const;
435 CBufferT
<ElxInterface
*> m_elxlist
;
438 typedef CAlternativeElxT
<0> CAlternativeElx
;
443 template <int x
> class CAssertElxT
: public ElxInterface
446 int Match (CContext
* pContext
) const;
447 int MatchNext(CContext
* pContext
) const;
450 CAssertElxT(ElxInterface
* pelx
, int byes
= 1);
453 ElxInterface
* m_pelx
;
457 typedef CAssertElxT
<0> CAssertElx
;
460 // Back reference elx
462 template <class CHART
> class CBackrefElxT
: public ElxInterface
465 int Match (CContext
* pContext
) const;
466 int MatchNext(CContext
* pContext
) const;
469 CBackrefElxT(int nnumber
, int brightleft
, int bignorecase
);
476 CBufferT
<CHART
> m_szNamed
;
482 template <class CHART
> CBackrefElxT
<CHART
> :: CBackrefElxT(int nnumber
, int brightleft
, int bignorecase
)
485 m_brightleft
= brightleft
;
486 m_bignorecase
= bignorecase
;
489 template <class CHART
> int CBackrefElxT
<CHART
> :: Match(CContext
* pContext
) const
491 // check number, for named
492 if( m_nnumber
< 0 || m_nnumber
>= pContext
->m_captureindex
.GetSize() ) return 0;
494 int index
= pContext
->m_captureindex
[m_nnumber
];
495 if( index
< 0 ) return 0;
498 int pos1
= pContext
->m_capturestack
[index
+ 1];
499 int pos2
= pContext
->m_capturestack
[index
+ 2];
501 if( pos2
< 0 ) pos2
= pContext
->m_nCurrentPos
;
504 int lpos
= pos1
< pos2
? pos1
: pos2
;
505 int rpos
= pos1
< pos2
? pos2
: pos1
;
506 int slen
= rpos
- lpos
;
508 const CHART
* pcsz
= (const CHART
*)pContext
->m_pMatchString
;
509 int npos
= pContext
->m_nCurrentPos
;
510 int tlen
= pContext
->m_pMatchStringLength
;
514 CBufferRefT
<CHART
> refstr(pcsz
+ lpos
, slen
);
522 bsucc
= ! refstr
.nCompareNoCase(pcsz
+ (npos
- slen
));
524 bsucc
= ! refstr
.nCompare (pcsz
+ (npos
- slen
));
528 pContext
->m_stack
.Push(npos
);
529 pContext
->m_nCurrentPos
-= slen
;
534 if(npos
+ slen
> tlen
)
538 bsucc
= ! refstr
.nCompareNoCase(pcsz
+ npos
);
540 bsucc
= ! refstr
.nCompare (pcsz
+ npos
);
544 pContext
->m_stack
.Push(npos
);
545 pContext
->m_nCurrentPos
+= slen
;
552 template <class CHART
> int CBackrefElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
556 pContext
->m_stack
.Pop(npos
);
557 pContext
->m_nCurrentPos
= npos
;
564 #define RCHART(ch) ((CHART)ch)
570 BOUNDARY_FILE_BEGIN
, // begin of whole text
571 BOUNDARY_FILE_END
, // end of whole text
572 BOUNDARY_LINE_BEGIN
, // begin of line
573 BOUNDARY_LINE_END
, // end of line
574 BOUNDARY_WORD_BEGIN
, // begin of word
575 BOUNDARY_WORD_END
, // end of word
582 template <class CHART
> class CBoundaryElxT
: public ElxInterface
585 int Match (CContext
* pContext
) const;
586 int MatchNext(CContext
* pContext
) const;
589 CBoundaryElxT(int ntype
, int byes
= 1);
592 static int IsWordChar(CHART ch
);
602 template <class CHART
> CBoundaryElxT
<CHART
> :: CBoundaryElxT(int ntype
, int byes
)
608 template <class CHART
> int CBoundaryElxT
<CHART
> :: Match(CContext
* pContext
) const
610 const CHART
* pcsz
= (const CHART
*)pContext
->m_pMatchString
;
611 int npos
= pContext
->m_nCurrentPos
;
612 int tlen
= pContext
->m_pMatchStringLength
;
614 CHART chL
= npos
> 0 ? pcsz
[npos
- 1] : 0;
615 CHART chR
= npos
< tlen
? pcsz
[npos
] : 0;
621 case BOUNDARY_FILE_BEGIN
:
625 case BOUNDARY_FILE_END
:
626 bsucc
= (npos
>= tlen
);
629 case BOUNDARY_LINE_BEGIN
:
630 bsucc
= (npos
<= 0 ) || (chL
== RCHART('\n')) || ((chL
== RCHART('\r')) && (chR
!= RCHART('\n')));
633 case BOUNDARY_LINE_END
:
634 bsucc
= (npos
>= tlen
) || (chR
== RCHART('\r')) || ((chR
== RCHART('\n')) && (chL
!= RCHART('\r')));
637 case BOUNDARY_WORD_BEGIN
:
638 bsucc
= ! IsWordChar(chL
) && IsWordChar(chR
);
641 case BOUNDARY_WORD_END
:
642 bsucc
= IsWordChar(chL
) && ! IsWordChar(chR
);
645 case BOUNDARY_WORD_EDGE
:
646 bsucc
= IsWordChar(chL
) ? ! IsWordChar(chR
) : IsWordChar(chR
);
653 template <class CHART
> int CBoundaryElxT
<CHART
> :: MatchNext(CContext
*) const
658 template <class CHART
> inline int CBoundaryElxT
<CHART
> :: IsWordChar(CHART ch
)
660 return (ch
>= RCHART('A') && ch
<= RCHART('Z')) || (ch
>= RCHART('a') && ch
<= RCHART('z')) || (ch
>= RCHART('0') && ch
<= RCHART('9')) || (ch
== RCHART('_'));
666 template <class CHART
> class CBracketElxT
: public ElxInterface
669 int Match (CContext
* pContext
) const;
670 int MatchNext(CContext
* pContext
) const;
673 CBracketElxT(int nnumber
, int bright
);
679 CBufferT
<CHART
> m_szNamed
;
682 template <class CHART
> CBracketElxT
<CHART
> :: CBracketElxT(int nnumber
, int bright
)
688 template <class CHART
> int CBracketElxT
<CHART
> :: Match(CContext
* pContext
) const
691 if(m_nnumber
< 0) return 0;
695 pContext
->m_captureindex
.Prepare(m_nnumber
, -1);
696 int index
= pContext
->m_captureindex
[m_nnumber
];
699 if(index
> 0 && index
< pContext
->m_capturestack
.GetSize() && pContext
->m_capturestack
[index
+2] < 0)
701 pContext
->m_capturestack
[index
+3] --;
706 pContext
->m_captureindex
[m_nnumber
] = pContext
->m_capturestack
.GetSize();
708 pContext
->m_capturestack
.Push(m_nnumber
);
709 pContext
->m_capturestack
.Push(pContext
->m_nCurrentPos
);
710 pContext
->m_capturestack
.Push(-1);
711 pContext
->m_capturestack
.Push( 0); // z-index
716 int index
= pContext
->m_captureindex
[m_nnumber
];
718 if(pContext
->m_capturestack
[index
+ 3] < 0)
720 pContext
->m_capturestack
[index
+ 3] ++;
725 pContext
->m_capturestack
[index
+ 2] = pContext
->m_nCurrentPos
;
726 pContext
->m_capturestack
[index
+ 3] = pContext
->m_nParenZindex
++;
732 template <class CHART
> int CBracketElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
734 int index
= pContext
->m_captureindex
[m_nnumber
];
738 if(pContext
->m_capturestack
[index
+ 3] < 0)
740 pContext
->m_capturestack
[index
+ 3] ++;
744 pContext
->m_capturestack
.Restore(pContext
->m_capturestack
.GetSize() - 4);
747 index
= pContext
->m_capturestack
.GetSize() - 4;
748 while(index
>= 0 && pContext
->m_capturestack
[index
] != m_nnumber
) index
-= 4;
751 pContext
->m_captureindex
[m_nnumber
] = index
;
755 if(pContext
->m_capturestack
[index
+ 3] < 0)
757 pContext
->m_capturestack
[index
+ 3] --;
761 pContext
->m_capturestack
[index
+ 2] = -1;
762 pContext
->m_capturestack
[index
+ 3] = 0;
771 template <class CHART
> class CDelegateElxT
: public ElxInterface
774 int Match (CContext
* pContext
) const;
775 int MatchNext(CContext
* pContext
) const;
778 CDelegateElxT(int ndata
= 0);
781 ElxInterface
* m_pelx
;
782 int m_ndata
; // +0 : recursive to
783 // -3 : named recursive
785 CBufferT
<CHART
> m_szNamed
;
788 template <class CHART
> CDelegateElxT
<CHART
> :: CDelegateElxT(int ndata
)
794 template <class CHART
> int CDelegateElxT
<CHART
> :: Match(CContext
* pContext
) const
797 return m_pelx
->Match(pContext
);
802 template <class CHART
> int CDelegateElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
805 return m_pelx
->MatchNext(pContext
);
813 template <int x
> class CEmptyElxT
: public ElxInterface
816 int Match (CContext
* pContext
) const;
817 int MatchNext(CContext
* pContext
) const;
823 typedef CEmptyElxT
<0> CEmptyElx
;
828 template <int x
> class CGlobalElxT
: public ElxInterface
831 int Match (CContext
* pContext
) const;
832 int MatchNext(CContext
* pContext
) const;
838 typedef CGlobalElxT
<0> CGlobalElx
;
843 template <int x
> class CRepeatElxT
: public ElxInterface
846 int Match (CContext
* pContext
) const;
847 int MatchNext(CContext
* pContext
) const;
850 CRepeatElxT(ElxInterface
* pelx
, int ntimes
);
853 int MatchFixed (CContext
* pContext
) const;
854 int MatchNextFixed(CContext
* pContext
) const;
857 ElxInterface
* m_pelx
;
861 typedef CRepeatElxT
<0> CRepeatElx
;
866 template <int x
> class CGreedyElxT
: public CRepeatElxT
<x
>
869 int Match (CContext
* pContext
) const;
870 int MatchNext(CContext
* pContext
) const;
873 CGreedyElxT(ElxInterface
* pelx
, int nmin
= 0, int nmax
= INT_MAX
);
876 int MatchVart (CContext
* pContext
) const;
877 int MatchNextVart(CContext
* pContext
) const;
883 typedef CGreedyElxT
<0> CGreedyElx
;
888 template <int x
> class CIndependentElxT
: public ElxInterface
891 int Match (CContext
* pContext
) const;
892 int MatchNext(CContext
* pContext
) const;
895 CIndependentElxT(ElxInterface
* pelx
);
898 ElxInterface
* m_pelx
;
901 typedef CIndependentElxT
<0> CIndependentElx
;
906 template <int x
> class CListElxT
: public ElxInterface
909 int Match (CContext
* pContext
) const;
910 int MatchNext(CContext
* pContext
) const;
913 CListElxT(int brightleft
);
916 CBufferT
<ElxInterface
*> m_elxlist
;
920 typedef CListElxT
<0> CListElx
;
925 template <class CHART
> class CPosixElxT
: public ElxInterface
928 int Match (CContext
* pContext
) const;
929 int MatchNext(CContext
* pContext
) const;
932 CPosixElxT(const char * posix
, int brightleft
);
935 static int misblank(int c
);
938 int (*m_posixfun
)(int);
946 template <class CHART
> CPosixElxT
<CHART
> :: CPosixElxT(const char * posix
, int brightleft
)
948 m_brightleft
= brightleft
;
961 if (!strncmp(posix
, "alnum:", 6)) m_posixfun
= isalnum
;
962 else if(!strncmp(posix
, "alpha:", 6)) m_posixfun
= isalpha
;
963 else if(!strncmp(posix
, "ascii:", 6)) m_posixfun
= isascii
;
964 else if(!strncmp(posix
, "cntrl:", 6)) m_posixfun
= iscntrl
;
965 else if(!strncmp(posix
, "digit:", 6)) m_posixfun
= isdigit
;
966 else if(!strncmp(posix
, "graph:", 6)) m_posixfun
= isgraph
;
967 else if(!strncmp(posix
, "lower:", 6)) m_posixfun
= islower
;
968 else if(!strncmp(posix
, "print:", 6)) m_posixfun
= isprint
;
969 else if(!strncmp(posix
, "punct:", 6)) m_posixfun
= ispunct
;
970 else if(!strncmp(posix
, "space:", 6)) m_posixfun
= isspace
;
971 else if(!strncmp(posix
, "upper:", 6)) m_posixfun
= isupper
;
972 else if(!strncmp(posix
, "xdigit:",7)) m_posixfun
= isxdigit
;
973 else if(!strncmp(posix
, "blank:", 6)) m_posixfun
= misblank
;
974 else m_posixfun
= 0 ;
977 template <class CHART
> int CPosixElxT
<CHART
> :: misblank(int c
)
979 return c
== 0x20 || c
== '\t';
982 template <class CHART
> int CPosixElxT
<CHART
> :: Match(CContext
* pContext
) const
984 if(m_posixfun
== 0) return 0;
986 int tlen
= pContext
->m_pMatchStringLength
;
987 int npos
= pContext
->m_nCurrentPos
;
990 int at
= m_brightleft
? npos
- 1 : npos
;
991 if( at
< 0 || at
>= tlen
)
994 CHART ch
= ((const CHART
*)pContext
->m_pMatchString
)[at
];
996 int bsucc
= (*m_posixfun
)(ch
);
1002 pContext
->m_nCurrentPos
+= m_brightleft
? -1 : 1;
1007 template <class CHART
> int CPosixElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
1009 pContext
->m_nCurrentPos
-= m_brightleft
? -1 : 1;
1016 template <int x
> class CPossessiveElxT
: public CGreedyElxT
<x
>
1019 int Match (CContext
* pContext
) const;
1020 int MatchNext(CContext
* pContext
) const;
1023 CPossessiveElxT(ElxInterface
* pelx
, int nmin
= 0, int nmax
= INT_MAX
);
1026 typedef CPossessiveElxT
<0> CPossessiveElx
;
1031 template <class CHART
> class CRangeElxT
: public ElxInterface
1034 int Match (CContext
* pContext
) const;
1035 int MatchNext(CContext
* pContext
) const;
1038 CRangeElxT(int brightleft
, int byes
);
1041 CBufferT
<CHART
> m_ranges
;
1042 CBufferT
<CHART
> m_chars
;
1043 CBufferT
<ElxInterface
*> m_embeds
;
1053 template <class CHART
> CRangeElxT
<CHART
> :: CRangeElxT(int brightleft
, int byes
)
1055 m_brightleft
= brightleft
;
1059 template <class CHART
> int CRangeElxT
<CHART
> :: Match(CContext
* pContext
) const
1061 int tlen
= pContext
->m_pMatchStringLength
;
1062 int npos
= pContext
->m_nCurrentPos
;
1065 int at
= m_brightleft
? npos
- 1 : npos
;
1066 if( at
< 0 || at
>= tlen
)
1069 CHART ch
= ((const CHART
*)pContext
->m_pMatchString
)[at
];
1073 for(i
=0; !bsucc
&& i
<m_ranges
.GetSize(); i
+=2)
1075 if(m_ranges
[i
] <= ch
&& ch
<= m_ranges
[i
+1]) bsucc
= 1;
1078 for(i
=0; !bsucc
&& i
<m_chars
.GetSize(); i
++)
1080 if(m_chars
[i
] == ch
) bsucc
= 1;
1083 for(i
=0; !bsucc
&& i
<m_embeds
.GetSize(); i
++)
1085 if(m_embeds
[i
]->Match(pContext
))
1087 pContext
->m_nCurrentPos
= npos
;
1096 pContext
->m_nCurrentPos
+= m_brightleft
? -1 : 1;
1101 template <class CHART
> int CRangeElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
1103 pContext
->m_nCurrentPos
-= m_brightleft
? -1 : 1;
1110 template <int x
> class CReluctantElxT
: public CRepeatElxT
<x
>
1113 int Match (CContext
* pContext
) const;
1114 int MatchNext(CContext
* pContext
) const;
1117 CReluctantElxT(ElxInterface
* pelx
, int nmin
= 0, int nmax
= INT_MAX
);
1120 int MatchVart (CContext
* pContext
) const;
1121 int MatchNextVart(CContext
* pContext
) const;
1127 typedef CReluctantElxT
<0> CReluctantElx
;
1132 template <class CHART
> class CStringElxT
: public ElxInterface
1135 int Match (CContext
* pContext
) const;
1136 int MatchNext(CContext
* pContext
) const;
1139 CStringElxT(const CHART
* fixed
, int nlength
, int brightleft
, int bignorecase
);
1142 CBufferT
<CHART
> m_szPattern
;
1150 template <class CHART
> CStringElxT
<CHART
> :: CStringElxT(const CHART
* fixed
, int nlength
, int brightleft
, int bignorecase
) : m_szPattern(fixed
, nlength
)
1152 m_brightleft
= brightleft
;
1153 m_bignorecase
= bignorecase
;
1156 template <class CHART
> int CStringElxT
<CHART
> :: Match(CContext
* pContext
) const
1158 const CHART
* pcsz
= (const CHART
*)pContext
->m_pMatchString
;
1159 int npos
= pContext
->m_nCurrentPos
;
1160 int tlen
= pContext
->m_pMatchStringLength
;
1161 int slen
= m_szPattern
.GetSize();
1171 bsucc
= ! m_szPattern
.nCompareNoCase(pcsz
+ (npos
- slen
));
1173 bsucc
= ! m_szPattern
.nCompare (pcsz
+ (npos
- slen
));
1176 pContext
->m_nCurrentPos
-= slen
;
1180 if(npos
+ slen
> tlen
)
1184 bsucc
= ! m_szPattern
.nCompareNoCase(pcsz
+ npos
);
1186 bsucc
= ! m_szPattern
.nCompare (pcsz
+ npos
);
1189 pContext
->m_nCurrentPos
+= slen
;
1195 template <class CHART
> int CStringElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
1197 int slen
= m_szPattern
.GetSize();
1200 pContext
->m_nCurrentPos
+= slen
;
1202 pContext
->m_nCurrentPos
-= slen
;
1210 template <class CHART
> class CConditionElxT
: public ElxInterface
1213 int Match (CContext
* pContext
) const;
1214 int MatchNext(CContext
* pContext
) const;
1220 // backref condition
1222 CBufferT
<CHART
> m_szNamed
;
1225 ElxInterface
* m_pelxask
;
1228 ElxInterface
* m_pelxyes
, * m_pelxno
;
1231 template <class CHART
> CConditionElxT
<CHART
> :: CConditionElxT()
1236 template <class CHART
> int CConditionElxT
<CHART
> :: Match(CContext
* pContext
) const
1239 int nbegin
= pContext
->m_nCurrentPos
;
1240 int nsize
= pContext
->m_stack
.GetSize();
1241 int ncsize
= pContext
->m_capturestack
.GetSize();
1244 int condition_yes
= 0;
1247 if( m_nnumber
>= 0 )
1251 if(m_nnumber
>= pContext
->m_captureindex
.GetSize()) break;
1253 int index
= pContext
->m_captureindex
[m_nnumber
];
1254 if( index
< 0) break;
1263 if( m_pelxask
== 0 )
1266 condition_yes
= m_pelxask
->Match(pContext
);
1268 pContext
->m_stack
.Restore(nsize
);
1269 pContext
->m_nCurrentPos
= nbegin
;
1275 bsucc
= m_pelxyes
== 0 ? 1 : m_pelxyes
->Match(pContext
);
1277 bsucc
= m_pelxno
== 0 ? 1 : m_pelxno
->Match(pContext
);
1281 pContext
->m_stack
.Push(ncsize
);
1282 pContext
->m_stack
.Push(condition_yes
);
1286 pContext
->m_capturestack
.Restore(ncsize
);
1292 template <class CHART
> int CConditionElxT
<CHART
> :: MatchNext(CContext
* pContext
) const
1295 int ncsize
, condition_yes
;
1297 pContext
->m_stack
.Pop(condition_yes
);
1298 pContext
->m_stack
.Pop(ncsize
);
1303 bsucc
= m_pelxyes
== 0 ? 0 : m_pelxyes
->MatchNext(pContext
);
1305 bsucc
= m_pelxno
== 0 ? 0 : m_pelxno
->MatchNext(pContext
);
1309 pContext
->m_stack
.Push(ncsize
);
1310 pContext
->m_stack
.Push(condition_yes
);
1314 pContext
->m_capturestack
.Restore(ncsize
);
1323 template <int x
> class MatchResultT
1326 int IsMatched() const;
1329 int GetStart() const;
1330 int GetEnd () const;
1333 int MaxGroupNumber() const;
1334 int GetGroupStart(int nGroupNumber
) const;
1335 int GetGroupEnd (int nGroupNumber
) const;
1338 MatchResultT(CContext
* pContext
, int nMaxNumber
= -1);
1339 MatchResultT
<x
> & operator = (const MatchResultT
<x
> &);
1340 inline operator int() const { return IsMatched(); }
1343 CBufferT
<int> m_result
;
1346 typedef MatchResultT
<0> MatchResult
;
1349 enum STOCKELX_ID_DEFINES
1353 ///////////////////////
1356 STOCKELX_DOT_NOT_ALL
,
1365 STOCKELX_DIGITAL_NOT
,
1367 //////////////////////
1369 STOCKELX_DOT_ALL_RIGHTLEFT
,
1370 STOCKELX_DOT_NOT_ALL_RIGHTLEFT
,
1372 STOCKELX_WORD_RIGHTLEFT
,
1373 STOCKELX_WORD_RIGHTLEFT_NOT
,
1375 STOCKELX_SPACE_RIGHTLEFT
,
1376 STOCKELX_SPACE_RIGHTLEFT_NOT
,
1378 STOCKELX_DIGITAL_RIGHTLEFT
,
1379 STOCKELX_DIGITAL_RIGHTLEFT_NOT
,
1381 /////////////////////
1387 #ifndef _REGEX_FLAGS_DEFINED
1398 #define _REGEX_FLAGS_DEFINED
1404 template <class CHART
> class CBuilderT
1407 typedef CDelegateElxT
<CHART
> CDelegateElx
;
1408 typedef CBracketElxT
<CHART
> CBracketElx
;
1409 typedef CBackrefElxT
<CHART
> CBackrefElx
;
1410 typedef CConditionElxT
<CHART
> CConditionElx
;
1414 ElxInterface
* Build(const CBufferRefT
<CHART
> & pattern
, int flags
);
1415 int GetNamedNumber(const CBufferRefT
<CHART
> & named
) const;
1422 // Public Attributes
1424 ElxInterface
* m_pTopElx
;
1430 CBufferT
<ElxInterface
*> m_objlist
;
1431 CBufferT
<ElxInterface
*> m_grouplist
;
1432 CBufferT
<CDelegateElx
*> m_recursivelist
;
1433 CBufferT
<CListElx
*> m_namedlist
;
1434 CBufferT
<CBackrefElx
*> m_namedbackreflist
;
1435 CBufferT
<CConditionElx
*> m_namedconditionlist
;
1448 CHART_INFO(CHART c
, int t
, int p
= 0, int l
= 0) { ch
= c
; type
= t
; pos
= p
; len
= l
; }
1449 inline int operator == (const CHART_INFO
& ci
) { return ch
== ci
.ch
&& type
== ci
.type
; }
1450 inline int operator != (const CHART_INFO
& ci
) { return ! operator == (ci
); }
1454 static unsigned int Hex2Int(const CHART
* pcsz
, int length
, int & used
);
1455 static int ReadDec(char * & str
, unsigned int & dec
);
1459 ElxInterface
* BuildAlternative(int vaflags
);
1460 ElxInterface
* BuildList (int & flags
);
1461 ElxInterface
* BuildRepeat (int & flags
);
1462 ElxInterface
* BuildSimple (int & flags
);
1463 ElxInterface
* BuildCharset (int & flags
);
1464 ElxInterface
* BuildRecursive (int & flags
);
1465 ElxInterface
* BuildBoundary (int & flags
);
1466 ElxInterface
* BuildBackref (int & flags
);
1468 ElxInterface
* GetStockElx (int nStockId
);
1469 ElxInterface
* Keep(ElxInterface
* pElx
);
1471 // Private Attributes
1473 CBufferRefT
<CHART
> m_pattern
;
1474 CHART_INFO prev
, curr
, next
, nex2
;
1476 int m_nCharsetDepth
;
1478 int (*m_quote_fun
)(int);
1480 ElxInterface
* m_pStockElxs
[STOCKELX_COUNT
];
1486 template <class CHART
> CBuilderT
<CHART
> :: CBuilderT() : m_pattern(0, 0), prev(0, 0), curr(0, 0), next(0, 0), nex2(0, 0)
1491 template <class CHART
> CBuilderT
<CHART
> :: ~CBuilderT()
1496 template <class CHART
> int CBuilderT
<CHART
> :: GetNamedNumber(const CBufferRefT
<CHART
> & named
) const
1498 for(int i
=0; i
<m_namedlist
.GetSize(); i
++)
1500 if( ! ((CBracketElx
*)m_namedlist
[i
]->m_elxlist
[0])->m_szNamed
.CompareNoCase(named
) )
1501 return ((CBracketElx
*)m_namedlist
[i
]->m_elxlist
[0])->m_nnumber
;
1507 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: Build(const CBufferRefT
<CHART
> & pattern
, int flags
)
1510 m_pattern
= pattern
;
1512 m_nCharsetDepth
= 0;
1519 m_grouplist
.Restore(0);
1520 m_recursivelist
.Restore(0);
1521 m_namedlist
.Restore(0);
1522 m_namedbackreflist
.Restore(0);
1523 m_namedconditionlist
.Restore(0);
1526 for(i
=0; i
<3; i
++) MoveNext();
1529 m_pTopElx
= BuildAlternative(flags
);
1532 m_grouplist
.Prepare(0);
1533 m_grouplist
[0] = m_pTopElx
;
1535 // append named to unnamed
1536 m_nGroupCount
= m_grouplist
.GetSize();
1538 m_grouplist
.Prepare(m_nMaxNumber
+ m_namedlist
.GetSize());
1540 for(i
=0; i
<m_namedlist
.GetSize(); i
++)
1542 CBracketElx
* pleft
= (CBracketElx
*)m_namedlist
[i
]->m_elxlist
[0];
1543 CBracketElx
* pright
= (CBracketElx
*)m_namedlist
[i
]->m_elxlist
[2];
1546 m_grouplist
[m_nGroupCount
++] = m_namedlist
[i
];
1548 if( pleft
->m_nnumber
> 0 )
1552 int find_same_name
= GetNamedNumber(pleft
->m_szNamed
);
1553 if( find_same_name
>= 0 )
1555 pleft
->m_nnumber
= find_same_name
;
1556 pright
->m_nnumber
= find_same_name
;
1562 pleft
->m_nnumber
= m_nMaxNumber
;
1563 pright
->m_nnumber
= m_nMaxNumber
;
1567 for(i
=1; i
<m_nGroupCount
; i
++)
1569 CBracketElx
* pleft
= (CBracketElx
*)((CListElx
*)m_grouplist
[i
])->m_elxlist
[0];
1571 if( pleft
->m_nnumber
> m_nMaxNumber
)
1572 m_nMaxNumber
= pleft
->m_nnumber
;
1575 // connect recursive
1576 for(i
=0; i
<m_recursivelist
.GetSize(); i
++)
1578 if( m_recursivelist
[i
]->m_ndata
== -3 )
1579 m_recursivelist
[i
]->m_ndata
= GetNamedNumber(m_recursivelist
[i
]->m_szNamed
);
1581 if( m_recursivelist
[i
]->m_ndata
>= 0 && m_recursivelist
[i
]->m_ndata
< m_grouplist
.GetSize() )
1582 m_recursivelist
[i
]->m_pelx
= m_grouplist
[m_recursivelist
[i
]->m_ndata
];
1586 for(i
=0; i
<m_namedbackreflist
.GetSize(); i
++)
1588 m_namedbackreflist
[i
]->m_nnumber
= GetNamedNumber(m_namedbackreflist
[i
]->m_szNamed
);
1592 for(i
=0; i
<m_namedconditionlist
.GetSize(); i
++)
1594 int nn
= GetNamedNumber(m_namedconditionlist
[i
]->m_szNamed
);
1597 m_namedconditionlist
[i
]->m_nnumber
= nn
;
1598 m_namedconditionlist
[i
]->m_pelxask
= 0;
1605 template <class CHART
> void CBuilderT
<CHART
> :: Clear()
1607 for(int i
=0; i
<m_objlist
.GetSize(); i
++)
1609 delete m_objlist
[i
];
1612 m_objlist
.Restore(0);
1615 memset(m_pStockElxs
, 0, sizeof(m_pStockElxs
));
1621 template <class CHART
> unsigned int CBuilderT
<CHART
> :: Hex2Int(const CHART
* pcsz
, int length
, int & used
)
1623 unsigned int result
= 0;
1626 for(i
=0; i
<length
; i
++)
1628 if(pcsz
[i
] >= RCHART('0') && pcsz
[i
] <= RCHART('9'))
1629 result
= (result
<< 4) + (pcsz
[i
] - RCHART('0'));
1630 else if(pcsz
[i
] >= RCHART('A') && pcsz
[i
] <= RCHART('F'))
1631 result
= (result
<< 4) + (0x0A + (pcsz
[i
] - RCHART('A')));
1632 else if(pcsz
[i
] >= RCHART('a') && pcsz
[i
] <= RCHART('f'))
1633 result
= (result
<< 4) + (0x0A + (pcsz
[i
] - RCHART('a')));
1641 template <class CHART
> inline ElxInterface
* CBuilderT
<CHART
> :: Keep(ElxInterface
* pelx
)
1643 m_objlist
.Push(pelx
);
1647 template <class CHART
> void CBuilderT
<CHART
> :: MoveNext()
1655 while( ! GetNext2() ) {};
1658 template <class CHART
> int CBuilderT
<CHART
> :: GetNext2()
1661 if(m_nNextPos
>= m_pattern
.GetSize())
1663 nex2
= CHART_INFO(0, 1, m_nNextPos
, 0);
1668 CHART ch
= m_pattern
[m_nNextPos
];
1673 if(ch
== RCHART('\\'))
1675 if(m_pattern
[m_nNextPos
+ 1] == RCHART('E'))
1684 if(m_quote_fun
!= 0)
1685 nex2
= CHART_INFO((CHART
)(*m_quote_fun
)((int)ch
), 0, m_nNextPos
, delta
);
1687 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1689 m_nNextPos
+= delta
;
1699 CHART ch1
= m_pattern
[m_nNextPos
+1];
1702 if(ch1
>= RCHART('0') && ch1
<= RCHART('9'))
1704 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1724 nex2
= CHART_INFO(ch1
, 1, m_nNextPos
, delta
);
1728 if(m_nCharsetDepth
> 0)
1729 nex2
= CHART_INFO('\b', 0, m_nNextPos
, delta
);
1731 nex2
= CHART_INFO(ch1
, 1, m_nNextPos
, delta
);
1737 if(m_nCharsetDepth > 0)
1738 nex2 = CHART_INFO(ch1, 0, m_nNextPos, delta);
1740 nex2 = CHART_INFO(ch1, 1, m_nNextPos, delta);
1745 if(m_pattern
[m_nNextPos
+2] != '{')
1748 unsigned int ch2
= Hex2Int(m_pattern
.GetBuffer() + m_nNextPos
+ 2, 2, red
);
1753 nex2
= CHART_INFO(RCHART(ch2
), 0, m_nNextPos
, delta
);
1755 nex2
= CHART_INFO(ch1
, 0, m_nNextPos
, delta
);
1761 if(m_pattern
[m_nNextPos
+2] != '{')
1764 unsigned int ch2
= Hex2Int(m_pattern
.GetBuffer() + m_nNextPos
+ 2, 4, red
);
1769 nex2
= CHART_INFO(RCHART(ch2
), 0, m_nNextPos
, delta
);
1771 nex2
= CHART_INFO(ch1
, 0, m_nNextPos
, delta
);
1776 unsigned int ch2
= Hex2Int(m_pattern
.GetBuffer() + m_nNextPos
+ 3, sizeof(int) * 2, red
);
1780 while(m_nNextPos
+ delta
< m_pattern
.GetSize() && m_pattern
.At(m_nNextPos
+ delta
) != RCHART('}'))
1783 delta
++; // skip '}'
1785 nex2
= CHART_INFO(RCHART(ch2
), 0, m_nNextPos
, delta
);
1789 case RCHART('a'): nex2
= CHART_INFO(RCHART('\a'), 0, m_nNextPos
, delta
); break;
1790 case RCHART('f'): nex2
= CHART_INFO(RCHART('\f'), 0, m_nNextPos
, delta
); break;
1791 case RCHART('n'): nex2
= CHART_INFO(RCHART('\n'), 0, m_nNextPos
, delta
); break;
1792 case RCHART('r'): nex2
= CHART_INFO(RCHART('\r'), 0, m_nNextPos
, delta
); break;
1793 case RCHART('t'): nex2
= CHART_INFO(RCHART('\t'), 0, m_nNextPos
, delta
); break;
1794 case RCHART('v'): nex2
= CHART_INFO(RCHART('\v'), 0, m_nNextPos
, delta
); break;
1795 case RCHART('e'): nex2
= CHART_INFO(RCHART( 27 ), 0, m_nNextPos
, delta
); break;
1797 case RCHART('G'): // skip '\G'
1798 if(m_nCharsetDepth
> 0)
1805 nex2
= CHART_INFO(ch1
, 1, m_nNextPos
, delta
);
1810 if( ! m_quote_fun
) m_quote_fun
= ::tolower
;
1813 if( ! m_quote_fun
) m_quote_fun
= ::toupper
;
1831 if(m_nNextPos
+1 >= m_pattern
.GetSize())
1834 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1837 nex2
= CHART_INFO(ch1
, 0, m_nNextPos
, delta
); // common '\0' char
1841 nex2
= CHART_INFO(ch1
, 0, m_nNextPos
, delta
);
1856 if(m_nCharsetDepth
> 0)
1857 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1859 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1863 if(m_nCharsetDepth
> 0)
1864 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1866 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1871 CHART ch1
= m_pattern
[m_nNextPos
+1];
1872 CHART ch2
= m_pattern
[m_nNextPos
+2];
1875 if(ch1
== RCHART('?') && ch2
== RCHART('#'))
1878 while(m_nNextPos
< m_pattern
.GetSize())
1880 if(m_pattern
[m_nNextPos
] == RCHART(')'))
1886 if(m_pattern
[m_nNextPos
] == RCHART(')'))
1896 if(m_nCharsetDepth
> 0)
1897 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1899 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1905 if(m_nFlags
& EXTENDED
)
1910 while(m_nNextPos
< m_pattern
.GetSize())
1912 if(m_pattern
[m_nNextPos
] == RCHART('\n') || m_pattern
[m_nNextPos
] == RCHART('\r'))
1923 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1933 if(m_nFlags
& EXTENDED
)
1942 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1948 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1952 if(m_nCharsetDepth
> 0)
1955 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1959 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1964 if(next
== CHART_INFO(RCHART('['), 1))
1965 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1967 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1971 if(m_nCharsetDepth
== 0 || next
== CHART_INFO(RCHART('['), 1) || (curr
== CHART_INFO(RCHART('['), 1) && next
== CHART_INFO(RCHART(':'), 1)))
1972 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
);
1974 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1978 if(m_nNextPos
>= m_pattern
.GetSize())
1979 nex2
= CHART_INFO(ch
, 1, m_nNextPos
, delta
); // end of string
1981 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
); // common '\0' char
1985 nex2
= CHART_INFO(ch
, 0, m_nNextPos
, delta
);
1989 m_nNextPos
+= delta
;
1994 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: GetStockElx(int nStockId
)
1996 ElxInterface
** pStockElxs
= m_pStockElxs
;
1999 if(nStockId
< 0 || nStockId
>= STOCKELX_COUNT
)
2000 return GetStockElx(0);
2003 if(pStockElxs
[nStockId
] == 0)
2007 case STOCKELX_EMPTY
:
2008 pStockElxs
[nStockId
] = Keep(new CEmptyElx());
2013 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 1));
2015 pRange
->m_ranges
.Push(RCHART('A')); pRange
->m_ranges
.Push(RCHART('Z'));
2016 pRange
->m_ranges
.Push(RCHART('a')); pRange
->m_ranges
.Push(RCHART('z'));
2017 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2018 pRange
->m_chars
.Push(RCHART('_'));
2020 pStockElxs
[nStockId
] = pRange
;
2024 case STOCKELX_WORD_NOT
:
2026 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 0));
2028 pRange
->m_ranges
.Push(RCHART('A')); pRange
->m_ranges
.Push(RCHART('Z'));
2029 pRange
->m_ranges
.Push(RCHART('a')); pRange
->m_ranges
.Push(RCHART('z'));
2030 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2031 pRange
->m_chars
.Push(RCHART('_'));
2033 pStockElxs
[nStockId
] = pRange
;
2037 case STOCKELX_DOT_ALL
:
2038 pStockElxs
[nStockId
] = Keep(new CRangeElxT
<CHART
> (0, 0));
2041 case STOCKELX_DOT_NOT_ALL
:
2043 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 0));
2045 pRange
->m_chars
.Push(RCHART('\n'));
2047 pStockElxs
[nStockId
] = pRange
;
2051 case STOCKELX_SPACE
:
2053 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 1));
2055 pRange
->m_chars
.Push(RCHART(' '));
2056 pRange
->m_chars
.Push(RCHART('\t'));
2057 pRange
->m_chars
.Push(RCHART('\r'));
2058 pRange
->m_chars
.Push(RCHART('\n'));
2060 pStockElxs
[nStockId
] = pRange
;
2064 case STOCKELX_SPACE_NOT
:
2066 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 0));
2068 pRange
->m_chars
.Push(RCHART(' '));
2069 pRange
->m_chars
.Push(RCHART('\t'));
2070 pRange
->m_chars
.Push(RCHART('\r'));
2071 pRange
->m_chars
.Push(RCHART('\n'));
2073 pStockElxs
[nStockId
] = pRange
;
2077 case STOCKELX_DIGITAL
:
2079 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 1));
2081 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2083 pStockElxs
[nStockId
] = pRange
;
2087 case STOCKELX_DIGITAL_NOT
:
2089 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (0, 0));
2091 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2093 pStockElxs
[nStockId
] = pRange
;
2097 case STOCKELX_WORD_RIGHTLEFT
:
2099 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 1));
2101 pRange
->m_ranges
.Push(RCHART('A')); pRange
->m_ranges
.Push(RCHART('Z'));
2102 pRange
->m_ranges
.Push(RCHART('a')); pRange
->m_ranges
.Push(RCHART('z'));
2103 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2104 pRange
->m_chars
.Push(RCHART('_'));
2106 pStockElxs
[nStockId
] = pRange
;
2110 case STOCKELX_WORD_RIGHTLEFT_NOT
:
2112 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 0));
2114 pRange
->m_ranges
.Push(RCHART('A')); pRange
->m_ranges
.Push(RCHART('Z'));
2115 pRange
->m_ranges
.Push(RCHART('a')); pRange
->m_ranges
.Push(RCHART('z'));
2116 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2117 pRange
->m_chars
.Push(RCHART('_'));
2119 pStockElxs
[nStockId
] = pRange
;
2123 case STOCKELX_DOT_ALL_RIGHTLEFT
:
2124 pStockElxs
[nStockId
] = Keep(new CRangeElxT
<CHART
> (1, 0));
2127 case STOCKELX_DOT_NOT_ALL_RIGHTLEFT
:
2129 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 0));
2131 pRange
->m_chars
.Push(RCHART('\n'));
2133 pStockElxs
[nStockId
] = pRange
;
2137 case STOCKELX_SPACE_RIGHTLEFT
:
2139 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 1));
2141 pRange
->m_chars
.Push(RCHART(' '));
2142 pRange
->m_chars
.Push(RCHART('\t'));
2143 pRange
->m_chars
.Push(RCHART('\r'));
2144 pRange
->m_chars
.Push(RCHART('\n'));
2145 pRange
->m_chars
.Push(RCHART('\f'));
2146 pRange
->m_chars
.Push(RCHART('\v'));
2148 pStockElxs
[nStockId
] = pRange
;
2152 case STOCKELX_SPACE_RIGHTLEFT_NOT
:
2154 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 0));
2156 pRange
->m_chars
.Push(RCHART(' '));
2157 pRange
->m_chars
.Push(RCHART('\t'));
2158 pRange
->m_chars
.Push(RCHART('\r'));
2159 pRange
->m_chars
.Push(RCHART('\n'));
2160 pRange
->m_chars
.Push(RCHART('\f'));
2161 pRange
->m_chars
.Push(RCHART('\v'));
2163 pStockElxs
[nStockId
] = pRange
;
2167 case STOCKELX_DIGITAL_RIGHTLEFT
:
2169 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 1));
2171 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2173 pStockElxs
[nStockId
] = pRange
;
2177 case STOCKELX_DIGITAL_RIGHTLEFT_NOT
:
2179 CRangeElxT
<CHART
> * pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (1, 0));
2181 pRange
->m_ranges
.Push(RCHART('0')); pRange
->m_ranges
.Push(RCHART('9'));
2183 pStockElxs
[nStockId
] = pRange
;
2190 return pStockElxs
[nStockId
];
2193 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildAlternative(int vaflags
)
2195 if(curr
== CHART_INFO(0, 1))
2196 return GetStockElx(STOCKELX_EMPTY
);
2199 int flags
= vaflags
;
2202 ElxInterface
* pAlternativeOne
= BuildList(flags
);
2204 // check alternative
2205 if(curr
== CHART_INFO(RCHART('|'), 1))
2207 CAlternativeElx
* pAlternative
= (CAlternativeElx
*)Keep(new CAlternativeElx());
2208 pAlternative
->m_elxlist
.Push(pAlternativeOne
);
2211 while(curr
== CHART_INFO(RCHART('|'), 1))
2216 pAlternativeOne
= BuildList(flags
);
2217 pAlternative
->m_elxlist
.Push(pAlternativeOne
);
2220 return pAlternative
;
2223 return pAlternativeOne
;
2226 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildList(int & flags
)
2228 if(curr
== CHART_INFO(0, 1) || curr
== CHART_INFO(RCHART('|'), 1) || curr
== CHART_INFO(RCHART(')'), 1))
2229 return GetStockElx(STOCKELX_EMPTY
);
2232 ElxInterface
* pListOne
= BuildRepeat(flags
);
2234 if(curr
!= CHART_INFO(0, 1) && curr
!= CHART_INFO(RCHART('|'), 1) && curr
!= CHART_INFO(RCHART(')'), 1))
2236 CListElx
* pList
= (CListElx
*)Keep(new CListElx(flags
& RIGHTTOLEFT
));
2237 pList
->m_elxlist
.Push(pListOne
);
2239 while(curr
!= CHART_INFO(0, 1) && curr
!= CHART_INFO(RCHART('|'), 1) && curr
!= CHART_INFO(RCHART(')'), 1))
2241 pListOne
= BuildRepeat(flags
);
2244 pList
->m_elxlist
.Push(pListOne
);
2253 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildRepeat(int & flags
)
2256 ElxInterface
* pSimple
= BuildSimple(flags
);
2258 if(curr
.type
== 0) return pSimple
;
2260 // is quantifier or not
2261 int bIsQuantifier
= 1;
2264 unsigned int nMin
= 0, nMax
= 0;
2276 while(curr
!= CHART_INFO(0, 1) && curr
!= CHART_INFO(RCHART('}'), 1))
2278 re
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2287 char * str
= re
.GetBuffer();
2289 if( ! ReadDec(str
, nMin
) )
2291 else if( *str
!= ',' )
2297 if( ! ReadDec(str
, nMax
) )
2304 if(red
<= 1 ) nMax
= nMin
;
2305 if(red
== 2 ) nMax
= INT_MAX
;
2306 if(nMax
< nMin
) nMax
= nMin
;
2344 return GetStockElx(STOCKELX_EMPTY
);
2349 if(curr
== CHART_INFO(RCHART('?'), 1) || curr
== CHART_INFO(RCHART('+'), 1))
2352 return Keep(new CRepeatElx(pSimple
, nMin
));
2356 if(curr
== CHART_INFO(RCHART('?'), 1))
2359 return Keep(new CReluctantElx(pSimple
, nMin
, nMax
));
2361 else if(curr
== CHART_INFO(RCHART('+'), 1))
2364 return Keep(new CPossessiveElx(pSimple
, nMin
, nMax
));
2368 return Keep(new CGreedyElx(pSimple
, nMin
, nMax
));
2375 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildSimple(int & flags
)
2377 CBufferT
<CHART
> fixed
;
2379 while(curr
!= CHART_INFO(0, 1))
2383 if(next
== CHART_INFO(RCHART('{'), 1) || next
== CHART_INFO(RCHART('?'), 1) || next
== CHART_INFO(RCHART('*'), 1) || next
== CHART_INFO(RCHART('+'), 1))
2385 if(fixed
.GetSize() == 0)
2387 fixed
.Append(curr
.ch
, 1);
2395 fixed
.Append(curr
.ch
, 1);
2399 else if(curr
.type
== 1)
2401 CHART vch
= curr
.ch
;
2404 if(vch
== RCHART(')') || vch
== RCHART('|'))
2407 // has fixed already
2408 if(fixed
.GetSize() > 0)
2412 if(vch
== RCHART('('))
2414 return BuildRecursive(flags
);
2418 if( vch
== RCHART('[') || vch
== RCHART('.') || vch
== RCHART('w') || vch
== RCHART('W') ||
2419 vch
== RCHART('s') || vch
== RCHART('S') || vch
== RCHART('d') || vch
== RCHART('D')
2422 return BuildCharset(flags
);
2426 if( vch
== RCHART('^') || vch
== RCHART('$') || vch
== RCHART('A') || vch
== RCHART('Z') ||
2427 vch
== RCHART('b') || vch
== RCHART('B') || vch
== RCHART('G') // vch == RCHART('<') || vch == RCHART('>')
2430 return BuildBoundary(flags
);
2434 if(vch
== RCHART('\\') || vch
== RCHART('k') || vch
== RCHART('g'))
2436 return BuildBackref(flags
);
2439 // treat vchar as char
2440 fixed
.Append(curr
.ch
, 1);
2445 if(fixed
.GetSize() > 0)
2446 return Keep(new CStringElxT
<CHART
> (fixed
.GetBuffer(), fixed
.GetSize(), flags
& RIGHTTOLEFT
, flags
& IGNORECASE
));
2448 return GetStockElx(STOCKELX_EMPTY
);
2451 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildCharset(int & flags
)
2463 flags
& RIGHTTOLEFT
?
2464 ((flags
& SINGLELINE
) ? STOCKELX_DOT_ALL_RIGHTLEFT
: STOCKELX_DOT_NOT_ALL_RIGHTLEFT
) :
2465 ((flags
& SINGLELINE
) ? STOCKELX_DOT_ALL
: STOCKELX_DOT_NOT_ALL
)
2469 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_WORD_RIGHTLEFT
: STOCKELX_WORD
);
2472 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_WORD_RIGHTLEFT_NOT
: STOCKELX_WORD_NOT
);
2475 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_SPACE_RIGHTLEFT
: STOCKELX_SPACE
);
2478 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_SPACE_RIGHTLEFT_NOT
: STOCKELX_SPACE_NOT
);
2481 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_DIGITAL_RIGHTLEFT
: STOCKELX_DIGITAL
);
2484 return GetStockElx(flags
& RIGHTTOLEFT
? STOCKELX_DIGITAL_RIGHTLEFT_NOT
: STOCKELX_DIGITAL_NOT
);
2488 CRangeElxT
<CHART
> * pRange
;
2491 if(curr
== CHART_INFO(RCHART(':'), 1))
2493 CBufferT
<char> posix
;
2496 posix
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2499 while(curr
.ch
!= RCHART(0) && curr
!= CHART_INFO(RCHART(']'), 1));
2501 MoveNext(); // skip ']'
2504 return Keep(new CPosixElxT
<CHART
> (posix
.GetBuffer(), flags
& RIGHTTOLEFT
));
2506 else if(curr
== CHART_INFO(RCHART('^'), 1))
2508 MoveNext(); // skip '^'
2509 pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (flags
& RIGHTTOLEFT
, 0));
2513 pRange
= (CRangeElxT
<CHART
> *)Keep(new CRangeElxT
<CHART
> (flags
& RIGHTTOLEFT
, 1));
2517 while(curr
!= CHART_INFO(0, 1) && curr
!= CHART_INFO(RCHART(']'), 1))
2521 if(curr
.type
== 1 && (
2522 ch
== RCHART('.') || ch
== RCHART('w') || ch
== RCHART('W') || ch
== RCHART('s') || ch
== RCHART('S') || ch
== RCHART('d') || ch
== RCHART('D') ||
2523 (ch
== RCHART('[') && next
== CHART_INFO(RCHART(':'), 1))
2526 pRange
->m_embeds
.Push(BuildCharset(flags
));
2528 else if(next
== CHART_INFO(RCHART('-'), 1) && nex2
.type
== 0)
2530 pRange
->m_ranges
.Push(ch
); pRange
->m_ranges
.Push(nex2
.ch
);
2539 pRange
->m_chars
.Push(ch
);
2553 return GetStockElx(STOCKELX_EMPTY
);
2556 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildRecursive(int & flags
)
2561 if(curr
== CHART_INFO(RCHART('?'), 1))
2563 ElxInterface
* pElx
= 0;
2569 CHART named_end
= RCHART('>');
2578 MoveNext(); // skip '!' or '='
2579 pElx
= Keep(new CAssertElx(BuildAlternative(flags
& ~RIGHTTOLEFT
), !bNegative
));
2590 MoveNext(); // skip '<'
2591 MoveNext(); // skip '!' or '='
2593 pElx
= Keep(new CAssertElx(BuildAlternative(flags
| RIGHTTOLEFT
), !bNegative
));
2597 default: // named group
2600 // break if assertion // else named
2601 if(pElx
!= 0) break;
2604 if(curr
.ch
== RCHART('P')) MoveNext(); // skip 'P'
2607 if (curr
.ch
== RCHART('<' )) named_end
= RCHART('>' );
2608 else if(curr
.ch
== RCHART('\'')) named_end
= RCHART('\'');
2609 MoveNext(); // skip '<' or '\''
2612 int nThisBackref
= m_nNextNamed
++;
2614 CListElx
* pList
= (CListElx
*)Keep(new CListElx(flags
& RIGHTTOLEFT
));
2615 CBracketElx
* pleft
= (CBracketElx
*)Keep(new CBracketElx(-1, flags
& RIGHTTOLEFT
? 1 : 0));
2616 CBracketElx
* pright
= (CBracketElx
*)Keep(new CBracketElx(-1, flags
& RIGHTTOLEFT
? 0 : 1));
2619 CBufferT
<CHART
> & name
= pleft
->m_szNamed
;
2620 CBufferT
<char> num
;
2622 while(curr
.ch
!= RCHART(0) && curr
.ch
!= named_end
)
2624 name
.Append(curr
.ch
, 1);
2625 num
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2628 MoveNext(); // skip '>' or '\''
2631 unsigned int number
;
2632 char * str
= num
.GetBuffer();
2634 if( ReadDec(str
, number
) ? ( *str
== '\0') : 0 )
2636 pleft
->m_nnumber
= number
;
2637 pright
->m_nnumber
= number
;
2642 // left, center, right
2643 pList
->m_elxlist
.Push(pleft
);
2644 pList
->m_elxlist
.Push(BuildAlternative(flags
));
2645 pList
->m_elxlist
.Push(pright
);
2648 m_namedlist
.Prepare(nThisBackref
);
2649 m_namedlist
[nThisBackref
] = pList
;
2657 MoveNext(); // skip '>'
2658 pElx
= Keep(new CIndependentElx(BuildAlternative(flags
)));
2663 MoveNext(); // skip 'R'
2664 while(curr
.ch
!= RCHART(0) && isspace(curr
.ch
)) MoveNext(); // skip space
2666 if(curr
.ch
== RCHART('<') || curr
.ch
== RCHART('\''))
2668 named_end
= curr
.ch
== RCHART('<') ? RCHART('>') : RCHART('\'');
2669 CDelegateElx
* pDelegate
= (CDelegateElx
*)Keep(new CDelegateElx(-3));
2671 MoveNext(); // skip '<' or '\\'
2674 CBufferT
<CHART
> & name
= pDelegate
->m_szNamed
;
2675 CBufferT
<char> num
;
2677 while(curr
.ch
!= RCHART(0) && curr
.ch
!= named_end
)
2679 name
.Append(curr
.ch
, 1);
2680 num
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2683 MoveNext(); // skip '>' or '\''
2686 unsigned int number
;
2687 char * str
= num
.GetBuffer();
2689 if( ReadDec(str
, number
) ? ( *str
== '\0') : 0 )
2691 pDelegate
->m_ndata
= number
;
2695 m_recursivelist
.Push(pDelegate
);
2700 CBufferT
<char> rto
;
2701 while(curr
.ch
!= RCHART(0) && curr
.ch
!= RCHART(')'))
2703 rto
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2707 unsigned int rtono
= 0;
2708 char * str
= rto
.GetBuffer();
2709 ReadDec(str
, rtono
);
2711 CDelegateElx
* pDelegate
= (CDelegateElx
*)Keep(new CDelegateElx(rtono
));
2713 m_recursivelist
.Push(pDelegate
);
2720 CConditionElx
* pConditionElx
= (CConditionElx
*)Keep(new CConditionElx());
2723 ElxInterface
* & pCondition
= pConditionElx
->m_pelxask
;
2725 if(next
== CHART_INFO(RCHART('?'), 1))
2727 pCondition
= BuildRecursive(flags
);
2729 else // named, assert or number
2731 MoveNext(); // skip '('
2732 int pos0
= curr
.pos
;
2734 // save elx condition
2735 pCondition
= Keep(new CAssertElx(BuildAlternative(flags
), 1));
2738 pConditionElx
->m_szNamed
.Append(m_pattern
.GetBuffer() + pos0
, curr
.pos
- pos0
, 1);
2741 CBufferT
<char> numstr
;
2742 while(pos0
< curr
.pos
)
2744 CHART ch
= m_pattern
[pos0
];
2745 numstr
.Append(((ch
& (CHART
)0xff) == ch
) ? (char)ch
: 0, 1);
2749 unsigned int number
;
2750 char * str
= numstr
.GetBuffer();
2752 // valid group number
2753 if( ReadDec(str
, number
) ? ( *str
== '\0') : 0 )
2755 pConditionElx
->m_nnumber
= number
;
2758 else // maybe elx, maybe named
2760 pConditionElx
->m_nnumber
= -1;
2761 m_namedconditionlist
.Push(pConditionElx
);
2764 MoveNext(); // skip ')'
2769 int newflags
= flags
;
2771 pConditionElx
->m_pelxyes
= BuildList(newflags
);
2774 if(curr
.ch
== RCHART('|'))
2776 MoveNext(); // skip '|'
2778 pConditionElx
->m_pelxno
= BuildAlternative(flags
);
2782 pConditionElx
->m_pelxno
= 0;
2785 pElx
= pConditionElx
;
2790 while(curr
.ch
!= RCHART(0) && isspace(curr
.ch
)) MoveNext(); // skip space
2792 if(curr
.ch
>= RCHART('0') && curr
.ch
<= RCHART('9')) // recursive (?1) => (?R1)
2794 CBufferT
<char> rto
;
2795 while(curr
.ch
!= RCHART(0) && curr
.ch
!= RCHART(')'))
2797 rto
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2801 unsigned int rtono
= 0;
2802 char * str
= rto
.GetBuffer();
2803 ReadDec(str
, rtono
);
2805 CDelegateElx
* pDelegate
= (CDelegateElx
*)Keep(new CDelegateElx(rtono
));
2807 m_recursivelist
.Push(pDelegate
);
2813 int newflags
= flags
;
2814 while(curr
!= CHART_INFO(0, 1) && curr
.ch
!= RCHART(':') && curr
.ch
!= RCHART(')') && curr
!= CHART_INFO(RCHART('('), 1))
2822 tochange
= IGNORECASE
;
2827 tochange
= SINGLELINE
;
2832 tochange
= MULTILINE
;
2846 newflags
&= ~tochange
;
2848 newflags
|= tochange
;
2850 // move to next char
2854 if(curr
.ch
== RCHART(':') || curr
== CHART_INFO(RCHART('('), 1))
2857 if(curr
.ch
== RCHART(':')) MoveNext();
2859 pElx
= BuildAlternative(newflags
);
2863 // change parent flags
2866 pElx
= GetStockElx(STOCKELX_EMPTY
);
2872 MoveNext(); // skip ')'
2879 CListElx
* pList
= (CListElx
*)Keep(new CListElx(flags
& RIGHTTOLEFT
));
2880 int nThisBackref
= ++ m_nMaxNumber
;
2882 // left, center, right
2883 pList
->m_elxlist
.Push(Keep(new CBracketElx(nThisBackref
, flags
& RIGHTTOLEFT
? 1 : 0)));
2884 pList
->m_elxlist
.Push(BuildAlternative(flags
));
2885 pList
->m_elxlist
.Push(Keep(new CBracketElx(nThisBackref
, flags
& RIGHTTOLEFT
? 0 : 1)));
2888 m_grouplist
.Prepare(nThisBackref
);
2889 m_grouplist
[nThisBackref
] = pList
;
2892 MoveNext(); // skip ')'
2898 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildBoundary(int & flags
)
2909 return Keep(new CBoundaryElxT
<CHART
> ((flags
& MULTILINE
) ? BOUNDARY_LINE_BEGIN
: BOUNDARY_FILE_BEGIN
));
2912 return Keep(new CBoundaryElxT
<CHART
> ((flags
& MULTILINE
) ? BOUNDARY_LINE_END
: BOUNDARY_FILE_END
));
2915 return Keep(new CBoundaryElxT
<CHART
> (BOUNDARY_WORD_EDGE
));
2918 return Keep(new CBoundaryElxT
<CHART
> (BOUNDARY_WORD_EDGE
, 0));
2921 return Keep(new CBoundaryElxT
<CHART
> (BOUNDARY_FILE_BEGIN
));
2924 return Keep(new CBoundaryElxT
<CHART
> (BOUNDARY_FILE_END
));
2928 return Keep(new CGlobalElx());
2930 return GetStockElx(STOCKELX_EMPTY
);
2933 return GetStockElx(STOCKELX_EMPTY
);
2937 template <class CHART
> ElxInterface
* CBuilderT
<CHART
> :: BuildBackref(int & flags
)
2939 // skip '\\' or '\k' or '\g'
2942 if(curr
.ch
== RCHART('<') || curr
.ch
== RCHART('\''))
2944 CHART named_end
= curr
.ch
== RCHART('<') ? RCHART('>') : RCHART('\'');
2945 CBackrefElxT
<CHART
> * pbackref
= (CBackrefElxT
<CHART
> *)Keep(new CBackrefElxT
<CHART
> (-1, flags
& RIGHTTOLEFT
, flags
& IGNORECASE
));
2947 MoveNext(); // skip '<' or '\''
2950 CBufferT
<CHART
> & name
= pbackref
->m_szNamed
;
2951 CBufferT
<char> num
;
2953 while(curr
.ch
!= RCHART(0) && curr
.ch
!= named_end
)
2955 name
.Append(curr
.ch
, 1);
2956 num
.Append(((curr
.ch
& (CHART
)0xff) == curr
.ch
) ? (char)curr
.ch
: 0, 1);
2959 MoveNext(); // skip '>' or '\''
2962 unsigned int number
;
2963 char * str
= num
.GetBuffer();
2965 if( ReadDec(str
, number
) ? ( *str
== '\0') : 0 )
2967 pbackref
->m_nnumber
= number
;
2972 m_namedbackreflist
.Push(pbackref
);
2979 unsigned int nbackref
= 0;
2981 for(int i
=0; i
<3; i
++)
2983 if(curr
.ch
>= RCHART('0') && curr
.ch
<= RCHART('9'))
2984 nbackref
= nbackref
* 10 + (curr
.ch
- RCHART('0'));
2991 return Keep(new CBackrefElxT
<CHART
> (nbackref
, flags
& RIGHTTOLEFT
, flags
& IGNORECASE
));
2995 template <class CHART
> int CBuilderT
<CHART
> :: ReadDec(char * & str
, unsigned int & dec
)
2998 while(str
[s
] != 0 && isspace(str
[s
])) s
++;
3000 if(str
[s
] < '0' || str
[s
] > '9') return 0;
3005 for(i
= s
; i
<sizeof(CHART
)*3 + s
; i
++)
3007 if(str
[i
] >= '0' && str
[i
] <= '9')
3008 dec
= dec
* 10 + (str
[i
] - '0');
3013 while(str
[i
] != 0 && isspace(str
[i
])) i
++;
3022 template <class CHART
> class CRegexpT
3025 CRegexpT(const CHART
* pattern
= 0, int flags
= 0);
3026 CRegexpT(const CHART
* pattern
, int length
, int flags
);
3027 void Compile(const CHART
* pattern
, int flags
= 0);
3028 void Compile(const CHART
* pattern
, int length
, int flags
);
3031 MatchResult
MatchExact(const CHART
* tstring
, CContext
* pContext
= 0) const;
3032 MatchResult
MatchExact(const CHART
* tstring
, int length
, CContext
* pContext
= 0) const;
3033 MatchResult
Match(const CHART
* tstring
, int start
= -1, CContext
* pContext
= 0) const;
3034 MatchResult
Match(const CHART
* tstring
, int length
, int start
, CContext
* pContext
= 0) const;
3035 MatchResult
Match(CContext
* pContext
) const;
3036 CContext
* PrepareMatch(const CHART
* tstring
, int start
= -1, CContext
* pContext
= 0) const;
3037 CContext
* PrepareMatch(const CHART
* tstring
, int length
, int start
, CContext
* pContext
= 0) const;
3038 CHART
* Replace(const CHART
* tstring
, const CHART
* replaceto
, int start
= -1, int ntimes
= -1, MatchResult
* result
= 0, CContext
* pContext
= 0) const;
3039 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;
3040 int GetNamedGroupNumber(const CHART
* group_name
) const;
3043 static void ReleaseString (CHART
* tstring
);
3044 static void ReleaseContext(CContext
* pContext
);
3047 CBuilderT
<CHART
> m_builder
;
3053 template <class CHART
> CRegexpT
<CHART
> :: CRegexpT(const CHART
* pattern
, int flags
)
3055 Compile(pattern
, CBufferRefT
<CHART
>(pattern
).GetSize(), flags
);
3058 template <class CHART
> CRegexpT
<CHART
> :: CRegexpT(const CHART
* pattern
, int length
, int flags
)
3060 Compile(pattern
, length
, flags
);
3063 template <class CHART
> inline void CRegexpT
<CHART
> :: Compile(const CHART
* pattern
, int flags
)
3065 Compile(pattern
, CBufferRefT
<CHART
>(pattern
).GetSize(), flags
);
3068 template <class CHART
> void CRegexpT
<CHART
> :: Compile(const CHART
* pattern
, int length
, int flags
)
3071 if(pattern
!= 0) m_builder
.Build(CBufferRefT
<CHART
>(pattern
, length
), flags
);
3074 template <class CHART
> inline MatchResult CRegexpT
<CHART
> :: MatchExact(const CHART
* tstring
, CContext
* pContext
) const
3076 return MatchExact(tstring
, CBufferRefT
<CHART
>(tstring
).GetSize(), pContext
);
3079 template <class CHART
> MatchResult CRegexpT
<CHART
> :: MatchExact(const CHART
* tstring
, int length
, CContext
* pContext
) const
3081 if(m_builder
.m_pTopElx
== 0)
3088 if(pContext
== 0) pContext
= &context
;
3090 pContext
->m_stack
.Restore(0);
3091 pContext
->m_capturestack
.Restore(0);
3092 pContext
->m_captureindex
.Restore(0);
3094 pContext
->m_nParenZindex
= 0;
3095 pContext
->m_nLastBeginPos
= -1;
3096 pContext
->m_pMatchString
= (void*)tstring
;
3097 pContext
->m_pMatchStringLength
= length
;
3099 if(m_builder
.m_nFlags
& RIGHTTOLEFT
)
3101 pContext
->m_nBeginPos
= length
;
3102 pContext
->m_nCurrentPos
= length
;
3107 pContext
->m_nBeginPos
= 0;
3108 pContext
->m_nCurrentPos
= 0;
3112 pContext
->m_captureindex
.Prepare(m_builder
.m_nMaxNumber
, -1);
3113 pContext
->m_captureindex
[0] = 0;
3114 pContext
->m_capturestack
.Push(0);
3115 pContext
->m_capturestack
.Push(pContext
->m_nCurrentPos
);
3116 pContext
->m_capturestack
.Push(-1);
3117 pContext
->m_capturestack
.Push(-1);
3120 if( ! m_builder
.m_pTopElx
->Match( pContext
) )
3124 while( pContext
->m_nCurrentPos
!= endpos
)
3126 if( ! m_builder
.m_pTopElx
->MatchNext( pContext
) )
3130 if( pContext
->m_nLastBeginPos
== pContext
->m_nBeginPos
&& pContext
->m_nBeginPos
== pContext
->m_nCurrentPos
)
3133 pContext
->m_nLastBeginPos
= pContext
->m_nCurrentPos
;
3138 pContext
->m_capturestack
[2] = pContext
->m_nCurrentPos
;
3140 return MatchResult( pContext
, m_builder
.m_nMaxNumber
);
3144 template <class CHART
> MatchResult CRegexpT
<CHART
> :: Match(const CHART
* tstring
, int start
, CContext
* pContext
) const
3146 return Match(tstring
, CBufferRefT
<CHART
>(tstring
).GetSize(), start
, pContext
);
3149 template <class CHART
> MatchResult CRegexpT
<CHART
> :: Match(const CHART
* tstring
, int length
, int start
, CContext
* pContext
) const
3151 if(m_builder
.m_pTopElx
== 0)
3155 if(pContext
== 0) pContext
= &context
;
3157 pContext
->m_nParenZindex
= 0;
3158 pContext
->m_nLastBeginPos
= -1;
3159 pContext
->m_pMatchString
= (void*)tstring
;
3160 pContext
->m_pMatchStringLength
= length
;
3164 if(m_builder
.m_nFlags
& RIGHTTOLEFT
)
3166 pContext
->m_nBeginPos
= length
;
3167 pContext
->m_nCurrentPos
= length
;
3171 pContext
->m_nBeginPos
= 0;
3172 pContext
->m_nCurrentPos
= 0;
3177 pContext
->m_nBeginPos
= start
;
3178 pContext
->m_nCurrentPos
= start
;
3181 return Match( pContext
);
3184 template <class CHART
> MatchResult CRegexpT
<CHART
> :: Match(CContext
* pContext
) const
3186 if(m_builder
.m_pTopElx
== 0)
3191 if(m_builder
.m_nFlags
& RIGHTTOLEFT
)
3198 endpos
= pContext
->m_pMatchStringLength
+ 1;
3202 while(pContext
->m_nCurrentPos
!= endpos
)
3204 pContext
->m_captureindex
.Restore(0);
3205 pContext
->m_stack
.Restore(0);
3206 pContext
->m_capturestack
.Restore(0);
3208 pContext
->m_captureindex
.Prepare(m_builder
.m_nMaxNumber
, -1);
3209 pContext
->m_captureindex
[0] = 0;
3210 pContext
->m_capturestack
.Push(0);
3211 pContext
->m_capturestack
.Push(pContext
->m_nCurrentPos
);
3212 pContext
->m_capturestack
.Push(-1);
3213 pContext
->m_capturestack
.Push(-1);
3215 if( m_builder
.m_pTopElx
->Match( pContext
) )
3218 if( pContext
->m_nLastBeginPos
== pContext
->m_nBeginPos
&& pContext
->m_nBeginPos
== pContext
->m_nCurrentPos
)
3220 pContext
->m_nCurrentPos
+= delta
;
3225 pContext
->m_nLastBeginPos
= pContext
->m_nBeginPos
;
3226 pContext
->m_nBeginPos
= pContext
->m_nCurrentPos
;
3227 pContext
->m_capturestack
[2] = pContext
->m_nCurrentPos
;
3230 return MatchResult( pContext
, m_builder
.m_nMaxNumber
);
3234 pContext
->m_nCurrentPos
+= delta
;
3241 template <class CHART
> inline CContext
* CRegexpT
<CHART
> :: PrepareMatch(const CHART
* tstring
, int start
, CContext
* pContext
) const
3243 return PrepareMatch(tstring
, CBufferRefT
<CHART
>(tstring
).GetSize(), start
, pContext
);
3246 template <class CHART
> CContext
* CRegexpT
<CHART
> :: PrepareMatch(const CHART
* tstring
, int length
, int start
, CContext
* pContext
) const
3248 if(m_builder
.m_pTopElx
== 0)
3251 if(pContext
== 0) pContext
= new CContext();
3253 pContext
->m_nParenZindex
= 0;
3254 pContext
->m_nLastBeginPos
= -1;
3255 pContext
->m_pMatchString
= (void*)tstring
;
3256 pContext
->m_pMatchStringLength
= length
;
3260 if(m_builder
.m_nFlags
& RIGHTTOLEFT
)
3262 pContext
->m_nBeginPos
= length
;
3263 pContext
->m_nCurrentPos
= length
;
3267 pContext
->m_nBeginPos
= 0;
3268 pContext
->m_nCurrentPos
= 0;
3273 pContext
->m_nBeginPos
= start
;
3274 pContext
->m_nCurrentPos
= start
;
3280 template <class CHART
> inline int CRegexpT
<CHART
> :: GetNamedGroupNumber(const CHART
* group_name
) const
3282 return m_builder
.GetNamedNumber(group_name
);
3285 template <class CHART
> CHART
* CRegexpT
<CHART
> :: Replace(const CHART
* tstring
, const CHART
* replaceto
, int start
, int ntimes
, MatchResult
* result
, CContext
* pContext
) const
3287 int result_length
= 0;
3288 return Replace(tstring
, CBufferRefT
<CHART
>(tstring
).GetSize(), replaceto
, CBufferRefT
<CHART
>(replaceto
).GetSize(), result_length
, start
, ntimes
, result
, pContext
);
3291 template <class CHART
> CHART
* CRegexpT
<CHART
> :: Replace(const CHART
* tstring
, int string_length
, const CHART
* replaceto
, int to_length
, int & result_length
, int start
, int ntimes
, MatchResult
* remote_result
, CContext
* oContext
) const
3293 typedef CBufferRefT
<CHART
> StringRef
;
3295 MatchResult
local_result(0), * result
= remote_result
? remote_result
: & local_result
;
3297 if(m_builder
.m_pTopElx
== 0) return 0;
3300 CContext
* pContext
= PrepareMatch(tstring
, string_length
, start
, oContext
);
3302 int flags
= m_builder
.m_nFlags
;
3303 int lastIndex
= (flags
& RIGHTTOLEFT
) ? string_length
: 0;
3304 int endpos
= (flags
& RIGHTTOLEFT
) ? 0 : string_length
;
3305 int toIndex
= 0, toLastIndex
= 0;
3308 CBufferT
<StringRef
*> buffer
, buf
;
3310 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') };
3311 static int rtoptnlen
= StringRef(rtoptn
).GetSize();
3312 static CRegexpT
<CHART
> rtoreg(rtoptn
, rtoptnlen
, 0);
3315 for(ntime
= 0; ntimes
< 0 || ntime
< ntimes
; ntime
++)
3317 (*result
) = Match(pContext
);
3319 if( ! result
->IsMatched() )
3322 toIndex
= toLastIndex
;
3325 if( flags
& RIGHTTOLEFT
)
3327 int distance
= lastIndex
- result
->GetEnd();
3330 buffer
.Push(new StringRef(tstring
+ result
->GetEnd(), distance
));
3331 toIndex
-= distance
;
3333 lastIndex
= result
->GetStart();
3337 int distance
= result
->GetStart() - lastIndex
;
3340 buffer
.Push(new StringRef(tstring
+ lastIndex
, distance
));
3341 toIndex
+= distance
;
3343 lastIndex
= result
->GetEnd();
3346 toLastIndex
= toIndex
;
3349 CContext
* pCtx
= rtoreg
.PrepareMatch(replaceto
, to_length
, -1);
3356 MatchResult res
= rtoreg
.Match(pCtx
);
3358 if( ! res
.IsMatched() )
3362 int distance
= res
.GetStart() - lastI
;
3365 buf
.Push(new StringRef(replaceto
+ lastI
, distance
));
3367 lastI
= res
.GetStart();
3370 int delta
= 2, nmatch
= 0;
3372 switch(replaceto
[res
.GetStart() + 1])
3375 buf
.Push(new StringRef(rtoptn
+ 1, 1)); // '$' itself
3379 buf
.Push(new StringRef(tstring
+ result
->GetStart(), result
->GetEnd() - result
->GetStart()));
3383 buf
.Push(new StringRef(tstring
, result
->GetStart()));
3387 buf
.Push(new StringRef(tstring
+ result
->GetEnd(), string_length
- result
->GetEnd()));
3391 for(nmatch
= result
->MaxGroupNumber(); nmatch
>= 0; nmatch
--)
3393 if(result
->GetGroupStart(nmatch
) >= 0) break;
3395 buf
.Push(new StringRef(tstring
+ result
->GetGroupStart(nmatch
), result
->GetGroupEnd(nmatch
) - result
->GetGroupStart(nmatch
)));
3399 buf
.Push(new StringRef(tstring
, string_length
));
3403 delta
= res
.GetEnd() - res
.GetStart();
3404 nmatch
= m_builder
.GetNamedNumber(StringRef(replaceto
+ (res
.GetStart() + 2), delta
- 3));
3406 if(nmatch
> 0 && nmatch
<= m_builder
.m_nMaxNumber
)
3407 buf
.Push(new StringRef(tstring
+ result
->GetGroupStart(nmatch
), result
->GetGroupEnd(nmatch
) - result
->GetGroupStart(nmatch
)));
3409 buf
.Push(new StringRef(replaceto
+ res
.GetStart(), delta
));
3414 for(delta
=1; delta
<=3; delta
++)
3416 CHART ch
= replaceto
[lastI
+ delta
];
3418 if(ch
< RCHART('0') || ch
> RCHART('9'))
3421 nmatch
= nmatch
* 10 + (ch
- RCHART('0'));
3424 if(nmatch
> m_builder
.m_nMaxNumber
)
3426 while(nmatch
> m_builder
.m_nMaxNumber
)
3439 buf
.Push(new StringRef(rtoptn
+ 1, 1)); // '$' itself
3441 buf
.Push(new StringRef(tstring
+ result
->GetGroupStart(nmatch
), result
->GetGroupEnd(nmatch
) - result
->GetGroupStart(nmatch
)));
3449 if(lastI
< to_length
)
3450 buf
.Push(new StringRef(replaceto
+ lastI
, to_length
- lastI
));
3453 if(flags
& RIGHTTOLEFT
)
3455 for(i
=buf
.GetSize()-1; i
>=0; i
--)
3457 buffer
.Push(buf
[i
]);
3458 toLastIndex
-= buf
[i
]->GetSize();
3463 for(i
=0; i
<buf
.GetSize(); i
++)
3465 buffer
.Push(buf
[i
]);
3466 toLastIndex
+= buf
[i
]->GetSize();
3470 rtoreg
.ReleaseContext(pCtx
);
3474 if(flags
& RIGHTTOLEFT
)
3476 if(endpos
< lastIndex
) buffer
.Push(new StringRef(tstring
+ endpos
, lastIndex
- endpos
));
3480 if(lastIndex
< endpos
) buffer
.Push(new StringRef(tstring
+ lastIndex
, endpos
- lastIndex
));
3483 if(oContext
== 0) ReleaseContext(pContext
);
3487 for(i
=0; i
<buffer
.GetSize(); i
++) result_length
+= buffer
[i
]->GetSize();
3489 CBufferT
<CHART
> result_string
;
3490 result_string
.Prepare(result_length
);
3491 result_string
.Restore(0);
3493 if(flags
& RIGHTTOLEFT
)
3495 for(i
=buffer
.GetSize()-1; i
>=0; i
--)
3497 result_string
.Append(buffer
[i
]->GetBuffer(), buffer
[i
]->GetSize());
3503 for(i
=0; i
<buffer
.GetSize(); i
++)
3505 result_string
.Append(buffer
[i
]->GetBuffer(), buffer
[i
]->GetSize());
3510 result_string
[result_length
] = 0;
3512 result
->m_result
.Append(toIndex
< toLastIndex
? toIndex
: toLastIndex
, 2);
3513 result
->m_result
.Append(toIndex
> toLastIndex
? toIndex
: toLastIndex
);
3514 result
->m_result
.Append(ntime
);
3516 return result_string
.Detach();
3519 template <class CHART
> inline void CRegexpT
<CHART
> :: ReleaseString(CHART
* tstring
)
3521 if(tstring
!= 0) delete [] tstring
;
3524 template <class CHART
> inline void CRegexpT
<CHART
> :: ReleaseContext(CContext
* pContext
)
3526 if(pContext
!= 0) delete pContext
;
3530 // All implementations
3532 template <int x
> CAlternativeElxT
<x
> :: CAlternativeElxT()
3536 template <int x
> int CAlternativeElxT
<x
> :: Match(CContext
* pContext
) const
3538 if(m_elxlist
.GetSize() == 0)
3542 for(int n
= 0; n
< m_elxlist
.GetSize(); n
++)
3544 if(m_elxlist
[n
]->Match(pContext
))
3546 pContext
->m_stack
.Push(n
);
3554 template <int x
> int CAlternativeElxT
<x
> :: MatchNext(CContext
* pContext
) const
3556 if(m_elxlist
.GetSize() == 0)
3562 pContext
->m_stack
.Pop(n
);
3565 if(m_elxlist
[n
]->MatchNext(pContext
))
3567 pContext
->m_stack
.Push(n
);
3573 for(n
++; n
< m_elxlist
.GetSize(); n
++)
3575 if(m_elxlist
[n
]->Match(pContext
))
3577 pContext
->m_stack
.Push(n
);
3586 // assertx.cpp: implementation of the CAssertElx class.
3588 template <int x
> CAssertElxT
<x
> :: CAssertElxT(ElxInterface
* pelx
, int byes
)
3594 template <int x
> int CAssertElxT
<x
> :: Match(CContext
* pContext
) const
3596 int nbegin
= pContext
->m_nCurrentPos
;
3597 int nsize
= pContext
->m_stack
.GetSize();
3598 int ncsize
= pContext
->m_capturestack
.GetSize();
3603 bsucc
= m_pelx
->Match(pContext
);
3605 bsucc
= ! m_pelx
->Match(pContext
);
3608 pContext
->m_stack
.Restore(nsize
);
3609 pContext
->m_nCurrentPos
= nbegin
;
3612 pContext
->m_stack
.Push(ncsize
);
3614 pContext
->m_capturestack
.Restore(ncsize
);
3619 template <int x
> int CAssertElxT
<x
> :: MatchNext(CContext
* pContext
) const
3623 pContext
->m_stack
.Pop(ncsize
);
3624 pContext
->m_capturestack
.Restore(ncsize
);
3629 // emptyelx.cpp: implementation of the CEmptyElx class.
3631 template <int x
> CEmptyElxT
<x
> :: CEmptyElxT()
3635 template <int x
> int CEmptyElxT
<x
> :: Match(CContext
*) const
3640 template <int x
> int CEmptyElxT
<x
> :: MatchNext(CContext
*) const
3645 // globalx.cpp: implementation of the CGlobalElx class.
3647 template <int x
> CGlobalElxT
<x
> ::CGlobalElxT()
3651 template <int x
> int CGlobalElxT
<x
> :: Match(CContext
* pContext
) const
3653 return pContext
->m_nCurrentPos
== pContext
->m_nBeginPos
;
3656 template <int x
> int CGlobalElxT
<x
> :: MatchNext(CContext
*) const
3661 // greedelx.cpp: implementation of the CGreedyElx class.
3663 template <int x
> CGreedyElxT
<x
> :: CGreedyElxT(ElxInterface
* pelx
, int nmin
, int nmax
) : CRepeatElxT
<x
> (pelx
, nmin
)
3665 m_nvart
= nmax
- nmin
;
3668 template <int x
> int CGreedyElxT
<x
> :: Match(CContext
* pContext
) const
3670 if( ! CRepeatElxT
<x
> :: MatchFixed(pContext
) )
3673 while( ! MatchVart(pContext
) )
3675 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
3682 template <int x
> int CGreedyElxT
<x
> :: MatchNext(CContext
* pContext
) const
3684 if( MatchNextVart(pContext
) )
3687 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
3690 while( ! MatchVart(pContext
) )
3692 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
3699 template <int x
> int CGreedyElxT
<x
> :: MatchVart(CContext
* pContext
) const
3702 int nbegin
= pContext
->m_nCurrentPos
;
3704 while(n
< m_nvart
&& CRepeatElxT
<x
> :: m_pelx
->Match(pContext
))
3706 while(pContext
->m_nCurrentPos
== nbegin
)
3708 if( ! CRepeatElxT
<x
> :: m_pelx
->MatchNext(pContext
) ) break;
3711 if(pContext
->m_nCurrentPos
== nbegin
) break;
3714 nbegin
= pContext
->m_nCurrentPos
;
3717 pContext
->m_stack
.Push(n
);
3722 template <int x
> int CGreedyElxT
<x
> :: MatchNextVart(CContext
* pContext
) const
3725 pContext
->m_stack
.Pop(n
);
3727 if(n
== 0) return 0;
3729 if( ! CRepeatElxT
<x
> :: m_pelx
->MatchNext(pContext
) )
3734 pContext
->m_stack
.Push(n
);
3739 // indepelx.cpp: implementation of the CIndependentElx class.
3741 template <int x
> CIndependentElxT
<x
> :: CIndependentElxT(ElxInterface
* pelx
)
3746 template <int x
> int CIndependentElxT
<x
> :: Match(CContext
* pContext
) const
3748 int nbegin
= pContext
->m_nCurrentPos
;
3749 int nsize
= pContext
->m_stack
.GetSize();
3750 int ncsize
= pContext
->m_capturestack
.GetSize();
3753 int bsucc
= m_pelx
->Match(pContext
);
3756 pContext
->m_stack
.Restore(nsize
);
3760 pContext
->m_stack
.Push(nbegin
);
3761 pContext
->m_stack
.Push(ncsize
);
3767 template <int x
> int CIndependentElxT
<x
> :: MatchNext(CContext
* pContext
) const
3769 int nbegin
= 0, ncsize
= 0;
3771 pContext
->m_stack
.Pop(ncsize
);
3772 pContext
->m_stack
.Pop(nbegin
);
3774 pContext
->m_capturestack
.Restore(ncsize
);
3775 pContext
->m_nCurrentPos
= nbegin
;
3780 // listelx.cpp: implementation of the CListElx class.
3782 template <int x
> CListElxT
<x
> :: CListElxT(int brightleft
)
3784 m_brightleft
= brightleft
;
3787 template <int x
> int CListElxT
<x
> :: Match(CContext
* pContext
) const
3789 if(m_elxlist
.GetSize() == 0)
3793 int bol
= m_brightleft
? m_elxlist
.GetSize() : -1;
3794 int stp
= m_brightleft
? -1 : 1;
3795 int eol
= m_brightleft
? -1 : m_elxlist
.GetSize();
3803 if(m_elxlist
[n
]->Match(pContext
))
3811 while(n
!= bol
&& ! m_elxlist
[n
]->MatchNext(pContext
))
3824 template <int x
> int CListElxT
<x
> :: MatchNext(CContext
* pContext
) const
3826 if(m_elxlist
.GetSize() == 0)
3830 int bol
= m_brightleft
? m_elxlist
.GetSize() : -1;
3831 int stp
= m_brightleft
? -1 : 1;
3832 int eol
= m_brightleft
? -1 : m_elxlist
.GetSize();
3837 while(n
!= bol
&& ! m_elxlist
[n
]->MatchNext(pContext
))
3848 if(m_elxlist
[n
]->Match(pContext
))
3856 while(n
!= bol
&& ! m_elxlist
[n
]->MatchNext(pContext
))
3869 // mresult.cpp: implementation of the MatchResult class.
3871 template <int x
> MatchResultT
<x
> :: MatchResultT(CContext
* pContext
, int nMaxNumber
)
3875 m_result
.Prepare(nMaxNumber
* 2 + 3, -1);
3879 m_result
[1] = nMaxNumber
;
3881 for(int n
= 0; n
<= nMaxNumber
; n
++)
3883 int index
= pContext
->m_captureindex
[n
];
3884 if( index
< 0 ) continue;
3887 int pos1
= pContext
->m_capturestack
[index
+ 1];
3888 int pos2
= pContext
->m_capturestack
[index
+ 2];
3891 m_result
[n
*2 + 2] = pos1
< pos2
? pos1
: pos2
;
3892 m_result
[n
*2 + 3] = pos1
< pos2
? pos2
: pos1
;
3897 template <int x
> inline int MatchResultT
<x
> :: IsMatched() const
3899 return m_result
.At(0, 0);
3902 template <int x
> inline int MatchResultT
<x
> :: MaxGroupNumber() const
3904 return m_result
.At(1, 0);
3907 template <int x
> inline int MatchResultT
<x
> :: GetStart() const
3909 return m_result
.At(2, -1);
3912 template <int x
> inline int MatchResultT
<x
> :: GetEnd() const
3914 return m_result
.At(3, -1);
3917 template <int x
> inline int MatchResultT
<x
> :: GetGroupStart(int nGroupNumber
) const
3919 return m_result
.At(2 + nGroupNumber
* 2, -1);
3922 template <int x
> inline int MatchResultT
<x
> :: GetGroupEnd(int nGroupNumber
) const
3924 return m_result
.At(2 + nGroupNumber
* 2 + 1, -1);
3927 template <int x
> MatchResultT
<x
> & MatchResultT
<x
> :: operator = (const MatchResultT
<x
> & result
)
3929 m_result
.Restore(0);
3930 if(result
.m_result
.GetSize() > 0) m_result
.Append(result
.m_result
.GetBuffer(), result
.m_result
.GetSize());
3935 // posselx.cpp: implementation of the CPossessiveElx class.
3937 template <int x
> CPossessiveElxT
<x
> :: CPossessiveElxT(ElxInterface
* pelx
, int nmin
, int nmax
) : CGreedyElxT
<x
> (pelx
, nmin
, nmax
)
3941 template <int x
> int CPossessiveElxT
<x
> :: Match(CContext
* pContext
) const
3943 int nbegin
= pContext
->m_nCurrentPos
;
3944 int nsize
= pContext
->m_stack
.GetSize();
3945 int ncsize
= pContext
->m_capturestack
.GetSize();
3949 if( ! CRepeatElxT
<x
> :: MatchFixed(pContext
) )
3955 while( ! CGreedyElxT
<x
> :: MatchVart(pContext
) )
3957 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
3966 pContext
->m_stack
.Restore(nsize
);
3970 pContext
->m_stack
.Push(nbegin
);
3971 pContext
->m_stack
.Push(ncsize
);
3977 template <int x
> int CPossessiveElxT
<x
> :: MatchNext(CContext
* pContext
) const
3979 int nbegin
= 0, ncsize
= 0;
3981 pContext
->m_stack
.Pop(ncsize
);
3982 pContext
->m_stack
.Pop(nbegin
);
3984 pContext
->m_capturestack
.Restore(ncsize
);
3985 pContext
->m_nCurrentPos
= nbegin
;
3990 // reluctx.cpp: implementation of the CReluctantElx class.
3992 template <int x
> CReluctantElxT
<x
> :: CReluctantElxT(ElxInterface
* pelx
, int nmin
, int nmax
) : CRepeatElxT
<x
> (pelx
, nmin
)
3994 m_nvart
= nmax
- nmin
;
3997 template <int x
> int CReluctantElxT
<x
> :: Match(CContext
* pContext
) const
3999 if( ! CRepeatElxT
<x
> :: MatchFixed(pContext
) )
4002 while( ! MatchVart(pContext
) )
4004 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
4011 template <int x
> int CReluctantElxT
<x
> :: MatchNext(CContext
* pContext
) const
4013 if( MatchNextVart(pContext
) )
4016 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
4019 while( ! MatchVart(pContext
) )
4021 if( ! CRepeatElxT
<x
> :: MatchNextFixed(pContext
) )
4028 template <int x
> int CReluctantElxT
<x
> :: MatchVart(CContext
* pContext
) const
4030 pContext
->m_stack
.Push(0);
4035 template <int x
> int CReluctantElxT
<x
> :: MatchNextVart(CContext
* pContext
) const
4037 int n
= 0, nbegin
= pContext
->m_nCurrentPos
;
4039 pContext
->m_stack
.Pop(n
);
4041 if(n
< m_nvart
&& CRepeatElxT
<x
> :: m_pelx
->Match(pContext
))
4043 while(pContext
->m_nCurrentPos
== nbegin
)
4045 if( ! CRepeatElxT
<x
> :: m_pelx
->MatchNext(pContext
) ) break;
4048 if(pContext
->m_nCurrentPos
!= nbegin
)
4052 pContext
->m_stack
.Push(nbegin
);
4053 pContext
->m_stack
.Push(n
);
4061 pContext
->m_stack
.Pop(nbegin
);
4063 while( CRepeatElxT
<x
> :: m_pelx
->MatchNext(pContext
) )
4065 if(pContext
->m_nCurrentPos
!= nbegin
)
4067 pContext
->m_stack
.Push(nbegin
);
4068 pContext
->m_stack
.Push(n
);
4080 // repeatx.cpp: implementation of the CRepeatElx class.
4082 template <int x
> CRepeatElxT
<x
> :: CRepeatElxT(ElxInterface
* pelx
, int ntimes
)
4088 template <int x
> int CRepeatElxT
<x
> :: Match(CContext
* pContext
) const
4090 return MatchFixed(pContext
);
4093 template <int x
> int CRepeatElxT
<x
> :: MatchNext(CContext
* pContext
) const
4095 return MatchNextFixed(pContext
);
4098 template <int x
> int CRepeatElxT
<x
> :: MatchFixed(CContext
* pContext
) const
4107 if(m_pelx
->Match(pContext
))
4115 while(n
>= 0 && ! m_pelx
->MatchNext(pContext
))
4128 template <int x
> int CRepeatElxT
<x
> :: MatchNextFixed(CContext
* pContext
) const
4134 int n
= m_nfixed
- 1;
4136 while(n
>= 0 && ! m_pelx
->MatchNext(pContext
))
4147 if(m_pelx
->Match(pContext
))
4155 while(n
>= 0 && ! m_pelx
->MatchNext(pContext
))
4169 typedef CRegexpT
<char> CRegexpA
;
4170 typedef CRegexpT
<unsigned short> CRegexpW
;
4172 #if defined(_UNICODE) || defined(UNICODE)
4173 typedef CRegexpW CRegexp
;
4175 typedef CRegexpA CRegexp
;
4178 #endif//__DEELX_REGEXP__H__