summaryrefslogtreecommitdiff
path: root/xfa/src/fde/xml
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2016-03-09 15:33:14 -0500
committerDan Sinclair <dsinclair@chromium.org>2016-03-09 15:33:14 -0500
commit2e95951e06bd4d11459fb257c7c2b8fc881854e8 (patch)
tree742484ab5d944d9c2c930133cc5968d6c6a5678d /xfa/src/fde/xml
parentea2a252c40f95616eb0f03318222f0c32ef90eff (diff)
downloadpdfium-2e95951e06bd4d11459fb257c7c2b8fc881854e8.tar.xz
Cleanup the xfa/src/fdp directory.
This CL renames xfa/src/fdp to xfa/src/fde to better match all of the content (nothing mentions fdp other then the directory name). The inner src/ and include/ folders are collapsed up a level and xfa/src/fdp/src/fde is moved up to xfa/src/fde. Some of the header moves conflicted with existing headers. In that case, the existing header had the content moved into the .cpp file and we replaced the existing header with the one from include/. R=tsepez@chromium.org Review URL: https://codereview.chromium.org/1784543002 .
Diffstat (limited to 'xfa/src/fde/xml')
-rw-r--r--xfa/src/fde/xml/fde_xml.h226
-rw-r--r--xfa/src/fde/xml/fde_xml_imp.cpp2100
-rw-r--r--xfa/src/fde/xml/fde_xml_imp.h354
3 files changed, 2680 insertions, 0 deletions
diff --git a/xfa/src/fde/xml/fde_xml.h b/xfa/src/fde/xml/fde_xml.h
new file mode 100644
index 0000000000..03e2a60806
--- /dev/null
+++ b/xfa/src/fde/xml/fde_xml.h
@@ -0,0 +1,226 @@
+// 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
+
+#ifndef XFA_SRC_FDE_XML_FDE_XML_H_
+#define XFA_SRC_FDE_XML_FDE_XML_H_
+
+#include "xfa/src/fgas/crt/fgas_stream.h"
+#include "xfa/src/fgas/crt/fgas_utils.h"
+
+class IFDE_XMLNode;
+class IFDE_XMLInstruction;
+class IFDE_XMLDeclaration;
+class IFDE_XMLElement;
+class IFDE_XMLText;
+class IFDE_XMLDoc;
+class IFDE_XMLParser;
+class IFDE_XMLSyntaxParser;
+
+enum FDE_XMLNODETYPE {
+ FDE_XMLNODE_Unknown = 0,
+ FDE_XMLNODE_Instruction,
+ FDE_XMLNODE_Element,
+ FDE_XMLNODE_Text,
+ FDE_XMLNODE_CharData,
+};
+
+struct FDE_XMLNODE {
+ int32_t iNodeNum;
+ FDE_XMLNODETYPE eNodeType;
+};
+typedef CFX_StackTemplate<FDE_XMLNODE> CFDE_XMLNodeStack;
+
+FX_BOOL FDE_IsXMLValidChar(FX_WCHAR ch);
+FX_BOOL FDE_IsXMLWhiteSpace(FX_WCHAR ch);
+FX_BOOL FDE_IsXMLNameChar(FX_WCHAR ch, FX_BOOL bFirstChar);
+
+class IFDE_XMLNode {
+ public:
+ virtual ~IFDE_XMLNode() {}
+ virtual void Release() = 0;
+ virtual FDE_XMLNODETYPE GetType() const = 0;
+ virtual int32_t CountChildNodes() const = 0;
+ virtual IFDE_XMLNode* GetChildNode(int32_t index) const = 0;
+ virtual int32_t GetChildNodeIndex(IFDE_XMLNode* pNode) const = 0;
+ virtual IFDE_XMLNode* GetPath(const FX_WCHAR* pPath,
+ int32_t iLength = -1,
+ FX_BOOL bQualifiedName = TRUE) const = 0;
+ virtual int32_t InsertChildNode(IFDE_XMLNode* pNode, int32_t index = -1) = 0;
+ virtual void RemoveChildNode(IFDE_XMLNode* pNode) = 0;
+ virtual void DeleteChildren() = 0;
+ enum NodeItem {
+ Root = 0,
+ Parent,
+ FirstSibling,
+ PriorSibling,
+ NextSibling,
+ LastSibling,
+ FirstNeighbor,
+ PriorNeighbor,
+ NextNeighbor,
+ LastNeighbor,
+ FirstChild,
+ LastChild
+ };
+ virtual IFDE_XMLNode* GetNodeItem(NodeItem eItem) const = 0;
+ virtual int32_t GetNodeLevel() const = 0;
+ virtual FX_BOOL InsertNodeItem(IFDE_XMLNode::NodeItem eItem,
+ IFDE_XMLNode* pNode) = 0;
+ virtual IFDE_XMLNode* RemoveNodeItem(IFDE_XMLNode::NodeItem eItem) = 0;
+ virtual IFDE_XMLNode* Clone(FX_BOOL bRecursive) = 0;
+ virtual void SaveXMLNode(IFX_Stream* pXMLStream) = 0;
+};
+class IFDE_XMLInstruction : public IFDE_XMLNode {
+ public:
+ static IFDE_XMLInstruction* Create(const CFX_WideString& wsTarget);
+ virtual void GetTargetName(CFX_WideString& wsTarget) const = 0;
+ virtual int32_t CountAttributes() const = 0;
+ virtual FX_BOOL GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const = 0;
+ virtual FX_BOOL HasAttribute(const FX_WCHAR* pwsAttriName) const = 0;
+ virtual void GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue = NULL) const = 0;
+ virtual void SetString(const CFX_WideString& wsAttriName,
+ const CFX_WideString& wsAttriValue) = 0;
+ virtual int32_t GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue = 0) const = 0;
+ virtual void SetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iAttriValue) = 0;
+ virtual FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue = 0) const = 0;
+ virtual void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue) = 0;
+ virtual void RemoveAttribute(const FX_WCHAR* pwsAttriName) = 0;
+ virtual int32_t CountData() const = 0;
+ virtual FX_BOOL GetData(int32_t index, CFX_WideString& wsData) const = 0;
+ virtual void AppendData(const CFX_WideString& wsData) = 0;
+ virtual void RemoveData(int32_t index) = 0;
+};
+class IFDE_XMLElement : public IFDE_XMLNode {
+ public:
+ static IFDE_XMLElement* Create(const CFX_WideString& wsTag);
+ virtual void GetTagName(CFX_WideString& wsTag) const = 0;
+ virtual void GetLocalTagName(CFX_WideString& wsTag) const = 0;
+ virtual void GetNamespacePrefix(CFX_WideString& wsPrefix) const = 0;
+ virtual void GetNamespaceURI(CFX_WideString& wsNamespace) const = 0;
+ virtual int32_t CountAttributes() const = 0;
+ virtual FX_BOOL GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const = 0;
+ virtual FX_BOOL HasAttribute(const FX_WCHAR* pwsAttriName) const = 0;
+ virtual void GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue = NULL) const = 0;
+ virtual void SetString(const CFX_WideString& wsAttriName,
+ const CFX_WideString& wsAttriValue) = 0;
+ virtual int32_t GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue = 0) const = 0;
+ virtual void SetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iAttriValue) = 0;
+ virtual FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue = 0) const = 0;
+ virtual void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue) = 0;
+ virtual void RemoveAttribute(const FX_WCHAR* pwsAttriName) = 0;
+ virtual void GetTextData(CFX_WideString& wsText) const = 0;
+ virtual void SetTextData(const CFX_WideString& wsText) = 0;
+};
+class IFDE_XMLText : public IFDE_XMLNode {
+ public:
+ static IFDE_XMLText* Create(const CFX_WideString& wsText);
+ virtual void GetText(CFX_WideString& wsText) const = 0;
+ virtual void SetText(const CFX_WideString& wsText) = 0;
+};
+class IFDE_XMLDeclaration : public IFDE_XMLNode {
+ public:
+};
+class IFDE_XMLCharData : public IFDE_XMLDeclaration {
+ public:
+ static IFDE_XMLCharData* Create(const CFX_WideString& wsCData);
+ virtual ~IFDE_XMLCharData() {}
+
+ virtual void GetCharData(CFX_WideString& wsCData) const = 0;
+ virtual void SetCharData(const CFX_WideString& wsCData) = 0;
+};
+
+struct FDE_XMLREADERHANDLER {
+ void* pData;
+ void (*OnTagEnter)(FDE_XMLREADERHANDLER* pThis,
+ FDE_XMLNODETYPE eType,
+ const CFX_WideString& wsTagName);
+ void (*OnTagBreak)(FDE_XMLREADERHANDLER* pThis,
+ const CFX_WideString& wsTagName);
+ void (*OnTagClose)(FDE_XMLREADERHANDLER* pThis,
+ const CFX_WideString& wsTagName);
+ void (*OnAttribute)(FDE_XMLREADERHANDLER* pThis,
+ const CFX_WideString& wsName,
+ const CFX_WideString& wsValue);
+ void (*OnData)(FDE_XMLREADERHANDLER* pThis,
+ FDE_XMLNODETYPE eType,
+ const CFX_WideString& wsValue);
+};
+
+class IFDE_XMLDoc {
+ public:
+ static IFDE_XMLDoc* Create();
+ virtual ~IFDE_XMLDoc() {}
+ virtual void Release() = 0;
+ virtual FX_BOOL LoadXML(IFX_Stream* pXMLStream,
+ int32_t iXMLPlaneSize = 8192,
+ int32_t iTextDataSize = 256,
+ FDE_XMLREADERHANDLER* pHandler = NULL) = 0;
+ virtual FX_BOOL LoadXML(IFDE_XMLParser* pXMLParser) = 0;
+ virtual int32_t DoLoad(IFX_Pause* pPause = NULL) = 0;
+ virtual void CloseXML() = 0;
+ virtual IFDE_XMLNode* GetRoot() const = 0;
+ virtual void SaveXML(IFX_Stream* pXMLStream = NULL,
+ FX_BOOL bSaveBOM = TRUE) = 0;
+ virtual void SaveXMLNode(IFX_Stream* pXMLStream, IFDE_XMLNode* pNode) = 0;
+};
+class IFDE_XMLParser {
+ public:
+ virtual ~IFDE_XMLParser() {}
+ virtual void Release() = 0;
+ virtual int32_t DoParser(IFX_Pause* pPause) = 0;
+};
+#define FDE_XMLSYNTAXSTATUS_None 0x00
+#define FDE_XMLSYNTAXSTATUS_InstructionOpen 0x01
+#define FDE_XMLSYNTAXSTATUS_InstructionClose 0x02
+#define FDE_XMLSYNTAXSTATUS_ElementOpen 0x03
+#define FDE_XMLSYNTAXSTATUS_ElementBreak 0x04
+#define FDE_XMLSYNTAXSTATUS_ElementClose 0x05
+#define FDE_XMLSYNTAXSTATUS_TargetName 0x06
+#define FDE_XMLSYNTAXSTATUS_TagName 0x07
+#define FDE_XMLSYNTAXSTATUS_AttriName 0x08
+#define FDE_XMLSYNTAXSTATUS_AttriValue 0x09
+#define FDE_XMLSYNTAXSTATUS_Text 0x0A
+#define FDE_XMLSYNTAXSTATUS_CData 0x0B
+#define FDE_XMLSYNTAXSTATUS_TargetData 0x0C
+#define FDE_XMLSYNTAXSTATUS_Error 0xFE
+#define FDE_XMLSYNTAXSTATUS_EOS 0xFF
+class IFDE_XMLSyntaxParser {
+ public:
+ static IFDE_XMLSyntaxParser* Create();
+ virtual ~IFDE_XMLSyntaxParser() {}
+ virtual void Release() = 0;
+ virtual void Init(IFX_Stream* pStream,
+ int32_t iXMLPlaneSize,
+ int32_t iTextDataSize = 256) = 0;
+ virtual FX_DWORD DoSyntaxParse() = 0;
+ virtual int32_t GetStatus() const = 0;
+ virtual int32_t GetCurrentPos() const = 0;
+ virtual FX_FILESIZE GetCurrentBinaryPos() const = 0;
+ virtual int32_t GetCurrentNodeNumber() const = 0;
+ virtual int32_t GetLastNodeNumber() const = 0;
+ virtual void GetTargetName(CFX_WideString& wsTarget) const = 0;
+ virtual void GetTagName(CFX_WideString& wsTag) const = 0;
+ virtual void GetAttributeName(CFX_WideString& wsAttriName) const = 0;
+ virtual void GetAttributeValue(CFX_WideString& wsAttriValue) const = 0;
+ virtual void GetTextData(CFX_WideString& wsText) const = 0;
+ virtual void GetTargetData(CFX_WideString& wsData) const = 0;
+};
+
+#endif // XFA_SRC_FDE_XML_FDE_XML_H_
diff --git a/xfa/src/fde/xml/fde_xml_imp.cpp b/xfa/src/fde/xml/fde_xml_imp.cpp
new file mode 100644
index 0000000000..94e5de6b93
--- /dev/null
+++ b/xfa/src/fde/xml/fde_xml_imp.cpp
@@ -0,0 +1,2100 @@
+// 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 "xfa/src/fde/xml/fde_xml_imp.h"
+
+#include <algorithm>
+
+#include "xfa/src/fgas/crt/fgas_system.h"
+#include "xfa/src/fgas/crt/fgas_codepage.h"
+
+#define FDE_XMLVALIDCHARRANGENUM 5
+
+static const FX_WCHAR g_XMLValidCharRange[FDE_XMLVALIDCHARRANGENUM][2] = {
+ {0x09, 0x09},
+ {0x0A, 0x0A},
+ {0x0D, 0x0D},
+ {0x20, 0xD7FF},
+ {0xE000, 0xFFFD}};
+
+FX_BOOL FDE_IsXMLValidChar(FX_WCHAR ch) {
+ int32_t 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;
+}
+
+struct FDE_XMLNAMECHAR {
+ FX_WCHAR wStart;
+ FX_WCHAR wEnd;
+ FX_BOOL bStartChar;
+};
+
+#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) {
+ int32_t 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;
+}
+
+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;
+}
+int32_t CFDE_XMLNode::CountChildNodes() const {
+ int32_t iCount = 0;
+ CFDE_XMLNode* pChild = m_pChild;
+ while (pChild != NULL) {
+ iCount++;
+ pChild = pChild->m_pNext;
+ }
+ return iCount;
+}
+CFDE_XMLNode* CFDE_XMLNode::GetChildNode(int32_t index) const {
+ CFDE_XMLNode* pChild = m_pChild;
+ while (pChild != NULL) {
+ if (index == 0) {
+ return pChild;
+ }
+ index--;
+ pChild = pChild->m_pNext;
+ }
+ return NULL;
+}
+int32_t CFDE_XMLNode::GetChildNodeIndex(CFDE_XMLNode* pNode) const {
+ int32_t 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(const FX_WCHAR* pPath,
+ int32_t iLength,
+ FX_BOOL bQualifiedName) const {
+ FXSYS_assert(pPath != NULL);
+ if (iLength < 0) {
+ iLength = FXSYS_wcslen(pPath);
+ }
+ if (iLength == 0) {
+ return NULL;
+ }
+ CFX_WideString csPath;
+ const FX_WCHAR* pStart = pPath;
+ const FX_WCHAR* 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);
+}
+int32_t CFDE_XMLNode::InsertChildNode(CFDE_XMLNode* pNode, int32_t 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;
+ }
+ int32_t 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;
+}
+int32_t CFDE_XMLNode::GetNodeLevel() const {
+ int32_t 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(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray& attributes = pInstruction->m_Attributes;
+ int32_t 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(L"&", L"&amp;");
+ wsValue.Replace(L"<", L"&lt;");
+ wsValue.Replace(L">", L"&gt;");
+ wsValue.Replace(L"\'", L"&apos;");
+ wsValue.Replace(L"\"", 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;
+ int32_t iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (int32_t i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace(L"&", L"&amp;");
+ wsValue.Replace(L"<", L"&lt;");
+ wsValue.Replace(L">", L"&gt;");
+ wsValue.Replace(L"\'", L"&apos;");
+ wsValue.Replace(L"\"", 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(L"&", L"&amp;");
+ ws.Replace(L"<", L"&lt;");
+ ws.Replace(L">", L"&gt;");
+ ws.Replace(L"\'", L"&apos;");
+ ws.Replace(L"\"", 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*)new CFDE_XMLInstruction(wsTarget);
+}
+CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString& wsTarget)
+ : m_wsTarget(wsTarget) {
+ FXSYS_assert(m_wsTarget.GetLength() > 0);
+}
+CFDE_XMLNode* CFDE_XMLInstruction::Clone(FX_BOOL bRecursive) {
+ CFDE_XMLInstruction* pClone = 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;
+}
+int32_t CFDE_XMLInstruction::CountAttributes() const {
+ return m_Attributes.GetSize() / 2;
+}
+FX_BOOL CFDE_XMLInstruction::GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ FXSYS_assert(index > -1 && index < iCount / 2);
+ for (int32_t 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(const FX_WCHAR* pwsAttriName) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void CFDE_XMLInstruction::GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t 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);
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t 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);
+}
+int32_t CFDE_XMLInstruction::GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]);
+ }
+ }
+ return iDefValue;
+}
+void CFDE_XMLInstruction::SetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iAttriValue) {
+ CFX_WideString wsValue;
+ wsValue.Format(L"%d", iAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+FX_FLOAT CFDE_XMLInstruction::GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]);
+ }
+ }
+ return fDefValue;
+}
+void CFDE_XMLInstruction::SetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fAttriValue) {
+ CFX_WideString wsValue;
+ wsValue.Format(L"%f", fAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+void CFDE_XMLInstruction::RemoveAttribute(const FX_WCHAR* pwsAttriName) {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ m_Attributes.RemoveAt(i + 1);
+ m_Attributes.RemoveAt(i);
+ return;
+ }
+ }
+}
+int32_t CFDE_XMLInstruction::CountData() const {
+ return m_TargetData.GetSize();
+}
+FX_BOOL CFDE_XMLInstruction::GetData(int32_t 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(int32_t index) {
+ m_TargetData.RemoveAt(index);
+}
+IFDE_XMLElement* IFDE_XMLElement::Create(const CFX_WideString& wsTag) {
+ return (IFDE_XMLElement*)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 = 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;
+ }
+}
+int32_t CFDE_XMLElement::CountAttributes() const {
+ return m_Attributes.GetSize() / 2;
+}
+FX_BOOL CFDE_XMLElement::GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ FXSYS_assert(index > -1 && index < iCount / 2);
+ for (int32_t 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(const FX_WCHAR* pwsAttriName) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void CFDE_XMLElement::GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t 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);
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t 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);
+}
+int32_t CFDE_XMLElement::GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]);
+ }
+ }
+ return iDefValue;
+}
+void CFDE_XMLElement::SetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iAttriValue) {
+ CFX_WideString wsValue;
+ wsValue.Format(L"%d", iAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+FX_FLOAT CFDE_XMLElement::GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue) const {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t i = 0; i < iCount; i += 2) {
+ if (m_Attributes[i].Compare(pwsAttriName) == 0) {
+ return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]);
+ }
+ }
+ return fDefValue;
+}
+void CFDE_XMLElement::SetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fAttriValue) {
+ CFX_WideString wsValue;
+ wsValue.Format(L"%f", fAttriValue);
+ SetString(pwsAttriName, wsValue);
+}
+void CFDE_XMLElement::RemoveAttribute(const FX_WCHAR* pwsAttriName) {
+ int32_t iCount = m_Attributes.GetSize();
+ for (int32_t 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(new CFDE_XMLText(wsText));
+}
+IFDE_XMLText* IFDE_XMLText::Create(const CFX_WideString& wsText) {
+ return (IFDE_XMLText*)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 = new CFDE_XMLText(m_wsText);
+ return pClone;
+}
+IFDE_XMLCharData* IFDE_XMLCharData::Create(const CFX_WideString& wsCData) {
+ return (IFDE_XMLCharData*)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 = new CFDE_XMLCharData(m_wsCharData);
+ return pClone;
+}
+IFDE_XMLDoc* IFDE_XMLDoc::Create() {
+ return (IFDE_XMLDoc*)new CFDE_XMLDoc;
+}
+CFDE_XMLDoc::CFDE_XMLDoc()
+ : m_pRoot(NULL), m_pSyntaxParser(NULL), m_pXMLParser(NULL) {
+ Reset(TRUE);
+ CFDE_XMLInstruction* pXML = new CFDE_XMLInstruction(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 = 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,
+ int32_t iXMLPlaneSize,
+ int32_t iTextDataSize,
+ FDE_XMLREADERHANDLER* 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 = new CFDE_XMLDOMParser(m_pRoot, m_pSyntaxParser);
+ } else {
+ m_pXMLParser = new CFDE_XMLSAXParser(pHandler, m_pSyntaxParser);
+ }
+ return TRUE;
+}
+FX_BOOL CFDE_XMLDoc::LoadXML(IFDE_XMLParser* pXMLParser) {
+ if (pXMLParser == NULL) {
+ return FALSE;
+ }
+ Reset(TRUE);
+ m_pXMLParser = pXMLParser;
+ return m_pXMLParser != NULL;
+}
+int32_t 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(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
+ pXMLStream->WriteString(ws, ws.GetLength());
+ CFX_WideStringArray& attributes = pInstruction->m_Attributes;
+ int32_t 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(L"&", L"&amp;");
+ wsValue.Replace(L"<", L"&lt;");
+ wsValue.Replace(L">", L"&gt;");
+ wsValue.Replace(L"\'", L"&apos;");
+ wsValue.Replace(L"\"", 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;
+ int32_t iCount = attributes.GetSize();
+ CFX_WideString wsValue;
+ for (int32_t i = 0; i < iCount; i += 2) {
+ ws = L" ";
+ ws += attributes[i];
+ ws += L"=\"";
+ wsValue = attributes[i + 1];
+ wsValue.Replace(L"&", L"&amp;");
+ wsValue.Replace(L"<", L"&lt;");
+ wsValue.Replace(L">", L"&gt;");
+ wsValue.Replace(L"\'", L"&apos;");
+ wsValue.Replace(L"\"", 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(L"&", L"&amp;");
+ ws.Replace(L"<", L"&lt;");
+ ws.Replace(L">", L"&gt;");
+ ws.Replace(L"\'", L"&apos;");
+ ws.Replace(L"\"", 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(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) {
+ int32_t iPos = pXMLStream->GetPosition();
+ pXMLStream->SetLength(iPos);
+ }
+}
+CFDE_XMLDOMParser::CFDE_XMLDOMParser(CFDE_XMLNode* pRoot,
+ IFDE_XMLSyntaxParser* pParser)
+ : 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();
+}
+int32_t CFDE_XMLDOMParser::DoParser(IFX_Pause* pPause) {
+ FX_DWORD dwRet;
+ int32_t 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 = 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 = 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 = 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 = 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_XMLREADERHANDLER* 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();
+}
+int32_t CFDE_XMLSAXParser::DoParser(IFX_Pause* pPause) {
+ FX_DWORD dwRet = 0;
+ int32_t 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();
+}
+
+CFDE_BlockBuffer::CFDE_BlockBuffer(int32_t iAllocStep)
+ : m_iDataLength(0),
+ m_iBufferSize(0),
+ m_iAllocStep(iAllocStep),
+ m_iStartPosition(0) {}
+CFDE_BlockBuffer::~CFDE_BlockBuffer() {
+ ClearBuffer();
+}
+FX_WCHAR* CFDE_BlockBuffer::GetAvailableBlock(int32_t& iIndexInBlock) {
+ iIndexInBlock = 0;
+ if (!m_BlockArray.GetSize()) {
+ return nullptr;
+ }
+ int32_t iRealIndex = m_iStartPosition + m_iDataLength;
+ if (iRealIndex == m_iBufferSize) {
+ FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep);
+ m_BlockArray.Add(pBlock);
+ m_iBufferSize += m_iAllocStep;
+ return pBlock;
+ }
+ iIndexInBlock = iRealIndex % m_iAllocStep;
+ return (FX_WCHAR*)m_BlockArray[iRealIndex / m_iAllocStep];
+}
+FX_BOOL CFDE_BlockBuffer::InitBuffer(int32_t iBufferSize) {
+ ClearBuffer();
+ int32_t iNumOfBlock = (iBufferSize - 1) / m_iAllocStep + 1;
+ for (int32_t i = 0; i < iNumOfBlock; i++) {
+ m_BlockArray.Add(FX_Alloc(FX_WCHAR, m_iAllocStep));
+ }
+ m_iBufferSize = iNumOfBlock * m_iAllocStep;
+ return TRUE;
+}
+void CFDE_BlockBuffer::SetTextChar(int32_t iIndex, FX_WCHAR ch) {
+ if (iIndex < 0) {
+ return;
+ }
+ int32_t iRealIndex = m_iStartPosition + iIndex;
+ int32_t iBlockIndex = iRealIndex / m_iAllocStep;
+ int32_t iInnerIndex = iRealIndex % m_iAllocStep;
+ int32_t iBlockSize = m_BlockArray.GetSize();
+ if (iBlockIndex >= iBlockSize) {
+ int32_t iNewBlocks = iBlockIndex - iBlockSize + 1;
+ do {
+ FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep);
+ m_BlockArray.Add(pBlock);
+ m_iBufferSize += m_iAllocStep;
+ } while (--iNewBlocks);
+ }
+ FX_WCHAR* pTextData = (FX_WCHAR*)m_BlockArray[iBlockIndex];
+ *(pTextData + iInnerIndex) = ch;
+ if (m_iDataLength <= iIndex) {
+ m_iDataLength = iIndex + 1;
+ }
+}
+int32_t CFDE_BlockBuffer::DeleteTextChars(int32_t 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,
+ int32_t iStart,
+ int32_t iLength) const {
+ wsTextData.Empty();
+ int32_t iMaybeDataLength = m_iBufferSize - 1 - m_iStartPosition;
+ if (iStart < 0 || iStart > iMaybeDataLength) {
+ return;
+ }
+ if (iLength == -1 || iLength > iMaybeDataLength) {
+ iLength = iMaybeDataLength;
+ }
+ if (iLength <= 0) {
+ return;
+ }
+ FX_WCHAR* pBuf = wsTextData.GetBuffer(iLength);
+ if (!pBuf) {
+ return;
+ }
+ int32_t iStartBlockIndex = 0;
+ int32_t iStartInnerIndex = 0;
+ TextDataIndex2BufIndex(iStart, iStartBlockIndex, iStartInnerIndex);
+ int32_t iEndBlockIndex = 0;
+ int32_t iEndInnerIndex = 0;
+ TextDataIndex2BufIndex(iStart + iLength, iEndBlockIndex, iEndInnerIndex);
+ int32_t iPointer = 0;
+ for (int32_t i = iStartBlockIndex; i <= iEndBlockIndex; i++) {
+ int32_t iBufferPointer = 0;
+ int32_t iCopyLength = m_iAllocStep;
+ if (i == iStartBlockIndex) {
+ iCopyLength -= iStartInnerIndex;
+ iBufferPointer = iStartInnerIndex;
+ }
+ if (i == iEndBlockIndex) {
+ iCopyLength -= ((m_iAllocStep - 1) - iEndInnerIndex);
+ }
+ FX_WCHAR* pBlockBuf = (FX_WCHAR*)m_BlockArray[i];
+ FXSYS_memcpy(pBuf + iPointer, pBlockBuf + iBufferPointer,
+ iCopyLength * sizeof(FX_WCHAR));
+ iPointer += iCopyLength;
+ }
+ wsTextData.ReleaseBuffer(iLength);
+}
+void CFDE_BlockBuffer::TextDataIndex2BufIndex(const int32_t iIndex,
+ int32_t& iBlockIndex,
+ int32_t& iInnerIndex) const {
+ FXSYS_assert(iIndex >= 0);
+ int32_t iRealIndex = m_iStartPosition + iIndex;
+ iBlockIndex = iRealIndex / m_iAllocStep;
+ iInnerIndex = iRealIndex % m_iAllocStep;
+}
+void CFDE_BlockBuffer::ClearBuffer() {
+ m_iBufferSize = 0;
+ int32_t iSize = m_BlockArray.GetSize();
+ for (int32_t i = 0; i < iSize; i++) {
+ FX_Free(m_BlockArray[i]);
+ m_BlockArray[i] = NULL;
+ }
+ m_BlockArray.RemoveAll();
+}
+
+IFDE_XMLSyntaxParser* IFDE_XMLSyntaxParser::Create() {
+ return new CFDE_XMLSyntaxParser;
+}
+
+CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser()
+ : m_pStream(nullptr),
+ m_iXMLPlaneSize(-1),
+ m_iCurrentPos(0),
+ m_iCurrentNodeNum(-1),
+ m_iLastNodeNum(-1),
+ m_iParsedChars(0),
+ m_iParsedBytes(0),
+ m_pBuffer(nullptr),
+ m_iBufferChars(0),
+ m_bEOS(FALSE),
+ m_pStart(nullptr),
+ m_pEnd(nullptr),
+ m_XMLNodeStack(16),
+ m_iAllocStep(m_BlockBuffer.GetAllocStep()),
+ m_iDataLength(m_BlockBuffer.GetDataLengthRef()),
+ m_pCurrentBlock(nullptr),
+ m_iIndexInBlock(0),
+ m_iTextDataLength(0),
+ m_dwStatus(FDE_XMLSYNTAXSTATUS_None),
+ m_dwMode(FDE_XMLSYNTAXMODE_Text),
+ m_wQuotationMark(0),
+ m_iEntityStart(-1),
+ m_SkipStack(16) {
+ m_CurNode.iNodeNum = -1;
+ m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
+}
+void CFDE_XMLSyntaxParser::Init(IFX_Stream* pStream,
+ int32_t iXMLPlaneSize,
+ int32_t iTextDataSize) {
+ FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL);
+ FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0);
+ int32_t iStreamLength = pStream->GetLength();
+ FXSYS_assert(iStreamLength > 0);
+ m_pStream = pStream;
+ m_iXMLPlaneSize = std::min(iXMLPlaneSize, iStreamLength);
+ uint8_t bom[4];
+ m_iCurrentPos = m_pStream->GetBOM(bom);
+ FXSYS_assert(m_pBuffer == NULL);
+ m_pBuffer = FX_Alloc(FX_WCHAR, m_iXMLPlaneSize);
+ 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 && m_pBuffer && m_BlockBuffer.IsInitialized());
+ int32_t iStreamLength = m_pStream->GetLength();
+ int32_t 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;
+ 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();
+ 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_XMLNODE* 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_XMLNODE* 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_DWORD* 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_DWORD* 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;
+}
+
+CFDE_XMLSyntaxParser::~CFDE_XMLSyntaxParser() {
+ if (m_pCurrentBlock) {
+ m_pCurrentBlock = NULL;
+ }
+ FX_Free(m_pBuffer);
+}
+
+int32_t CFDE_XMLSyntaxParser::GetStatus() const {
+ if (m_pStream == NULL) {
+ return -1;
+ }
+ int32_t 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 int32_t FX_GetUTF8EncodeLength(const FX_WCHAR* pSrc, int32_t iSrcLen) {
+ FX_DWORD unicode = 0;
+ int32_t 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;
+ }
+ int32_t nSrcLen = m_pStart - m_pBuffer;
+ int32_t nDstLen = FX_GetUTF8EncodeLength(m_pBuffer, nSrcLen);
+ return m_iParsedBytes + nDstLen;
+}
+
+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);
+ int32_t iLen = csEntity.GetLength();
+ if (iLen > 0) {
+ if (csEntity[0] == L'#') {
+ ch = 0;
+ FX_WCHAR w;
+ if (iLen > 1 && csEntity[1] == L'x') {
+ for (int32_t 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 (int32_t 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++;
+}
diff --git a/xfa/src/fde/xml/fde_xml_imp.h b/xfa/src/fde/xml/fde_xml_imp.h
new file mode 100644
index 0000000000..815d746d31
--- /dev/null
+++ b/xfa/src/fde/xml/fde_xml_imp.h
@@ -0,0 +1,354 @@
+// 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
+
+#ifndef XFA_SRC_FDE_XML_FDE_XML_IMP_H_
+#define XFA_SRC_FDE_XML_FDE_XML_IMP_H_
+
+#include "core/include/fxcrt/fx_system.h"
+#include "xfa/src/fde/xml/fde_xml.h"
+#include "xfa/src/fgas/crt/fgas_memory.h"
+#include "xfa/src/fgas/crt/fgas_stream.h"
+
+class CFDE_BlockBuffer;
+class CFDE_XMLInstruction;
+class CFDE_XMLElement;
+class CFDE_XMLText;
+class CFDE_XMLDoc;
+class IFDE_XMLParser;
+class CFDE_XMLDOMParser;
+class CFDE_XMLSAXParser;
+class CFDE_XMLSyntaxParser;
+
+class CFDE_XMLNode : public CFX_Target {
+ public:
+ CFDE_XMLNode();
+ virtual void Release() { delete this; }
+ virtual FDE_XMLNODETYPE GetType() const { return FDE_XMLNODE_Unknown; }
+ virtual int32_t CountChildNodes() const;
+ virtual CFDE_XMLNode* GetChildNode(int32_t index) const;
+ virtual int32_t GetChildNodeIndex(CFDE_XMLNode* pNode) const;
+ virtual CFDE_XMLNode* GetPath(const FX_WCHAR* pPath,
+ int32_t iLength = -1,
+ FX_BOOL bQualifiedName = TRUE) const;
+ virtual int32_t InsertChildNode(CFDE_XMLNode* pNode, int32_t index = -1);
+ virtual void RemoveChildNode(CFDE_XMLNode* pNode);
+ virtual void DeleteChildren();
+ virtual CFDE_XMLNode* GetNodeItem(IFDE_XMLNode::NodeItem eItem) const;
+ virtual int32_t GetNodeLevel() const;
+ virtual FX_BOOL InsertNodeItem(IFDE_XMLNode::NodeItem eItem,
+ CFDE_XMLNode* pNode);
+ virtual CFDE_XMLNode* RemoveNodeItem(IFDE_XMLNode::NodeItem eItem);
+ virtual CFDE_XMLNode* Clone(FX_BOOL bRecursive);
+ virtual void SaveXMLNode(IFX_Stream* pXMLStream);
+
+ public:
+ ~CFDE_XMLNode();
+ void CloneChildren(CFDE_XMLNode* pClone);
+ CFDE_XMLNode* m_pParent;
+ CFDE_XMLNode* m_pChild;
+ CFDE_XMLNode* m_pPrior;
+ CFDE_XMLNode* m_pNext;
+};
+class CFDE_XMLInstruction : public CFDE_XMLNode {
+ public:
+ CFDE_XMLInstruction(const CFX_WideString& wsTarget);
+ virtual void Release() { delete this; }
+ virtual FDE_XMLNODETYPE GetType() const { return FDE_XMLNODE_Instruction; }
+ virtual CFDE_XMLNode* Clone(FX_BOOL bRecursive);
+ virtual void GetTargetName(CFX_WideString& wsTarget) const {
+ wsTarget = m_wsTarget;
+ }
+ virtual int32_t CountAttributes() const;
+ virtual FX_BOOL GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const;
+ virtual FX_BOOL HasAttribute(const FX_WCHAR* pwsAttriName) const;
+ virtual void GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue = NULL) const;
+ virtual void SetString(const CFX_WideString& wsAttriName,
+ const CFX_WideString& wsAttriValue);
+ virtual int32_t GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue = 0) const;
+ virtual void SetInteger(const FX_WCHAR* pwsAttriName, int32_t iAttriValue);
+ virtual FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue = 0) const;
+ virtual void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue);
+ virtual void RemoveAttribute(const FX_WCHAR* pwsAttriName);
+ virtual int32_t CountData() const;
+ virtual FX_BOOL GetData(int32_t index, CFX_WideString& wsData) const;
+ virtual void AppendData(const CFX_WideString& wsData);
+ virtual void RemoveData(int32_t index);
+
+ public:
+ ~CFDE_XMLInstruction() {}
+ CFX_WideString m_wsTarget;
+ CFX_WideStringArray m_Attributes;
+ CFX_WideStringArray m_TargetData;
+};
+class CFDE_XMLElement : public CFDE_XMLNode {
+ public:
+ CFDE_XMLElement(const CFX_WideString& wsTag);
+ virtual void Release() { delete this; }
+ virtual FDE_XMLNODETYPE GetType() const { return FDE_XMLNODE_Element; }
+ virtual CFDE_XMLNode* Clone(FX_BOOL bRecursive);
+ virtual void GetTagName(CFX_WideString& wsTag) const;
+ virtual void GetLocalTagName(CFX_WideString& wsTag) const;
+ virtual void GetNamespacePrefix(CFX_WideString& wsPrefix) const;
+ virtual void GetNamespaceURI(CFX_WideString& wsNamespace) const;
+ virtual int32_t CountAttributes() const;
+ virtual FX_BOOL GetAttribute(int32_t index,
+ CFX_WideString& wsAttriName,
+ CFX_WideString& wsAttriValue) const;
+ virtual FX_BOOL HasAttribute(const FX_WCHAR* pwsAttriName) const;
+ virtual void GetString(const FX_WCHAR* pwsAttriName,
+ CFX_WideString& wsAttriValue,
+ const FX_WCHAR* pwsDefValue = NULL) const;
+ virtual void SetString(const CFX_WideString& wsAttriName,
+ const CFX_WideString& wsAttriValue);
+ virtual int32_t GetInteger(const FX_WCHAR* pwsAttriName,
+ int32_t iDefValue = 0) const;
+ virtual void SetInteger(const FX_WCHAR* pwsAttriName, int32_t iAttriValue);
+ virtual FX_FLOAT GetFloat(const FX_WCHAR* pwsAttriName,
+ FX_FLOAT fDefValue = 0) const;
+ virtual void SetFloat(const FX_WCHAR* pwsAttriName, FX_FLOAT fAttriValue);
+ virtual void RemoveAttribute(const FX_WCHAR* pwsAttriName);
+ virtual void GetTextData(CFX_WideString& wsText) const;
+ virtual void SetTextData(const CFX_WideString& wsText);
+
+ public:
+ ~CFDE_XMLElement();
+ CFX_WideString m_wsTag;
+ CFX_WideStringArray m_Attributes;
+};
+class CFDE_XMLText : public CFDE_XMLNode {
+ public:
+ CFDE_XMLText(const CFX_WideString& wsText);
+ virtual void Release() { delete this; }
+ virtual FDE_XMLNODETYPE GetType() const { return FDE_XMLNODE_Text; }
+ virtual CFDE_XMLNode* Clone(FX_BOOL bRecursive);
+ virtual void GetText(CFX_WideString& wsText) const { wsText = m_wsText; }
+ virtual void SetText(const CFX_WideString& wsText) { m_wsText = wsText; }
+
+ public:
+ ~CFDE_XMLText() {}
+ CFX_WideString m_wsText;
+};
+class CFDE_XMLDeclaration : public CFDE_XMLNode {
+ public:
+ CFDE_XMLDeclaration() : CFDE_XMLNode() {}
+};
+class CFDE_XMLCharData : public CFDE_XMLDeclaration {
+ public:
+ CFDE_XMLCharData(const CFX_WideString& wsCData);
+
+ virtual void Release() { delete this; }
+ virtual FDE_XMLNODETYPE GetType() const { return FDE_XMLNODE_CharData; }
+ virtual CFDE_XMLNode* Clone(FX_BOOL bRecursive);
+ virtual void GetCharData(CFX_WideString& wsCharData) const {
+ wsCharData = m_wsCharData;
+ }
+ virtual void SetCharData(const CFX_WideString& wsCData) {
+ m_wsCharData = wsCData;
+ }
+
+ public:
+ ~CFDE_XMLCharData() {}
+
+ CFX_WideString m_wsCharData;
+};
+class CFDE_XMLDoc : public CFX_Target {
+ public:
+ CFDE_XMLDoc();
+ ~CFDE_XMLDoc();
+ virtual void Release() { delete this; }
+ virtual FX_BOOL LoadXML(IFX_Stream* pXMLStream,
+ int32_t iXMLPlaneSize = 8192,
+ int32_t iTextDataSize = 256,
+ FDE_XMLREADERHANDLER* pHandler = NULL);
+ virtual FX_BOOL LoadXML(IFDE_XMLParser* pXMLParser);
+ virtual int32_t DoLoad(IFX_Pause* pPause = NULL);
+ virtual void CloseXML();
+ virtual CFDE_XMLNode* GetRoot() const { return m_pRoot; }
+ virtual void SaveXML(IFX_Stream* pXMLStream = NULL, FX_BOOL bSaveBOM = TRUE);
+ virtual void SaveXMLNode(IFX_Stream* pXMLStream, IFDE_XMLNode* pNode);
+
+ protected:
+ IFX_Stream* m_pStream;
+ int32_t m_iStatus;
+ CFDE_XMLNode* m_pRoot;
+ IFDE_XMLSyntaxParser* m_pSyntaxParser;
+ IFDE_XMLParser* m_pXMLParser;
+ void Reset(FX_BOOL bInitRoot);
+ void ReleaseParser();
+};
+typedef CFX_StackTemplate<CFDE_XMLNode*> CFDE_XMLDOMNodeStack;
+class CFDE_XMLDOMParser : public IFDE_XMLParser, public CFX_Target {
+ public:
+ CFDE_XMLDOMParser(CFDE_XMLNode* pRoot, IFDE_XMLSyntaxParser* pParser);
+ ~CFDE_XMLDOMParser();
+
+ virtual void Release() { delete this; }
+ virtual int32_t DoParser(IFX_Pause* pPause);
+
+ private:
+ IFDE_XMLSyntaxParser* m_pParser;
+ CFDE_XMLNode* m_pParent;
+ CFDE_XMLNode* m_pChild;
+ CFDE_XMLDOMNodeStack m_NodeStack;
+ CFX_WideString m_ws1;
+ CFX_WideString m_ws2;
+};
+class CFDE_XMLTAG : public CFX_Target {
+ public:
+ CFDE_XMLTAG() : eType(FDE_XMLNODE_Unknown) {}
+ CFDE_XMLTAG(const CFDE_XMLTAG& src)
+ : wsTagName(src.wsTagName), eType(src.eType) {}
+ CFX_WideString wsTagName;
+ FDE_XMLNODETYPE eType;
+};
+typedef CFX_ObjectStackTemplate<CFDE_XMLTAG> CFDE_XMLTagStack;
+class CFDE_XMLSAXParser : public IFDE_XMLParser, public CFX_Target {
+ public:
+ CFDE_XMLSAXParser(FDE_XMLREADERHANDLER* pHandler,
+ IFDE_XMLSyntaxParser* pParser);
+ ~CFDE_XMLSAXParser();
+
+ virtual void Release() { delete this; }
+ virtual int32_t DoParser(IFX_Pause* pPause);
+
+ private:
+ void Push(const CFDE_XMLTAG& xmlTag);
+ void Pop();
+ FDE_XMLREADERHANDLER* m_pHandler;
+ IFDE_XMLSyntaxParser* m_pParser;
+ CFDE_XMLTagStack m_TagStack;
+ CFDE_XMLTAG* m_pTagTop;
+ CFX_WideString m_ws1;
+ CFX_WideString m_ws2;
+};
+
+class CFDE_BlockBuffer : public CFX_Target {
+ public:
+ CFDE_BlockBuffer(int32_t iAllocStep = 1024 * 1024);
+ ~CFDE_BlockBuffer();
+
+ FX_BOOL InitBuffer(int32_t iBufferSize = 1024 * 1024);
+ FX_BOOL IsInitialized() { return m_iBufferSize / m_iAllocStep >= 1; }
+ void ReleaseBuffer() { delete this; }
+ FX_WCHAR* GetAvailableBlock(int32_t& iIndexInBlock);
+ inline int32_t GetAllocStep() const { return m_iAllocStep; }
+ inline int32_t& GetDataLengthRef() { return m_iDataLength; }
+ inline void Reset(FX_BOOL bReserveData = TRUE) {
+ if (!bReserveData) {
+ m_iStartPosition = 0;
+ }
+ m_iDataLength = 0;
+ }
+ void SetTextChar(int32_t iIndex, FX_WCHAR ch);
+ int32_t DeleteTextChars(int32_t iCount, FX_BOOL bDirection = TRUE);
+ void GetTextData(CFX_WideString& wsTextData,
+ int32_t iStart = 0,
+ int32_t iLength = -1) const;
+
+ protected:
+ inline void TextDataIndex2BufIndex(const int32_t iIndex,
+ int32_t& iBlockIndex,
+ int32_t& iInnerIndex) const;
+ void ClearBuffer();
+ CFX_PtrArray m_BlockArray;
+ int32_t m_iDataLength;
+ int32_t m_iBufferSize;
+ int32_t m_iAllocStep;
+ int32_t m_iStartPosition;
+};
+
+#define FDE_XMLSYNTAXMODE_Text 0
+#define FDE_XMLSYNTAXMODE_Node 1
+#define FDE_XMLSYNTAXMODE_Target 2
+#define FDE_XMLSYNTAXMODE_Tag 3
+#define FDE_XMLSYNTAXMODE_AttriName 4
+#define FDE_XMLSYNTAXMODE_AttriEqualSign 5
+#define FDE_XMLSYNTAXMODE_AttriQuotation 6
+#define FDE_XMLSYNTAXMODE_AttriValue 7
+#define FDE_XMLSYNTAXMODE_Entity 8
+#define FDE_XMLSYNTAXMODE_EntityDecimal 9
+#define FDE_XMLSYNTAXMODE_EntityHex 10
+#define FDE_XMLSYNTAXMODE_CloseInstruction 11
+#define FDE_XMLSYNTAXMODE_BreakElement 12
+#define FDE_XMLSYNTAXMODE_CloseElement 13
+#define FDE_XMLSYNTAXMODE_SkipDeclNode 14
+#define FDE_XMLSYNTAXMODE_DeclCharData 15
+#define FDE_XMLSYNTAXMODE_SkipComment 16
+#define FDE_XMLSYNTAXMODE_SkipCommentOrDecl 17
+#define FDE_XMLSYNTAXMODE_TargetData 18
+class CFDE_XMLSyntaxParser : public IFDE_XMLSyntaxParser, public CFX_Target {
+ public:
+ CFDE_XMLSyntaxParser();
+ ~CFDE_XMLSyntaxParser();
+ virtual void Release() { delete this; }
+ virtual void Init(IFX_Stream* pStream,
+ int32_t iXMLPlaneSize,
+ int32_t iTextDataSize = 256);
+ virtual FX_DWORD DoSyntaxParse();
+ virtual int32_t GetStatus() const;
+ virtual int32_t GetCurrentPos() const {
+ return m_iParsedChars + (m_pStart - m_pBuffer);
+ }
+ virtual FX_FILESIZE GetCurrentBinaryPos() const;
+ virtual int32_t GetCurrentNodeNumber() const { return m_iCurrentNodeNum; }
+ virtual int32_t GetLastNodeNumber() const { return m_iLastNodeNum; }
+
+ virtual void GetTargetName(CFX_WideString& wsTarget) const {
+ m_BlockBuffer.GetTextData(wsTarget, 0, m_iTextDataLength);
+ }
+ virtual void GetTagName(CFX_WideString& wsTag) const {
+ m_BlockBuffer.GetTextData(wsTag, 0, m_iTextDataLength);
+ }
+ virtual void GetAttributeName(CFX_WideString& wsAttriName) const {
+ m_BlockBuffer.GetTextData(wsAttriName, 0, m_iTextDataLength);
+ }
+ virtual void GetAttributeValue(CFX_WideString& wsAttriValue) const {
+ m_BlockBuffer.GetTextData(wsAttriValue, 0, m_iTextDataLength);
+ }
+ virtual void GetTextData(CFX_WideString& wsText) const {
+ m_BlockBuffer.GetTextData(wsText, 0, m_iTextDataLength);
+ }
+ virtual void GetTargetData(CFX_WideString& wsData) const {
+ m_BlockBuffer.GetTextData(wsData, 0, m_iTextDataLength);
+ }
+
+ protected:
+ IFX_Stream* m_pStream;
+ int32_t m_iXMLPlaneSize;
+ int32_t m_iCurrentPos;
+ int32_t m_iCurrentNodeNum;
+ int32_t m_iLastNodeNum;
+ int32_t m_iParsedChars;
+ int32_t m_iParsedBytes;
+ FX_WCHAR* m_pBuffer;
+ int32_t m_iBufferChars;
+ FX_BOOL m_bEOS;
+ FX_WCHAR* m_pStart;
+ FX_WCHAR* m_pEnd;
+ FDE_XMLNODE m_CurNode;
+ CFDE_XMLNodeStack m_XMLNodeStack;
+ CFDE_BlockBuffer m_BlockBuffer;
+ int32_t m_iAllocStep;
+ int32_t& m_iDataLength;
+ FX_WCHAR* m_pCurrentBlock;
+ int32_t m_iIndexInBlock;
+ int32_t m_iTextDataLength;
+ FX_DWORD m_dwStatus;
+ FX_DWORD m_dwMode;
+ FX_WCHAR m_wQuotationMark;
+ int32_t m_iEntityStart;
+ CFX_DWordStack m_SkipStack;
+ FX_WCHAR m_SkipChar;
+ inline void ParseTextChar(FX_WCHAR ch);
+};
+
+#endif // XFA_SRC_FDE_XML_FDE_XML_IMP_H_