diff --git a/scintilla/Scintilla.vcxproj b/scintilla/Scintilla.vcxproj
index 4e7822ee6..cd26e7b95 100644
--- a/scintilla/Scintilla.vcxproj
+++ b/scintilla/Scintilla.vcxproj
@@ -121,7 +121,7 @@
true
Disabled
NotUsing
- _SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
+ _SCL_SECURE_NO_WARNINGS;WIN32;SCI_OWNREGEX;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
MultiThreadedDebug
Level3
@@ -134,7 +134,7 @@
true
Disabled
NotUsing
- _SCL_SECURE_NO_WARNINGS;_WIN64;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
+ _SCL_SECURE_NO_WARNINGS;_WIN64;SCI_OWNREGEX;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
MultiThreadedDebug
Level3
@@ -150,7 +150,7 @@
true
MaxSpeed
NotUsing
- _SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
+ _SCL_SECURE_NO_WARNINGS;WIN32;SCI_OWNREGEX;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
MultiThreaded
Level3
@@ -162,7 +162,7 @@
true
MaxSpeed
NotUsing
- _SCL_SECURE_NO_WARNINGS;_WIN64;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
+ _SCL_SECURE_NO_WARNINGS;_WIN64;SCI_OWNREGEX;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES;STATIC_BUILD;SCI_LEXER;USE_D2D;%(PreprocessorDefinitions)
MultiThreaded
Level3
@@ -171,6 +171,7 @@
+
@@ -249,6 +250,7 @@
+
@@ -304,6 +306,9 @@
+
+
+
diff --git a/scintilla/Scintilla.vcxproj.filters b/scintilla/Scintilla.vcxproj.filters
index e49186e26..a944b9d5d 100644
--- a/scintilla/Scintilla.vcxproj.filters
+++ b/scintilla/Scintilla.vcxproj.filters
@@ -16,6 +16,12 @@
{afe7e35e-cd81-406c-a770-df29d2b3fc95}
+
+ {67242aad-9133-44e7-9774-c36f5a9194bc}
+
+
+ {4e167b73-0447-4a31-a66b-64c2d684516d}
+
@@ -237,6 +243,18 @@
win32
+
+ deelx
+
+
+ lexers
+
+
+ lexers
+
+
+ lexers
+
@@ -398,6 +416,16 @@
win32
-
+
+ deelx
+
+
+ include
+
+
+
+
+ deelx\doc
+
\ No newline at end of file
diff --git a/scintilla/deelx/DeelxRegexSearch.cxx b/scintilla/deelx/DeelxRegexSearch.cxx
new file mode 100644
index 000000000..d7a3875fb
--- /dev/null
+++ b/scintilla/deelx/DeelxRegexSearch.cxx
@@ -0,0 +1,330 @@
+/**
+ * @file DeelxRegexSearch.cxx
+ * @brief integrate DeelX regex searching for Scintilla library
+ * (Scintilla Lib is copyright 1998-2016 by Neil Hodgson )
+ *
+ * uses DEELX - Regular Expression Engine (v1.3) (deelx.h) - http://www.regexlab.com/deelx/
+ * download: http://www.regexlab.com/download/deelx/deelx.zip (v1.2)
+ * or : https://github.com/AndreasMartin72/mksqlite/blob/master/deelx/deelx.h (v1.3)
+ * (Copyright Announcement: Free to use/redistribute. Provenance must be declared when redistributed)
+ * API documentation see accompanying "deelx_en.chm" HTML Help.
+ *
+ * @autor Rainer Kottenhoff (RaPeHoff)
+ *
+ * Install:
+ * - place files (deelx64.h, DeelxRegexSearch.cxx, deelx_en.chm)
+ * in a directory (deelx) within the scintilla project (.../scintilla/deelx/)
+ * - add source files to scintilla project (Scintilla.vcxproj in VS)
+ * - define compiler (preprocessor) macro for scintilla project named "SCI_OWNREGEX"
+ * -> this will switch from scintilla's buildin regex engine to deelx's regex engine
+ * - recompile and link scintilla library
+ * - build application
+ */
+
+#ifdef SCI_OWNREGEX
+
+#include
+#include
+#include
+
+#pragma warning( push )
+#pragma warning( disable : 4996 ) // Scintilla's "unsafe" use of std::copy() (SplitVector.h)
+// // or use -D_SCL_SECURE_NO_WARNINGS preprocessor define
+
+#include "Platform.h"
+#include "Scintilla.h"
+#include "ILexer.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "CellBuffer.h"
+#include "CaseFolder.h"
+#include "RunStyles.h"
+#include "Decoration.h"
+#include "CharClassify.h"
+#include "Document.h"
+// ---------------------------------------------------------------
+#include "deelx64.h" // DEELX - Regular Expression Engine (v1.3)
+// ---------------------------------------------------------------
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+class DeelxRegexSearch : public RegexSearchBase
+{
+public:
+
+ explicit DeelxRegexSearch(CharClassify* charClassTable)
+ : m_RegExpr()
+ , m_Match()
+ , m_MatchPos(-1)
+ , m_MatchLength(0)
+ , m_pContext(nullptr)
+ , m_SubstitutionBuffer(nullptr)
+ {}
+
+ virtual ~DeelxRegexSearch()
+ {
+ ReleaseSubstitutionBuffer();
+ ReleaseContext();
+ }
+
+ virtual long FindText(Document* doc, int minPos, int maxPos, const char* pattern,
+ bool caseSensitive, bool word, bool wordStart, int flags, int* length) override;
+
+ virtual const char* SubstituteByPosition(Document* doc, const char* text, int* length) override;
+
+
+private:
+
+ inline void ReleaseContext()
+ {
+ if (m_pContext != nullptr) {
+ m_RegExpr.ReleaseContext(m_pContext);
+ m_pContext = nullptr;
+ }
+ }
+
+ inline void ReleaseSubstitutionBuffer()
+ {
+ if (m_SubstitutionBuffer) {
+ m_RegExpr.ReleaseString(m_SubstitutionBuffer);
+ m_SubstitutionBuffer = nullptr;
+ }
+ }
+
+private:
+ deelx::CRegexpT m_RegExpr;
+ deelx::MatchResult m_Match;
+ deelx::index_t m_MatchPos;
+ deelx::index_t m_MatchLength;
+ deelx::CContext* m_pContext;
+ char* m_SubstitutionBuffer;
+};
+// ============================================================================
+
+
+#ifdef SCI_NAMESPACE
+RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable)
+{
+ return new DeelxRegexSearch(charClassTable);
+}
+#else
+RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable)
+{
+ return new DeelxRegexSearch(charClassTable);
+}
+#endif
+
+// ============================================================================
+
+/**
+ * forward declaration of utility functions
+ */
+std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool wordStart);
+std::string& convertReplExpr(std::string& replStr);
+
+
+// ============================================================================
+
+
+/**
+ * Find text in document, supporting both forward and backward
+ * searches (just pass minPos > maxPos to do a backward search)
+ * Has not been tested with backwards DBCS searches yet.
+ */
+long DeelxRegexSearch::FindText(Document* doc, int minPos, int maxPos, const char *pattern,
+ bool caseSensitive, bool word, bool wordStart, int searchFlags, int *length)
+{
+ int startPos, endPos;
+ bool left2right;
+
+ if (minPos <= maxPos) {
+ left2right = true;
+ startPos = minPos;
+ endPos = maxPos;
+ }
+ else { // backward search
+ left2right = false;
+ startPos = maxPos;
+ endPos = minPos;
+ }
+
+ // Range endpoints should not be inside DBCS characters, but just in case, move them.
+ startPos = doc->MovePositionOutsideChar(startPos, 1, false);
+ endPos = doc->MovePositionOutsideChar(endPos, 1, false);
+
+ int compileFlags(deelx::MULTILINE | deelx::GLOBAL | deelx::EXTENDED); // the .(dot) does not match line-breaks
+ //int compileFlags(deelx::SINGLELINE | deelx::MULTILINE | deelx::GLOBAL | deelx::EXTENDED); // the .(dot) also matches line-breaks
+ compileFlags |= (caseSensitive) ? deelx::NO_FLAG : deelx::IGNORECASE;
+ compileFlags |= (left2right) ? deelx::NO_FLAG : deelx::RIGHTTOLEFT;
+
+ std::string sRegExprStrg = translateRegExpr(std::string(pattern, *length), word, wordStart);
+
+ try {
+ m_RegExpr.Compile(sRegExprStrg.c_str(), compileFlags);
+ }
+ catch (...) {
+ return -2; // -1 is normally used for not found, -2 is used here for invalid regex
+ }
+
+ int rangeLen = endPos - startPos;
+ int searchStartPos = left2right ? 0 : rangeLen;
+ ReleaseContext();
+ m_pContext = m_RegExpr.PrepareMatch(doc->RangePointer(startPos, rangeLen), searchStartPos);
+
+ m_Match = m_RegExpr.Match(m_pContext);
+
+ m_MatchPos = -1; // not found
+ m_MatchLength = 0;
+ if (m_Match.IsMatched()) {
+ m_MatchPos = startPos + m_Match.GetStart();
+ m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart());
+ }
+
+ //NOTE: potential 64-bit-size issue at interface here:
+ *length = static_cast(m_MatchLength);
+ return static_cast(m_MatchPos);
+}
+// ============================================================================
+
+
+const char* DeelxRegexSearch::SubstituteByPosition(Document* doc, const char* text, int* length)
+{
+ if (!m_Match.IsMatched() || (m_MatchPos < 0)) {
+ *length = 0;
+ return nullptr;
+ }
+ std::string sReplStrg = convertReplExpr(std::string(text, *length));
+
+ //NOTE: potential 64-bit-size issue at interface here:
+ const char* pString = doc->RangePointer(static_cast(m_MatchPos), static_cast(m_MatchLength));
+
+ deelx::index_t resLength;
+ ReleaseSubstitutionBuffer();
+ m_SubstitutionBuffer = m_RegExpr.Replace(pString, m_MatchLength, sReplStrg.c_str(),
+ static_cast(sReplStrg.length()), resLength);
+
+ //NOTE: potential 64-bit-size issue at interface here:
+ *length = static_cast(resLength);
+
+ return m_SubstitutionBuffer;
+}
+// ============================================================================
+
+
+
+
+// ============================================================================
+// Some Helpers
+// ============================================================================
+
+
+void replaceAll(std::string& source, const std::string& from, const std::string& to)
+{
+ std::string newString;
+ newString.reserve(source.length() * 2); // avoids a few memory allocations
+
+ std::string::size_type lastPos = 0;
+ std::string::size_type findPos;
+
+ while (std::string::npos != (findPos = source.find(from, lastPos))) {
+ newString.append(source, lastPos, findPos - lastPos);
+ newString += to;
+ lastPos = findPos + from.length();
+ }
+ // Care for the rest after last occurrence
+ newString += source.substr(lastPos);
+
+ source.swap(newString);
+}
+// ----------------------------------------------------------------------------
+
+
+
+std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool wordStart)
+{
+ std::string tmpStr;
+
+ if (wholeWord || wordStart) { // push '\b' at the begin of regexpr
+ tmpStr.push_back('\\');
+ tmpStr.push_back('b');
+ tmpStr.append(regExprStr);
+ if (wholeWord) { // push '\b' at the end of regexpr
+ tmpStr.push_back('\\');
+ tmpStr.push_back('b');
+ }
+ replaceAll(tmpStr, ".", "\\w");
+ }
+ else {
+ tmpStr.append(regExprStr);
+ }
+ std::swap(regExprStr, tmpStr);
+ return regExprStr;
+}
+// ----------------------------------------------------------------------------
+
+
+
+std::string& convertReplExpr(std::string& replStr)
+{
+ std::string tmpStr;
+ for (size_t i = 0; i < replStr.length(); ++i) {
+ char ch = replStr[i];
+ if (ch == '\\') {
+ ch = replStr[++i]; // next char
+ if (ch == '\\') {
+ // skip 2nd backslash ("\\")
+ if (i < replStr.length()) { ch = replStr[++i]; }
+ else { break; }
+ }
+ if (ch >= '1' && ch <= '9') {
+ // former behavior convenience:
+ // change "\\" to deelx's group reference ($)
+ tmpStr.push_back('$');
+ }
+ switch (ch) {
+ // check for escape seq:
+ case 'a':
+ tmpStr.push_back('\a');
+ break;
+ case 'b':
+ tmpStr.push_back('\b');
+ break;
+ case 'f':
+ tmpStr.push_back('\f');
+ break;
+ case 'n':
+ tmpStr.push_back('\n');
+ break;
+ case 'r':
+ tmpStr.push_back('\r');
+ break;
+ case 't':
+ tmpStr.push_back('\t');
+ break;
+ case 'v':
+ tmpStr.push_back('\v');
+ break;
+ case '\\':
+ tmpStr.push_back('\\');
+ break;
+ default:
+ // unknown ctrl seq
+ tmpStr.push_back(ch);
+ break;
+ }
+ }
+ else {
+ tmpStr.push_back(ch);
+ }
+ } //for
+
+ std::swap(replStr, tmpStr);
+ return replStr;
+}
+// ============================================================================
+
+#pragma warning( pop )
+
+#endif //SCI_OWNREGEX
diff --git a/scintilla/deelx/deelx64.h b/scintilla/deelx/deelx64.h
new file mode 100644
index 000000000..a63a33648
--- /dev/null
+++ b/scintilla/deelx/deelx64.h
@@ -0,0 +1,4830 @@
+// deelx64.h
+//
+// DEELX Regular Expression Engine (v1.3)
+//
+// Copyright 2006 ~ 2013 (c) RegExLab.com
+// All Rights Reserved.
+//
+// http://www.regexlab.com/deelx/
+//
+// Author: Ê·ÊÙΰ (sswater shi)
+// sswater@gmail.com
+//
+// $Revision $
+//
+// + adaption for 64-bit usage: "basetsd : INT_PTR" replaces int-pointer arithmetic and buffer indexes
+// + Cppcheck cleanup
+
+#ifndef __DEELX_REGEXP64__H__
+#define __DEELX_REGEXP64__H__
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+namespace deelx
+{
+ // integer type for pointer arithmetic & casts (64-bit aware)
+ //typedef int index_t; // preserve original "deelx.h" v1.3 behavior
+ typedef INT_PTR index_t;
+
+extern "C" {
+ typedef int(*POSIX_FUNC)(int);
+ int isblank(int c);
+}
+
+//
+// Data Reference
+//
+template class CBufferRefT
+{
+public:
+ explicit CBufferRefT(const ELT * pcsz, index_t length);
+ explicit CBufferRefT(const ELT * pcsz);
+
+public:
+ int nCompare(const ELT * pcsz) const;
+ int nCompareNoCase(const ELT * pcsz) const;
+ int Compare(const ELT * pcsz) const;
+ int CompareNoCase(const ELT * pcsz) const;
+ int Compare(const CBufferRefT &) const;
+ int CompareNoCase(const CBufferRefT &) const;
+
+ ELT At(index_t nIndex, ELT def = 0) const;
+ ELT operator [] (index_t nIndex) const;
+
+ const ELT * GetBuffer() const;
+ index_t GetSize() const;
+
+public:
+ virtual ~CBufferRefT();
+
+ // Content
+protected:
+ ELT * m_pBuffer;
+ index_t m_nSize;
+};
+
+//
+// Implemenation
+//
+template CBufferRefT ::CBufferRefT(const ELT * pcsz, index_t length)
+ : m_pBuffer((ELT *)pcsz)
+ , m_nSize(length)
+{
+}
+
+template CBufferRefT ::CBufferRefT(const ELT * pcsz)
+ : m_pBuffer((ELT *)pcsz)
+ , m_nSize(0)
+{
+ if (pcsz != 0) while (m_pBuffer[m_nSize] != 0) m_nSize++;
+}
+
+template int CBufferRefT ::nCompare(const ELT * pcsz) const
+{
+ for (index_t i = 0; i < m_nSize; i++)
+ {
+ if (m_pBuffer[i] != pcsz[i])
+ return m_pBuffer[i] - pcsz[i];
+ }
+ return 0;
+}
+
+template int CBufferRefT ::nCompareNoCase(const ELT * pcsz) const
+{
+ for (index_t i = 0; i < m_nSize; i++)
+ {
+ if (m_pBuffer[i] != pcsz[i])
+ {
+ if (toupper((int)m_pBuffer[i]) != toupper((int)pcsz[i]))
+ return m_pBuffer[i] - pcsz[i];
+ }
+ }
+
+ return 0;
+}
+
+template inline int CBufferRefT ::Compare(const ELT * pcsz) const
+{
+ return nCompare(pcsz) ? 1 : (int)pcsz[m_nSize];
+}
+
+template inline int CBufferRefT ::CompareNoCase(const ELT * pcsz) const
+{
+ return nCompareNoCase(pcsz) ? 1 : (int)pcsz[m_nSize];
+}
+
+template inline int CBufferRefT ::Compare(const CBufferRefT & cref) const
+{
+ return m_nSize == cref.m_nSize ? nCompare(cref.GetBuffer()) : 1;
+}
+
+template inline int CBufferRefT ::CompareNoCase(const CBufferRefT & cref) const
+{
+ return m_nSize == cref.m_nSize ? nCompareNoCase(cref.GetBuffer()) : 1;
+}
+
+template inline ELT CBufferRefT ::At(index_t nIndex, ELT def) const
+{
+ return nIndex >= m_nSize ? def : m_pBuffer[nIndex];
+}
+
+template inline ELT CBufferRefT :: operator [] (index_t nIndex) const
+{
+ return nIndex >= m_nSize ? 0 : m_pBuffer[nIndex];
+}
+
+template const ELT * CBufferRefT ::GetBuffer() const
+{
+ static const ELT _def[] = { 0 }; return m_pBuffer ? m_pBuffer : _def;
+}
+
+template inline index_t CBufferRefT ::GetSize() const
+{
+ return m_nSize;
+}
+
+template CBufferRefT :: ~CBufferRefT()
+{}
+
+//
+// Data Buffer
+//
+template class CBufferT : public CBufferRefT
+{
+public:
+ explicit CBufferT(const ELT * pcsz, index_t length);
+ explicit CBufferT(const ELT * pcsz);
+ CBufferT();
+
+public:
+ ELT & operator [] (index_t nIndex);
+ const ELT & operator [] (index_t nIndex) const;
+ void Append(const ELT * pcsz, index_t length, index_t eol = 0);
+ void Append(ELT el, index_t eol = 0);
+
+public:
+ void Push(ELT el);
+ void Push(const CBufferRefT & buf);
+ int Pop(ELT & el);
+ int Pop(CBufferT & buf);
+ int Peek(ELT & el) const;
+
+public:
+ const ELT * GetBuffer() const;
+ ELT * GetBuffer();
+ ELT * Detach();
+ void Release();
+ void Prepare(index_t index, int fill = 0);
+ void Restore(index_t size);
+
+ ELT * PrepareInsert(index_t nPos, index_t nSize)
+ {
+ index_t nOldSize = CBufferRefT::m_nSize;
+ Restore(nPos > CBufferRefT::m_nSize ? nPos : CBufferRefT::m_nSize + nSize);
+
+ if (nPos < nOldSize)
+ {
+ ELT * from = CBufferRefT::m_pBuffer + nPos, *to = CBufferRefT::m_pBuffer + nPos + nSize;
+ memmove(to, from, sizeof(ELT) * (nOldSize - nPos));
+ }
+
+ return CBufferRefT::m_pBuffer + nPos;
+ }
+
+ void Insert(index_t nIndex, const ELT & rT)
+ {
+ Insert(nIndex, &rT, 1);
+ }
+
+ void Insert(index_t nIndex, const ELT * pT, index_t nSize)
+ {
+ memcpy(PrepareInsert(nIndex, nSize), pT, sizeof(ELT) * nSize);
+ }
+
+ void Remove(index_t nIndex)
+ {
+ Remove(nIndex, 1);
+ }
+
+ void Remove(index_t nIndex, index_t nSize)
+ {
+ if (nIndex < CBufferRefT ::m_nSize)
+ {
+ if (nIndex + nSize >= CBufferRefT ::m_nSize)
+ {
+ Restore(nIndex);
+ }
+ else
+ {
+ memmove(CBufferRefT ::m_pBuffer + nIndex, CBufferRefT ::m_pBuffer + nIndex + nSize, sizeof(ELT) * (CBufferRefT ::m_nSize - nIndex - nSize));
+ Restore(CBufferRefT ::m_nSize - nSize);
+ }
+ }
+ }
+
+ void SetMaxLength(index_t nSize)
+ {
+ if (nSize > m_nMaxLength)
+ {
+ if (m_nMaxLength < 8)
+ m_nMaxLength = 8;
+
+ if (nSize > m_nMaxLength)
+ m_nMaxLength *= 2;
+
+ if (nSize > m_nMaxLength)
+ {
+ m_nMaxLength = nSize + 11;
+ m_nMaxLength -= m_nMaxLength & 0x07;
+ }
+
+ CBufferRefT ::m_pBuffer = (ELT *)realloc(CBufferRefT ::m_pBuffer, sizeof(ELT) * m_nMaxLength);
+ }
+ }
+
+public:
+ virtual ~CBufferT();
+
+ // Content
+protected:
+ index_t m_nMaxLength;
+};
+
+//
+// Implemenation
+//
+template CBufferT ::CBufferT(const ELT * pcsz, index_t length) : CBufferRefT (0, length)
+{
+ m_nMaxLength = CBufferRefT ::m_nSize + 1;
+
+ CBufferRefT ::m_pBuffer = (ELT *)malloc(sizeof(ELT) * m_nMaxLength);
+ memcpy(CBufferRefT::m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT ::m_nSize);
+ CBufferRefT::m_pBuffer[CBufferRefT ::m_nSize] = 0;
+}
+
+template CBufferT ::CBufferT(const ELT * pcsz) : CBufferRefT (pcsz)
+{
+ m_nMaxLength = CBufferRefT ::m_nSize + 1;
+
+ CBufferRefT ::m_pBuffer = (ELT *)malloc(sizeof(ELT) * m_nMaxLength);
+ memcpy(CBufferRefT::m_pBuffer, pcsz, sizeof(ELT) * CBufferRefT ::m_nSize);
+ CBufferRefT::m_pBuffer[CBufferRefT ::m_nSize] = 0;
+}
+
+template CBufferT ::CBufferT() : CBufferRefT (0, 0)
+{
+ m_nMaxLength = 0;
+ CBufferRefT::m_pBuffer = 0;
+}
+
+template inline ELT & CBufferT :: operator [] (index_t nIndex)
+{
+ return CBufferRefT::m_pBuffer[nIndex];
+}
+
+template inline const ELT & CBufferT :: operator [] (index_t nIndex) const
+{
+ return CBufferRefT::m_pBuffer[nIndex];
+}
+
+template void CBufferT ::Append(const ELT * pcsz, index_t length, index_t eol)
+{
+ index_t nNewLength = m_nMaxLength;
+
+ // Check length
+ if (nNewLength < 8)
+ nNewLength = 8;
+
+ if (CBufferRefT ::m_nSize + length + eol > nNewLength)
+ nNewLength *= 2;
+
+ if (CBufferRefT ::m_nSize + length + eol > nNewLength)
+ {
+ nNewLength = CBufferRefT ::m_nSize + length + eol + 11;
+ nNewLength -= nNewLength % 8;
+ }
+
+ // Realloc
+ if (nNewLength > m_nMaxLength)
+ {
+ CBufferRefT ::m_pBuffer = (ELT *)realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength);
+ m_nMaxLength = nNewLength;
+ }
+
+ // Append
+ memcpy(CBufferRefT::m_pBuffer + CBufferRefT ::m_nSize, pcsz, sizeof(ELT) * length);
+ CBufferRefT ::m_nSize += length;
+
+ if (eol > 0) CBufferRefT::m_pBuffer[CBufferRefT ::m_nSize] = 0;
+}
+
+template inline void CBufferT ::Append(ELT el, index_t eol)
+{
+ Append(&el, 1, eol);
+}
+
+template void CBufferT ::Push(ELT el)
+{
+ // Realloc
+ if (CBufferRefT ::m_nSize >= m_nMaxLength)
+ {
+ index_t nNewLength = m_nMaxLength * 2;
+ if (nNewLength < 8) nNewLength = 8;
+
+ CBufferRefT ::m_pBuffer = (ELT *)realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength);
+ m_nMaxLength = nNewLength;
+ }
+
+ // Append
+ CBufferRefT::m_pBuffer[CBufferRefT ::m_nSize++] = el;
+}
+
+template void CBufferT ::Push(const CBufferRefT & buf)
+{
+ for (index_t i = 0; i < buf.GetSize(); i++)
+ {
+ Push(buf[i]);
+ }
+
+ Push((ELT)buf.GetSize());
+}
+
+template inline int CBufferT ::Pop(ELT & el)
+{
+ if (CBufferRefT ::m_nSize > 0)
+ {
+ el = CBufferRefT::m_pBuffer[--CBufferRefT ::m_nSize];
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+template int CBufferT ::Pop(CBufferT & buf)
+{
+ index_t size;
+ int res = 1;
+ res = res && Pop(*(ELT*)&size);
+ buf.Restore(size);
+
+ for (index_t i = size - 1; i >= 0; i--)
+ {
+ res = res && Pop(buf[i]);
+ }
+
+ return res;
+}
+
+template inline int CBufferT ::Peek(ELT & el) const
+{
+ if (CBufferRefT ::m_nSize > 0)
+ {
+ el = CBufferRefT::m_pBuffer[CBufferRefT ::m_nSize - 1];
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+template const ELT * CBufferT ::GetBuffer() const
+{
+ static const ELT _def[] = { 0 }; return CBufferRefT::m_pBuffer ? CBufferRefT::m_pBuffer : _def;
+}
+
+template ELT * CBufferT ::GetBuffer()
+{
+ static const ELT _def[] = { 0 }; return CBufferRefT::m_pBuffer ? CBufferRefT::m_pBuffer : (ELT *)_def;
+}
+
+template ELT * CBufferT ::Detach()
+{
+ ELT * pBuffer = CBufferRefT::m_pBuffer;
+
+ CBufferRefT ::m_pBuffer = 0;
+ CBufferRefT ::m_nSize = m_nMaxLength = 0;
+
+ return pBuffer;
+}
+
+template void CBufferT ::Release()
+{
+ ELT * pBuffer = Detach();
+
+ if (pBuffer != 0) free(pBuffer);
+}
+
+template void CBufferT ::Prepare(index_t index, int fill)
+{
+ index_t nNewSize = index + 1;
+
+ // Realloc
+ if (nNewSize > m_nMaxLength)
+ {
+ index_t nNewLength = m_nMaxLength;
+
+ if (nNewLength < 8)
+ nNewLength = 8;
+
+ if (nNewSize > nNewLength)
+ nNewLength *= 2;
+
+ if (nNewSize > nNewLength)
+ {
+ nNewLength = nNewSize + 11;
+ nNewLength -= nNewLength % 8;
+ }
+
+ CBufferRefT ::m_pBuffer = (ELT *)realloc(CBufferRefT::m_pBuffer, sizeof(ELT) * nNewLength);
+ m_nMaxLength = nNewLength;
+ }
+
+ // size
+ if (CBufferRefT ::m_nSize < nNewSize)
+ {
+ memset(CBufferRefT::m_pBuffer + CBufferRefT ::m_nSize, fill, sizeof(ELT) * (nNewSize - CBufferRefT ::m_nSize));
+ CBufferRefT ::m_nSize = nNewSize;
+ }
+}
+
+template inline void CBufferT ::Restore(index_t size)
+{
+ SetMaxLength(size);
+ CBufferRefT ::m_nSize = size;
+}
+
+template CBufferT :: ~CBufferT()
+{
+ if (CBufferRefT::m_pBuffer != 0) free(CBufferRefT::m_pBuffer);
+}
+
+template class CSortedBufferT : public CBufferT
+{
+public:
+ explicit CSortedBufferT(int reverse = 0);
+ explicit CSortedBufferT(int(*)(const void *, const void *));
+
+public:
+ void Add(const T & rT);
+ void Add(const T * pT, index_t nSize);
+ int Remove(const T & rT);
+ static void RemoveAll();
+
+ void SortFreeze() { m_bSortFreezed = 1; }
+ void SortUnFreeze();
+
+public:
+ int Find(const T & rT, int(*compare)(const void *, const void *) = 0) { return FindAs(*(T*)&rT, compare); }
+ int FindAs(const T & rT, int(*)(const void *, const void *) = 0);
+ index_t GetSize() const { return CBufferRefT::m_nSize; }
+ T & operator [] (index_t nIndex) { return CBufferT :: operator [] (nIndex); }
+
+protected:
+ int(*m_fncompare)(const void *, const void *);
+ static int compareT(const void *, const void *);
+ static int compareReverseT(const void *, const void *);
+
+ int m_bSortFreezed;
+};
+
+template CSortedBufferT ::CSortedBufferT(int reverse)
+{
+ m_fncompare = reverse ? compareReverseT : compareT;
+ m_bSortFreezed = 0;
+}
+
+template CSortedBufferT ::CSortedBufferT(int(*compare)(const void *, const void *))
+{
+ m_fncompare = compare;
+ m_bSortFreezed = 0;
+}
+
+template void CSortedBufferT ::Add(const T & rT)
+{
+ if (m_bSortFreezed != 0)
+ {
+ CBufferT ::Append(rT);
+ return;
+ }
+
+ index_t a = 0, b = CBufferRefT::m_nSize - 1, c = CBufferRefT::m_nSize / 2;
+
+ while (a <= b)
+ {
+ int r = m_fncompare(&rT, &CBufferRefT::m_pBuffer[c]);
+
+ if (r < 0) b = c - 1;
+ else if (r > 0) a = c + 1;
+ else break;
+
+ c = (a + b + 1) / 2;
+ }
+
+ CBufferT ::Insert(c, rT);
+}
+
+template void CSortedBufferT ::Add(const T * pT, index_t nSize)
+{
+ CBufferT ::Append(pT, nSize);
+
+ if (m_bSortFreezed == 0)
+ {
+ qsort(CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), m_fncompare);
+ }
+}
+
+template int CSortedBufferT ::FindAs(const T & rT, int(*compare)(const void *, const void *))
+{
+ const T * pT = (const T *)bsearch(&rT, CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), compare == 0 ? m_fncompare : compare);
+
+ if (pT != NULL)
+ return static_cast(pT - CBufferRefT::m_pBuffer); //TODO: x64bit > 4GB ?
+ else
+ return -1;
+}
+
+template int CSortedBufferT ::Remove(const T & rT)
+{
+ int pos = Find(rT);
+ if (pos >= 0) CBufferT ::Remove(pos);
+ return pos;
+}
+
+template inline void CSortedBufferT ::RemoveAll()
+{
+ CBufferT::Restore(0);
+}
+
+template void CSortedBufferT ::SortUnFreeze()
+{
+ if (m_bSortFreezed != 0)
+ {
+ m_bSortFreezed = 0;
+ qsort(CBufferRefT::m_pBuffer, CBufferRefT::m_nSize, sizeof(T), m_fncompare);
+ }
+}
+
+template int CSortedBufferT ::compareT(const void * elem1, const void * elem2)
+{
+ if (*(const T *)elem1 == *(const T *)elem2)
+ return 0;
+ else if (*(const T *)elem1 < *(const T *)elem2)
+ return -1;
+ else
+ return 1;
+}
+
+template int CSortedBufferT ::compareReverseT(const void * elem1, const void * elem2)
+{
+ if (*(const T *)elem1 == *(const T *)elem2)
+ return 0;
+ else if (*(const T *)elem1 > *(const T *)elem2)
+ return -1;
+ else
+ return 1;
+}
+
+//
+// Context
+//
+class CContext
+{
+public:
+ CBufferT m_stack;
+ CBufferT m_capturestack, m_captureindex;
+
+public:
+ index_t m_nCurrentPos;
+ index_t m_nBeginPos;
+ index_t m_nLastBeginPos;
+ index_t m_nParenZindex;
+ index_t m_nCursiveLimit;
+
+ void * m_pMatchString;
+ index_t m_pMatchStringLength;
+};
+
+class CContextShot
+{
+public:
+ explicit CContextShot(CContext * pContext)
+ {
+ m_nCurrentPos = pContext->m_nCurrentPos;
+ nsize = pContext->m_stack.GetSize();
+ ncsize = pContext->m_capturestack.GetSize();
+ }
+
+ void Restore(CContext * pContext)
+ {
+ pContext->m_stack.Restore(nsize);
+ pContext->m_capturestack.Restore(ncsize);
+ pContext->m_nCurrentPos = m_nCurrentPos;
+ }
+
+public:
+ index_t m_nCurrentPos;
+ index_t nsize;
+ index_t ncsize;
+};
+
+//
+// Interface
+//
+class ElxInterface
+{
+public:
+ virtual int Match(CContext * pContext) const = 0;
+ virtual int MatchNext(CContext * pContext) const = 0;
+
+public:
+ virtual ~ElxInterface() {};
+};
+
+//
+// Alternative
+//
+template class CAlternativeElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CAlternativeElxT();
+
+public:
+ CBufferT m_elxlist;
+};
+
+typedef CAlternativeElxT <0> CAlternativeElx;
+
+//
+// Assert
+//
+template class CAssertElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CAssertElxT(ElxInterface * pelx, int byes = 1);
+
+public:
+ ElxInterface * m_pelx;
+ int m_byes;
+};
+
+typedef CAssertElxT <0> CAssertElx;
+
+//
+// Back reference elx
+//
+template class CBackrefElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CBackrefElxT(int nnumber, int brightleft, int bignorecase);
+
+public:
+ index_t m_nnumber;
+ int m_brightleft;
+ int m_bignorecase;
+
+ CBufferT m_szNamed;
+};
+
+//
+// Implementation
+//
+template CBackrefElxT ::CBackrefElxT(int nnumber, int brightleft, int bignorecase)
+{
+ m_nnumber = nnumber;
+ m_brightleft = brightleft;
+ m_bignorecase = bignorecase;
+}
+
+template int CBackrefElxT ::Match(CContext * pContext) const
+{
+ // check number, for named
+ if (m_nnumber < 0 || m_nnumber >= pContext->m_captureindex.GetSize()) return 0;
+
+ index_t index = pContext->m_captureindex[m_nnumber];
+ if (index < 0) return 0;
+
+ // check enclosed
+ index_t pos1 = pContext->m_capturestack[index + 1];
+ index_t pos2 = pContext->m_capturestack[index + 2];
+
+ if (pos2 < 0) pos2 = pContext->m_nCurrentPos;
+
+ // info
+ index_t lpos = pos1 < pos2 ? pos1 : pos2;
+ index_t rpos = pos1 < pos2 ? pos2 : pos1;
+ index_t slen = rpos - lpos;
+
+ const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
+ index_t npos = pContext->m_nCurrentPos;
+ index_t tlen = pContext->m_pMatchStringLength;
+
+ // compare
+ int bsucc;
+ CBufferRefT refstr(pcsz + lpos, slen);
+
+ if (m_brightleft)
+ {
+ if (npos < slen)
+ return 0;
+
+ if (m_bignorecase)
+ bsucc = !refstr.nCompareNoCase(pcsz + (npos - slen));
+ else
+ bsucc = !refstr.nCompare(pcsz + (npos - slen));
+
+ if (bsucc)
+ {
+ pContext->m_stack.Push(npos);
+ pContext->m_nCurrentPos -= slen;
+ }
+ }
+ else
+ {
+ if (npos + slen > tlen)
+ return 0;
+
+ if (m_bignorecase)
+ bsucc = !refstr.nCompareNoCase(pcsz + npos);
+ else
+ bsucc = !refstr.nCompare(pcsz + npos);
+
+ if (bsucc)
+ {
+ pContext->m_stack.Push(npos);
+ pContext->m_nCurrentPos += slen;
+ }
+ }
+
+ return bsucc;
+}
+
+template int CBackrefElxT ::MatchNext(CContext * pContext) const
+{
+ index_t npos = 0;
+
+ pContext->m_stack.Pop(npos);
+ pContext->m_nCurrentPos = npos;
+
+ return 0;
+}
+
+// RCHART
+#ifndef RCHART
+#define RCHART(ch) ((CHART)ch)
+#endif
+
+// BOUNDARY_TYPE
+enum BOUNDARY_TYPE
+{
+ BOUNDARY_FILE_BEGIN, // begin of whole text
+ BOUNDARY_FILE_END, // end of whole text
+ BOUNDARY_FILE_END_N, // end of whole text, or before newline at the end
+ BOUNDARY_LINE_BEGIN, // begin of line
+ BOUNDARY_LINE_END, // end of line
+ BOUNDARY_WORD_BEGIN, // begin of word
+ BOUNDARY_WORD_END, // end of word
+ BOUNDARY_WORD_EDGE
+};
+
+//
+// Boundary Elx
+//
+template class CBoundaryElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CBoundaryElxT(int ntype, int byes = 1);
+
+protected:
+ static int IsWordChar(CHART ch);
+
+public:
+ int m_ntype;
+ int m_byes;
+};
+
+//
+// Implementation
+//
+template CBoundaryElxT ::CBoundaryElxT(int ntype, int byes)
+{
+ m_ntype = ntype;
+ m_byes = byes;
+}
+
+template int CBoundaryElxT ::Match(CContext * pContext) const
+{
+ const CHART * pcsz = (const CHART *)pContext->m_pMatchString;
+ index_t npos = pContext->m_nCurrentPos;
+ index_t 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_FILE_END_N:
+ bsucc = (npos >= tlen) || (pcsz[tlen - 1] == RCHART('\n') && (npos == tlen - 1 || (pcsz[tlen - 2] == RCHART('\r') && npos == tlen - 2)));
+ break;
+
+ case BOUNDARY_LINE_BEGIN:
+ bsucc = (npos <= 0) || (chL == RCHART('\n')) || ((chL == RCHART('\r')) && (chR != RCHART('\n')));
+ break;
+
+ case BOUNDARY_LINE_END:
+ bsucc = (npos >= tlen) || (chR == RCHART('\r')) || ((chR == RCHART('\n')) && (chL != RCHART('\r')));
+ break;
+
+ case BOUNDARY_WORD_BEGIN:
+ bsucc = !IsWordChar(chL) && IsWordChar(chR);
+ break;
+
+ case BOUNDARY_WORD_END:
+ bsucc = IsWordChar(chL) && !IsWordChar(chR);
+ break;
+
+ case BOUNDARY_WORD_EDGE:
+ bsucc = IsWordChar(chL) ? !IsWordChar(chR) : IsWordChar(chR);
+ break;
+ }
+
+ return m_byes ? bsucc : !bsucc;
+}
+
+template int CBoundaryElxT ::MatchNext(CContext *) const
+{
+ return 0;
+}
+
+template inline int CBoundaryElxT ::IsWordChar(CHART ch)
+{
+ return (ch >= RCHART('A') && ch <= RCHART('Z')) || (ch >= RCHART('a') && ch <= RCHART('z')) || (ch >= RCHART('0') && ch <= RCHART('9')) || (ch == RCHART('_'));
+}
+
+//
+// Bracket
+//
+template class CBracketElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CBracketElxT(index_t nnumber, int bright);
+ static int CheckCaptureIndex(index_t & index, CContext * pContext, index_t number);
+
+public:
+ index_t m_nnumber;
+ index_t m_balancing;
+ int m_bright;
+
+ CBufferT m_szNamed;
+ CBufferT m_szBalancing;
+};
+
+template CBracketElxT ::CBracketElxT(index_t nnumber, int bright)
+{
+ m_nnumber = nnumber;
+ m_bright = bright;
+ m_balancing = -1;
+}
+
+template inline int CBracketElxT ::CheckCaptureIndex(index_t & index, CContext * pContext, index_t number)
+{
+ if (index >= pContext->m_capturestack.GetSize())
+ index = pContext->m_capturestack.GetSize() - 4;
+
+ while (index >= 0)
+ {
+ if (pContext->m_capturestack[index] == number)
+ {
+ return 1;
+ }
+
+ index -= 4;
+ }
+ return 0;
+}
+
+//
+// capturestack[index+0] => Group number
+// capturestack[index+1] => Capture start pos
+// capturestack[index+2] => Capture end pos
+// capturestack[index+3] => Capture enclose z-index, zindex<0 means inner group with same name
+//
+template int CBracketElxT ::Match(CContext * pContext) const
+{
+ // check, for named
+ if (m_nnumber < 0) return 0;
+
+ if (!m_bright)
+ {
+ pContext->m_captureindex.Prepare(m_nnumber, -1);
+ index_t index = pContext->m_captureindex[m_nnumber];
+
+ // check
+ if (CheckCaptureIndex(index, pContext, m_nnumber) && pContext->m_capturestack[index + 2] < 0)
+ {
+ pContext->m_capturestack[index + 3] --;
+ return 1;
+ }
+
+ // balancing left
+ if (m_balancing >= 0)
+ {
+ index_t balancing_index = pContext->m_captureindex[m_balancing];
+ if (!CheckCaptureIndex(balancing_index, pContext, m_balancing) ||
+ pContext->m_capturestack[balancing_index + 2] < 0)
+ {
+ return 0;
+ }
+ }
+
+ // 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
+ index_t index = pContext->m_captureindex[m_nnumber];
+
+ if (CheckCaptureIndex(index, pContext, m_nnumber))
+ {
+ if (pContext->m_capturestack[index + 3] < 0) // check inner group with same name
+ {
+ pContext->m_capturestack[index + 3] ++;
+ return 1;
+ }
+
+ // balancing right
+ index_t balancing_index = -1;
+ if (m_balancing >= 0)
+ {
+ balancing_index = pContext->m_captureindex[m_balancing];
+ if (!CheckCaptureIndex(balancing_index, pContext, m_balancing))
+ {
+ // TODO ERROR
+ return 0;
+ }
+ }
+
+ // save
+ pContext->m_capturestack[index + 2] = pContext->m_nCurrentPos;
+ pContext->m_capturestack[index + 3] = pContext->m_nParenZindex++;
+
+ // balancing right
+ if (m_balancing >= 0)
+ {
+ // backup index
+ pContext->m_stack.Push(balancing_index);
+
+ if (balancing_index >= 0)
+ {
+ pContext->m_capturestack[index + 2] = pContext->m_capturestack[index + 1];
+ pContext->m_capturestack[index + 1] = pContext->m_capturestack[balancing_index + 2];
+
+ // destopy capture
+ pContext->m_capturestack[balancing_index] = -1;
+ balancing_index -= 4;
+ CheckCaptureIndex(balancing_index, pContext, m_balancing);
+ pContext->m_captureindex[m_balancing] = balancing_index;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+template int CBracketElxT ::MatchNext(CContext * pContext) const
+{
+ index_t index = pContext->m_captureindex[m_nnumber];
+ if (!CheckCaptureIndex(index, pContext, m_nnumber))
+ {
+ return 0;
+ }
+
+ 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
+ CheckCaptureIndex(index, pContext, m_nnumber);
+
+ // new index
+ pContext->m_captureindex[m_nnumber] = index;
+ }
+ else
+ {
+ if (pContext->m_capturestack[index + 2] >= 0)
+ {
+ // balancing right
+ if (m_balancing >= 0)
+ {
+ index_t balancing_index = -1;
+ pContext->m_stack.Pop(balancing_index);
+
+ if (balancing_index >= 0)
+ {
+ pContext->m_capturestack[balancing_index] = m_balancing;
+ pContext->m_captureindex[m_balancing] = balancing_index;
+ }
+ }
+ pContext->m_capturestack[index + 2] = -1;
+ pContext->m_capturestack[index + 3] = 0;
+ }
+ else
+ {
+ pContext->m_capturestack[index + 3] --;
+ }
+ }
+
+ return 0;
+}
+
+//
+// Deletage
+//
+template class CDelegateElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ explicit CDelegateElxT(int ndata = 0);
+
+public:
+ ElxInterface * m_pelx;
+ index_t m_ndata; // +0 : recursive to
+ // -3 : named recursive
+
+ CBufferT m_szNamed;
+};
+
+template CDelegateElxT ::CDelegateElxT(int ndata)
+{
+ m_pelx = 0;
+ m_ndata = ndata;
+}
+
+template int CDelegateElxT ::Match(CContext * pContext) const
+{
+ if (m_pelx != 0)
+ {
+ if (pContext->m_nCursiveLimit > 0)
+ {
+ pContext->m_nCursiveLimit--;
+ int result = m_pelx->Match(pContext);
+ pContext->m_nCursiveLimit++;
+ return result;
+ }
+ else
+ return 0;
+ }
+ else
+ return 1;
+}
+
+template int CDelegateElxT ::MatchNext(CContext * pContext) const
+{
+ if (m_pelx != 0)
+ return m_pelx->MatchNext(pContext);
+ else
+ return 0;
+}
+
+//
+// Empty
+//
+template class CEmptyElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CEmptyElxT();
+};
+
+typedef CEmptyElxT <0> CEmptyElx;
+
+//
+// Global
+//
+template class CGlobalElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CGlobalElxT();
+};
+
+typedef CGlobalElxT <0> CGlobalElx;
+
+//
+// Repeat
+//
+template class CRepeatElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CRepeatElxT(ElxInterface * pelx, int ntimes);
+
+protected:
+ int MatchFixed(CContext * pContext) const;
+ int MatchNextFixed(CContext * pContext) const;
+ int MatchForward(CContext * pContext) const
+ {
+ CContextShot shot(pContext);
+
+ if (!m_pelx->Match(pContext))
+ return 0;
+
+ if (pContext->m_nCurrentPos != shot.m_nCurrentPos)
+ return 1;
+
+ if (!m_pelx->MatchNext(pContext))
+ return 0;
+
+ if (pContext->m_nCurrentPos != shot.m_nCurrentPos)
+ return 1;
+
+ shot.Restore(pContext);
+ return 0;
+ }
+
+public:
+ ElxInterface * m_pelx;
+ int m_nfixed;
+};
+
+typedef CRepeatElxT <0> CRepeatElx;
+
+//
+// Greedy
+//
+template class CGreedyElxT : public CRepeatElxT
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ CGreedyElxT(ElxInterface * pelx, int nmin = 0, int nmax = INT_MAX);
+
+protected:
+ int MatchVart(CContext * pContext) const;
+ int MatchNextVart(CContext * pContext) const;
+
+public:
+ int m_nvart;
+};
+
+typedef CGreedyElxT <0> CGreedyElx;
+
+//
+// Independent
+//
+template class CIndependentElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ explicit CIndependentElxT(ElxInterface * pelx);
+
+public:
+ ElxInterface * m_pelx;
+};
+
+typedef CIndependentElxT <0> CIndependentElx;
+
+//
+// List
+//
+template class CListElxT : public ElxInterface
+{
+public:
+ int Match(CContext * pContext) const;
+ int MatchNext(CContext * pContext) const;
+
+public:
+ explicit CListElxT(int brightleft);
+
+public:
+ CBufferT m_elxlist;
+ int m_brightleft;
+};
+
+typedef CListElxT <0> CListElx;
+
+//
+// Posix Elx
+//
+template