summaryrefslogtreecommitdiff
path: root/xfa/src/fdp/src/xml/fde_xml.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/src/fdp/src/xml/fde_xml.cpp')
-rw-r--r--xfa/src/fdp/src/xml/fde_xml.cpp2712
1 files changed, 2712 insertions, 0 deletions
diff --git a/xfa/src/fdp/src/xml/fde_xml.cpp b/xfa/src/fdp/src/xml/fde_xml.cpp
new file mode 100644
index 0000000000..3ee4b4028c
--- /dev/null
+++ b/xfa/src/fdp/src/xml/fde_xml.cpp
@@ -0,0 +1,2712 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../../foxitlib.h"
+#include "fde_xml.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define FDE_XMLVALIDCHARRANGENUM 5
+static FX_WCHAR g_XMLValidCharRange[FDE_XMLVALIDCHARRANGENUM][2] = {{0x09, 0x09}, {0x0A, 0x0A}, {0x0D, 0x0D}, {0x20, 0xD7FF}, {0xE000, 0xFFFD}};
+FX_BOOL FDE_IsXMLValidChar(FX_WCHAR ch)
+{
+ FX_INT32 iStart = 0, iEnd = FDE_XMLVALIDCHARRANGENUM - 1, iMid;
+ while (iStart <= iEnd) {
+ iMid = (iStart + iEnd) / 2;
+ if (ch < g_XMLValidCharRange[iMid][0]) {
+ iEnd = iMid - 1;
+ } else if (ch > g_XMLValidCharRange[iMid][1]) {
+ iStart = iMid + 1;
+ } else {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL FDE_IsXMLWhiteSpace(FX_WCHAR ch)
+{
+ return ch == L' ' || ch == 0x0A || ch == 0x0D || ch == 0x09;
+}
+typedef struct _FDE_XMLNAMECHAR {
+ FX_WCHAR wStart;
+ FX_WCHAR wEnd;
+ FX_BOOL bStartChar;
+} FDE_XMLNAMECHAR;
+#define FDE_XMLNAMECHARSNUM 20
+static FDE_XMLNAMECHAR g_XMLNameChars[FDE_XMLNAMECHARSNUM] = {
+ {L'-', L'.', FALSE}, {L'0', L'9', FALSE}, {L':', L':', FALSE}, {L'A', L'Z', TRUE},
+ {L'_', L'_', TRUE}, {L'a', L'z', TRUE}, {0xB7, 0xB7, FALSE}, {0xC0, 0xD6, TRUE},
+ {0xD8, 0xF6, TRUE}, {0xF8, 0x02FF, TRUE}, {0x0300, 0x036F, FALSE}, {0x0370, 0x037D, TRUE},
+ {0x037F, 0x1FFF, TRUE}, {0x200C, 0x200D, TRUE}, {0x203F, 0x2040, FALSE}, {0x2070, 0x218F, TRUE},
+ {0x2C00, 0x2FEF, TRUE}, {0x3001, 0xD7FF, TRUE}, {0xF900, 0xFDCF, TRUE}, {0xFDF0, 0xFFFD, TRUE},
+};
+FX_BOOL FDE_IsXMLNameChar(FX_WCHAR ch, FX_BOOL bFirstChar)
+{
+ FX_INT32 iStart = 0, iEnd = FDE_XMLNAMECHARSNUM - 1, iMid;
+ while (iStart <= iEnd) {
+ iMid = (iStart + iEnd) / 2;
+ if (ch < g_XMLNameChars[iMid].wStart) {
+ iEnd = iMid - 1;
+ } else if (ch > g_XMLNameChars[iMid].wEnd) {
+ iStart = iMid + 1;
+ } else {
+ if (bFirstChar) {
+ return g_XMLNameChars[iMid].bStartChar;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+#ifdef __cplusplus
+}
+#endif
+CFDE_XMLNode::CFDE_XMLNode()
+ : m_pParent(NULL)
+ , m_pChild(NULL)
+ , m_pPrior(NULL)
+ , m_pNext(NULL)
+{
+}
+CFDE_XMLNode::~CFDE_XMLNode()
+{
+ DeleteChildren();
+}
+void CFDE_XMLNode::DeleteChildren()
+{
+ CFDE_XMLNode *pChild = m_pChild, *pTemp;
+ while (pChild != NULL) {
+ pTemp = pChild->m_pNext;
+ pChild->Release();
+ pChild = pTemp;
+ }
+ m_pChild = NULL;
+}
+FX_INT32 CFDE_XMLNode::CountChildNodes() const
+{
+ FX_INT32 iCount = 0;
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild != NULL) {
+ iCount ++;
+ pChild = pChild->m_pNext;
+ }
+ return iCount;
+}
+CFDE_XMLNode* CFDE_XMLNode::GetChildNode(FX_INT32 index) const
+{
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild != NULL) {
+ if (index == 0) {
+ return pChild;
+ }
+ index --;
+ pChild = pChild->m_pNext;
+ }
+ return NULL;
+}
+FX_INT32 CFDE_XMLNode::GetChildNodeIndex(CFDE_XMLNode *pNode) const
+{
+ FX_INT32 index = 0;
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild != NULL) {
+ if (pChild == pNode) {
+ return index;
+ }
+ index ++;
+ pChild = pChild->m_pNext;
+ }
+ return -1;
+}
+CFDE_XMLNode* CFDE_XMLNode::GetPath(FX_LPCWSTR pPath, FX_INT32 iLength, FX_BOOL bQualifiedName) const
+{
+ FXSYS_assert(pPath != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pPath);
+ }
+ if (iLength == 0) {
+ return NULL;
+ }
+ CFX_WideString csPath;
+ FX_LPCWSTR pStart = pPath, pEnd = pPath + iLength;
+ FX_WCHAR ch;
+ while (pStart < pEnd) {
+ ch = *pStart ++;
+ if (ch == L'/') {
+ break;
+ } else {
+ csPath += ch;
+ }
+ }
+ iLength -= pStart - pPath;
+ CFDE_XMLNode *pFind = NULL;
+ if (csPath.GetLength() < 1) {
+ pFind = GetNodeItem(IFDE_XMLNode::Root);
+ } else if (csPath.Compare(L"..") == 0) {
+ pFind = m_pParent;
+ } else if (csPath.Compare(L".") == 0) {
+ pFind = (CFDE_XMLNode*)this;
+ } else {
+ CFX_WideString wsTag;
+ CFDE_XMLNode *pNode = m_pChild;
+ while (pNode != NULL) {
+ if (pNode->GetType() == FDE_XMLNODE_Element) {
+ if (bQualifiedName) {
+ ((CFDE_XMLElement*)pNode)->GetTagName(wsTag);
+ } else {
+ ((CFDE_XMLElement*)pNode)->GetLocalTagName(wsTag);
+ }
+ if (wsTag.Compare(csPath) == 0) {
+ if (iLength < 1) {
+ pFind = pNode;
+ } else {
+ pFind = pNode->GetPath(pStart, iLength, bQualifiedName);
+ }
+ if (pFind != NULL) {
+ return pFind;
+ }
+ }
+ }
+ pNode = pNode->m_pNext;
+ }
+ }
+ if (pFind == NULL || iLength < 1) {
+ return pFind;
+ }
+ return pFind->GetPath(pStart, iLength, bQualifiedName);
+}
+FX_INT32 CFDE_XMLNode::InsertChildNode(CFDE_XMLNode *pNode, FX_INT32 index)
+{
+ FXSYS_assert(pNode != NULL);
+ pNode->m_pParent = this;
+ if (m_pChild == NULL) {
+ m_pChild = pNode;
+ pNode->m_pPrior = NULL;
+ pNode->m_pNext = NULL;
+ return 0;
+ } else if (index == 0) {
+ pNode->m_pNext = m_pChild;
+ pNode->m_pPrior = NULL;
+ m_pChild->m_pPrior = pNode;
+ m_pChild = pNode;
+ return 0;
+ }
+ FX_INT32 iCount = 0;
+ CFDE_XMLNode *pFind = m_pChild;
+ while (++iCount != index && pFind->m_pNext != NULL) {
+ pFind = pFind->m_pNext;
+ }
+ pNode->m_pPrior = pFind;
+ pNode->m_pNext = pFind->m_pNext;
+ if (pFind->m_pNext != NULL) {
+ pFind->m_pNext->m_pPrior = pNode;
+ }
+ pFind->m_pNext = pNode;
+ return iCount;
+}
+void CFDE_XMLNode::RemoveChildNode(CFDE_XMLNode *pNode)
+{
+ FXSYS_assert(m_pChild != NULL && pNode != NULL);
+ if (m_pChild == pNode) {
+ m_pChild = pNode->m_pNext;
+ } else {
+ pNode->m_pPrior->m_pNext = pNode->m_pNext;
+ }
+ if (pNode->m_pNext != NULL) {
+ pNode->m_pNext->m_pPrior = pNode->m_pPrior;
+ }
+ pNode->m_pParent = NULL;
+ pNode->m_pNext = NULL;
+ pNode->m_pPrior = NULL;
+}
+CFDE_XMLNode* CFDE_XMLNode::GetNodeItem(IFDE_XMLNode::NodeItem eItem) const
+{
+ switch (eItem) {
+ case IFDE_XMLNode::Root: {
+ CFDE_XMLNode *pParent = (CFDE_XMLNode*)this;
+ while (pParent->m_pParent != NULL) {
+ pParent = pParent->m_pParent;
+ }
+ return pParent;
+ }
+ case IFDE_XMLNode::Parent:
+ return m_pParent;
+ case IFDE_XMLNode::FirstSibling: {
+ CFDE_XMLNode *pItem = (CFDE_XMLNode*)this;
+ while (pItem->m_pPrior != NULL) {
+ pItem = pItem->m_pPrior;
+ }
+ return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
+ }
+ case IFDE_XMLNode::PriorSibling:
+ return m_pPrior;
+ case IFDE_XMLNode::NextSibling:
+ return m_pNext;
+ case IFDE_XMLNode::LastSibling: {
+ CFDE_XMLNode *pItem = (CFDE_XMLNode*)this;
+ while (pItem->m_pNext != NULL) {
+ pItem = pItem->m_pNext;
+ }
+ return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
+ }
+ case IFDE_XMLNode::FirstNeighbor: {
+ CFDE_XMLNode *pParent = (CFDE_XMLNode*)this;
+ while (pParent->m_pParent != NULL) {
+ pParent = pParent->m_pParent;
+ }
+ return pParent == (CFDE_XMLNode*)this ? NULL : pParent;
+ }
+ case IFDE_XMLNode::PriorNeighbor: {
+ if (m_pPrior == NULL) {
+ return m_pParent;
+ }
+ CFDE_XMLNode *pItem = m_pPrior;
+ while (CFDE_XMLNode *pTemp = pItem->m_pChild) {
+ pItem = pTemp;
+ while ((pTemp = pItem->m_pNext) != NULL) {
+ pItem = pTemp;
+ }
+ }
+ return pItem;
+ }
+ case IFDE_XMLNode::NextNeighbor: {
+ if (m_pChild != NULL) {
+ return m_pChild;
+ }
+ if (m_pNext != NULL) {
+ return m_pNext;
+ }
+ CFDE_XMLNode *pItem = m_pParent;
+ while (pItem != NULL) {
+ if (pItem->m_pNext != NULL) {
+ return pItem->m_pNext;
+ }
+ pItem = pItem->m_pParent;
+ }
+ return NULL;
+ }
+ case IFDE_XMLNode::LastNeighbor: {
+ CFDE_XMLNode *pItem = (CFDE_XMLNode*)this;
+ while (pItem->m_pParent != NULL) {
+ pItem = pItem->m_pParent;
+ }
+ while (TRUE) {
+ while (pItem->m_pNext != NULL) {
+ pItem = pItem->m_pNext;
+ }
+ if (pItem->m_pChild == NULL) {
+ break;
+ }
+ pItem = pItem->m_pChild;
+ }
+ return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
+ }
+ case IFDE_XMLNode::FirstChild:
+ return m_pChild;
+ case IFDE_XMLNode::LastChild: {
+ if (m_pChild == NULL) {
+ return NULL;
+ }
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild->m_pNext != NULL) {
+ pChild = pChild->m_pNext;
+ }
+ return pChild;
+ }
+ default:
+ break;
+ }
+ return NULL;
+}
+FX_INT32 CFDE_XMLNode::GetNodeLevel() const
+{
+ FX_INT32 iLevel = 0;
+ CFDE_XMLNode *pItem = (CFDE_XMLNode*)this;
+ while ((pItem = pItem->m_pParent) != NULL) {
+ iLevel ++;
+ }
+ return iLevel;
+}
+FX_BOOL CFDE_XMLNode::InsertNodeItem(IFDE_XMLNode::NodeItem eItem, CFDE_XMLNode *pNode)
+{
+ FXSYS_assert(pNode != NULL);
+ switch (eItem) {
+ case IFDE_XMLNode::NextSibling: {
+ pNode->m_pParent = m_pParent;
+ pNode->m_pNext = m_pNext;
+ pNode->m_pPrior = this;
+ if (m_pNext) {
+ m_pNext->m_pPrior = pNode;
+ }
+ m_pNext = pNode;
+ return TRUE;
+ }
+ case IFDE_XMLNode::PriorSibling: {
+ pNode->m_pParent = m_pParent;
+ pNode->m_pNext = this;
+ pNode->m_pPrior = m_pPrior;
+ if (m_pPrior) {
+ m_pPrior->m_pNext = pNode;
+ } else if (m_pParent) {
+ m_pParent->m_pChild = pNode;
+ }
+ m_pPrior = pNode;
+ return TRUE;
+ }
+ default:
+ return FALSE;
+ }
+ return FALSE;
+}
+CFDE_XMLNode* CFDE_XMLNode::RemoveNodeItem(IFDE_XMLNode::NodeItem eItem)
+{
+ CFDE_XMLNode* pNode = NULL;
+ switch (eItem) {
+ case IFDE_XMLNode::NextSibling:
+ if (m_pNext) {
+ pNode = m_pNext;
+ m_pNext = pNode->m_pNext;
+ if (m_pNext) {
+ m_pNext->m_pPrior = this;
+ }
+ pNode->m_pParent = NULL;
+ pNode->m_pNext = NULL;
+ pNode->m_pPrior = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return pNode;
+}
+CFDE_XMLNode* CFDE_XMLNode::Clone(FX_BOOL bRecursive)
+{
+ return NULL;
+}
+void CFDE_XMLNode::SaveXMLNode(IFX_Stream *pXMLStream)
+{
+ CFDE_XMLNode *pNode = (CFDE_XMLNode*)this;
+ FXSYS_assert(pXMLStream != NULL && pNode != NULL);
+ switch (pNode->GetType()) {
+ case FDE_XMLNODE_Instruction: {
+ CFX_WideString ws;
+ CFDE_XMLInstruction *pInstruction = (CFDE_XMLInstruction*)pNode;
+ if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
+ ws = L"<?xml version=\"1.0\" encoding=\"";
+ FX_WORD wCodePage = pXMLStream->GetCodePage();
+ if (wCodePage == FX_CODEPAGE_UTF16LE) {
+ ws += L"UTF-16";
+ } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
+ ws += L"UTF-16be";
+ } else {
+ ws += L"UTF-8";
+ }
+ ws += L"\"?>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ } else {
+ ws.Format((FX_LPCWSTR)L"<?%s", (FX_LPCWSTR)pInstruction->m_wsTarget);
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray &attributes = pInstruction->m_Attributes;
+ FX_INT32 i, iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ wsValue.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ wsValue.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ wsValue.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ wsValue.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ ws += wsValue;
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ CFX_WideStringArray &targetdata = pInstruction->m_TargetData;
+ iCount = targetdata.GetSize();
+ for (i = 0; i < iCount; i++) {
+ ws = L" \"";
+ ws += targetdata[i];
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ ws = L"?>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ }
+ break;
+ case FDE_XMLNODE_Element: {
+ CFX_WideString ws;
+ ws = L"<";
+ ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray &attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
+ FX_INT32 iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ wsValue.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ wsValue.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ wsValue.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ wsValue.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ ws += wsValue;
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ if (pNode->m_pChild == NULL) {
+ ws = L"\n/>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ } else {
+ ws = L"\n>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFDE_XMLNode *pChild = pNode->m_pChild;
+ while (pChild != NULL) {
+ pChild->SaveXMLNode(pXMLStream);
+ pChild = pChild->m_pNext;
+ }
+ ws = L"</";
+ ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
+ ws += L"\n>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ }
+ break;
+ case FDE_XMLNODE_Text: {
+ CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
+ ws.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ ws.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ ws.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ ws.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ ws.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ break;
+ case FDE_XMLNODE_CharData: {
+ CFX_WideString ws = L"<![CDATA[";
+ ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
+ ws += L"]]>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ break;
+ case FDE_XMLNODE_Unknown:
+ break;
+ default:
+ break;
+ }
+}
+void CFDE_XMLNode::CloneChildren(CFDE_XMLNode* pClone)
+{
+ if (!m_pChild) {
+ return;
+ }
+ CFDE_XMLNode* pNext = m_pChild;
+ CFDE_XMLNode* pCloneNext = pNext->Clone(TRUE);
+ pClone->InsertChildNode(pCloneNext);
+ pNext = pNext->m_pNext;
+ while (pNext) {
+ CFDE_XMLNode* pChild = pNext->Clone(TRUE);
+ pCloneNext->InsertNodeItem(IFDE_XMLNode::NextSibling, pChild);
+ pCloneNext = pChild;
+ pNext = pNext->m_pNext;
+ }
+}
+IFDE_XMLInstruction* IFDE_XMLInstruction::Create(const CFX_WideString &wsTarget)
+{
+ return (IFDE_XMLInstruction*)FDE_New CFDE_XMLInstruction(wsTarget);
+}
+CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString &wsTarget)
+ : CFDE_XMLNode()
+ , m_wsTarget(wsTarget)
+ , m_TargetData()
+ , m_Attributes()
+{
+ FXSYS_assert(m_wsTarget.GetLength() > 0);
+}
+CFDE_XMLNode* CFDE_XMLInstruction::Clone(FX_BOOL bRecursive)
+{
+ CFDE_XMLInstruction* pClone = FDE_New CFDE_XMLInstruction(m_wsTarget);
+ if (!pClone) {
+ return pClone;
+ }
+ pClone->m_Attributes.Copy(m_Attributes);
+ pClone->m_TargetData.Copy(m_TargetData);
+ if (bRecursive) {
+ CloneChildren(pClone);
+ }
+ return pClone;
+}
+FX_INT32 CFDE_XMLInstruction::CountAttributes() const
+{
+ return m_Attributes.GetSize() / 2;
+}
+FX_BOOL CFDE_XMLInstruction::GetAttribute(FX_INT32 index, CFX_WideString &wsAttriName, CFX_WideString &wsAttriValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ FXSYS_assert(index > -1 && index < iCount / 2);
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (index == 0) {
+ wsAttriName = m_Attributes[i];
+ wsAttriValue = m_Attributes[i + 1];
+ return TRUE;
+ }
+ index --;
+ }
+ return FALSE;
+}
+FX_BOOL CFDE_XMLInstruction::HasAttribute(FX_LPCWSTR pwsAttriName) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void CFDE_XMLInstruction::GetString(FX_LPCWSTR pwsAttriName, CFX_WideString &wsAttriValue, FX_LPCWSTR pwsDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ wsAttriValue = m_Attributes[i + 1];
+ return;
+ }
+ }
+ wsAttriValue = pwsDefValue;
+}
+void CFDE_XMLInstruction::SetString(const CFX_WideString &wsAttriName, const CFX_WideString &wsAttriValue)
+{
+ FXSYS_assert(wsAttriName.GetLength() > 0);
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(wsAttriName) == 0) {
+ m_Attributes[i] = wsAttriName;
+ m_Attributes[i + 1] = wsAttriValue;
+ return;
+ }
+ }
+ m_Attributes.Add(wsAttriName);
+ m_Attributes.Add(wsAttriValue);
+}
+FX_INT32 CFDE_XMLInstruction::GetInteger(FX_LPCWSTR pwsAttriName, FX_INT32 iDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FXSYS_wtoi((FX_LPCWSTR)m_Attributes[i + 1]);
+ }
+ }
+ return iDefValue;
+}
+void CFDE_XMLInstruction::SetInteger(FX_LPCWSTR pwsAttriName, FX_INT32 iAttriValue)
+{
+ CFX_WideString wsValue;
+ wsValue.Format((FX_LPCWSTR)L"%d", iAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+FX_FLOAT CFDE_XMLInstruction::GetFloat(FX_LPCWSTR pwsAttriName, FX_FLOAT fDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FX_wcstof((FX_LPCWSTR)m_Attributes[i + 1]);
+ }
+ }
+ return fDefValue;
+}
+void CFDE_XMLInstruction::SetFloat(FX_LPCWSTR pwsAttriName, FX_FLOAT fAttriValue)
+{
+ CFX_WideString wsValue;
+ wsValue.Format((FX_LPCWSTR)L"%f", fAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+void CFDE_XMLInstruction::RemoveAttribute(FX_LPCWSTR pwsAttriName)
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ m_Attributes.RemoveAt(i + 1);
+ m_Attributes.RemoveAt(i);
+ return;
+ }
+ }
+}
+FX_INT32 CFDE_XMLInstruction::CountData() const
+{
+ return m_TargetData.GetSize();
+}
+FX_BOOL CFDE_XMLInstruction::GetData(FX_INT32 index, CFX_WideString &wsData) const
+{
+ if (index < 0 || index >= m_TargetData.GetSize()) {
+ return FALSE;
+ }
+ wsData = m_TargetData[index];
+ return TRUE;
+}
+void CFDE_XMLInstruction::AppendData(const CFX_WideString &wsData)
+{
+ m_TargetData.Add(wsData);
+}
+void CFDE_XMLInstruction::RemoveData(FX_INT32 index)
+{
+ m_TargetData.RemoveAt(index);
+}
+IFDE_XMLElement* IFDE_XMLElement::Create(const CFX_WideString &wsTag)
+{
+ return (IFDE_XMLElement*)FDE_New CFDE_XMLElement(wsTag);
+}
+CFDE_XMLElement::CFDE_XMLElement(const CFX_WideString &wsTag)
+ : CFDE_XMLNode()
+ , m_wsTag(wsTag)
+ , m_Attributes()
+{
+ FXSYS_assert(m_wsTag.GetLength() > 0);
+}
+CFDE_XMLElement::~CFDE_XMLElement()
+{
+ m_Attributes.RemoveAll();
+}
+CFDE_XMLNode* CFDE_XMLElement::Clone(FX_BOOL bRecursive)
+{
+ CFDE_XMLElement* pClone = FDE_New CFDE_XMLElement(m_wsTag);
+ if (!pClone) {
+ return NULL;
+ }
+ pClone->m_Attributes.Copy(m_Attributes);
+ if (bRecursive) {
+ CloneChildren(pClone);
+ } else {
+ CFX_WideString wsText;
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild != NULL) {
+ switch (pChild->GetType()) {
+ case FDE_XMLNODE_Text:
+ wsText += ((CFDE_XMLText*)pChild)->m_wsText;
+ break;
+ default:
+ break;
+ }
+ pChild = pChild->m_pNext;
+ }
+ pClone->SetTextData(wsText);
+ }
+ return pClone;
+}
+void CFDE_XMLElement::GetTagName(CFX_WideString &wsTag) const
+{
+ wsTag = m_wsTag;
+}
+void CFDE_XMLElement::GetLocalTagName(CFX_WideString &wsTag) const
+{
+ FX_STRSIZE iFind = m_wsTag.Find(L':', 0);
+ if (iFind < 0) {
+ wsTag = m_wsTag;
+ } else {
+ wsTag = m_wsTag.Right(m_wsTag.GetLength() - iFind - 1);
+ }
+}
+void CFDE_XMLElement::GetNamespacePrefix(CFX_WideString &wsPrefix) const
+{
+ FX_STRSIZE iFind = m_wsTag.Find(L':', 0);
+ if (iFind < 0) {
+ wsPrefix.Empty();
+ } else {
+ wsPrefix = m_wsTag.Left(iFind);
+ }
+}
+void CFDE_XMLElement::GetNamespaceURI(CFX_WideString &wsNamespace) const
+{
+ CFX_WideString wsAttri(L"xmlns"), wsPrefix;
+ GetNamespacePrefix(wsPrefix);
+ if (wsPrefix.GetLength() > 0) {
+ wsAttri += L":";
+ wsAttri += wsPrefix;
+ }
+ wsNamespace.Empty();
+ CFDE_XMLNode *pNode = (CFDE_XMLNode*)this;
+ while (pNode != NULL) {
+ if (pNode->GetType() != FDE_XMLNODE_Element) {
+ break;
+ }
+ CFDE_XMLElement *pElement = (CFDE_XMLElement*)pNode;
+ if (!pElement->HasAttribute(wsAttri)) {
+ pNode = pNode->GetNodeItem(IFDE_XMLNode::Parent);
+ continue;
+ }
+ pElement->GetString(wsAttri, wsNamespace);
+ break;
+ }
+}
+FX_INT32 CFDE_XMLElement::CountAttributes() const
+{
+ return m_Attributes.GetSize() / 2;
+}
+FX_BOOL CFDE_XMLElement::GetAttribute(FX_INT32 index, CFX_WideString &wsAttriName, CFX_WideString &wsAttriValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ FXSYS_assert(index > -1 && index < iCount / 2);
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (index == 0) {
+ wsAttriName = m_Attributes[i];
+ wsAttriValue = m_Attributes[i + 1];
+ return TRUE;
+ }
+ index --;
+ }
+ return FALSE;
+}
+FX_BOOL CFDE_XMLElement::HasAttribute(FX_LPCWSTR pwsAttriName) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void CFDE_XMLElement::GetString(FX_LPCWSTR pwsAttriName, CFX_WideString &wsAttriValue, FX_LPCWSTR pwsDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ wsAttriValue = m_Attributes[i + 1];
+ return;
+ }
+ }
+ wsAttriValue = pwsDefValue;
+}
+void CFDE_XMLElement::SetString(const CFX_WideString &wsAttriName, const CFX_WideString &wsAttriValue)
+{
+ FXSYS_assert(wsAttriName.GetLength() > 0);
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(wsAttriName) == 0) {
+ m_Attributes[i] = wsAttriName;
+ m_Attributes[i + 1] = wsAttriValue;
+ return;
+ }
+ }
+ m_Attributes.Add(wsAttriName);
+ m_Attributes.Add(wsAttriValue);
+}
+FX_INT32 CFDE_XMLElement::GetInteger(FX_LPCWSTR pwsAttriName, FX_INT32 iDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FXSYS_wtoi((FX_LPCWSTR)m_Attributes[i + 1]);
+ }
+ }
+ return iDefValue;
+}
+void CFDE_XMLElement::SetInteger(FX_LPCWSTR pwsAttriName, FX_INT32 iAttriValue)
+{
+ CFX_WideString wsValue;
+ wsValue.Format((FX_LPCWSTR)L"%d", iAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+FX_FLOAT CFDE_XMLElement::GetFloat(FX_LPCWSTR pwsAttriName, FX_FLOAT fDefValue) const
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FX_wcstof((FX_LPCWSTR)m_Attributes[i + 1]);
+ }
+ }
+ return fDefValue;
+}
+void CFDE_XMLElement::SetFloat(FX_LPCWSTR pwsAttriName, FX_FLOAT fAttriValue)
+{
+ CFX_WideString wsValue;
+ wsValue.Format((FX_LPCWSTR)L"%f", fAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+void CFDE_XMLElement::RemoveAttribute(FX_LPCWSTR pwsAttriName)
+{
+ FX_INT32 iCount = m_Attributes.GetSize();
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ m_Attributes.RemoveAt(i + 1);
+ m_Attributes.RemoveAt(i);
+ return;
+ }
+ }
+}
+void CFDE_XMLElement::GetTextData(CFX_WideString &wsText) const
+{
+ CFX_WideTextBuf buffer;
+ CFDE_XMLNode *pChild = m_pChild;
+ while (pChild != NULL) {
+ switch (pChild->GetType()) {
+ case FDE_XMLNODE_Text:
+ buffer << ((CFDE_XMLText*)pChild)->m_wsText;
+ break;
+ case FDE_XMLNODE_CharData:
+ buffer << ((CFDE_XMLCharData*)pChild)->m_wsCharData;
+ break;
+ default:
+ break;
+ }
+ pChild = pChild->m_pNext;
+ }
+ wsText = buffer.GetWideString();
+}
+void CFDE_XMLElement::SetTextData(const CFX_WideString &wsText)
+{
+ if (wsText.GetLength() < 1) {
+ return;
+ }
+ InsertChildNode(FDE_New CFDE_XMLText(wsText));
+}
+IFDE_XMLText* IFDE_XMLText::Create(const CFX_WideString &wsText)
+{
+ return (IFDE_XMLText*)FDE_New CFDE_XMLText(wsText);
+}
+CFDE_XMLText::CFDE_XMLText(const CFX_WideString &wsText)
+ : CFDE_XMLNode()
+ , m_wsText(wsText)
+{
+}
+CFDE_XMLNode* CFDE_XMLText::Clone(FX_BOOL bRecursive)
+{
+ CFDE_XMLText* pClone = FDE_New CFDE_XMLText(m_wsText);
+ return pClone;
+}
+IFDE_XMLCharData* IFDE_XMLCharData::Create(const CFX_WideString &wsCData)
+{
+ return (IFDE_XMLCharData*)FDE_New CFDE_XMLCharData(wsCData);
+}
+CFDE_XMLCharData::CFDE_XMLCharData(const CFX_WideString &wsCData)
+ : CFDE_XMLDeclaration()
+ , m_wsCharData(wsCData)
+{
+}
+CFDE_XMLNode* CFDE_XMLCharData::Clone(FX_BOOL bRecursive)
+{
+ CFDE_XMLCharData* pClone = FDE_New CFDE_XMLCharData(m_wsCharData);
+ return pClone;
+}
+IFDE_XMLDoc* IFDE_XMLDoc::Create()
+{
+ return (IFDE_XMLDoc*)FDE_New CFDE_XMLDoc;
+}
+CFDE_XMLDoc::CFDE_XMLDoc()
+ : m_pRoot(NULL)
+ , m_pSyntaxParser(NULL)
+ , m_pXMLParser(NULL)
+{
+ Reset(TRUE);
+ CFDE_XMLInstruction *pXML = FDE_New CFDE_XMLInstruction((FX_LPCWSTR)L"xml");
+ m_pRoot->InsertChildNode(pXML);
+}
+CFDE_XMLDoc::~CFDE_XMLDoc()
+{
+ Reset(FALSE);
+}
+void CFDE_XMLDoc::Reset(FX_BOOL bInitRoot)
+{
+ m_iStatus = 0;
+ m_pStream = NULL;
+ if (bInitRoot) {
+ if (m_pRoot == NULL) {
+ m_pRoot = FDE_New CFDE_XMLNode;
+ } else {
+ m_pRoot->DeleteChildren();
+ }
+ } else {
+ if (m_pRoot != NULL) {
+ m_pRoot->Release();
+ m_pRoot = NULL;
+ }
+ }
+ ReleaseParser();
+}
+void CFDE_XMLDoc::ReleaseParser()
+{
+ if (m_pXMLParser != NULL) {
+ m_pXMLParser->Release();
+ m_pXMLParser = NULL;
+ }
+ if (m_pSyntaxParser != NULL) {
+ m_pSyntaxParser->Release();
+ m_pSyntaxParser = NULL;
+ }
+}
+FX_BOOL CFDE_XMLDoc::LoadXML(IFX_Stream *pXMLStream, FX_INT32 iXMLPlaneSize , FX_INT32 iTextDataSize , FDE_LPXMLREADERHANDLER pHandler )
+{
+ if (pXMLStream == NULL) {
+ return FALSE;
+ }
+ Reset(TRUE);
+ iXMLPlaneSize = iXMLPlaneSize / 1024;
+ if (iXMLPlaneSize < 1) {
+ iXMLPlaneSize = 1;
+ }
+ iXMLPlaneSize *= 1024;
+ if (iXMLPlaneSize < 4096) {
+ iXMLPlaneSize = 4096;
+ }
+ iTextDataSize = iTextDataSize / 128;
+ if (iTextDataSize < 1) {
+ iTextDataSize = 1;
+ }
+ iTextDataSize *= 128;
+ if (iTextDataSize < 128) {
+ iTextDataSize = 128;
+ }
+ m_pStream = pXMLStream;
+ FX_WORD wCodePage = m_pStream->GetCodePage();
+ if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && wCodePage != FX_CODEPAGE_UTF8) {
+ m_pStream->SetCodePage(FX_CODEPAGE_UTF8);
+ }
+ m_pSyntaxParser = IFDE_XMLSyntaxParser::Create();
+ if (m_pSyntaxParser == NULL) {
+ return FALSE;
+ }
+ m_pSyntaxParser->Init(m_pStream, iXMLPlaneSize, iTextDataSize);
+ if (pHandler == NULL) {
+ m_pXMLParser = FDE_New CFDE_XMLDOMParser(m_pRoot, m_pSyntaxParser);
+ } else {
+ m_pXMLParser = FDE_New CFDE_XMLSAXParser(pHandler, m_pSyntaxParser);
+ }
+ return m_pXMLParser != NULL;
+}
+FX_BOOL CFDE_XMLDoc::LoadXML(IFDE_XMLParser *pXMLParser)
+{
+ if (pXMLParser == NULL) {
+ return FALSE;
+ }
+ Reset(TRUE);
+ m_pXMLParser = pXMLParser;
+ return m_pXMLParser != NULL;
+}
+FX_INT32 CFDE_XMLDoc::DoLoad(IFX_Pause *pPause)
+{
+ if (m_iStatus >= 100) {
+ return m_iStatus;
+ }
+ FXSYS_assert(m_pXMLParser != NULL);
+ return m_iStatus = m_pXMLParser->DoParser(pPause);
+}
+void CFDE_XMLDoc::CloseXML()
+{
+ ReleaseParser();
+}
+void CFDE_XMLDoc::SaveXMLNode(IFX_Stream *pXMLStream, IFDE_XMLNode *pINode)
+{
+ CFDE_XMLNode *pNode = (CFDE_XMLNode*)pINode;
+ FXSYS_assert(pXMLStream != NULL && pNode != NULL);
+ switch (pNode->GetType()) {
+ case FDE_XMLNODE_Instruction: {
+ CFX_WideString ws;
+ CFDE_XMLInstruction *pInstruction = (CFDE_XMLInstruction*)pNode;
+ if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
+ ws = L"<?xml version=\"1.0\" encoding=\"";
+ FX_WORD wCodePage = pXMLStream->GetCodePage();
+ if (wCodePage == FX_CODEPAGE_UTF16LE) {
+ ws += L"UTF-16";
+ } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
+ ws += L"UTF-16be";
+ } else {
+ ws += L"UTF-8";
+ }
+ ws += L"\"?>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ } else {
+ ws.Format((FX_LPCWSTR)L"<?%s", (FX_LPCWSTR)pInstruction->m_wsTarget);
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray &attributes = pInstruction->m_Attributes;
+ FX_INT32 i, iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ wsValue.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ wsValue.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ wsValue.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ wsValue.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ ws += wsValue;
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ CFX_WideStringArray &targetdata = pInstruction->m_TargetData;
+ iCount = targetdata.GetSize();
+ for (i = 0; i < iCount; i++) {
+ ws = L" \"";
+ ws += targetdata[i];
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ ws = L"?>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ }
+ break;
+ case FDE_XMLNODE_Element: {
+ CFX_WideString ws;
+ ws = L"<";
+ ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray &attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
+ FX_INT32 iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (FX_INT32 i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ wsValue.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ wsValue.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ wsValue.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ wsValue.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ ws += wsValue;
+ ws += L"\"";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ if (pNode->m_pChild == NULL) {
+ ws = L"\n/>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ } else {
+ ws = L"\n>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFDE_XMLNode *pChild = pNode->m_pChild;
+ while (pChild != NULL) {
+ SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pChild);
+ pChild = pChild->m_pNext;
+ }
+ ws = L"</";
+ ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
+ ws += L"\n>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ }
+ break;
+ case FDE_XMLNODE_Text: {
+ CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
+ ws.Replace((FX_LPCWSTR)L"&", (FX_LPCWSTR)L"&amp;");
+ ws.Replace((FX_LPCWSTR)L"<", (FX_LPCWSTR)L"&lt;");
+ ws.Replace((FX_LPCWSTR)L">", (FX_LPCWSTR)L"&gt;");
+ ws.Replace((FX_LPCWSTR)L"\'", (FX_LPCWSTR)L"&apos;");
+ ws.Replace((FX_LPCWSTR)L"\"", (FX_LPCWSTR)L"&quot;");
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ break;
+ case FDE_XMLNODE_CharData: {
+ CFX_WideString ws = L"<![CDATA[";
+ ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
+ ws += L"]]>";
+ pXMLStream->WriteString(ws, ws.GetLength());
+ }
+ break;
+ case FDE_XMLNODE_Unknown:
+ break;
+ default:
+ break;
+ }
+}
+void CFDE_XMLDoc::SaveXML(IFX_Stream *pXMLStream, FX_BOOL bSaveBOM)
+{
+ if (pXMLStream == NULL || pXMLStream == m_pStream) {
+ m_pStream->Seek(FX_STREAMSEEK_Begin, 0);
+ pXMLStream = m_pStream;
+ }
+ FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Text) != 0);
+ FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Write) != 0);
+ FX_WORD wCodePage = pXMLStream->GetCodePage();
+ if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && wCodePage != FX_CODEPAGE_UTF8) {
+ wCodePage = FX_CODEPAGE_UTF8;
+ pXMLStream->SetCodePage(wCodePage);
+ }
+ if (bSaveBOM) {
+ pXMLStream->WriteString((FX_LPCWSTR)L"\xFEFF", 1);
+ }
+ CFDE_XMLNode *pNode = m_pRoot->m_pChild;
+ while (pNode != NULL) {
+ SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pNode);
+ pNode = pNode->m_pNext;
+ }
+ if (pXMLStream == m_pStream) {
+ FX_INT32 iPos = pXMLStream->GetPosition();
+ pXMLStream->SetLength(iPos);
+ }
+}
+CFDE_XMLDOMParser::CFDE_XMLDOMParser(CFDE_XMLNode *pRoot, IFDE_XMLSyntaxParser *pParser)
+ : m_pRoot(pRoot)
+ , m_pParser(pParser)
+ , m_pParent(pRoot)
+ , m_pChild(NULL)
+ , m_NodeStack(16)
+ , m_ws1()
+ , m_ws2()
+{
+ m_NodeStack.Push(m_pParent);
+}
+CFDE_XMLDOMParser::~CFDE_XMLDOMParser()
+{
+ m_NodeStack.RemoveAll();
+ m_ws1.Empty();
+ m_ws2.Empty();
+}
+FX_INT32 CFDE_XMLDOMParser::DoParser(IFX_Pause *pPause)
+{
+ FX_DWORD dwRet;
+ FX_INT32 iCount = 0;
+ while (TRUE) {
+ dwRet = m_pParser->DoSyntaxParse();
+ switch (dwRet) {
+ case FDE_XMLSYNTAXSTATUS_InstructionOpen:
+ break;
+ case FDE_XMLSYNTAXSTATUS_InstructionClose:
+ if (m_pChild->GetType() != FDE_XMLNODE_Instruction) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_pChild = m_pParent;
+ break;
+ case FDE_XMLSYNTAXSTATUS_ElementOpen:
+ case FDE_XMLSYNTAXSTATUS_ElementBreak:
+ break;
+ case FDE_XMLSYNTAXSTATUS_ElementClose:
+ if (m_pChild->GetType() != FDE_XMLNODE_Element) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_pParser->GetTagName(m_ws1);
+ ((CFDE_XMLElement*)m_pChild)->GetTagName(m_ws2);
+ if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_ws2) != 0) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_NodeStack.Pop();
+ if (m_NodeStack.GetSize() < 1) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_pParent = (CFDE_XMLNode*)*m_NodeStack.GetTopElement();
+ m_pChild = m_pParent;
+ iCount++;
+ break;
+ case FDE_XMLSYNTAXSTATUS_TargetName:
+ m_pParser->GetTargetName(m_ws1);
+ m_pChild = FDE_New CFDE_XMLInstruction(m_ws1);
+ m_pParent->InsertChildNode(m_pChild);
+ m_ws1.Empty();
+ break;
+ case FDE_XMLSYNTAXSTATUS_TagName:
+ m_pParser->GetTagName(m_ws1);
+ m_pChild = FDE_New CFDE_XMLElement(m_ws1);
+ m_pParent->InsertChildNode(m_pChild);
+ m_NodeStack.Push(m_pChild);
+ m_pParent = m_pChild;
+ break;
+ case FDE_XMLSYNTAXSTATUS_AttriName:
+ m_pParser->GetAttributeName(m_ws1);
+ break;
+ case FDE_XMLSYNTAXSTATUS_AttriValue:
+ if (m_pChild == NULL) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_pParser->GetAttributeName(m_ws2);
+ if (m_pChild->GetType() == FDE_XMLNODE_Element) {
+ ((CFDE_XMLElement*)m_pChild)->SetString(m_ws1, m_ws2);
+ } else if (m_pChild->GetType() == FDE_XMLNODE_Instruction) {
+ ((CFDE_XMLInstruction*)m_pChild)->SetString(m_ws1, m_ws2);
+ }
+ m_ws1.Empty();
+ break;
+ case FDE_XMLSYNTAXSTATUS_Text:
+ m_pParser->GetTextData(m_ws1);
+ m_pChild = FDE_New CFDE_XMLText(m_ws1);
+ m_pParent->InsertChildNode(m_pChild);
+ m_pChild = m_pParent;
+ break;
+ case FDE_XMLSYNTAXSTATUS_CData:
+ m_pParser->GetTextData(m_ws1);
+ m_pChild = FDE_New CFDE_XMLCharData(m_ws1);
+ m_pParent->InsertChildNode(m_pChild);
+ m_pChild = m_pParent;
+ break;
+ case FDE_XMLSYNTAXSTATUS_TargetData:
+ if (m_pChild == NULL || m_pChild->GetType() != FDE_XMLNODE_Instruction) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ if (!m_ws1.IsEmpty()) {
+ ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1);
+ }
+ m_pParser->GetTargetData(m_ws1);
+ ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1);
+ m_ws1.Empty();
+ break;
+ default:
+ break;
+ }
+ if (dwRet == FDE_XMLSYNTAXSTATUS_Error || dwRet == FDE_XMLSYNTAXSTATUS_EOS) {
+ break;
+ }
+ if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) {
+ break;
+ }
+ }
+ return m_pParser->GetStatus();
+}
+CFDE_XMLSAXParser::CFDE_XMLSAXParser(FDE_LPXMLREADERHANDLER pHandler, IFDE_XMLSyntaxParser *pParser)
+ : m_pHandler(pHandler)
+ , m_pParser(pParser)
+ , m_TagStack(16)
+ , m_pTagTop(NULL)
+ , m_ws1()
+ , m_ws2()
+{
+}
+CFDE_XMLSAXParser::~CFDE_XMLSAXParser()
+{
+ m_TagStack.RemoveAll();
+ m_ws1.Empty();
+ m_ws2.Empty();
+}
+FX_INT32 CFDE_XMLSAXParser::DoParser(IFX_Pause *pPause)
+{
+ FX_DWORD dwRet = 0;
+ FX_INT32 iCount = 0;
+ while (TRUE) {
+ dwRet = m_pParser->DoSyntaxParse();
+ switch (dwRet) {
+ case FDE_XMLSYNTAXSTATUS_ElementBreak:
+ if (m_pTagTop == NULL) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ if (m_pTagTop->eType == FDE_XMLNODE_Element) {
+ m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName);
+ }
+ break;
+ case FDE_XMLSYNTAXSTATUS_ElementClose:
+ if (m_pTagTop == NULL || m_pTagTop->eType != FDE_XMLNODE_Element) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ m_pParser->GetTagName(m_ws1);
+ if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_pTagTop->wsTagName) != 0) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ } else if (m_ws1.GetLength() == 0) {
+ m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName);
+ }
+ m_pHandler->OnTagClose(m_pHandler, m_pTagTop->wsTagName);
+ Pop();
+ iCount++;
+ break;
+ case FDE_XMLSYNTAXSTATUS_TargetName: {
+ m_pParser->GetTargetName(m_ws1);
+ CFDE_XMLTAG xmlTag;
+ xmlTag.wsTagName = m_ws1;
+ xmlTag.eType = FDE_XMLNODE_Instruction;
+ Push(xmlTag);
+ m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Instruction, m_pTagTop->wsTagName);
+ m_ws1.Empty();
+ }
+ break;
+ case FDE_XMLSYNTAXSTATUS_TagName: {
+ m_pParser->GetTargetName(m_ws1);
+ CFDE_XMLTAG xmlTag;
+ xmlTag.wsTagName = m_ws1;
+ xmlTag.eType = FDE_XMLNODE_Element;
+ Push(xmlTag);
+ m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Element, m_pTagTop->wsTagName);
+ }
+ break;
+ case FDE_XMLSYNTAXSTATUS_AttriName:
+ m_pParser->GetTargetName(m_ws1);
+ break;
+ case FDE_XMLSYNTAXSTATUS_AttriValue:
+ m_pParser->GetAttributeName(m_ws2);
+ if (m_pTagTop == NULL) {
+ dwRet = FDE_XMLSYNTAXSTATUS_Error;
+ break;
+ }
+ if (m_pTagTop->eType == FDE_XMLNODE_Element) {
+ m_pHandler->OnAttribute(m_pHandler, m_ws1, m_ws2);
+ }
+ m_ws1.Empty();
+ break;
+ case FDE_XMLSYNTAXSTATUS_CData:
+ m_pParser->GetTextData(m_ws1);
+ m_pHandler->OnData(m_pHandler, FDE_XMLNODE_CharData, m_ws1);
+ break;
+ case FDE_XMLSYNTAXSTATUS_Text:
+ m_pParser->GetTextData(m_ws1);
+ m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Text, m_ws1);
+ break;
+ case FDE_XMLSYNTAXSTATUS_TargetData:
+ m_pParser->GetTargetData(m_ws1);
+ m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Instruction, m_ws1);
+ m_ws1.Empty();
+ break;
+ default:
+ break;
+ }
+ if (dwRet == FDE_XMLSYNTAXSTATUS_Error || dwRet == FDE_XMLSYNTAXSTATUS_EOS) {
+ break;
+ }
+ if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) {
+ break;
+ }
+ }
+ return m_pParser->GetStatus();
+}
+inline void CFDE_XMLSAXParser::Push(const CFDE_XMLTAG &xmlTag)
+{
+ m_TagStack.Push(xmlTag);
+ m_pTagTop = m_TagStack.GetTopElement();
+}
+inline void CFDE_XMLSAXParser::Pop()
+{
+ m_TagStack.Pop();
+ m_pTagTop = m_TagStack.GetTopElement();
+}
+#ifdef _FDE_BLOCK_BUFFER
+CFDE_BlockBuffer::CFDE_BlockBuffer(FX_INT32 iAllocStep)
+ : m_iAllocStep(iAllocStep),
+ m_iStartPosition(0),
+ m_iBufferSize(0),
+ m_iDataLength(0)
+{
+}
+CFDE_BlockBuffer::~CFDE_BlockBuffer()
+{
+ ClearBuffer();
+}
+FX_LPWSTR CFDE_BlockBuffer::GetAvailableBlock(FX_INT32& iIndexInBlock)
+{
+ iIndexInBlock = 0;
+ FX_INT32 iBlockNum = m_BlockArray.GetSize();
+ if (iBlockNum == 0) {
+ return NULL;
+ }
+ FX_INT32 iRealIndex = m_iStartPosition + m_iDataLength;
+ FX_LPWSTR pDataBlock = NULL;
+ if(iRealIndex == m_iBufferSize) {
+ FX_LPWSTR pBlock = (FX_LPWSTR)FDE_Alloc(m_iAllocStep * sizeof(FX_WCHAR));
+ if (pBlock) {
+ m_BlockArray.Add(pBlock);
+ m_iBufferSize += m_iAllocStep;
+ }
+ iIndexInBlock = 0;
+ pDataBlock = pBlock;
+ } else {
+ FX_INT32 iBlockIndex = iRealIndex / m_iAllocStep;
+ FX_INT32 iInnerIndex = iRealIndex % m_iAllocStep;
+ iIndexInBlock = iInnerIndex;
+ pDataBlock = (FX_LPWSTR)m_BlockArray[iBlockIndex];
+ }
+ return pDataBlock;
+}
+FX_BOOL CFDE_BlockBuffer::InitBuffer(FX_INT32 iBufferSize)
+{
+ ClearBuffer();
+ FX_INT32 iNumOfBlock = (iBufferSize - 1) / m_iAllocStep + 1;
+ for (FX_INT32 i = 0; i < iNumOfBlock; i++) {
+ FX_LPWSTR pBlockBuffer = (FX_LPWSTR)FDE_Alloc(m_iAllocStep * sizeof(FX_WCHAR));
+ if (pBlockBuffer == NULL) {
+ ClearBuffer();
+ return FALSE;
+ }
+ m_BlockArray.Add(pBlockBuffer);
+ }
+ m_iBufferSize = iNumOfBlock * m_iAllocStep;
+ return TRUE;
+}
+void CFDE_BlockBuffer::SetTextChar(FX_INT32 iIndex, FX_WCHAR ch)
+{
+ if (iIndex < 0) {
+ return;
+ }
+ FX_INT32 iRealIndex = m_iStartPosition + iIndex;
+ FX_INT32 iBlockIndex = iRealIndex / m_iAllocStep;
+ FX_INT32 iInnerIndex = iRealIndex % m_iAllocStep;
+ FX_INT32 iBlockSize = m_BlockArray.GetSize();
+ if (iBlockIndex >= iBlockSize) {
+ FX_INT32 iNewBlocks = iBlockIndex - iBlockSize + 1;
+ do {
+ FX_LPWSTR pBlock = (FX_LPWSTR)FDE_Alloc(m_iAllocStep * sizeof(FX_WCHAR));
+ if (!pBlock) {
+ return;
+ }
+ m_BlockArray.Add(pBlock);
+ m_iBufferSize += m_iAllocStep;
+ } while (--iNewBlocks);
+ }
+ FX_LPWSTR pTextData = (FX_LPWSTR)m_BlockArray[iBlockIndex];
+ *(pTextData + iInnerIndex) = ch;
+ if (m_iDataLength <= iIndex) {
+ m_iDataLength = iIndex + 1;
+ }
+}
+FX_INT32 CFDE_BlockBuffer::DeleteTextChars(FX_INT32 iCount, FX_BOOL bDirection )
+{
+ if (iCount <= 0) {
+ return m_iDataLength;
+ }
+ if (iCount >= m_iDataLength) {
+ Reset(FALSE);
+ return 0;
+ }
+ if (bDirection) {
+ m_iStartPosition += iCount;
+ m_iDataLength -= iCount;
+ } else {
+ m_iDataLength -= iCount;
+ }
+ return m_iDataLength;
+}
+void CFDE_BlockBuffer::GetTextData(CFX_WideString& wsTextData, FX_INT32 iStart, FX_INT32 iLength) const
+{
+ wsTextData.Empty();
+ FX_INT32 iMaybeDataLength = m_iBufferSize - 1 - m_iStartPosition;
+ if (iStart < 0 || iStart > iMaybeDataLength) {
+ return;
+ }
+ if (iLength == -1 || iLength > iMaybeDataLength) {
+ iLength = iMaybeDataLength;
+ }
+ if (iLength <= 0) {
+ return;
+ }
+ FX_LPWSTR pBuf = wsTextData.GetBuffer(iLength);
+ if (!pBuf) {
+ return;
+ }
+ FX_INT32 iStartBlockIndex = 0;
+ FX_INT32 iStartInnerIndex = 0;
+ TextDataIndex2BufIndex(iStart, iStartBlockIndex, iStartInnerIndex);
+ FX_INT32 iEndBlockIndex = 0;
+ FX_INT32 iEndInnerIndex = 0;
+ TextDataIndex2BufIndex(iStart + iLength, iEndBlockIndex, iEndInnerIndex);
+ FX_INT32 iPointer = 0;
+ for (FX_INT32 i = iStartBlockIndex; i <= iEndBlockIndex; i++) {
+ FX_INT32 iBufferPointer = 0;
+ FX_INT32 iCopyLength = m_iAllocStep;
+ if (i == iStartBlockIndex) {
+ iCopyLength -= iStartInnerIndex;
+ iBufferPointer = iStartInnerIndex;
+ }
+ if (i == iEndBlockIndex) {
+ iCopyLength -= ((m_iAllocStep - 1) - iEndInnerIndex);
+ }
+ FX_LPWSTR pBlockBuf = (FX_LPWSTR)m_BlockArray[i];
+ FXSYS_memcpy(pBuf + iPointer, pBlockBuf + iBufferPointer, iCopyLength * sizeof(FX_WCHAR));
+ iPointer += iCopyLength;
+ }
+ wsTextData.ReleaseBuffer(iLength);
+}
+void CFDE_BlockBuffer::TextDataIndex2BufIndex(const FX_INT32 iIndex, FX_INT32& iBlockIndex, FX_INT32& iInnerIndex) const
+{
+ FXSYS_assert(iIndex >= 0);
+ FX_INT32 iRealIndex = m_iStartPosition + iIndex;
+ iBlockIndex = iRealIndex / m_iAllocStep;
+ iInnerIndex = iRealIndex % m_iAllocStep;
+}
+void CFDE_BlockBuffer::ClearBuffer()
+{
+ m_iBufferSize = 0;
+ FX_INT32 iSize = m_BlockArray.GetSize();
+ for (FX_INT32 i = 0; i < iSize; i++) {
+ FDE_Free(m_BlockArray[i]);
+ m_BlockArray[i] = NULL;
+ }
+ m_BlockArray.RemoveAll();
+}
+#endif
+IFDE_XMLSyntaxParser* IFDE_XMLSyntaxParser::Create()
+{
+ return FDE_New CFDE_XMLSyntaxParser;
+}
+#ifdef _FDE_BLOCK_BUFFER
+CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser()
+ : m_pStream(NULL)
+ , m_iXMLPlaneSize(-1)
+ , m_iCurrentPos(0)
+ , m_iCurrentNodeNum(-1)
+ , m_iLastNodeNum(-1)
+ , m_iParsedChars(0)
+ , m_iParsedBytes(0)
+ , m_pBuffer(NULL)
+ , m_iBufferChars(0)
+ , m_bEOS(FALSE)
+ , m_pStart(NULL)
+ , m_pEnd(NULL)
+ , m_XMLNodeStack(16)
+ , m_dwStatus(FDE_XMLSYNTAXSTATUS_None)
+ , m_dwMode(FDE_XMLSYNTAXMODE_Text)
+ , m_wQuotationMark(0)
+ , m_BlockBuffer()
+ , m_pCurrentBlock(NULL)
+ , m_iIndexInBlock(0)
+ , m_iDataLength(m_BlockBuffer.GetDataLengthRef())
+ , m_iAllocStep(m_BlockBuffer.GetAllocStep())
+ , m_iTextDataLength(0)
+ , m_iEntityStart(-1)
+ , m_SkipStack(16)
+{
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+}
+void CFDE_XMLSyntaxParser::Init(IFX_Stream *pStream, FX_INT32 iXMLPlaneSize, FX_INT32 iTextDataSize )
+{
+ FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL);
+ FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0);
+ FX_INT32 iStreamLength = pStream->GetLength();
+ FXSYS_assert(iStreamLength > 0);
+ m_pStream = pStream;
+ m_iXMLPlaneSize = FX_MIN(iXMLPlaneSize, iStreamLength);
+ FX_BYTE bom[4];
+ m_iCurrentPos = m_pStream->GetBOM(bom);
+ FXSYS_assert(m_pBuffer == NULL);
+ m_pBuffer = (FX_LPWSTR)FDE_Alloc(m_iXMLPlaneSize * sizeof(FX_WCHAR));
+ m_pStart = m_pEnd = m_pBuffer;
+ FXSYS_assert(!m_BlockBuffer.IsInitialized());
+ m_BlockBuffer.InitBuffer();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_iParsedBytes = m_iParsedChars = 0;
+ m_iBufferChars = 0;
+}
+FX_DWORD CFDE_XMLSyntaxParser::DoSyntaxParse()
+{
+ if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error || m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
+ return m_dwStatus;
+ }
+ FXSYS_assert(m_pStream != NULL && m_pBuffer != NULL && m_BlockBuffer.IsInitialized());
+ FX_INT32 iStreamLength = m_pStream->GetLength();
+ FX_INT32 iPos;
+ FX_WCHAR ch;
+ FX_DWORD dwStatus = FDE_XMLSYNTAXSTATUS_None;
+ while (TRUE) {
+ if (m_pStart >= m_pEnd) {
+ if (m_bEOS || m_iCurrentPos >= iStreamLength) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
+ return m_dwStatus;
+ }
+ m_iParsedChars += (m_pEnd - m_pBuffer);
+ m_iParsedBytes = m_iCurrentPos;
+ m_pStream->Lock();
+ if (m_pStream->GetPosition() != m_iCurrentPos) {
+ m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos);
+ }
+ m_iBufferChars = m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS);
+ iPos = m_pStream->GetPosition();
+ m_pStream->Unlock();
+ if (m_iBufferChars < 1) {
+ m_iCurrentPos = iStreamLength;
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
+ return m_dwStatus;
+ }
+ m_iCurrentPos = iPos;
+ m_pStart = m_pBuffer;
+ m_pEnd = m_pBuffer + m_iBufferChars;
+ }
+ while (m_pStart < m_pEnd) {
+ ch = *m_pStart;
+ switch (m_dwMode) {
+ case FDE_XMLSYNTAXMODE_Text:
+ if (ch == L'<') {
+ if (m_iDataLength > 0) {
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_iEntityStart = -1;
+ dwStatus = FDE_XMLSYNTAXSTATUS_Text;
+ } else {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_Node;
+ }
+ } else {
+ ParseTextChar(ch);
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_Node:
+ if (ch == L'!') {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipCommentOrDecl;
+ } else if (ch == L'/') {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
+ } else if (ch == L'?') {
+ m_iLastNodeNum ++;
+ m_iCurrentNodeNum = m_iLastNodeNum;
+ m_CurNode.iNodeNum = m_iLastNodeNum;
+ m_CurNode.eNodeType = FDE_XMLNODE_Instruction;
+ m_XMLNodeStack.Push(m_CurNode);
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_Target;
+ dwStatus = FDE_XMLSYNTAXSTATUS_InstructionOpen;
+ } else {
+ m_iLastNodeNum ++;
+ m_iCurrentNodeNum = m_iLastNodeNum;
+ m_CurNode.iNodeNum = m_iLastNodeNum;
+ m_CurNode.eNodeType = FDE_XMLNODE_Element;
+ m_XMLNodeStack.Push(m_CurNode);
+ m_dwMode = FDE_XMLSYNTAXMODE_Tag;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementOpen;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_Target:
+ case FDE_XMLSYNTAXMODE_Tag:
+ if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
+ if (m_iDataLength < 1) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (m_dwMode != FDE_XMLSYNTAXMODE_Target) {
+ dwStatus = FDE_XMLSYNTAXSTATUS_TagName;
+ } else {
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetName;
+ }
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
+ }
+ } else {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriName:
+ if (m_iDataLength < 1 && FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
+ if (m_iDataLength < 1) {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Element) {
+ if (ch == L'>' || ch == L'/') {
+ m_dwMode = FDE_XMLSYNTAXMODE_BreakElement;
+ break;
+ }
+ } else if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ if (ch == L'?') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
+ m_pStart++;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ }
+ break;
+ }
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ if (ch != '=' && !FDE_IsXMLWhiteSpace(ch)) {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ break;
+ }
+ }
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriEqualSign;
+ dwStatus = FDE_XMLSYNTAXSTATUS_AttriName;
+ }
+ } else {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriEqualSign:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (ch != L'=') {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ break;
+ }
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriQuotation;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriQuotation:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (ch != L'\"' && ch != L'\'') {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_wQuotationMark = ch;
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriValue;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriValue:
+ if (ch == m_wQuotationMark) {
+ if (m_iEntityStart > -1) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_iTextDataLength = m_iDataLength;
+ m_wQuotationMark = 0;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
+ dwStatus = FDE_XMLSYNTAXSTATUS_AttriValue;
+ } else {
+ ParseTextChar(ch);
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_CloseInstruction:
+ if (ch != L'>') {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ } else if (m_iDataLength > 0) {
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ } else {
+ m_pStart ++;
+ FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_XMLNodeStack.Pop();
+ pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+ } else {
+ m_CurNode = *pXMLNode;
+ }
+ m_iCurrentNodeNum = m_CurNode.iNodeNum;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_InstructionClose;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_BreakElement:
+ if (ch == L'>') {
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementBreak;
+ } else if (ch == L'/') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
+ } else {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_pStart ++;
+ break;
+ case FDE_XMLSYNTAXMODE_CloseElement:
+ if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
+ if (ch == L'>') {
+ FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_XMLNodeStack.Pop();
+ pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+ } else {
+ m_CurNode = *pXMLNode;
+ }
+ m_iCurrentNodeNum = m_CurNode.iNodeNum;
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementClose;
+ } else if (!FDE_IsXMLWhiteSpace(ch)) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ } else {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ }
+ m_pStart ++;
+ break;
+ case FDE_XMLSYNTAXMODE_SkipCommentOrDecl:
+ if (ch == '-') {
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipComment;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipDeclNode;
+ m_SkipChar = L'>';
+ m_SkipStack.Push(L'>');
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_SkipDeclNode:
+ if (m_SkipChar == L'\'' || m_SkipChar == L'\"') {
+ m_pStart ++;
+ if (ch != m_SkipChar) {
+ break;
+ }
+ m_SkipStack.Pop();
+ FX_LPDWORD pDWord = m_SkipStack.GetTopElement();
+ if (pDWord == NULL) {
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ } else {
+ m_SkipChar = (FX_WCHAR) * pDWord;
+ }
+ } else {
+ switch (ch) {
+ case L'<':
+ m_SkipChar = L'>';
+ m_SkipStack.Push(L'>');
+ break;
+ case L'[':
+ m_SkipChar = L']';
+ m_SkipStack.Push(L']');
+ break;
+ case L'(':
+ m_SkipChar = L')';
+ m_SkipStack.Push(L')');
+ break;
+ case L'\'':
+ m_SkipChar = L'\'';
+ m_SkipStack.Push(L'\'');
+ break;
+ case L'\"':
+ m_SkipChar = L'\"';
+ m_SkipStack.Push(L'\"');
+ break;
+ default:
+ if (ch == m_SkipChar) {
+ m_SkipStack.Pop();
+ FX_LPDWORD pDWord = m_SkipStack.GetTopElement();
+ if (pDWord == NULL) {
+ if (m_iDataLength >= 9) {
+ CFX_WideString wsHeader;
+ m_BlockBuffer.GetTextData(wsHeader, 0, 7);
+ if (wsHeader.Equal(FX_WSTRC(L"[CDATA["))) {
+ CFX_WideString wsTailer;
+ m_BlockBuffer.GetTextData(wsTailer, m_iDataLength - 2, 2);
+ if (wsTailer.Equal(FX_WSTRC(L"]]"))) {
+ m_BlockBuffer.DeleteTextChars(7, TRUE);
+ m_BlockBuffer.DeleteTextChars(2, FALSE);
+ dwStatus = FDE_XMLSYNTAXSTATUS_CData;
+ }
+ }
+ }
+ m_iTextDataLength = m_iDataLength;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ } else {
+ m_SkipChar = (FX_WCHAR) * pDWord;
+ }
+ }
+ break;
+ }
+ if (m_SkipStack.GetSize() > 0) {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ }
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_SkipComment:
+ if (ch == L'-') {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = L'-';
+ m_iDataLength++;
+ } else if (ch == L'>') {
+ if (m_iDataLength > 1) {
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ }
+ } else {
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ }
+ m_pStart++;
+ break;
+ case FDE_XMLSYNTAXMODE_TargetData:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ if (m_iDataLength < 1) {
+ m_pStart ++;
+ break;
+ } else if (m_wQuotationMark == 0) {
+ m_iTextDataLength = m_iDataLength;
+ m_wQuotationMark = 0;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_pStart ++;
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ break;
+ }
+ }
+ if (ch == '?') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
+ m_pStart++;
+ } else if (ch == '\"') {
+ if (m_wQuotationMark == 0) {
+ m_wQuotationMark = ch;
+ m_pStart++;
+ } else if (ch == m_wQuotationMark) {
+ m_iTextDataLength = m_iDataLength;
+ m_wQuotationMark = 0;
+ m_BlockBuffer.Reset();
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_pStart ++;
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ } else {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ } else {
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return FDE_XMLSYNTAXSTATUS_Error;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ m_pStart ++;
+ }
+ break;
+ default:
+ break;
+ }
+ if (dwStatus != FDE_XMLSYNTAXSTATUS_None) {
+ return dwStatus;
+ }
+ }
+ }
+ return 0;
+}
+#else
+CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser()
+ : m_pStream(NULL)
+ , m_iXMLPlaneSize(-1)
+ , m_iTextDataSize(256)
+ , m_iCurrentPos(0)
+ , m_iCurrentNodeNum(-1)
+ , m_iLastNodeNum(-1)
+ , m_iParsedChars(0)
+ , m_iParsedBytes(0)
+ , m_pBuffer(NULL)
+ , m_iBufferChars(0)
+ , m_bEOS(FALSE)
+ , m_pStart(NULL)
+ , m_pEnd(NULL)
+ , m_XMLNodeStack(16)
+ , m_pwsTextData(NULL)
+ , m_iDataPos(0)
+ , m_dwStatus(FDE_XMLSYNTAXSTATUS_None)
+ , m_dwMode(FDE_XMLSYNTAXMODE_Text)
+ , m_wQuotationMark(0)
+ , m_iTextDataLength(0)
+ , m_iEntityStart(-1)
+ , m_SkipStack(16)
+{
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+}
+void CFDE_XMLSyntaxParser::Init(IFX_Stream *pStream, FX_INT32 iXMLPlaneSize, FX_INT32 iTextDataSize )
+{
+ FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL);
+ FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0 && iTextDataSize > 0);
+ FX_INT32 iStreamLength = pStream->GetLength();
+ FXSYS_assert(iStreamLength > 0);
+ m_pStream = pStream;
+ m_iXMLPlaneSize = FX_MIN(iXMLPlaneSize, iStreamLength);
+ m_iTextDataSize = iTextDataSize;
+ FX_BYTE bom[4];
+ m_iCurrentPos = m_pStream->GetBOM(bom);
+ FXSYS_assert(m_pBuffer == NULL);
+ m_pBuffer = (FX_LPWSTR)FDE_Alloc(m_iXMLPlaneSize * sizeof(FX_WCHAR));
+ m_pStart = m_pEnd = m_pBuffer;
+ FXSYS_assert(m_pwsTextData == NULL);
+ m_pwsTextData = (FX_LPWSTR)FDE_Alloc(m_iTextDataSize * sizeof(FX_WCHAR));
+ m_iParsedBytes = m_iParsedChars = 0;
+ m_iBufferChars = 0;
+}
+FX_DWORD CFDE_XMLSyntaxParser::DoSyntaxParse()
+{
+ if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error || m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
+ return m_dwStatus;
+ }
+ FXSYS_assert(m_pStream != NULL && m_pBuffer != NULL && m_pwsTextData != NULL);
+ FX_INT32 iStreamLength = m_pStream->GetLength();
+ FX_INT32 iPos;
+ FX_WCHAR ch;
+ FX_DWORD dwStatus = FDE_XMLSYNTAXSTATUS_None;
+ while (TRUE) {
+ if (m_pStart >= m_pEnd) {
+ if (m_bEOS || m_iCurrentPos >= iStreamLength) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
+ return m_dwStatus;
+ }
+ m_iParsedChars += (m_pEnd - m_pBuffer);
+ m_iParsedBytes = m_iCurrentPos;
+ m_pStream->Lock();
+ if (m_pStream->GetPosition() != m_iCurrentPos) {
+ m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos);
+ }
+ m_iBufferChars = m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS);
+ iPos = m_pStream->GetPosition();
+ m_pStream->Unlock();
+ if (m_iBufferChars < 1) {
+ m_iCurrentPos = iStreamLength;
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
+ return m_dwStatus;
+ }
+ m_iCurrentPos = iPos;
+ m_pStart = m_pBuffer;
+ m_pEnd = m_pBuffer + m_iBufferChars;
+ }
+ while (m_pStart < m_pEnd) {
+ ch = *m_pStart;
+ switch (m_dwMode) {
+ case FDE_XMLSYNTAXMODE_Text:
+ if (ch == L'<') {
+ if (m_iDataPos > 0) {
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ m_iEntityStart = -1;
+ dwStatus = FDE_XMLSYNTAXSTATUS_Text;
+ } else {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_Node;
+ }
+ } else {
+ ParseTextChar(ch);
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_Node:
+ if (ch == L'!') {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipCommentOrDecl;
+ } else if (ch == L'/') {
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
+ } else if (ch == L'?') {
+ m_iLastNodeNum ++;
+ m_iCurrentNodeNum = m_iLastNodeNum;
+ m_CurNode.iNodeNum = m_iLastNodeNum;
+ m_CurNode.eNodeType = FDE_XMLNODE_Instruction;
+ m_XMLNodeStack.Push(m_CurNode);
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_Target;
+ dwStatus = FDE_XMLSYNTAXSTATUS_InstructionOpen;
+ } else {
+ m_iLastNodeNum ++;
+ m_iCurrentNodeNum = m_iLastNodeNum;
+ m_CurNode.iNodeNum = m_iLastNodeNum;
+ m_CurNode.eNodeType = FDE_XMLNODE_Element;
+ m_XMLNodeStack.Push(m_CurNode);
+ m_dwMode = FDE_XMLSYNTAXMODE_Tag;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementOpen;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_Target:
+ case FDE_XMLSYNTAXMODE_Tag:
+ if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
+ if (m_iDataPos < 1) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_dwMode != FDE_XMLSYNTAXMODE_Target) {
+ dwStatus = FDE_XMLSYNTAXSTATUS_TagName;
+ } else {
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetName;
+ }
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
+ }
+ } else {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriName:
+ if (m_iDataPos < 1 && FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
+ if (m_iDataPos < 1) {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Element) {
+ if (ch == L'>' || ch == L'/') {
+ m_dwMode = FDE_XMLSYNTAXMODE_BreakElement;
+ break;
+ }
+ } else if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ if (ch == L'?') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
+ m_pStart++;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ }
+ break;
+ }
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ if (ch != '=' && !FDE_IsXMLWhiteSpace(ch)) {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ break;
+ }
+ }
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriEqualSign;
+ dwStatus = FDE_XMLSYNTAXSTATUS_AttriName;
+ }
+ } else {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriEqualSign:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (ch != L'=') {
+ if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ break;
+ }
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriQuotation;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriQuotation:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ m_pStart ++;
+ break;
+ }
+ if (ch != L'\"' && ch != L'\'') {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ } else {
+ m_wQuotationMark = ch;
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriValue;
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_AttriValue:
+ if (ch == m_wQuotationMark) {
+ if (m_iEntityStart > -1) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_iTextDataLength = m_iDataPos;
+ m_wQuotationMark = 0;
+ m_iDataPos = 0;
+ m_pStart ++;
+ m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
+ dwStatus = FDE_XMLSYNTAXSTATUS_AttriValue;
+ } else {
+ ParseTextChar(ch);
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_CloseInstruction:
+ if (ch != L'>') {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
+ } else if (m_iDataPos > 0) {
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ } else {
+ m_pStart ++;
+ FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_XMLNodeStack.Pop();
+ pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+ } else {
+ m_CurNode = *pXMLNode;
+ }
+ m_iCurrentNodeNum = m_CurNode.iNodeNum;
+ m_iDataPos = 0;
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_InstructionClose;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_BreakElement:
+ if (ch == L'>') {
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementBreak;
+ } else if (ch == L'/') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
+ } else {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_pStart ++;
+ break;
+ case FDE_XMLSYNTAXMODE_CloseElement:
+ if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
+ if (ch == L'>') {
+ FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ m_XMLNodeStack.Pop();
+ pXMLNode = m_XMLNodeStack.GetTopElement();
+ if (pXMLNode == NULL) {
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+ } else {
+ m_CurNode = *pXMLNode;
+ }
+ m_iCurrentNodeNum = m_CurNode.iNodeNum;
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ dwStatus = FDE_XMLSYNTAXSTATUS_ElementClose;
+ } else if (!FDE_IsXMLWhiteSpace(ch)) {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ } else {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ }
+ m_pStart ++;
+ break;
+ case FDE_XMLSYNTAXMODE_SkipCommentOrDecl:
+ if (ch == '-') {
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipComment;
+ } else {
+ m_dwMode = FDE_XMLSYNTAXMODE_SkipDeclNode;
+ m_SkipChar = L'>';
+ m_SkipStack.Push(L'>');
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_SkipDeclNode:
+ if (m_SkipChar == L'\'' || m_SkipChar == L'\"') {
+ m_pStart ++;
+ if (ch != m_SkipChar) {
+ break;
+ }
+ m_SkipStack.Pop();
+ FX_LPDWORD pDWord = m_SkipStack.GetTopElement();
+ if (pDWord == NULL) {
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ } else {
+ m_SkipChar = (FX_WCHAR) * pDWord;
+ }
+ } else {
+ switch (ch) {
+ case L'<':
+ m_SkipChar = L'>';
+ m_SkipStack.Push(L'>');
+ break;
+ case L'[':
+ m_SkipChar = L']';
+ m_SkipStack.Push(L']');
+ break;
+ case L'(':
+ m_SkipChar = L')';
+ m_SkipStack.Push(L')');
+ break;
+ case L'\'':
+ m_SkipChar = L'\'';
+ m_SkipStack.Push(L'\'');
+ break;
+ case L'\"':
+ m_SkipChar = L'\"';
+ m_SkipStack.Push(L'\"');
+ break;
+ default:
+ if (ch == m_SkipChar) {
+ m_SkipStack.Pop();
+ FX_LPDWORD pDWord = m_SkipStack.GetTopElement();
+ if (pDWord == NULL) {
+ m_iTextDataLength = m_iDataPos;
+ m_iDataPos = 0;
+ if (m_iTextDataLength >= 9
+ && FXSYS_memcmp(m_pwsTextData, L"[CDATA[", 7 * sizeof(FX_WCHAR)) == 0
+ && FXSYS_memcmp(m_pwsTextData + m_iTextDataLength - 2, L"]]", 2 * sizeof(FX_WCHAR)) == 0) {
+ m_iTextDataLength -= 9;
+ FXSYS_memmove(m_pwsTextData, m_pwsTextData + 7, m_iTextDataLength * sizeof(FX_WCHAR));
+ dwStatus = FDE_XMLSYNTAXSTATUS_CData;
+ }
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ } else {
+ m_SkipChar = (FX_WCHAR) * pDWord;
+ }
+ }
+ break;
+ }
+ if (m_SkipStack.GetSize() > 0) {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ }
+ m_pStart ++;
+ }
+ break;
+ case FDE_XMLSYNTAXMODE_SkipComment:
+ if (ch == L'-') {
+ m_iDataPos++;
+ } else if (ch == L'>') {
+ if (m_iDataPos > 1) {
+ m_iDataPos = 0;
+ m_dwMode = FDE_XMLSYNTAXMODE_Text;
+ }
+ } else {
+ m_iDataPos = 0;
+ }
+ m_pStart++;
+ break;
+ case FDE_XMLSYNTAXMODE_TargetData:
+ if (FDE_IsXMLWhiteSpace(ch)) {
+ if (m_iDataPos < 1) {
+ m_pStart ++;
+ break;
+ } else if (m_wQuotationMark == 0) {
+ m_iTextDataLength = m_iDataPos;
+ m_wQuotationMark = 0;
+ m_iDataPos = 0;
+ m_pStart ++;
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ break;
+ }
+ }
+ if (ch == '?') {
+ m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
+ m_pStart++;
+ } else if (ch == '\"') {
+ if (m_wQuotationMark == 0) {
+ m_wQuotationMark = ch;
+ m_pStart++;
+ } else if (ch == m_wQuotationMark) {
+ m_iTextDataLength = m_iDataPos;
+ m_wQuotationMark = 0;
+ m_iDataPos = 0;
+ m_pStart ++;
+ dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
+ } else {
+ m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
+ return m_dwStatus;
+ }
+ } else {
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos ++] = ch;
+ m_pStart ++;
+ }
+ break;
+ default:
+ break;
+ }
+ if (dwStatus != FDE_XMLSYNTAXSTATUS_None) {
+ return dwStatus;
+ }
+ }
+ }
+ return 0;
+}
+#endif
+CFDE_XMLSyntaxParser::~CFDE_XMLSyntaxParser()
+{
+#ifdef _FDE_BLOCK_BUFFER
+ if (m_pCurrentBlock) {
+ m_pCurrentBlock = NULL;
+ }
+#else
+ if (m_pwsTextData != NULL) {
+ FDE_Free(m_pwsTextData);
+ }
+#endif
+ if (m_pBuffer != NULL) {
+ FDE_Free(m_pBuffer);
+ }
+}
+FX_INT32 CFDE_XMLSyntaxParser::GetStatus() const
+{
+ if (m_pStream == NULL) {
+ return -1;
+ }
+ FX_INT32 iStreamLength = m_pStream->GetLength();
+ if (iStreamLength < 1) {
+ return 100;
+ }
+ if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error) {
+ return -1;
+ }
+ if (m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
+ return 100;
+ }
+ return m_iParsedBytes * 100 / iStreamLength;
+}
+static FX_INT32 FX_GetUTF8EncodeLength(FX_LPCWSTR pSrc, FX_INT32 iSrcLen)
+{
+ FX_DWORD unicode = 0;
+ FX_INT32 iDstNum = 0;
+ while (iSrcLen -- > 0) {
+ unicode = *pSrc ++;
+ int nbytes = 0;
+ if ((FX_DWORD)unicode < 0x80) {
+ nbytes = 1;
+ } else if ((FX_DWORD)unicode < 0x800) {
+ nbytes = 2;
+ } else if ((FX_DWORD)unicode < 0x10000) {
+ nbytes = 3;
+ } else if ((FX_DWORD)unicode < 0x200000) {
+ nbytes = 4;
+ } else if ((FX_DWORD)unicode < 0x4000000) {
+ nbytes = 5;
+ } else {
+ nbytes = 6;
+ }
+ iDstNum += nbytes;
+ }
+ return iDstNum;
+}
+FX_FILESIZE CFDE_XMLSyntaxParser::GetCurrentBinaryPos() const
+{
+ if (m_pStream == NULL) {
+ return 0;
+ }
+ FX_INT32 nSrcLen = m_pStart - m_pBuffer;
+ FX_INT32 nDstLen = FX_GetUTF8EncodeLength(m_pBuffer, nSrcLen);
+ return m_iParsedBytes + nDstLen;
+}
+#ifdef _FDE_BLOCK_BUFFER
+void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR ch)
+{
+ if (m_iIndexInBlock == m_iAllocStep) {
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ if (!m_pCurrentBlock) {
+ return;
+ }
+ }
+ m_pCurrentBlock[m_iIndexInBlock++] = ch;
+ m_iDataLength++;
+ if (m_iEntityStart > -1 && ch == L';') {
+ CFX_WideString csEntity;
+ m_BlockBuffer.GetTextData(csEntity, m_iEntityStart + 1, (m_iDataLength - 1) - m_iEntityStart - 1);
+ FX_INT32 iLen = csEntity.GetLength();
+ if (iLen > 0) {
+ if (csEntity[0] == L'#') {
+ ch = 0;
+ FX_WCHAR w;
+ if (iLen > 1 && csEntity[1] == L'x') {
+ for (FX_INT32 i = 2; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w >= L'0' && w <= L'9') {
+ ch = (ch << 4) + w - L'0';
+ } else if (w >= L'A' && w <= L'F') {
+ ch = (ch << 4) + w - 55;
+ } else if (w >= L'a' && w <= L'f') {
+ ch = (ch << 4) + w - 87;
+ } else {
+ break;
+ }
+ }
+ } else {
+ for (FX_INT32 i = 1; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w < L'0' || w > L'9') {
+ break;
+ }
+ ch = ch * 10 + w - L'0';
+ }
+ }
+ if (ch != 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, ch);
+ m_iEntityStart ++;
+ }
+ } else {
+ if (csEntity.Compare(L"amp") == 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, L'&');
+ m_iEntityStart ++;
+ } else if (csEntity.Compare(L"lt") == 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, L'<');
+ m_iEntityStart ++;
+ } else if (csEntity.Compare(L"gt") == 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, L'>');
+ m_iEntityStart ++;
+ } else if (csEntity.Compare(L"apos") == 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, L'\'');
+ m_iEntityStart ++;
+ } else if (csEntity.Compare(L"quot") == 0) {
+ m_BlockBuffer.SetTextChar(m_iEntityStart, L'\"');
+ m_iEntityStart ++;
+ }
+ }
+ }
+ m_BlockBuffer.DeleteTextChars(m_iDataLength - m_iEntityStart, FALSE);
+ m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
+ m_iEntityStart = -1;
+ } else {
+ if (m_iEntityStart < 0 && ch == L'&') {
+ m_iEntityStart = m_iDataLength - 1;
+ }
+ }
+ m_pStart ++;
+}
+#else
+void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR ch)
+{
+ if (m_iDataPos >= m_iTextDataSize) {
+ ReallocTextDataBuffer();
+ }
+ m_pwsTextData[m_iDataPos] = ch;
+ if (m_iEntityStart > -1 && ch == L';') {
+ CFX_WideString csEntity(m_pwsTextData + m_iEntityStart + 1, m_iDataPos - m_iEntityStart - 1);
+ FX_INT32 iLen = csEntity.GetLength();
+ if (iLen > 0) {
+ if (csEntity[0] == L'#') {
+ ch = 0;
+ FX_WCHAR w;
+ if (iLen > 1 && csEntity[1] == L'x') {
+ for (FX_INT32 i = 2; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w >= L'0' && w <= L'9') {
+ ch = (ch << 4) + w - L'0';
+ } else if (w >= L'A' && w <= L'F') {
+ ch = (ch << 4) + w - 55;
+ } else if (w >= L'a' && w <= L'f') {
+ ch = (ch << 4) + w - 87;
+ } else {
+ break;
+ }
+ }
+ } else {
+ for (FX_INT32 i = 1; i < iLen; i ++) {
+ w = csEntity[i];
+ if (w < L'0' || w > L'9') {
+ break;
+ }
+ ch = ch * 10 + w - L'0';
+ }
+ }
+ if (ch != 0) {
+ m_pwsTextData[m_iEntityStart ++] = ch;
+ }
+ } else {
+ if (csEntity.Compare(L"amp") == 0) {
+ m_pwsTextData[m_iEntityStart ++] = L'&';
+ } else if (csEntity.Compare(L"lt") == 0) {
+ m_pwsTextData[m_iEntityStart ++] = L'<';
+ } else if (csEntity.Compare(L"gt") == 0) {
+ m_pwsTextData[m_iEntityStart ++] = L'>';
+ } else if (csEntity.Compare(L"apos") == 0) {
+ m_pwsTextData[m_iEntityStart ++] = L'\'';
+ } else if (csEntity.Compare(L"quot") == 0) {
+ m_pwsTextData[m_iEntityStart ++] = L'\"';
+ }
+ }
+ }
+ m_iDataPos = m_iEntityStart;
+ m_iEntityStart = -1;
+ } else {
+ if (m_iEntityStart < 0 && ch == L'&') {
+ m_iEntityStart = m_iDataPos;
+ }
+ m_iDataPos ++;
+ }
+ m_pStart ++;
+}
+void CFDE_XMLSyntaxParser::ReallocTextDataBuffer()
+{
+ FXSYS_assert(m_pwsTextData != NULL);
+ if (m_iTextDataSize <= 1024 * 1024) {
+ m_iTextDataSize *= 2;
+ } else {
+ m_iTextDataSize += 1024 * 1024;
+ }
+ m_pwsTextData = (FX_LPWSTR)FDE_Realloc(m_pwsTextData, m_iTextDataSize * sizeof(FX_WCHAR));
+}
+void CFDE_XMLSyntaxParser::GetData(CFX_WideString &wsData) const
+{
+ FX_LPWSTR pBuf = wsData.GetBuffer(m_iTextDataLength);
+ FXSYS_memcpy(pBuf, m_pwsTextData, m_iTextDataLength * sizeof(FX_WCHAR));
+ wsData.ReleaseBuffer(m_iTextDataLength);
+}
+#endif