1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include <algorithm>
8 
9 #include "xfa/src/foxitlib.h"
10 #include "fde_xml.h"
11 #ifdef __cplusplus
12 extern "C" {
13 #endif
14 #define FDE_XMLVALIDCHARRANGENUM 5
15 static FX_WCHAR g_XMLValidCharRange[FDE_XMLVALIDCHARRANGENUM][2] = {
16     {0x09, 0x09},
17     {0x0A, 0x0A},
18     {0x0D, 0x0D},
19     {0x20, 0xD7FF},
20     {0xE000, 0xFFFD}};
FDE_IsXMLValidChar(FX_WCHAR ch)21 FX_BOOL FDE_IsXMLValidChar(FX_WCHAR ch) {
22   int32_t iStart = 0, iEnd = FDE_XMLVALIDCHARRANGENUM - 1, iMid;
23   while (iStart <= iEnd) {
24     iMid = (iStart + iEnd) / 2;
25     if (ch < g_XMLValidCharRange[iMid][0]) {
26       iEnd = iMid - 1;
27     } else if (ch > g_XMLValidCharRange[iMid][1]) {
28       iStart = iMid + 1;
29     } else {
30       return TRUE;
31     }
32   }
33   return FALSE;
34 }
FDE_IsXMLWhiteSpace(FX_WCHAR ch)35 FX_BOOL FDE_IsXMLWhiteSpace(FX_WCHAR ch) {
36   return ch == L' ' || ch == 0x0A || ch == 0x0D || ch == 0x09;
37 }
38 typedef struct _FDE_XMLNAMECHAR {
39   FX_WCHAR wStart;
40   FX_WCHAR wEnd;
41   FX_BOOL bStartChar;
42 } FDE_XMLNAMECHAR;
43 #define FDE_XMLNAMECHARSNUM 20
44 static FDE_XMLNAMECHAR g_XMLNameChars[FDE_XMLNAMECHARSNUM] = {
45     {L'-', L'.', FALSE},    {L'0', L'9', FALSE},     {L':', L':', FALSE},
46     {L'A', L'Z', TRUE},     {L'_', L'_', TRUE},      {L'a', L'z', TRUE},
47     {0xB7, 0xB7, FALSE},    {0xC0, 0xD6, TRUE},      {0xD8, 0xF6, TRUE},
48     {0xF8, 0x02FF, TRUE},   {0x0300, 0x036F, FALSE}, {0x0370, 0x037D, TRUE},
49     {0x037F, 0x1FFF, TRUE}, {0x200C, 0x200D, TRUE},  {0x203F, 0x2040, FALSE},
50     {0x2070, 0x218F, TRUE}, {0x2C00, 0x2FEF, TRUE},  {0x3001, 0xD7FF, TRUE},
51     {0xF900, 0xFDCF, TRUE}, {0xFDF0, 0xFFFD, TRUE},
52 };
FDE_IsXMLNameChar(FX_WCHAR ch,FX_BOOL bFirstChar)53 FX_BOOL FDE_IsXMLNameChar(FX_WCHAR ch, FX_BOOL bFirstChar) {
54   int32_t iStart = 0, iEnd = FDE_XMLNAMECHARSNUM - 1, iMid;
55   while (iStart <= iEnd) {
56     iMid = (iStart + iEnd) / 2;
57     if (ch < g_XMLNameChars[iMid].wStart) {
58       iEnd = iMid - 1;
59     } else if (ch > g_XMLNameChars[iMid].wEnd) {
60       iStart = iMid + 1;
61     } else {
62       if (bFirstChar) {
63         return g_XMLNameChars[iMid].bStartChar;
64       }
65       return TRUE;
66     }
67   }
68   return FALSE;
69 }
70 #ifdef __cplusplus
71 }
72 #endif
CFDE_XMLNode()73 CFDE_XMLNode::CFDE_XMLNode()
74     : m_pParent(NULL), m_pChild(NULL), m_pPrior(NULL), m_pNext(NULL) {}
~CFDE_XMLNode()75 CFDE_XMLNode::~CFDE_XMLNode() {
76   DeleteChildren();
77 }
DeleteChildren()78 void CFDE_XMLNode::DeleteChildren() {
79   CFDE_XMLNode *pChild = m_pChild, *pTemp;
80   while (pChild != NULL) {
81     pTemp = pChild->m_pNext;
82     pChild->Release();
83     pChild = pTemp;
84   }
85   m_pChild = NULL;
86 }
CountChildNodes() const87 int32_t CFDE_XMLNode::CountChildNodes() const {
88   int32_t iCount = 0;
89   CFDE_XMLNode* pChild = m_pChild;
90   while (pChild != NULL) {
91     iCount++;
92     pChild = pChild->m_pNext;
93   }
94   return iCount;
95 }
GetChildNode(int32_t index) const96 CFDE_XMLNode* CFDE_XMLNode::GetChildNode(int32_t index) const {
97   CFDE_XMLNode* pChild = m_pChild;
98   while (pChild != NULL) {
99     if (index == 0) {
100       return pChild;
101     }
102     index--;
103     pChild = pChild->m_pNext;
104   }
105   return NULL;
106 }
GetChildNodeIndex(CFDE_XMLNode * pNode) const107 int32_t CFDE_XMLNode::GetChildNodeIndex(CFDE_XMLNode* pNode) const {
108   int32_t index = 0;
109   CFDE_XMLNode* pChild = m_pChild;
110   while (pChild != NULL) {
111     if (pChild == pNode) {
112       return index;
113     }
114     index++;
115     pChild = pChild->m_pNext;
116   }
117   return -1;
118 }
GetPath(const FX_WCHAR * pPath,int32_t iLength,FX_BOOL bQualifiedName) const119 CFDE_XMLNode* CFDE_XMLNode::GetPath(const FX_WCHAR* pPath,
120                                     int32_t iLength,
121                                     FX_BOOL bQualifiedName) const {
122   FXSYS_assert(pPath != NULL);
123   if (iLength < 0) {
124     iLength = FXSYS_wcslen(pPath);
125   }
126   if (iLength == 0) {
127     return NULL;
128   }
129   CFX_WideString csPath;
130   const FX_WCHAR* pStart = pPath;
131   const FX_WCHAR* pEnd = pPath + iLength;
132   FX_WCHAR ch;
133   while (pStart < pEnd) {
134     ch = *pStart++;
135     if (ch == L'/') {
136       break;
137     } else {
138       csPath += ch;
139     }
140   }
141   iLength -= pStart - pPath;
142   CFDE_XMLNode* pFind = NULL;
143   if (csPath.GetLength() < 1) {
144     pFind = GetNodeItem(IFDE_XMLNode::Root);
145   } else if (csPath.Compare(L"..") == 0) {
146     pFind = m_pParent;
147   } else if (csPath.Compare(L".") == 0) {
148     pFind = (CFDE_XMLNode*)this;
149   } else {
150     CFX_WideString wsTag;
151     CFDE_XMLNode* pNode = m_pChild;
152     while (pNode != NULL) {
153       if (pNode->GetType() == FDE_XMLNODE_Element) {
154         if (bQualifiedName) {
155           ((CFDE_XMLElement*)pNode)->GetTagName(wsTag);
156         } else {
157           ((CFDE_XMLElement*)pNode)->GetLocalTagName(wsTag);
158         }
159         if (wsTag.Compare(csPath) == 0) {
160           if (iLength < 1) {
161             pFind = pNode;
162           } else {
163             pFind = pNode->GetPath(pStart, iLength, bQualifiedName);
164           }
165           if (pFind != NULL) {
166             return pFind;
167           }
168         }
169       }
170       pNode = pNode->m_pNext;
171     }
172   }
173   if (pFind == NULL || iLength < 1) {
174     return pFind;
175   }
176   return pFind->GetPath(pStart, iLength, bQualifiedName);
177 }
InsertChildNode(CFDE_XMLNode * pNode,int32_t index)178 int32_t CFDE_XMLNode::InsertChildNode(CFDE_XMLNode* pNode, int32_t index) {
179   FXSYS_assert(pNode != NULL);
180   pNode->m_pParent = this;
181   if (m_pChild == NULL) {
182     m_pChild = pNode;
183     pNode->m_pPrior = NULL;
184     pNode->m_pNext = NULL;
185     return 0;
186   } else if (index == 0) {
187     pNode->m_pNext = m_pChild;
188     pNode->m_pPrior = NULL;
189     m_pChild->m_pPrior = pNode;
190     m_pChild = pNode;
191     return 0;
192   }
193   int32_t iCount = 0;
194   CFDE_XMLNode* pFind = m_pChild;
195   while (++iCount != index && pFind->m_pNext != NULL) {
196     pFind = pFind->m_pNext;
197   }
198   pNode->m_pPrior = pFind;
199   pNode->m_pNext = pFind->m_pNext;
200   if (pFind->m_pNext != NULL) {
201     pFind->m_pNext->m_pPrior = pNode;
202   }
203   pFind->m_pNext = pNode;
204   return iCount;
205 }
RemoveChildNode(CFDE_XMLNode * pNode)206 void CFDE_XMLNode::RemoveChildNode(CFDE_XMLNode* pNode) {
207   FXSYS_assert(m_pChild != NULL && pNode != NULL);
208   if (m_pChild == pNode) {
209     m_pChild = pNode->m_pNext;
210   } else {
211     pNode->m_pPrior->m_pNext = pNode->m_pNext;
212   }
213   if (pNode->m_pNext != NULL) {
214     pNode->m_pNext->m_pPrior = pNode->m_pPrior;
215   }
216   pNode->m_pParent = NULL;
217   pNode->m_pNext = NULL;
218   pNode->m_pPrior = NULL;
219 }
GetNodeItem(IFDE_XMLNode::NodeItem eItem) const220 CFDE_XMLNode* CFDE_XMLNode::GetNodeItem(IFDE_XMLNode::NodeItem eItem) const {
221   switch (eItem) {
222     case IFDE_XMLNode::Root: {
223       CFDE_XMLNode* pParent = (CFDE_XMLNode*)this;
224       while (pParent->m_pParent != NULL) {
225         pParent = pParent->m_pParent;
226       }
227       return pParent;
228     }
229     case IFDE_XMLNode::Parent:
230       return m_pParent;
231     case IFDE_XMLNode::FirstSibling: {
232       CFDE_XMLNode* pItem = (CFDE_XMLNode*)this;
233       while (pItem->m_pPrior != NULL) {
234         pItem = pItem->m_pPrior;
235       }
236       return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
237     }
238     case IFDE_XMLNode::PriorSibling:
239       return m_pPrior;
240     case IFDE_XMLNode::NextSibling:
241       return m_pNext;
242     case IFDE_XMLNode::LastSibling: {
243       CFDE_XMLNode* pItem = (CFDE_XMLNode*)this;
244       while (pItem->m_pNext != NULL) {
245         pItem = pItem->m_pNext;
246       }
247       return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
248     }
249     case IFDE_XMLNode::FirstNeighbor: {
250       CFDE_XMLNode* pParent = (CFDE_XMLNode*)this;
251       while (pParent->m_pParent != NULL) {
252         pParent = pParent->m_pParent;
253       }
254       return pParent == (CFDE_XMLNode*)this ? NULL : pParent;
255     }
256     case IFDE_XMLNode::PriorNeighbor: {
257       if (m_pPrior == NULL) {
258         return m_pParent;
259       }
260       CFDE_XMLNode* pItem = m_pPrior;
261       while (CFDE_XMLNode* pTemp = pItem->m_pChild) {
262         pItem = pTemp;
263         while ((pTemp = pItem->m_pNext) != NULL) {
264           pItem = pTemp;
265         }
266       }
267       return pItem;
268     }
269     case IFDE_XMLNode::NextNeighbor: {
270       if (m_pChild != NULL) {
271         return m_pChild;
272       }
273       if (m_pNext != NULL) {
274         return m_pNext;
275       }
276       CFDE_XMLNode* pItem = m_pParent;
277       while (pItem != NULL) {
278         if (pItem->m_pNext != NULL) {
279           return pItem->m_pNext;
280         }
281         pItem = pItem->m_pParent;
282       }
283       return NULL;
284     }
285     case IFDE_XMLNode::LastNeighbor: {
286       CFDE_XMLNode* pItem = (CFDE_XMLNode*)this;
287       while (pItem->m_pParent != NULL) {
288         pItem = pItem->m_pParent;
289       }
290       while (TRUE) {
291         while (pItem->m_pNext != NULL) {
292           pItem = pItem->m_pNext;
293         }
294         if (pItem->m_pChild == NULL) {
295           break;
296         }
297         pItem = pItem->m_pChild;
298       }
299       return pItem == (CFDE_XMLNode*)this ? NULL : pItem;
300     }
301     case IFDE_XMLNode::FirstChild:
302       return m_pChild;
303     case IFDE_XMLNode::LastChild: {
304       if (m_pChild == NULL) {
305         return NULL;
306       }
307       CFDE_XMLNode* pChild = m_pChild;
308       while (pChild->m_pNext != NULL) {
309         pChild = pChild->m_pNext;
310       }
311       return pChild;
312     }
313     default:
314       break;
315   }
316   return NULL;
317 }
GetNodeLevel() const318 int32_t CFDE_XMLNode::GetNodeLevel() const {
319   int32_t iLevel = 0;
320   CFDE_XMLNode* pItem = (CFDE_XMLNode*)this;
321   while ((pItem = pItem->m_pParent) != NULL) {
322     iLevel++;
323   }
324   return iLevel;
325 }
InsertNodeItem(IFDE_XMLNode::NodeItem eItem,CFDE_XMLNode * pNode)326 FX_BOOL CFDE_XMLNode::InsertNodeItem(IFDE_XMLNode::NodeItem eItem,
327                                      CFDE_XMLNode* pNode) {
328   FXSYS_assert(pNode != NULL);
329   switch (eItem) {
330     case IFDE_XMLNode::NextSibling: {
331       pNode->m_pParent = m_pParent;
332       pNode->m_pNext = m_pNext;
333       pNode->m_pPrior = this;
334       if (m_pNext) {
335         m_pNext->m_pPrior = pNode;
336       }
337       m_pNext = pNode;
338       return TRUE;
339     }
340     case IFDE_XMLNode::PriorSibling: {
341       pNode->m_pParent = m_pParent;
342       pNode->m_pNext = this;
343       pNode->m_pPrior = m_pPrior;
344       if (m_pPrior) {
345         m_pPrior->m_pNext = pNode;
346       } else if (m_pParent) {
347         m_pParent->m_pChild = pNode;
348       }
349       m_pPrior = pNode;
350       return TRUE;
351     }
352     default:
353       return FALSE;
354   }
355   return FALSE;
356 }
RemoveNodeItem(IFDE_XMLNode::NodeItem eItem)357 CFDE_XMLNode* CFDE_XMLNode::RemoveNodeItem(IFDE_XMLNode::NodeItem eItem) {
358   CFDE_XMLNode* pNode = NULL;
359   switch (eItem) {
360     case IFDE_XMLNode::NextSibling:
361       if (m_pNext) {
362         pNode = m_pNext;
363         m_pNext = pNode->m_pNext;
364         if (m_pNext) {
365           m_pNext->m_pPrior = this;
366         }
367         pNode->m_pParent = NULL;
368         pNode->m_pNext = NULL;
369         pNode->m_pPrior = NULL;
370       }
371       break;
372     default:
373       break;
374   }
375   return pNode;
376 }
Clone(FX_BOOL bRecursive)377 CFDE_XMLNode* CFDE_XMLNode::Clone(FX_BOOL bRecursive) {
378   return NULL;
379 }
SaveXMLNode(IFX_Stream * pXMLStream)380 void CFDE_XMLNode::SaveXMLNode(IFX_Stream* pXMLStream) {
381   CFDE_XMLNode* pNode = (CFDE_XMLNode*)this;
382   FXSYS_assert(pXMLStream != NULL && pNode != NULL);
383   switch (pNode->GetType()) {
384     case FDE_XMLNODE_Instruction: {
385       CFX_WideString ws;
386       CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode;
387       if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
388         ws = L"<?xml version=\"1.0\" encoding=\"";
389         FX_WORD wCodePage = pXMLStream->GetCodePage();
390         if (wCodePage == FX_CODEPAGE_UTF16LE) {
391           ws += L"UTF-16";
392         } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
393           ws += L"UTF-16be";
394         } else {
395           ws += L"UTF-8";
396         }
397         ws += L"\"?>";
398         pXMLStream->WriteString(ws, ws.GetLength());
399       } else {
400         ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
401         pXMLStream->WriteString(ws, ws.GetLength());
402         CFX_WideStringArray& attributes = pInstruction->m_Attributes;
403         int32_t i, iCount = attributes.GetSize();
404         CFX_WideString wsValue;
405         for (i = 0; i < iCount; i += 2) {
406           ws = L" ";
407           ws += attributes[i];
408           ws += L"=\"";
409           wsValue = attributes[i + 1];
410           wsValue.Replace(L"&", L"&amp;");
411           wsValue.Replace(L"<", L"&lt;");
412           wsValue.Replace(L">", L"&gt;");
413           wsValue.Replace(L"\'", L"&apos;");
414           wsValue.Replace(L"\"", L"&quot;");
415           ws += wsValue;
416           ws += L"\"";
417           pXMLStream->WriteString(ws, ws.GetLength());
418         }
419         CFX_WideStringArray& targetdata = pInstruction->m_TargetData;
420         iCount = targetdata.GetSize();
421         for (i = 0; i < iCount; i++) {
422           ws = L" \"";
423           ws += targetdata[i];
424           ws += L"\"";
425           pXMLStream->WriteString(ws, ws.GetLength());
426         }
427         ws = L"?>";
428         pXMLStream->WriteString(ws, ws.GetLength());
429       }
430     } break;
431     case FDE_XMLNODE_Element: {
432       CFX_WideString ws;
433       ws = L"<";
434       ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
435       pXMLStream->WriteString(ws, ws.GetLength());
436       CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
437       int32_t iCount = attributes.GetSize();
438       CFX_WideString wsValue;
439       for (int32_t i = 0; i < iCount; i += 2) {
440         ws = L" ";
441         ws += attributes[i];
442         ws += L"=\"";
443         wsValue = attributes[i + 1];
444         wsValue.Replace(L"&", L"&amp;");
445         wsValue.Replace(L"<", L"&lt;");
446         wsValue.Replace(L">", L"&gt;");
447         wsValue.Replace(L"\'", L"&apos;");
448         wsValue.Replace(L"\"", L"&quot;");
449         ws += wsValue;
450         ws += L"\"";
451         pXMLStream->WriteString(ws, ws.GetLength());
452       }
453       if (pNode->m_pChild == NULL) {
454         ws = L"\n/>";
455         pXMLStream->WriteString(ws, ws.GetLength());
456       } else {
457         ws = L"\n>";
458         pXMLStream->WriteString(ws, ws.GetLength());
459         CFDE_XMLNode* pChild = pNode->m_pChild;
460         while (pChild != NULL) {
461           pChild->SaveXMLNode(pXMLStream);
462           pChild = pChild->m_pNext;
463         }
464         ws = L"</";
465         ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
466         ws += L"\n>";
467         pXMLStream->WriteString(ws, ws.GetLength());
468       }
469     } break;
470     case FDE_XMLNODE_Text: {
471       CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
472       ws.Replace(L"&", L"&amp;");
473       ws.Replace(L"<", L"&lt;");
474       ws.Replace(L">", L"&gt;");
475       ws.Replace(L"\'", L"&apos;");
476       ws.Replace(L"\"", L"&quot;");
477       pXMLStream->WriteString(ws, ws.GetLength());
478     } break;
479     case FDE_XMLNODE_CharData: {
480       CFX_WideString ws = L"<![CDATA[";
481       ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
482       ws += L"]]>";
483       pXMLStream->WriteString(ws, ws.GetLength());
484     } break;
485     case FDE_XMLNODE_Unknown:
486       break;
487     default:
488       break;
489   }
490 }
CloneChildren(CFDE_XMLNode * pClone)491 void CFDE_XMLNode::CloneChildren(CFDE_XMLNode* pClone) {
492   if (!m_pChild) {
493     return;
494   }
495   CFDE_XMLNode* pNext = m_pChild;
496   CFDE_XMLNode* pCloneNext = pNext->Clone(TRUE);
497   pClone->InsertChildNode(pCloneNext);
498   pNext = pNext->m_pNext;
499   while (pNext) {
500     CFDE_XMLNode* pChild = pNext->Clone(TRUE);
501     pCloneNext->InsertNodeItem(IFDE_XMLNode::NextSibling, pChild);
502     pCloneNext = pChild;
503     pNext = pNext->m_pNext;
504   }
505 }
Create(const CFX_WideString & wsTarget)506 IFDE_XMLInstruction* IFDE_XMLInstruction::Create(
507     const CFX_WideString& wsTarget) {
508   return (IFDE_XMLInstruction*)new CFDE_XMLInstruction(wsTarget);
509 }
CFDE_XMLInstruction(const CFX_WideString & wsTarget)510 CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString& wsTarget)
511     : m_wsTarget(wsTarget) {
512   FXSYS_assert(m_wsTarget.GetLength() > 0);
513 }
Clone(FX_BOOL bRecursive)514 CFDE_XMLNode* CFDE_XMLInstruction::Clone(FX_BOOL bRecursive) {
515   CFDE_XMLInstruction* pClone = new CFDE_XMLInstruction(m_wsTarget);
516   if (!pClone) {
517     return pClone;
518   }
519   pClone->m_Attributes.Copy(m_Attributes);
520   pClone->m_TargetData.Copy(m_TargetData);
521   if (bRecursive) {
522     CloneChildren(pClone);
523   }
524   return pClone;
525 }
CountAttributes() const526 int32_t CFDE_XMLInstruction::CountAttributes() const {
527   return m_Attributes.GetSize() / 2;
528 }
GetAttribute(int32_t index,CFX_WideString & wsAttriName,CFX_WideString & wsAttriValue) const529 FX_BOOL CFDE_XMLInstruction::GetAttribute(int32_t index,
530                                           CFX_WideString& wsAttriName,
531                                           CFX_WideString& wsAttriValue) const {
532   int32_t iCount = m_Attributes.GetSize();
533   FXSYS_assert(index > -1 && index < iCount / 2);
534   for (int32_t i = 0; i < iCount; i += 2) {
535     if (index == 0) {
536       wsAttriName = m_Attributes[i];
537       wsAttriValue = m_Attributes[i + 1];
538       return TRUE;
539     }
540     index--;
541   }
542   return FALSE;
543 }
HasAttribute(const FX_WCHAR * pwsAttriName) const544 FX_BOOL CFDE_XMLInstruction::HasAttribute(const FX_WCHAR* pwsAttriName) const {
545   int32_t iCount = m_Attributes.GetSize();
546   for (int32_t i = 0; i < iCount; i += 2) {
547     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
548       return TRUE;
549     }
550   }
551   return FALSE;
552 }
GetString(const FX_WCHAR * pwsAttriName,CFX_WideString & wsAttriValue,const FX_WCHAR * pwsDefValue) const553 void CFDE_XMLInstruction::GetString(const FX_WCHAR* pwsAttriName,
554                                     CFX_WideString& wsAttriValue,
555                                     const FX_WCHAR* pwsDefValue) const {
556   int32_t iCount = m_Attributes.GetSize();
557   for (int32_t i = 0; i < iCount; i += 2) {
558     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
559       wsAttriValue = m_Attributes[i + 1];
560       return;
561     }
562   }
563   wsAttriValue = pwsDefValue;
564 }
SetString(const CFX_WideString & wsAttriName,const CFX_WideString & wsAttriValue)565 void CFDE_XMLInstruction::SetString(const CFX_WideString& wsAttriName,
566                                     const CFX_WideString& wsAttriValue) {
567   FXSYS_assert(wsAttriName.GetLength() > 0);
568   int32_t iCount = m_Attributes.GetSize();
569   for (int32_t i = 0; i < iCount; i += 2) {
570     if (m_Attributes[i].Compare(wsAttriName) == 0) {
571       m_Attributes[i] = wsAttriName;
572       m_Attributes[i + 1] = wsAttriValue;
573       return;
574     }
575   }
576   m_Attributes.Add(wsAttriName);
577   m_Attributes.Add(wsAttriValue);
578 }
GetInteger(const FX_WCHAR * pwsAttriName,int32_t iDefValue) const579 int32_t CFDE_XMLInstruction::GetInteger(const FX_WCHAR* pwsAttriName,
580                                         int32_t iDefValue) const {
581   int32_t iCount = m_Attributes.GetSize();
582   for (int32_t i = 0; i < iCount; i += 2) {
583     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
584       return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]);
585     }
586   }
587   return iDefValue;
588 }
SetInteger(const FX_WCHAR * pwsAttriName,int32_t iAttriValue)589 void CFDE_XMLInstruction::SetInteger(const FX_WCHAR* pwsAttriName,
590                                      int32_t iAttriValue) {
591   CFX_WideString wsValue;
592   wsValue.Format(L"%d", iAttriValue);
593   SetString(pwsAttriName, wsValue);
594 }
GetFloat(const FX_WCHAR * pwsAttriName,FX_FLOAT fDefValue) const595 FX_FLOAT CFDE_XMLInstruction::GetFloat(const FX_WCHAR* pwsAttriName,
596                                        FX_FLOAT fDefValue) const {
597   int32_t iCount = m_Attributes.GetSize();
598   for (int32_t i = 0; i < iCount; i += 2) {
599     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
600       return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]);
601     }
602   }
603   return fDefValue;
604 }
SetFloat(const FX_WCHAR * pwsAttriName,FX_FLOAT fAttriValue)605 void CFDE_XMLInstruction::SetFloat(const FX_WCHAR* pwsAttriName,
606                                    FX_FLOAT fAttriValue) {
607   CFX_WideString wsValue;
608   wsValue.Format(L"%f", fAttriValue);
609   SetString(pwsAttriName, wsValue);
610 }
RemoveAttribute(const FX_WCHAR * pwsAttriName)611 void CFDE_XMLInstruction::RemoveAttribute(const FX_WCHAR* pwsAttriName) {
612   int32_t iCount = m_Attributes.GetSize();
613   for (int32_t i = 0; i < iCount; i += 2) {
614     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
615       m_Attributes.RemoveAt(i + 1);
616       m_Attributes.RemoveAt(i);
617       return;
618     }
619   }
620 }
CountData() const621 int32_t CFDE_XMLInstruction::CountData() const {
622   return m_TargetData.GetSize();
623 }
GetData(int32_t index,CFX_WideString & wsData) const624 FX_BOOL CFDE_XMLInstruction::GetData(int32_t index,
625                                      CFX_WideString& wsData) const {
626   if (index < 0 || index >= m_TargetData.GetSize()) {
627     return FALSE;
628   }
629   wsData = m_TargetData[index];
630   return TRUE;
631 }
AppendData(const CFX_WideString & wsData)632 void CFDE_XMLInstruction::AppendData(const CFX_WideString& wsData) {
633   m_TargetData.Add(wsData);
634 }
RemoveData(int32_t index)635 void CFDE_XMLInstruction::RemoveData(int32_t index) {
636   m_TargetData.RemoveAt(index);
637 }
Create(const CFX_WideString & wsTag)638 IFDE_XMLElement* IFDE_XMLElement::Create(const CFX_WideString& wsTag) {
639   return (IFDE_XMLElement*)new CFDE_XMLElement(wsTag);
640 }
CFDE_XMLElement(const CFX_WideString & wsTag)641 CFDE_XMLElement::CFDE_XMLElement(const CFX_WideString& wsTag)
642     : CFDE_XMLNode(), m_wsTag(wsTag), m_Attributes() {
643   FXSYS_assert(m_wsTag.GetLength() > 0);
644 }
~CFDE_XMLElement()645 CFDE_XMLElement::~CFDE_XMLElement() {
646   m_Attributes.RemoveAll();
647 }
Clone(FX_BOOL bRecursive)648 CFDE_XMLNode* CFDE_XMLElement::Clone(FX_BOOL bRecursive) {
649   CFDE_XMLElement* pClone = new CFDE_XMLElement(m_wsTag);
650   if (!pClone) {
651     return NULL;
652   }
653   pClone->m_Attributes.Copy(m_Attributes);
654   if (bRecursive) {
655     CloneChildren(pClone);
656   } else {
657     CFX_WideString wsText;
658     CFDE_XMLNode* pChild = m_pChild;
659     while (pChild != NULL) {
660       switch (pChild->GetType()) {
661         case FDE_XMLNODE_Text:
662           wsText += ((CFDE_XMLText*)pChild)->m_wsText;
663           break;
664         default:
665           break;
666       }
667       pChild = pChild->m_pNext;
668     }
669     pClone->SetTextData(wsText);
670   }
671   return pClone;
672 }
GetTagName(CFX_WideString & wsTag) const673 void CFDE_XMLElement::GetTagName(CFX_WideString& wsTag) const {
674   wsTag = m_wsTag;
675 }
GetLocalTagName(CFX_WideString & wsTag) const676 void CFDE_XMLElement::GetLocalTagName(CFX_WideString& wsTag) const {
677   FX_STRSIZE iFind = m_wsTag.Find(L':', 0);
678   if (iFind < 0) {
679     wsTag = m_wsTag;
680   } else {
681     wsTag = m_wsTag.Right(m_wsTag.GetLength() - iFind - 1);
682   }
683 }
GetNamespacePrefix(CFX_WideString & wsPrefix) const684 void CFDE_XMLElement::GetNamespacePrefix(CFX_WideString& wsPrefix) const {
685   FX_STRSIZE iFind = m_wsTag.Find(L':', 0);
686   if (iFind < 0) {
687     wsPrefix.Empty();
688   } else {
689     wsPrefix = m_wsTag.Left(iFind);
690   }
691 }
GetNamespaceURI(CFX_WideString & wsNamespace) const692 void CFDE_XMLElement::GetNamespaceURI(CFX_WideString& wsNamespace) const {
693   CFX_WideString wsAttri(L"xmlns"), wsPrefix;
694   GetNamespacePrefix(wsPrefix);
695   if (wsPrefix.GetLength() > 0) {
696     wsAttri += L":";
697     wsAttri += wsPrefix;
698   }
699   wsNamespace.Empty();
700   CFDE_XMLNode* pNode = (CFDE_XMLNode*)this;
701   while (pNode != NULL) {
702     if (pNode->GetType() != FDE_XMLNODE_Element) {
703       break;
704     }
705     CFDE_XMLElement* pElement = (CFDE_XMLElement*)pNode;
706     if (!pElement->HasAttribute(wsAttri)) {
707       pNode = pNode->GetNodeItem(IFDE_XMLNode::Parent);
708       continue;
709     }
710     pElement->GetString(wsAttri, wsNamespace);
711     break;
712   }
713 }
CountAttributes() const714 int32_t CFDE_XMLElement::CountAttributes() const {
715   return m_Attributes.GetSize() / 2;
716 }
GetAttribute(int32_t index,CFX_WideString & wsAttriName,CFX_WideString & wsAttriValue) const717 FX_BOOL CFDE_XMLElement::GetAttribute(int32_t index,
718                                       CFX_WideString& wsAttriName,
719                                       CFX_WideString& wsAttriValue) const {
720   int32_t iCount = m_Attributes.GetSize();
721   FXSYS_assert(index > -1 && index < iCount / 2);
722   for (int32_t i = 0; i < iCount; i += 2) {
723     if (index == 0) {
724       wsAttriName = m_Attributes[i];
725       wsAttriValue = m_Attributes[i + 1];
726       return TRUE;
727     }
728     index--;
729   }
730   return FALSE;
731 }
HasAttribute(const FX_WCHAR * pwsAttriName) const732 FX_BOOL CFDE_XMLElement::HasAttribute(const FX_WCHAR* pwsAttriName) const {
733   int32_t iCount = m_Attributes.GetSize();
734   for (int32_t i = 0; i < iCount; i += 2) {
735     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
736       return TRUE;
737     }
738   }
739   return FALSE;
740 }
GetString(const FX_WCHAR * pwsAttriName,CFX_WideString & wsAttriValue,const FX_WCHAR * pwsDefValue) const741 void CFDE_XMLElement::GetString(const FX_WCHAR* pwsAttriName,
742                                 CFX_WideString& wsAttriValue,
743                                 const FX_WCHAR* pwsDefValue) const {
744   int32_t iCount = m_Attributes.GetSize();
745   for (int32_t i = 0; i < iCount; i += 2) {
746     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
747       wsAttriValue = m_Attributes[i + 1];
748       return;
749     }
750   }
751   wsAttriValue = pwsDefValue;
752 }
SetString(const CFX_WideString & wsAttriName,const CFX_WideString & wsAttriValue)753 void CFDE_XMLElement::SetString(const CFX_WideString& wsAttriName,
754                                 const CFX_WideString& wsAttriValue) {
755   FXSYS_assert(wsAttriName.GetLength() > 0);
756   int32_t iCount = m_Attributes.GetSize();
757   for (int32_t i = 0; i < iCount; i += 2) {
758     if (m_Attributes[i].Compare(wsAttriName) == 0) {
759       m_Attributes[i] = wsAttriName;
760       m_Attributes[i + 1] = wsAttriValue;
761       return;
762     }
763   }
764   m_Attributes.Add(wsAttriName);
765   m_Attributes.Add(wsAttriValue);
766 }
GetInteger(const FX_WCHAR * pwsAttriName,int32_t iDefValue) const767 int32_t CFDE_XMLElement::GetInteger(const FX_WCHAR* pwsAttriName,
768                                     int32_t iDefValue) const {
769   int32_t iCount = m_Attributes.GetSize();
770   for (int32_t i = 0; i < iCount; i += 2) {
771     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
772       return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]);
773     }
774   }
775   return iDefValue;
776 }
SetInteger(const FX_WCHAR * pwsAttriName,int32_t iAttriValue)777 void CFDE_XMLElement::SetInteger(const FX_WCHAR* pwsAttriName,
778                                  int32_t iAttriValue) {
779   CFX_WideString wsValue;
780   wsValue.Format(L"%d", iAttriValue);
781   SetString(pwsAttriName, wsValue);
782 }
GetFloat(const FX_WCHAR * pwsAttriName,FX_FLOAT fDefValue) const783 FX_FLOAT CFDE_XMLElement::GetFloat(const FX_WCHAR* pwsAttriName,
784                                    FX_FLOAT fDefValue) const {
785   int32_t iCount = m_Attributes.GetSize();
786   for (int32_t i = 0; i < iCount; i += 2) {
787     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
788       return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]);
789     }
790   }
791   return fDefValue;
792 }
SetFloat(const FX_WCHAR * pwsAttriName,FX_FLOAT fAttriValue)793 void CFDE_XMLElement::SetFloat(const FX_WCHAR* pwsAttriName,
794                                FX_FLOAT fAttriValue) {
795   CFX_WideString wsValue;
796   wsValue.Format(L"%f", fAttriValue);
797   SetString(pwsAttriName, wsValue);
798 }
RemoveAttribute(const FX_WCHAR * pwsAttriName)799 void CFDE_XMLElement::RemoveAttribute(const FX_WCHAR* pwsAttriName) {
800   int32_t iCount = m_Attributes.GetSize();
801   for (int32_t i = 0; i < iCount; i += 2) {
802     if (m_Attributes[i].Compare(pwsAttriName) == 0) {
803       m_Attributes.RemoveAt(i + 1);
804       m_Attributes.RemoveAt(i);
805       return;
806     }
807   }
808 }
GetTextData(CFX_WideString & wsText) const809 void CFDE_XMLElement::GetTextData(CFX_WideString& wsText) const {
810   CFX_WideTextBuf buffer;
811   CFDE_XMLNode* pChild = m_pChild;
812   while (pChild != NULL) {
813     switch (pChild->GetType()) {
814       case FDE_XMLNODE_Text:
815         buffer << ((CFDE_XMLText*)pChild)->m_wsText;
816         break;
817       case FDE_XMLNODE_CharData:
818         buffer << ((CFDE_XMLCharData*)pChild)->m_wsCharData;
819         break;
820       default:
821         break;
822     }
823     pChild = pChild->m_pNext;
824   }
825   wsText = buffer.GetWideString();
826 }
SetTextData(const CFX_WideString & wsText)827 void CFDE_XMLElement::SetTextData(const CFX_WideString& wsText) {
828   if (wsText.GetLength() < 1) {
829     return;
830   }
831   InsertChildNode(new CFDE_XMLText(wsText));
832 }
Create(const CFX_WideString & wsText)833 IFDE_XMLText* IFDE_XMLText::Create(const CFX_WideString& wsText) {
834   return (IFDE_XMLText*)new CFDE_XMLText(wsText);
835 }
CFDE_XMLText(const CFX_WideString & wsText)836 CFDE_XMLText::CFDE_XMLText(const CFX_WideString& wsText)
837     : CFDE_XMLNode(), m_wsText(wsText) {}
Clone(FX_BOOL bRecursive)838 CFDE_XMLNode* CFDE_XMLText::Clone(FX_BOOL bRecursive) {
839   CFDE_XMLText* pClone = new CFDE_XMLText(m_wsText);
840   return pClone;
841 }
Create(const CFX_WideString & wsCData)842 IFDE_XMLCharData* IFDE_XMLCharData::Create(const CFX_WideString& wsCData) {
843   return (IFDE_XMLCharData*)new CFDE_XMLCharData(wsCData);
844 }
CFDE_XMLCharData(const CFX_WideString & wsCData)845 CFDE_XMLCharData::CFDE_XMLCharData(const CFX_WideString& wsCData)
846     : CFDE_XMLDeclaration(), m_wsCharData(wsCData) {}
Clone(FX_BOOL bRecursive)847 CFDE_XMLNode* CFDE_XMLCharData::Clone(FX_BOOL bRecursive) {
848   CFDE_XMLCharData* pClone = new CFDE_XMLCharData(m_wsCharData);
849   return pClone;
850 }
Create()851 IFDE_XMLDoc* IFDE_XMLDoc::Create() {
852   return (IFDE_XMLDoc*)new CFDE_XMLDoc;
853 }
CFDE_XMLDoc()854 CFDE_XMLDoc::CFDE_XMLDoc()
855     : m_pRoot(NULL), m_pSyntaxParser(NULL), m_pXMLParser(NULL) {
856   Reset(TRUE);
857   CFDE_XMLInstruction* pXML = new CFDE_XMLInstruction(L"xml");
858   m_pRoot->InsertChildNode(pXML);
859 }
~CFDE_XMLDoc()860 CFDE_XMLDoc::~CFDE_XMLDoc() {
861   Reset(FALSE);
862 }
Reset(FX_BOOL bInitRoot)863 void CFDE_XMLDoc::Reset(FX_BOOL bInitRoot) {
864   m_iStatus = 0;
865   m_pStream = NULL;
866   if (bInitRoot) {
867     if (m_pRoot == NULL) {
868       m_pRoot = new CFDE_XMLNode;
869     } else {
870       m_pRoot->DeleteChildren();
871     }
872   } else {
873     if (m_pRoot != NULL) {
874       m_pRoot->Release();
875       m_pRoot = NULL;
876     }
877   }
878   ReleaseParser();
879 }
ReleaseParser()880 void CFDE_XMLDoc::ReleaseParser() {
881   if (m_pXMLParser != NULL) {
882     m_pXMLParser->Release();
883     m_pXMLParser = NULL;
884   }
885   if (m_pSyntaxParser != NULL) {
886     m_pSyntaxParser->Release();
887     m_pSyntaxParser = NULL;
888   }
889 }
LoadXML(IFX_Stream * pXMLStream,int32_t iXMLPlaneSize,int32_t iTextDataSize,FDE_LPXMLREADERHANDLER pHandler)890 FX_BOOL CFDE_XMLDoc::LoadXML(IFX_Stream* pXMLStream,
891                              int32_t iXMLPlaneSize,
892                              int32_t iTextDataSize,
893                              FDE_LPXMLREADERHANDLER pHandler) {
894   if (pXMLStream == NULL) {
895     return FALSE;
896   }
897   Reset(TRUE);
898   iXMLPlaneSize = iXMLPlaneSize / 1024;
899   if (iXMLPlaneSize < 1) {
900     iXMLPlaneSize = 1;
901   }
902   iXMLPlaneSize *= 1024;
903   if (iXMLPlaneSize < 4096) {
904     iXMLPlaneSize = 4096;
905   }
906   iTextDataSize = iTextDataSize / 128;
907   if (iTextDataSize < 1) {
908     iTextDataSize = 1;
909   }
910   iTextDataSize *= 128;
911   if (iTextDataSize < 128) {
912     iTextDataSize = 128;
913   }
914   m_pStream = pXMLStream;
915   FX_WORD wCodePage = m_pStream->GetCodePage();
916   if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE &&
917       wCodePage != FX_CODEPAGE_UTF8) {
918     m_pStream->SetCodePage(FX_CODEPAGE_UTF8);
919   }
920   m_pSyntaxParser = IFDE_XMLSyntaxParser::Create();
921   if (m_pSyntaxParser == NULL) {
922     return FALSE;
923   }
924   m_pSyntaxParser->Init(m_pStream, iXMLPlaneSize, iTextDataSize);
925   if (pHandler == NULL) {
926     m_pXMLParser = new CFDE_XMLDOMParser(m_pRoot, m_pSyntaxParser);
927   } else {
928     m_pXMLParser = new CFDE_XMLSAXParser(pHandler, m_pSyntaxParser);
929   }
930   return TRUE;
931 }
LoadXML(IFDE_XMLParser * pXMLParser)932 FX_BOOL CFDE_XMLDoc::LoadXML(IFDE_XMLParser* pXMLParser) {
933   if (pXMLParser == NULL) {
934     return FALSE;
935   }
936   Reset(TRUE);
937   m_pXMLParser = pXMLParser;
938   return m_pXMLParser != NULL;
939 }
DoLoad(IFX_Pause * pPause)940 int32_t CFDE_XMLDoc::DoLoad(IFX_Pause* pPause) {
941   if (m_iStatus >= 100) {
942     return m_iStatus;
943   }
944   FXSYS_assert(m_pXMLParser != NULL);
945   return m_iStatus = m_pXMLParser->DoParser(pPause);
946 }
CloseXML()947 void CFDE_XMLDoc::CloseXML() {
948   ReleaseParser();
949 }
SaveXMLNode(IFX_Stream * pXMLStream,IFDE_XMLNode * pINode)950 void CFDE_XMLDoc::SaveXMLNode(IFX_Stream* pXMLStream, IFDE_XMLNode* pINode) {
951   CFDE_XMLNode* pNode = (CFDE_XMLNode*)pINode;
952   FXSYS_assert(pXMLStream != NULL && pNode != NULL);
953   switch (pNode->GetType()) {
954     case FDE_XMLNODE_Instruction: {
955       CFX_WideString ws;
956       CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode;
957       if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
958         ws = L"<?xml version=\"1.0\" encoding=\"";
959         FX_WORD wCodePage = pXMLStream->GetCodePage();
960         if (wCodePage == FX_CODEPAGE_UTF16LE) {
961           ws += L"UTF-16";
962         } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
963           ws += L"UTF-16be";
964         } else {
965           ws += L"UTF-8";
966         }
967         ws += L"\"?>";
968         pXMLStream->WriteString(ws, ws.GetLength());
969       } else {
970         ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
971         pXMLStream->WriteString(ws, ws.GetLength());
972         CFX_WideStringArray& attributes = pInstruction->m_Attributes;
973         int32_t i, iCount = attributes.GetSize();
974         CFX_WideString wsValue;
975         for (i = 0; i < iCount; i += 2) {
976           ws = L" ";
977           ws += attributes[i];
978           ws += L"=\"";
979           wsValue = attributes[i + 1];
980           wsValue.Replace(L"&", L"&amp;");
981           wsValue.Replace(L"<", L"&lt;");
982           wsValue.Replace(L">", L"&gt;");
983           wsValue.Replace(L"\'", L"&apos;");
984           wsValue.Replace(L"\"", L"&quot;");
985           ws += wsValue;
986           ws += L"\"";
987           pXMLStream->WriteString(ws, ws.GetLength());
988         }
989         CFX_WideStringArray& targetdata = pInstruction->m_TargetData;
990         iCount = targetdata.GetSize();
991         for (i = 0; i < iCount; i++) {
992           ws = L" \"";
993           ws += targetdata[i];
994           ws += L"\"";
995           pXMLStream->WriteString(ws, ws.GetLength());
996         }
997         ws = L"?>";
998         pXMLStream->WriteString(ws, ws.GetLength());
999       }
1000     } break;
1001     case FDE_XMLNODE_Element: {
1002       CFX_WideString ws;
1003       ws = L"<";
1004       ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
1005       pXMLStream->WriteString(ws, ws.GetLength());
1006       CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
1007       int32_t iCount = attributes.GetSize();
1008       CFX_WideString wsValue;
1009       for (int32_t i = 0; i < iCount; i += 2) {
1010         ws = L" ";
1011         ws += attributes[i];
1012         ws += L"=\"";
1013         wsValue = attributes[i + 1];
1014         wsValue.Replace(L"&", L"&amp;");
1015         wsValue.Replace(L"<", L"&lt;");
1016         wsValue.Replace(L">", L"&gt;");
1017         wsValue.Replace(L"\'", L"&apos;");
1018         wsValue.Replace(L"\"", L"&quot;");
1019         ws += wsValue;
1020         ws += L"\"";
1021         pXMLStream->WriteString(ws, ws.GetLength());
1022       }
1023       if (pNode->m_pChild == NULL) {
1024         ws = L"\n/>";
1025         pXMLStream->WriteString(ws, ws.GetLength());
1026       } else {
1027         ws = L"\n>";
1028         pXMLStream->WriteString(ws, ws.GetLength());
1029         CFDE_XMLNode* pChild = pNode->m_pChild;
1030         while (pChild != NULL) {
1031           SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pChild);
1032           pChild = pChild->m_pNext;
1033         }
1034         ws = L"</";
1035         ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
1036         ws += L"\n>";
1037         pXMLStream->WriteString(ws, ws.GetLength());
1038       }
1039     } break;
1040     case FDE_XMLNODE_Text: {
1041       CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
1042       ws.Replace(L"&", L"&amp;");
1043       ws.Replace(L"<", L"&lt;");
1044       ws.Replace(L">", L"&gt;");
1045       ws.Replace(L"\'", L"&apos;");
1046       ws.Replace(L"\"", L"&quot;");
1047       pXMLStream->WriteString(ws, ws.GetLength());
1048     } break;
1049     case FDE_XMLNODE_CharData: {
1050       CFX_WideString ws = L"<![CDATA[";
1051       ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
1052       ws += L"]]>";
1053       pXMLStream->WriteString(ws, ws.GetLength());
1054     } break;
1055     case FDE_XMLNODE_Unknown:
1056       break;
1057     default:
1058       break;
1059   }
1060 }
SaveXML(IFX_Stream * pXMLStream,FX_BOOL bSaveBOM)1061 void CFDE_XMLDoc::SaveXML(IFX_Stream* pXMLStream, FX_BOOL bSaveBOM) {
1062   if (pXMLStream == NULL || pXMLStream == m_pStream) {
1063     m_pStream->Seek(FX_STREAMSEEK_Begin, 0);
1064     pXMLStream = m_pStream;
1065   }
1066   FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Text) != 0);
1067   FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Write) != 0);
1068   FX_WORD wCodePage = pXMLStream->GetCodePage();
1069   if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE &&
1070       wCodePage != FX_CODEPAGE_UTF8) {
1071     wCodePage = FX_CODEPAGE_UTF8;
1072     pXMLStream->SetCodePage(wCodePage);
1073   }
1074   if (bSaveBOM) {
1075     pXMLStream->WriteString(L"\xFEFF", 1);
1076   }
1077   CFDE_XMLNode* pNode = m_pRoot->m_pChild;
1078   while (pNode != NULL) {
1079     SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pNode);
1080     pNode = pNode->m_pNext;
1081   }
1082   if (pXMLStream == m_pStream) {
1083     int32_t iPos = pXMLStream->GetPosition();
1084     pXMLStream->SetLength(iPos);
1085   }
1086 }
CFDE_XMLDOMParser(CFDE_XMLNode * pRoot,IFDE_XMLSyntaxParser * pParser)1087 CFDE_XMLDOMParser::CFDE_XMLDOMParser(CFDE_XMLNode* pRoot,
1088                                      IFDE_XMLSyntaxParser* pParser)
1089     : m_pParser(pParser),
1090       m_pParent(pRoot),
1091       m_pChild(NULL),
1092       m_NodeStack(16),
1093       m_ws1(),
1094       m_ws2() {
1095   m_NodeStack.Push(m_pParent);
1096 }
~CFDE_XMLDOMParser()1097 CFDE_XMLDOMParser::~CFDE_XMLDOMParser() {
1098   m_NodeStack.RemoveAll();
1099   m_ws1.Empty();
1100   m_ws2.Empty();
1101 }
DoParser(IFX_Pause * pPause)1102 int32_t CFDE_XMLDOMParser::DoParser(IFX_Pause* pPause) {
1103   FX_DWORD dwRet;
1104   int32_t iCount = 0;
1105   while (TRUE) {
1106     dwRet = m_pParser->DoSyntaxParse();
1107     switch (dwRet) {
1108       case FDE_XMLSYNTAXSTATUS_InstructionOpen:
1109         break;
1110       case FDE_XMLSYNTAXSTATUS_InstructionClose:
1111         if (m_pChild->GetType() != FDE_XMLNODE_Instruction) {
1112           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1113           break;
1114         }
1115         m_pChild = m_pParent;
1116         break;
1117       case FDE_XMLSYNTAXSTATUS_ElementOpen:
1118       case FDE_XMLSYNTAXSTATUS_ElementBreak:
1119         break;
1120       case FDE_XMLSYNTAXSTATUS_ElementClose:
1121         if (m_pChild->GetType() != FDE_XMLNODE_Element) {
1122           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1123           break;
1124         }
1125         m_pParser->GetTagName(m_ws1);
1126         ((CFDE_XMLElement*)m_pChild)->GetTagName(m_ws2);
1127         if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_ws2) != 0) {
1128           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1129           break;
1130         }
1131         m_NodeStack.Pop();
1132         if (m_NodeStack.GetSize() < 1) {
1133           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1134           break;
1135         }
1136         m_pParent = (CFDE_XMLNode*)*m_NodeStack.GetTopElement();
1137         m_pChild = m_pParent;
1138         iCount++;
1139         break;
1140       case FDE_XMLSYNTAXSTATUS_TargetName:
1141         m_pParser->GetTargetName(m_ws1);
1142         m_pChild = new CFDE_XMLInstruction(m_ws1);
1143         m_pParent->InsertChildNode(m_pChild);
1144         m_ws1.Empty();
1145         break;
1146       case FDE_XMLSYNTAXSTATUS_TagName:
1147         m_pParser->GetTagName(m_ws1);
1148         m_pChild = new CFDE_XMLElement(m_ws1);
1149         m_pParent->InsertChildNode(m_pChild);
1150         m_NodeStack.Push(m_pChild);
1151         m_pParent = m_pChild;
1152         break;
1153       case FDE_XMLSYNTAXSTATUS_AttriName:
1154         m_pParser->GetAttributeName(m_ws1);
1155         break;
1156       case FDE_XMLSYNTAXSTATUS_AttriValue:
1157         if (m_pChild == NULL) {
1158           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1159           break;
1160         }
1161         m_pParser->GetAttributeName(m_ws2);
1162         if (m_pChild->GetType() == FDE_XMLNODE_Element) {
1163           ((CFDE_XMLElement*)m_pChild)->SetString(m_ws1, m_ws2);
1164         } else if (m_pChild->GetType() == FDE_XMLNODE_Instruction) {
1165           ((CFDE_XMLInstruction*)m_pChild)->SetString(m_ws1, m_ws2);
1166         }
1167         m_ws1.Empty();
1168         break;
1169       case FDE_XMLSYNTAXSTATUS_Text:
1170         m_pParser->GetTextData(m_ws1);
1171         m_pChild = new CFDE_XMLText(m_ws1);
1172         m_pParent->InsertChildNode(m_pChild);
1173         m_pChild = m_pParent;
1174         break;
1175       case FDE_XMLSYNTAXSTATUS_CData:
1176         m_pParser->GetTextData(m_ws1);
1177         m_pChild = new CFDE_XMLCharData(m_ws1);
1178         m_pParent->InsertChildNode(m_pChild);
1179         m_pChild = m_pParent;
1180         break;
1181       case FDE_XMLSYNTAXSTATUS_TargetData:
1182         if (m_pChild == NULL ||
1183             m_pChild->GetType() != FDE_XMLNODE_Instruction) {
1184           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1185           break;
1186         }
1187         if (!m_ws1.IsEmpty()) {
1188           ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1);
1189         }
1190         m_pParser->GetTargetData(m_ws1);
1191         ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1);
1192         m_ws1.Empty();
1193         break;
1194       default:
1195         break;
1196     }
1197     if (dwRet == FDE_XMLSYNTAXSTATUS_Error ||
1198         dwRet == FDE_XMLSYNTAXSTATUS_EOS) {
1199       break;
1200     }
1201     if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) {
1202       break;
1203     }
1204   }
1205   return m_pParser->GetStatus();
1206 }
CFDE_XMLSAXParser(FDE_LPXMLREADERHANDLER pHandler,IFDE_XMLSyntaxParser * pParser)1207 CFDE_XMLSAXParser::CFDE_XMLSAXParser(FDE_LPXMLREADERHANDLER pHandler,
1208                                      IFDE_XMLSyntaxParser* pParser)
1209     : m_pHandler(pHandler),
1210       m_pParser(pParser),
1211       m_TagStack(16),
1212       m_pTagTop(NULL),
1213       m_ws1(),
1214       m_ws2() {}
~CFDE_XMLSAXParser()1215 CFDE_XMLSAXParser::~CFDE_XMLSAXParser() {
1216   m_TagStack.RemoveAll();
1217   m_ws1.Empty();
1218   m_ws2.Empty();
1219 }
DoParser(IFX_Pause * pPause)1220 int32_t CFDE_XMLSAXParser::DoParser(IFX_Pause* pPause) {
1221   FX_DWORD dwRet = 0;
1222   int32_t iCount = 0;
1223   while (TRUE) {
1224     dwRet = m_pParser->DoSyntaxParse();
1225     switch (dwRet) {
1226       case FDE_XMLSYNTAXSTATUS_ElementBreak:
1227         if (m_pTagTop == NULL) {
1228           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1229           break;
1230         }
1231         if (m_pTagTop->eType == FDE_XMLNODE_Element) {
1232           m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName);
1233         }
1234         break;
1235       case FDE_XMLSYNTAXSTATUS_ElementClose:
1236         if (m_pTagTop == NULL || m_pTagTop->eType != FDE_XMLNODE_Element) {
1237           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1238           break;
1239         }
1240         m_pParser->GetTagName(m_ws1);
1241         if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_pTagTop->wsTagName) != 0) {
1242           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1243           break;
1244         } else if (m_ws1.GetLength() == 0) {
1245           m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName);
1246         }
1247         m_pHandler->OnTagClose(m_pHandler, m_pTagTop->wsTagName);
1248         Pop();
1249         iCount++;
1250         break;
1251       case FDE_XMLSYNTAXSTATUS_TargetName: {
1252         m_pParser->GetTargetName(m_ws1);
1253         CFDE_XMLTAG xmlTag;
1254         xmlTag.wsTagName = m_ws1;
1255         xmlTag.eType = FDE_XMLNODE_Instruction;
1256         Push(xmlTag);
1257         m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Instruction,
1258                                m_pTagTop->wsTagName);
1259         m_ws1.Empty();
1260       } break;
1261       case FDE_XMLSYNTAXSTATUS_TagName: {
1262         m_pParser->GetTargetName(m_ws1);
1263         CFDE_XMLTAG xmlTag;
1264         xmlTag.wsTagName = m_ws1;
1265         xmlTag.eType = FDE_XMLNODE_Element;
1266         Push(xmlTag);
1267         m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Element,
1268                                m_pTagTop->wsTagName);
1269       } break;
1270       case FDE_XMLSYNTAXSTATUS_AttriName:
1271         m_pParser->GetTargetName(m_ws1);
1272         break;
1273       case FDE_XMLSYNTAXSTATUS_AttriValue:
1274         m_pParser->GetAttributeName(m_ws2);
1275         if (m_pTagTop == NULL) {
1276           dwRet = FDE_XMLSYNTAXSTATUS_Error;
1277           break;
1278         }
1279         if (m_pTagTop->eType == FDE_XMLNODE_Element) {
1280           m_pHandler->OnAttribute(m_pHandler, m_ws1, m_ws2);
1281         }
1282         m_ws1.Empty();
1283         break;
1284       case FDE_XMLSYNTAXSTATUS_CData:
1285         m_pParser->GetTextData(m_ws1);
1286         m_pHandler->OnData(m_pHandler, FDE_XMLNODE_CharData, m_ws1);
1287         break;
1288       case FDE_XMLSYNTAXSTATUS_Text:
1289         m_pParser->GetTextData(m_ws1);
1290         m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Text, m_ws1);
1291         break;
1292       case FDE_XMLSYNTAXSTATUS_TargetData:
1293         m_pParser->GetTargetData(m_ws1);
1294         m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Instruction, m_ws1);
1295         m_ws1.Empty();
1296         break;
1297       default:
1298         break;
1299     }
1300     if (dwRet == FDE_XMLSYNTAXSTATUS_Error ||
1301         dwRet == FDE_XMLSYNTAXSTATUS_EOS) {
1302       break;
1303     }
1304     if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) {
1305       break;
1306     }
1307   }
1308   return m_pParser->GetStatus();
1309 }
Push(const CFDE_XMLTAG & xmlTag)1310 inline void CFDE_XMLSAXParser::Push(const CFDE_XMLTAG& xmlTag) {
1311   m_TagStack.Push(xmlTag);
1312   m_pTagTop = m_TagStack.GetTopElement();
1313 }
Pop()1314 inline void CFDE_XMLSAXParser::Pop() {
1315   m_TagStack.Pop();
1316   m_pTagTop = m_TagStack.GetTopElement();
1317 }
1318 #ifdef _FDE_BLOCK_BUFFER
CFDE_BlockBuffer(int32_t iAllocStep)1319 CFDE_BlockBuffer::CFDE_BlockBuffer(int32_t iAllocStep)
1320     : m_iDataLength(0),
1321       m_iBufferSize(0),
1322       m_iAllocStep(iAllocStep),
1323       m_iStartPosition(0) {
1324 }
~CFDE_BlockBuffer()1325 CFDE_BlockBuffer::~CFDE_BlockBuffer() {
1326   ClearBuffer();
1327 }
GetAvailableBlock(int32_t & iIndexInBlock)1328 FX_WCHAR* CFDE_BlockBuffer::GetAvailableBlock(int32_t& iIndexInBlock) {
1329   iIndexInBlock = 0;
1330   if (!m_BlockArray.GetSize()) {
1331     return nullptr;
1332   }
1333   int32_t iRealIndex = m_iStartPosition + m_iDataLength;
1334   if (iRealIndex == m_iBufferSize) {
1335     FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep);
1336     m_BlockArray.Add(pBlock);
1337     m_iBufferSize += m_iAllocStep;
1338     return pBlock;
1339   }
1340   iIndexInBlock = iRealIndex % m_iAllocStep;
1341   return (FX_WCHAR*)m_BlockArray[iRealIndex / m_iAllocStep];
1342 }
InitBuffer(int32_t iBufferSize)1343 FX_BOOL CFDE_BlockBuffer::InitBuffer(int32_t iBufferSize) {
1344   ClearBuffer();
1345   int32_t iNumOfBlock = (iBufferSize - 1) / m_iAllocStep + 1;
1346   for (int32_t i = 0; i < iNumOfBlock; i++) {
1347     m_BlockArray.Add(FX_Alloc(FX_WCHAR, m_iAllocStep));
1348   }
1349   m_iBufferSize = iNumOfBlock * m_iAllocStep;
1350   return TRUE;
1351 }
SetTextChar(int32_t iIndex,FX_WCHAR ch)1352 void CFDE_BlockBuffer::SetTextChar(int32_t iIndex, FX_WCHAR ch) {
1353   if (iIndex < 0) {
1354     return;
1355   }
1356   int32_t iRealIndex = m_iStartPosition + iIndex;
1357   int32_t iBlockIndex = iRealIndex / m_iAllocStep;
1358   int32_t iInnerIndex = iRealIndex % m_iAllocStep;
1359   int32_t iBlockSize = m_BlockArray.GetSize();
1360   if (iBlockIndex >= iBlockSize) {
1361     int32_t iNewBlocks = iBlockIndex - iBlockSize + 1;
1362     do {
1363       FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep);
1364       m_BlockArray.Add(pBlock);
1365       m_iBufferSize += m_iAllocStep;
1366     } while (--iNewBlocks);
1367   }
1368   FX_WCHAR* pTextData = (FX_WCHAR*)m_BlockArray[iBlockIndex];
1369   *(pTextData + iInnerIndex) = ch;
1370   if (m_iDataLength <= iIndex) {
1371     m_iDataLength = iIndex + 1;
1372   }
1373 }
DeleteTextChars(int32_t iCount,FX_BOOL bDirection)1374 int32_t CFDE_BlockBuffer::DeleteTextChars(int32_t iCount, FX_BOOL bDirection) {
1375   if (iCount <= 0) {
1376     return m_iDataLength;
1377   }
1378   if (iCount >= m_iDataLength) {
1379     Reset(FALSE);
1380     return 0;
1381   }
1382   if (bDirection) {
1383     m_iStartPosition += iCount;
1384     m_iDataLength -= iCount;
1385   } else {
1386     m_iDataLength -= iCount;
1387   }
1388   return m_iDataLength;
1389 }
GetTextData(CFX_WideString & wsTextData,int32_t iStart,int32_t iLength) const1390 void CFDE_BlockBuffer::GetTextData(CFX_WideString& wsTextData,
1391                                    int32_t iStart,
1392                                    int32_t iLength) const {
1393   wsTextData.Empty();
1394   int32_t iMaybeDataLength = m_iBufferSize - 1 - m_iStartPosition;
1395   if (iStart < 0 || iStart > iMaybeDataLength) {
1396     return;
1397   }
1398   if (iLength == -1 || iLength > iMaybeDataLength) {
1399     iLength = iMaybeDataLength;
1400   }
1401   if (iLength <= 0) {
1402     return;
1403   }
1404   FX_WCHAR* pBuf = wsTextData.GetBuffer(iLength);
1405   if (!pBuf) {
1406     return;
1407   }
1408   int32_t iStartBlockIndex = 0;
1409   int32_t iStartInnerIndex = 0;
1410   TextDataIndex2BufIndex(iStart, iStartBlockIndex, iStartInnerIndex);
1411   int32_t iEndBlockIndex = 0;
1412   int32_t iEndInnerIndex = 0;
1413   TextDataIndex2BufIndex(iStart + iLength, iEndBlockIndex, iEndInnerIndex);
1414   int32_t iPointer = 0;
1415   for (int32_t i = iStartBlockIndex; i <= iEndBlockIndex; i++) {
1416     int32_t iBufferPointer = 0;
1417     int32_t iCopyLength = m_iAllocStep;
1418     if (i == iStartBlockIndex) {
1419       iCopyLength -= iStartInnerIndex;
1420       iBufferPointer = iStartInnerIndex;
1421     }
1422     if (i == iEndBlockIndex) {
1423       iCopyLength -= ((m_iAllocStep - 1) - iEndInnerIndex);
1424     }
1425     FX_WCHAR* pBlockBuf = (FX_WCHAR*)m_BlockArray[i];
1426     FXSYS_memcpy(pBuf + iPointer, pBlockBuf + iBufferPointer,
1427                  iCopyLength * sizeof(FX_WCHAR));
1428     iPointer += iCopyLength;
1429   }
1430   wsTextData.ReleaseBuffer(iLength);
1431 }
TextDataIndex2BufIndex(const int32_t iIndex,int32_t & iBlockIndex,int32_t & iInnerIndex) const1432 void CFDE_BlockBuffer::TextDataIndex2BufIndex(const int32_t iIndex,
1433                                               int32_t& iBlockIndex,
1434                                               int32_t& iInnerIndex) const {
1435   FXSYS_assert(iIndex >= 0);
1436   int32_t iRealIndex = m_iStartPosition + iIndex;
1437   iBlockIndex = iRealIndex / m_iAllocStep;
1438   iInnerIndex = iRealIndex % m_iAllocStep;
1439 }
ClearBuffer()1440 void CFDE_BlockBuffer::ClearBuffer() {
1441   m_iBufferSize = 0;
1442   int32_t iSize = m_BlockArray.GetSize();
1443   for (int32_t i = 0; i < iSize; i++) {
1444     FX_Free(m_BlockArray[i]);
1445     m_BlockArray[i] = NULL;
1446   }
1447   m_BlockArray.RemoveAll();
1448 }
1449 #endif
Create()1450 IFDE_XMLSyntaxParser* IFDE_XMLSyntaxParser::Create() {
1451   return new CFDE_XMLSyntaxParser;
1452 }
1453 #ifdef _FDE_BLOCK_BUFFER
CFDE_XMLSyntaxParser()1454 CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser()
1455     : m_pStream(nullptr),
1456       m_iXMLPlaneSize(-1),
1457       m_iCurrentPos(0),
1458       m_iCurrentNodeNum(-1),
1459       m_iLastNodeNum(-1),
1460       m_iParsedChars(0),
1461       m_iParsedBytes(0),
1462       m_pBuffer(nullptr),
1463       m_iBufferChars(0),
1464       m_bEOS(FALSE),
1465       m_pStart(nullptr),
1466       m_pEnd(nullptr),
1467       m_XMLNodeStack(16),
1468       m_iAllocStep(m_BlockBuffer.GetAllocStep()),
1469       m_iDataLength(m_BlockBuffer.GetDataLengthRef()),
1470       m_pCurrentBlock(nullptr),
1471       m_iIndexInBlock(0),
1472       m_iTextDataLength(0),
1473       m_dwStatus(FDE_XMLSYNTAXSTATUS_None),
1474       m_dwMode(FDE_XMLSYNTAXMODE_Text),
1475       m_wQuotationMark(0),
1476       m_iEntityStart(-1),
1477       m_SkipStack(16) {
1478   m_CurNode.iNodeNum = -1;
1479   m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
1480 }
Init(IFX_Stream * pStream,int32_t iXMLPlaneSize,int32_t iTextDataSize)1481 void CFDE_XMLSyntaxParser::Init(IFX_Stream* pStream,
1482                                 int32_t iXMLPlaneSize,
1483                                 int32_t iTextDataSize) {
1484   FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL);
1485   FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0);
1486   int32_t iStreamLength = pStream->GetLength();
1487   FXSYS_assert(iStreamLength > 0);
1488   m_pStream = pStream;
1489   m_iXMLPlaneSize = std::min(iXMLPlaneSize, iStreamLength);
1490   uint8_t bom[4];
1491   m_iCurrentPos = m_pStream->GetBOM(bom);
1492   FXSYS_assert(m_pBuffer == NULL);
1493   m_pBuffer = FX_Alloc(FX_WCHAR, m_iXMLPlaneSize);
1494   m_pStart = m_pEnd = m_pBuffer;
1495   FXSYS_assert(!m_BlockBuffer.IsInitialized());
1496   m_BlockBuffer.InitBuffer();
1497   m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1498   m_iParsedBytes = m_iParsedChars = 0;
1499   m_iBufferChars = 0;
1500 }
DoSyntaxParse()1501 FX_DWORD CFDE_XMLSyntaxParser::DoSyntaxParse() {
1502   if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error ||
1503       m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
1504     return m_dwStatus;
1505   }
1506   FXSYS_assert(m_pStream && m_pBuffer && m_BlockBuffer.IsInitialized());
1507   int32_t iStreamLength = m_pStream->GetLength();
1508   int32_t iPos;
1509   FX_WCHAR ch;
1510   FX_DWORD dwStatus = FDE_XMLSYNTAXSTATUS_None;
1511   while (TRUE) {
1512     if (m_pStart >= m_pEnd) {
1513       if (m_bEOS || m_iCurrentPos >= iStreamLength) {
1514         m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
1515         return m_dwStatus;
1516       }
1517       m_iParsedChars += (m_pEnd - m_pBuffer);
1518       m_iParsedBytes = m_iCurrentPos;
1519       m_pStream->Lock();
1520       if (m_pStream->GetPosition() != m_iCurrentPos) {
1521         m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos);
1522       }
1523       m_iBufferChars =
1524           m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS);
1525       iPos = m_pStream->GetPosition();
1526       m_pStream->Unlock();
1527       if (m_iBufferChars < 1) {
1528         m_iCurrentPos = iStreamLength;
1529         m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
1530         return m_dwStatus;
1531       }
1532       m_iCurrentPos = iPos;
1533       m_pStart = m_pBuffer;
1534       m_pEnd = m_pBuffer + m_iBufferChars;
1535     }
1536     while (m_pStart < m_pEnd) {
1537       ch = *m_pStart;
1538       switch (m_dwMode) {
1539         case FDE_XMLSYNTAXMODE_Text:
1540           if (ch == L'<') {
1541             if (m_iDataLength > 0) {
1542               m_iTextDataLength = m_iDataLength;
1543               m_BlockBuffer.Reset();
1544               m_pCurrentBlock =
1545                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1546               m_iEntityStart = -1;
1547               dwStatus = FDE_XMLSYNTAXSTATUS_Text;
1548             } else {
1549               m_pStart++;
1550               m_dwMode = FDE_XMLSYNTAXMODE_Node;
1551             }
1552           } else {
1553             ParseTextChar(ch);
1554           }
1555           break;
1556         case FDE_XMLSYNTAXMODE_Node:
1557           if (ch == L'!') {
1558             m_pStart++;
1559             m_dwMode = FDE_XMLSYNTAXMODE_SkipCommentOrDecl;
1560           } else if (ch == L'/') {
1561             m_pStart++;
1562             m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
1563           } else if (ch == L'?') {
1564             m_iLastNodeNum++;
1565             m_iCurrentNodeNum = m_iLastNodeNum;
1566             m_CurNode.iNodeNum = m_iLastNodeNum;
1567             m_CurNode.eNodeType = FDE_XMLNODE_Instruction;
1568             m_XMLNodeStack.Push(m_CurNode);
1569             m_pStart++;
1570             m_dwMode = FDE_XMLSYNTAXMODE_Target;
1571             dwStatus = FDE_XMLSYNTAXSTATUS_InstructionOpen;
1572           } else {
1573             m_iLastNodeNum++;
1574             m_iCurrentNodeNum = m_iLastNodeNum;
1575             m_CurNode.iNodeNum = m_iLastNodeNum;
1576             m_CurNode.eNodeType = FDE_XMLNODE_Element;
1577             m_XMLNodeStack.Push(m_CurNode);
1578             m_dwMode = FDE_XMLSYNTAXMODE_Tag;
1579             dwStatus = FDE_XMLSYNTAXSTATUS_ElementOpen;
1580           }
1581           break;
1582         case FDE_XMLSYNTAXMODE_Target:
1583         case FDE_XMLSYNTAXMODE_Tag:
1584           if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
1585             if (m_iDataLength < 1) {
1586               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1587               return m_dwStatus;
1588             } else {
1589               m_iTextDataLength = m_iDataLength;
1590               m_BlockBuffer.Reset();
1591               m_pCurrentBlock =
1592                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1593               if (m_dwMode != FDE_XMLSYNTAXMODE_Target) {
1594                 dwStatus = FDE_XMLSYNTAXSTATUS_TagName;
1595               } else {
1596                 dwStatus = FDE_XMLSYNTAXSTATUS_TargetName;
1597               }
1598               m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
1599             }
1600           } else {
1601             if (m_iIndexInBlock == m_iAllocStep) {
1602               m_pCurrentBlock =
1603                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1604               if (!m_pCurrentBlock) {
1605                 return FDE_XMLSYNTAXSTATUS_Error;
1606               }
1607             }
1608             m_pCurrentBlock[m_iIndexInBlock++] = ch;
1609             m_iDataLength++;
1610             m_pStart++;
1611           }
1612           break;
1613         case FDE_XMLSYNTAXMODE_AttriName:
1614           if (m_iDataLength < 1 && FDE_IsXMLWhiteSpace(ch)) {
1615             m_pStart++;
1616             break;
1617           }
1618           if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
1619             if (m_iDataLength < 1) {
1620               if (m_CurNode.eNodeType == FDE_XMLNODE_Element) {
1621                 if (ch == L'>' || ch == L'/') {
1622                   m_dwMode = FDE_XMLSYNTAXMODE_BreakElement;
1623                   break;
1624                 }
1625               } else if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
1626                 if (ch == L'?') {
1627                   m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
1628                   m_pStart++;
1629                 } else {
1630                   m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
1631                 }
1632                 break;
1633               }
1634               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1635               return m_dwStatus;
1636             } else {
1637               if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
1638                 if (ch != '=' && !FDE_IsXMLWhiteSpace(ch)) {
1639                   m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
1640                   break;
1641                 }
1642               }
1643               m_iTextDataLength = m_iDataLength;
1644               m_BlockBuffer.Reset();
1645               m_pCurrentBlock =
1646                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1647               m_dwMode = FDE_XMLSYNTAXMODE_AttriEqualSign;
1648               dwStatus = FDE_XMLSYNTAXSTATUS_AttriName;
1649             }
1650           } else {
1651             if (m_iIndexInBlock == m_iAllocStep) {
1652               m_pCurrentBlock =
1653                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1654               if (!m_pCurrentBlock) {
1655                 return FDE_XMLSYNTAXSTATUS_Error;
1656               }
1657             }
1658             m_pCurrentBlock[m_iIndexInBlock++] = ch;
1659             m_iDataLength++;
1660             m_pStart++;
1661           }
1662           break;
1663         case FDE_XMLSYNTAXMODE_AttriEqualSign:
1664           if (FDE_IsXMLWhiteSpace(ch)) {
1665             m_pStart++;
1666             break;
1667           }
1668           if (ch != L'=') {
1669             if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
1670               m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
1671               break;
1672             }
1673             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1674             return m_dwStatus;
1675           } else {
1676             m_dwMode = FDE_XMLSYNTAXMODE_AttriQuotation;
1677             m_pStart++;
1678           }
1679           break;
1680         case FDE_XMLSYNTAXMODE_AttriQuotation:
1681           if (FDE_IsXMLWhiteSpace(ch)) {
1682             m_pStart++;
1683             break;
1684           }
1685           if (ch != L'\"' && ch != L'\'') {
1686             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1687             return m_dwStatus;
1688           } else {
1689             m_wQuotationMark = ch;
1690             m_dwMode = FDE_XMLSYNTAXMODE_AttriValue;
1691             m_pStart++;
1692           }
1693           break;
1694         case FDE_XMLSYNTAXMODE_AttriValue:
1695           if (ch == m_wQuotationMark) {
1696             if (m_iEntityStart > -1) {
1697               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1698               return m_dwStatus;
1699             }
1700             m_iTextDataLength = m_iDataLength;
1701             m_wQuotationMark = 0;
1702             m_BlockBuffer.Reset();
1703             m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1704             m_pStart++;
1705             m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
1706             dwStatus = FDE_XMLSYNTAXSTATUS_AttriValue;
1707           } else {
1708             ParseTextChar(ch);
1709           }
1710           break;
1711         case FDE_XMLSYNTAXMODE_CloseInstruction:
1712           if (ch != L'>') {
1713             if (m_iIndexInBlock == m_iAllocStep) {
1714               m_pCurrentBlock =
1715                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1716               if (!m_pCurrentBlock) {
1717                 return FDE_XMLSYNTAXSTATUS_Error;
1718               }
1719             }
1720             m_pCurrentBlock[m_iIndexInBlock++] = ch;
1721             m_iDataLength++;
1722             m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
1723           } else if (m_iDataLength > 0) {
1724             m_iTextDataLength = m_iDataLength;
1725             m_BlockBuffer.Reset();
1726             m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1727             dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
1728           } else {
1729             m_pStart++;
1730             FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
1731             if (pXMLNode == NULL) {
1732               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1733               return m_dwStatus;
1734             }
1735             m_XMLNodeStack.Pop();
1736             pXMLNode = m_XMLNodeStack.GetTopElement();
1737             if (pXMLNode == NULL) {
1738               m_CurNode.iNodeNum = -1;
1739               m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
1740             } else {
1741               m_CurNode = *pXMLNode;
1742             }
1743             m_iCurrentNodeNum = m_CurNode.iNodeNum;
1744             m_BlockBuffer.Reset();
1745             m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1746             m_dwMode = FDE_XMLSYNTAXMODE_Text;
1747             dwStatus = FDE_XMLSYNTAXSTATUS_InstructionClose;
1748           }
1749           break;
1750         case FDE_XMLSYNTAXMODE_BreakElement:
1751           if (ch == L'>') {
1752             m_dwMode = FDE_XMLSYNTAXMODE_Text;
1753             dwStatus = FDE_XMLSYNTAXSTATUS_ElementBreak;
1754           } else if (ch == L'/') {
1755             m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
1756           } else {
1757             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1758             return m_dwStatus;
1759           }
1760           m_pStart++;
1761           break;
1762         case FDE_XMLSYNTAXMODE_CloseElement:
1763           if (!FDE_IsXMLNameChar(ch, m_iDataLength < 1)) {
1764             if (ch == L'>') {
1765               FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
1766               if (pXMLNode == NULL) {
1767                 m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1768                 return m_dwStatus;
1769               }
1770               m_XMLNodeStack.Pop();
1771               pXMLNode = m_XMLNodeStack.GetTopElement();
1772               if (pXMLNode == NULL) {
1773                 m_CurNode.iNodeNum = -1;
1774                 m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
1775               } else {
1776                 m_CurNode = *pXMLNode;
1777               }
1778               m_iCurrentNodeNum = m_CurNode.iNodeNum;
1779               m_iTextDataLength = m_iDataLength;
1780               m_BlockBuffer.Reset();
1781               m_pCurrentBlock =
1782                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1783               m_dwMode = FDE_XMLSYNTAXMODE_Text;
1784               dwStatus = FDE_XMLSYNTAXSTATUS_ElementClose;
1785             } else if (!FDE_IsXMLWhiteSpace(ch)) {
1786               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1787               return m_dwStatus;
1788             }
1789           } else {
1790             if (m_iIndexInBlock == m_iAllocStep) {
1791               m_pCurrentBlock =
1792                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1793               if (!m_pCurrentBlock) {
1794                 return FDE_XMLSYNTAXSTATUS_Error;
1795               }
1796             }
1797             m_pCurrentBlock[m_iIndexInBlock++] = ch;
1798             m_iDataLength++;
1799           }
1800           m_pStart++;
1801           break;
1802         case FDE_XMLSYNTAXMODE_SkipCommentOrDecl:
1803           if (ch == '-') {
1804             m_dwMode = FDE_XMLSYNTAXMODE_SkipComment;
1805           } else {
1806             m_dwMode = FDE_XMLSYNTAXMODE_SkipDeclNode;
1807             m_SkipChar = L'>';
1808             m_SkipStack.Push(L'>');
1809           }
1810           break;
1811         case FDE_XMLSYNTAXMODE_SkipDeclNode:
1812           if (m_SkipChar == L'\'' || m_SkipChar == L'\"') {
1813             m_pStart++;
1814             if (ch != m_SkipChar) {
1815               break;
1816             }
1817             m_SkipStack.Pop();
1818             FX_DWORD* pDWord = m_SkipStack.GetTopElement();
1819             if (pDWord == NULL) {
1820               m_dwMode = FDE_XMLSYNTAXMODE_Text;
1821             } else {
1822               m_SkipChar = (FX_WCHAR)*pDWord;
1823             }
1824           } else {
1825             switch (ch) {
1826               case L'<':
1827                 m_SkipChar = L'>';
1828                 m_SkipStack.Push(L'>');
1829                 break;
1830               case L'[':
1831                 m_SkipChar = L']';
1832                 m_SkipStack.Push(L']');
1833                 break;
1834               case L'(':
1835                 m_SkipChar = L')';
1836                 m_SkipStack.Push(L')');
1837                 break;
1838               case L'\'':
1839                 m_SkipChar = L'\'';
1840                 m_SkipStack.Push(L'\'');
1841                 break;
1842               case L'\"':
1843                 m_SkipChar = L'\"';
1844                 m_SkipStack.Push(L'\"');
1845                 break;
1846               default:
1847                 if (ch == m_SkipChar) {
1848                   m_SkipStack.Pop();
1849                   FX_DWORD* pDWord = m_SkipStack.GetTopElement();
1850                   if (pDWord == NULL) {
1851                     if (m_iDataLength >= 9) {
1852                       CFX_WideString wsHeader;
1853                       m_BlockBuffer.GetTextData(wsHeader, 0, 7);
1854                       if (wsHeader.Equal(FX_WSTRC(L"[CDATA["))) {
1855                         CFX_WideString wsTailer;
1856                         m_BlockBuffer.GetTextData(wsTailer, m_iDataLength - 2,
1857                                                   2);
1858                         if (wsTailer.Equal(FX_WSTRC(L"]]"))) {
1859                           m_BlockBuffer.DeleteTextChars(7, TRUE);
1860                           m_BlockBuffer.DeleteTextChars(2, FALSE);
1861                           dwStatus = FDE_XMLSYNTAXSTATUS_CData;
1862                         }
1863                       }
1864                     }
1865                     m_iTextDataLength = m_iDataLength;
1866                     m_BlockBuffer.Reset();
1867                     m_pCurrentBlock =
1868                         m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1869                     m_dwMode = FDE_XMLSYNTAXMODE_Text;
1870                   } else {
1871                     m_SkipChar = (FX_WCHAR)*pDWord;
1872                   }
1873                 }
1874                 break;
1875             }
1876             if (m_SkipStack.GetSize() > 0) {
1877               if (m_iIndexInBlock == m_iAllocStep) {
1878                 m_pCurrentBlock =
1879                     m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1880                 if (!m_pCurrentBlock) {
1881                   return FDE_XMLSYNTAXSTATUS_Error;
1882                 }
1883               }
1884               m_pCurrentBlock[m_iIndexInBlock++] = ch;
1885               m_iDataLength++;
1886             }
1887             m_pStart++;
1888           }
1889           break;
1890         case FDE_XMLSYNTAXMODE_SkipComment:
1891           if (ch == L'-') {
1892             if (m_iIndexInBlock == m_iAllocStep) {
1893               m_pCurrentBlock =
1894                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1895               if (!m_pCurrentBlock) {
1896                 return FDE_XMLSYNTAXSTATUS_Error;
1897               }
1898             }
1899             m_pCurrentBlock[m_iIndexInBlock++] = L'-';
1900             m_iDataLength++;
1901           } else if (ch == L'>') {
1902             if (m_iDataLength > 1) {
1903               m_BlockBuffer.Reset();
1904               m_pCurrentBlock =
1905                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1906               m_dwMode = FDE_XMLSYNTAXMODE_Text;
1907             }
1908           } else {
1909             m_BlockBuffer.Reset();
1910             m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1911           }
1912           m_pStart++;
1913           break;
1914         case FDE_XMLSYNTAXMODE_TargetData:
1915           if (FDE_IsXMLWhiteSpace(ch)) {
1916             if (m_iDataLength < 1) {
1917               m_pStart++;
1918               break;
1919             } else if (m_wQuotationMark == 0) {
1920               m_iTextDataLength = m_iDataLength;
1921               m_wQuotationMark = 0;
1922               m_BlockBuffer.Reset();
1923               m_pCurrentBlock =
1924                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1925               m_pStart++;
1926               dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
1927               break;
1928             }
1929           }
1930           if (ch == '?') {
1931             m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
1932             m_pStart++;
1933           } else if (ch == '\"') {
1934             if (m_wQuotationMark == 0) {
1935               m_wQuotationMark = ch;
1936               m_pStart++;
1937             } else if (ch == m_wQuotationMark) {
1938               m_iTextDataLength = m_iDataLength;
1939               m_wQuotationMark = 0;
1940               m_BlockBuffer.Reset();
1941               m_pCurrentBlock =
1942                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1943               m_pStart++;
1944               dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
1945             } else {
1946               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
1947               return m_dwStatus;
1948             }
1949           } else {
1950             if (m_iIndexInBlock == m_iAllocStep) {
1951               m_pCurrentBlock =
1952                   m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
1953               if (!m_pCurrentBlock) {
1954                 return FDE_XMLSYNTAXSTATUS_Error;
1955               }
1956             }
1957             m_pCurrentBlock[m_iIndexInBlock++] = ch;
1958             m_iDataLength++;
1959             m_pStart++;
1960           }
1961           break;
1962         default:
1963           break;
1964       }
1965       if (dwStatus != FDE_XMLSYNTAXSTATUS_None) {
1966         return dwStatus;
1967       }
1968     }
1969   }
1970   return 0;
1971 }
1972 #else
CFDE_XMLSyntaxParser()1973 CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser()
1974     : m_pStream(NULL),
1975       m_iXMLPlaneSize(-1),
1976       m_iTextDataSize(256),
1977       m_iCurrentPos(0),
1978       m_iCurrentNodeNum(-1),
1979       m_iLastNodeNum(-1),
1980       m_iParsedChars(0),
1981       m_iParsedBytes(0),
1982       m_pBuffer(NULL),
1983       m_iBufferChars(0),
1984       m_bEOS(FALSE),
1985       m_pStart(NULL),
1986       m_pEnd(NULL),
1987       m_XMLNodeStack(16),
1988       m_pwsTextData(NULL),
1989       m_iDataPos(0),
1990       m_dwStatus(FDE_XMLSYNTAXSTATUS_None),
1991       m_dwMode(FDE_XMLSYNTAXMODE_Text),
1992       m_wQuotationMark(0),
1993       m_iTextDataLength(0),
1994       m_iEntityStart(-1),
1995       m_SkipStack(16) {
1996   m_CurNode.iNodeNum = -1;
1997   m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
1998 }
Init(IFX_Stream * pStream,int32_t iXMLPlaneSize,int32_t iTextDataSize)1999 void CFDE_XMLSyntaxParser::Init(IFX_Stream* pStream,
2000                                 int32_t iXMLPlaneSize,
2001                                 int32_t iTextDataSize) {
2002   FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL);
2003   FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0 && iTextDataSize > 0);
2004   int32_t iStreamLength = pStream->GetLength();
2005   FXSYS_assert(iStreamLength > 0);
2006   m_pStream = pStream;
2007   m_iXMLPlaneSize = std::min(iXMLPlaneSize, iStreamLength);
2008   m_iTextDataSize = iTextDataSize;
2009   uint8_t bom[4];
2010   m_iCurrentPos = m_pStream->GetBOM(bom);
2011   FXSYS_assert(m_pBuffer == NULL);
2012   m_pBuffer = FX_Alloc(FX_WCHAR, m_iXMLPlaneSize);
2013   m_pStart = m_pEnd = m_pBuffer;
2014   FXSYS_assert(m_pwsTextData == NULL);
2015   m_pwsTextData = FX_Alloc(FX_WCHAR, m_iTextDataSize);
2016   m_iParsedBytes = 0;
2017   m_iParsedChars = 0;
2018   m_iBufferChars = 0;
2019 }
DoSyntaxParse()2020 FX_DWORD CFDE_XMLSyntaxParser::DoSyntaxParse() {
2021   if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error ||
2022       m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
2023     return m_dwStatus;
2024   }
2025   FXSYS_assert(m_pStream != NULL && m_pBuffer != NULL && m_pwsTextData != NULL);
2026   int32_t iStreamLength = m_pStream->GetLength();
2027   int32_t iPos;
2028   FX_WCHAR ch;
2029   FX_DWORD dwStatus = FDE_XMLSYNTAXSTATUS_None;
2030   while (TRUE) {
2031     if (m_pStart >= m_pEnd) {
2032       if (m_bEOS || m_iCurrentPos >= iStreamLength) {
2033         m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
2034         return m_dwStatus;
2035       }
2036       m_iParsedChars += (m_pEnd - m_pBuffer);
2037       m_iParsedBytes = m_iCurrentPos;
2038       m_pStream->Lock();
2039       if (m_pStream->GetPosition() != m_iCurrentPos) {
2040         m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos);
2041       }
2042       m_iBufferChars =
2043           m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS);
2044       iPos = m_pStream->GetPosition();
2045       m_pStream->Unlock();
2046       if (m_iBufferChars < 1) {
2047         m_iCurrentPos = iStreamLength;
2048         m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS;
2049         return m_dwStatus;
2050       }
2051       m_iCurrentPos = iPos;
2052       m_pStart = m_pBuffer;
2053       m_pEnd = m_pBuffer + m_iBufferChars;
2054     }
2055     while (m_pStart < m_pEnd) {
2056       ch = *m_pStart;
2057       switch (m_dwMode) {
2058         case FDE_XMLSYNTAXMODE_Text:
2059           if (ch == L'<') {
2060             if (m_iDataPos > 0) {
2061               m_iTextDataLength = m_iDataPos;
2062               m_iDataPos = 0;
2063               m_iEntityStart = -1;
2064               dwStatus = FDE_XMLSYNTAXSTATUS_Text;
2065             } else {
2066               m_pStart++;
2067               m_dwMode = FDE_XMLSYNTAXMODE_Node;
2068             }
2069           } else {
2070             ParseTextChar(ch);
2071           }
2072           break;
2073         case FDE_XMLSYNTAXMODE_Node:
2074           if (ch == L'!') {
2075             m_pStart++;
2076             m_dwMode = FDE_XMLSYNTAXMODE_SkipCommentOrDecl;
2077           } else if (ch == L'/') {
2078             m_pStart++;
2079             m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
2080           } else if (ch == L'?') {
2081             m_iLastNodeNum++;
2082             m_iCurrentNodeNum = m_iLastNodeNum;
2083             m_CurNode.iNodeNum = m_iLastNodeNum;
2084             m_CurNode.eNodeType = FDE_XMLNODE_Instruction;
2085             m_XMLNodeStack.Push(m_CurNode);
2086             m_pStart++;
2087             m_dwMode = FDE_XMLSYNTAXMODE_Target;
2088             dwStatus = FDE_XMLSYNTAXSTATUS_InstructionOpen;
2089           } else {
2090             m_iLastNodeNum++;
2091             m_iCurrentNodeNum = m_iLastNodeNum;
2092             m_CurNode.iNodeNum = m_iLastNodeNum;
2093             m_CurNode.eNodeType = FDE_XMLNODE_Element;
2094             m_XMLNodeStack.Push(m_CurNode);
2095             m_dwMode = FDE_XMLSYNTAXMODE_Tag;
2096             dwStatus = FDE_XMLSYNTAXSTATUS_ElementOpen;
2097           }
2098           break;
2099         case FDE_XMLSYNTAXMODE_Target:
2100         case FDE_XMLSYNTAXMODE_Tag:
2101           if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
2102             if (m_iDataPos < 1) {
2103               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2104               return m_dwStatus;
2105             } else {
2106               m_iTextDataLength = m_iDataPos;
2107               m_iDataPos = 0;
2108               if (m_dwMode != FDE_XMLSYNTAXMODE_Target) {
2109                 dwStatus = FDE_XMLSYNTAXSTATUS_TagName;
2110               } else {
2111                 dwStatus = FDE_XMLSYNTAXSTATUS_TargetName;
2112               }
2113               m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
2114             }
2115           } else {
2116             if (m_iDataPos >= m_iTextDataSize) {
2117               ReallocTextDataBuffer();
2118             }
2119             m_pwsTextData[m_iDataPos++] = ch;
2120             m_pStart++;
2121           }
2122           break;
2123         case FDE_XMLSYNTAXMODE_AttriName:
2124           if (m_iDataPos < 1 && FDE_IsXMLWhiteSpace(ch)) {
2125             m_pStart++;
2126             break;
2127           }
2128           if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
2129             if (m_iDataPos < 1) {
2130               if (m_CurNode.eNodeType == FDE_XMLNODE_Element) {
2131                 if (ch == L'>' || ch == L'/') {
2132                   m_dwMode = FDE_XMLSYNTAXMODE_BreakElement;
2133                   break;
2134                 }
2135               } else if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
2136                 if (ch == L'?') {
2137                   m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
2138                   m_pStart++;
2139                 } else {
2140                   m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
2141                 }
2142                 break;
2143               }
2144               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2145               return m_dwStatus;
2146             } else {
2147               if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
2148                 if (ch != '=' && !FDE_IsXMLWhiteSpace(ch)) {
2149                   m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
2150                   break;
2151                 }
2152               }
2153               m_iTextDataLength = m_iDataPos;
2154               m_iDataPos = 0;
2155               m_dwMode = FDE_XMLSYNTAXMODE_AttriEqualSign;
2156               dwStatus = FDE_XMLSYNTAXSTATUS_AttriName;
2157             }
2158           } else {
2159             if (m_iDataPos >= m_iTextDataSize) {
2160               ReallocTextDataBuffer();
2161             }
2162             m_pwsTextData[m_iDataPos++] = ch;
2163             m_pStart++;
2164           }
2165           break;
2166         case FDE_XMLSYNTAXMODE_AttriEqualSign:
2167           if (FDE_IsXMLWhiteSpace(ch)) {
2168             m_pStart++;
2169             break;
2170           }
2171           if (ch != L'=') {
2172             if (m_CurNode.eNodeType == FDE_XMLNODE_Instruction) {
2173               m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
2174               break;
2175             }
2176             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2177             return m_dwStatus;
2178           } else {
2179             m_dwMode = FDE_XMLSYNTAXMODE_AttriQuotation;
2180             m_pStart++;
2181           }
2182           break;
2183         case FDE_XMLSYNTAXMODE_AttriQuotation:
2184           if (FDE_IsXMLWhiteSpace(ch)) {
2185             m_pStart++;
2186             break;
2187           }
2188           if (ch != L'\"' && ch != L'\'') {
2189             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2190             return m_dwStatus;
2191           } else {
2192             m_wQuotationMark = ch;
2193             m_dwMode = FDE_XMLSYNTAXMODE_AttriValue;
2194             m_pStart++;
2195           }
2196           break;
2197         case FDE_XMLSYNTAXMODE_AttriValue:
2198           if (ch == m_wQuotationMark) {
2199             if (m_iEntityStart > -1) {
2200               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2201               return m_dwStatus;
2202             }
2203             m_iTextDataLength = m_iDataPos;
2204             m_wQuotationMark = 0;
2205             m_iDataPos = 0;
2206             m_pStart++;
2207             m_dwMode = FDE_XMLSYNTAXMODE_AttriName;
2208             dwStatus = FDE_XMLSYNTAXSTATUS_AttriValue;
2209           } else {
2210             ParseTextChar(ch);
2211           }
2212           break;
2213         case FDE_XMLSYNTAXMODE_CloseInstruction:
2214           if (ch != L'>') {
2215             if (m_iDataPos >= m_iTextDataSize) {
2216               ReallocTextDataBuffer();
2217             }
2218             m_pwsTextData[m_iDataPos++] = ch;
2219             m_dwMode = FDE_XMLSYNTAXMODE_TargetData;
2220           } else if (m_iDataPos > 0) {
2221             m_iTextDataLength = m_iDataPos;
2222             m_iDataPos = 0;
2223             dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
2224           } else {
2225             m_pStart++;
2226             FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
2227             if (pXMLNode == NULL) {
2228               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2229               return m_dwStatus;
2230             }
2231             m_XMLNodeStack.Pop();
2232             pXMLNode = m_XMLNodeStack.GetTopElement();
2233             if (pXMLNode == NULL) {
2234               m_CurNode.iNodeNum = -1;
2235               m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
2236             } else {
2237               m_CurNode = *pXMLNode;
2238             }
2239             m_iCurrentNodeNum = m_CurNode.iNodeNum;
2240             m_iDataPos = 0;
2241             m_dwMode = FDE_XMLSYNTAXMODE_Text;
2242             dwStatus = FDE_XMLSYNTAXSTATUS_InstructionClose;
2243           }
2244           break;
2245         case FDE_XMLSYNTAXMODE_BreakElement:
2246           if (ch == L'>') {
2247             m_dwMode = FDE_XMLSYNTAXMODE_Text;
2248             dwStatus = FDE_XMLSYNTAXSTATUS_ElementBreak;
2249           } else if (ch == L'/') {
2250             m_dwMode = FDE_XMLSYNTAXMODE_CloseElement;
2251           } else {
2252             m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2253             return m_dwStatus;
2254           }
2255           m_pStart++;
2256           break;
2257         case FDE_XMLSYNTAXMODE_CloseElement:
2258           if (!FDE_IsXMLNameChar(ch, m_iDataPos < 1)) {
2259             if (ch == L'>') {
2260               FDE_LPXMLNODE pXMLNode = m_XMLNodeStack.GetTopElement();
2261               if (pXMLNode == NULL) {
2262                 m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2263                 return m_dwStatus;
2264               }
2265               m_XMLNodeStack.Pop();
2266               pXMLNode = m_XMLNodeStack.GetTopElement();
2267               if (pXMLNode == NULL) {
2268                 m_CurNode.iNodeNum = -1;
2269                 m_CurNode.eNodeType = FDE_XMLNODE_Unknown;
2270               } else {
2271                 m_CurNode = *pXMLNode;
2272               }
2273               m_iCurrentNodeNum = m_CurNode.iNodeNum;
2274               m_iTextDataLength = m_iDataPos;
2275               m_iDataPos = 0;
2276               m_dwMode = FDE_XMLSYNTAXMODE_Text;
2277               dwStatus = FDE_XMLSYNTAXSTATUS_ElementClose;
2278             } else if (!FDE_IsXMLWhiteSpace(ch)) {
2279               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2280               return m_dwStatus;
2281             }
2282           } else {
2283             if (m_iDataPos >= m_iTextDataSize) {
2284               ReallocTextDataBuffer();
2285             }
2286             m_pwsTextData[m_iDataPos++] = ch;
2287           }
2288           m_pStart++;
2289           break;
2290         case FDE_XMLSYNTAXMODE_SkipCommentOrDecl:
2291           if (ch == '-') {
2292             m_dwMode = FDE_XMLSYNTAXMODE_SkipComment;
2293           } else {
2294             m_dwMode = FDE_XMLSYNTAXMODE_SkipDeclNode;
2295             m_SkipChar = L'>';
2296             m_SkipStack.Push(L'>');
2297           }
2298           break;
2299         case FDE_XMLSYNTAXMODE_SkipDeclNode:
2300           if (m_SkipChar == L'\'' || m_SkipChar == L'\"') {
2301             m_pStart++;
2302             if (ch != m_SkipChar) {
2303               break;
2304             }
2305             m_SkipStack.Pop();
2306             FX_DWORD* pDWord = m_SkipStack.GetTopElement();
2307             if (pDWord == NULL) {
2308               m_dwMode = FDE_XMLSYNTAXMODE_Text;
2309             } else {
2310               m_SkipChar = (FX_WCHAR)*pDWord;
2311             }
2312           } else {
2313             switch (ch) {
2314               case L'<':
2315                 m_SkipChar = L'>';
2316                 m_SkipStack.Push(L'>');
2317                 break;
2318               case L'[':
2319                 m_SkipChar = L']';
2320                 m_SkipStack.Push(L']');
2321                 break;
2322               case L'(':
2323                 m_SkipChar = L')';
2324                 m_SkipStack.Push(L')');
2325                 break;
2326               case L'\'':
2327                 m_SkipChar = L'\'';
2328                 m_SkipStack.Push(L'\'');
2329                 break;
2330               case L'\"':
2331                 m_SkipChar = L'\"';
2332                 m_SkipStack.Push(L'\"');
2333                 break;
2334               default:
2335                 if (ch == m_SkipChar) {
2336                   m_SkipStack.Pop();
2337                   FX_DWORD* pDWord = m_SkipStack.GetTopElement();
2338                   if (pDWord == NULL) {
2339                     m_iTextDataLength = m_iDataPos;
2340                     m_iDataPos = 0;
2341                     if (m_iTextDataLength >= 9 &&
2342                         FXSYS_memcmp(m_pwsTextData, L"[CDATA[",
2343                                      7 * sizeof(FX_WCHAR)) == 0 &&
2344                         FXSYS_memcmp(m_pwsTextData + m_iTextDataLength - 2,
2345                                      L"]]", 2 * sizeof(FX_WCHAR)) == 0) {
2346                       m_iTextDataLength -= 9;
2347                       FXSYS_memmove(m_pwsTextData, m_pwsTextData + 7,
2348                                     m_iTextDataLength * sizeof(FX_WCHAR));
2349                       dwStatus = FDE_XMLSYNTAXSTATUS_CData;
2350                     }
2351                     m_dwMode = FDE_XMLSYNTAXMODE_Text;
2352                   } else {
2353                     m_SkipChar = (FX_WCHAR)*pDWord;
2354                   }
2355                 }
2356                 break;
2357             }
2358             if (m_SkipStack.GetSize() > 0) {
2359               if (m_iDataPos >= m_iTextDataSize) {
2360                 ReallocTextDataBuffer();
2361               }
2362               m_pwsTextData[m_iDataPos++] = ch;
2363             }
2364             m_pStart++;
2365           }
2366           break;
2367         case FDE_XMLSYNTAXMODE_SkipComment:
2368           if (ch == L'-') {
2369             m_iDataPos++;
2370           } else if (ch == L'>') {
2371             if (m_iDataPos > 1) {
2372               m_iDataPos = 0;
2373               m_dwMode = FDE_XMLSYNTAXMODE_Text;
2374             }
2375           } else {
2376             m_iDataPos = 0;
2377           }
2378           m_pStart++;
2379           break;
2380         case FDE_XMLSYNTAXMODE_TargetData:
2381           if (FDE_IsXMLWhiteSpace(ch)) {
2382             if (m_iDataPos < 1) {
2383               m_pStart++;
2384               break;
2385             } else if (m_wQuotationMark == 0) {
2386               m_iTextDataLength = m_iDataPos;
2387               m_wQuotationMark = 0;
2388               m_iDataPos = 0;
2389               m_pStart++;
2390               dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
2391               break;
2392             }
2393           }
2394           if (ch == '?') {
2395             m_dwMode = FDE_XMLSYNTAXMODE_CloseInstruction;
2396             m_pStart++;
2397           } else if (ch == '\"') {
2398             if (m_wQuotationMark == 0) {
2399               m_wQuotationMark = ch;
2400               m_pStart++;
2401             } else if (ch == m_wQuotationMark) {
2402               m_iTextDataLength = m_iDataPos;
2403               m_wQuotationMark = 0;
2404               m_iDataPos = 0;
2405               m_pStart++;
2406               dwStatus = FDE_XMLSYNTAXSTATUS_TargetData;
2407             } else {
2408               m_dwStatus = FDE_XMLSYNTAXSTATUS_Error;
2409               return m_dwStatus;
2410             }
2411           } else {
2412             if (m_iDataPos >= m_iTextDataSize) {
2413               ReallocTextDataBuffer();
2414             }
2415             m_pwsTextData[m_iDataPos++] = ch;
2416             m_pStart++;
2417           }
2418           break;
2419         default:
2420           break;
2421       }
2422       if (dwStatus != FDE_XMLSYNTAXSTATUS_None) {
2423         return dwStatus;
2424       }
2425     }
2426   }
2427   return 0;
2428 }
2429 #endif
~CFDE_XMLSyntaxParser()2430 CFDE_XMLSyntaxParser::~CFDE_XMLSyntaxParser() {
2431 #ifdef _FDE_BLOCK_BUFFER
2432   if (m_pCurrentBlock) {
2433     m_pCurrentBlock = NULL;
2434   }
2435 #else
2436   FX_Free(m_pwsTextData);
2437 #endif
2438   FX_Free(m_pBuffer);
2439 }
GetStatus() const2440 int32_t CFDE_XMLSyntaxParser::GetStatus() const {
2441   if (m_pStream == NULL) {
2442     return -1;
2443   }
2444   int32_t iStreamLength = m_pStream->GetLength();
2445   if (iStreamLength < 1) {
2446     return 100;
2447   }
2448   if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error) {
2449     return -1;
2450   }
2451   if (m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) {
2452     return 100;
2453   }
2454   return m_iParsedBytes * 100 / iStreamLength;
2455 }
FX_GetUTF8EncodeLength(const FX_WCHAR * pSrc,int32_t iSrcLen)2456 static int32_t FX_GetUTF8EncodeLength(const FX_WCHAR* pSrc, int32_t iSrcLen) {
2457   FX_DWORD unicode = 0;
2458   int32_t iDstNum = 0;
2459   while (iSrcLen-- > 0) {
2460     unicode = *pSrc++;
2461     int nbytes = 0;
2462     if ((FX_DWORD)unicode < 0x80) {
2463       nbytes = 1;
2464     } else if ((FX_DWORD)unicode < 0x800) {
2465       nbytes = 2;
2466     } else if ((FX_DWORD)unicode < 0x10000) {
2467       nbytes = 3;
2468     } else if ((FX_DWORD)unicode < 0x200000) {
2469       nbytes = 4;
2470     } else if ((FX_DWORD)unicode < 0x4000000) {
2471       nbytes = 5;
2472     } else {
2473       nbytes = 6;
2474     }
2475     iDstNum += nbytes;
2476   }
2477   return iDstNum;
2478 }
GetCurrentBinaryPos() const2479 FX_FILESIZE CFDE_XMLSyntaxParser::GetCurrentBinaryPos() const {
2480   if (m_pStream == NULL) {
2481     return 0;
2482   }
2483   int32_t nSrcLen = m_pStart - m_pBuffer;
2484   int32_t nDstLen = FX_GetUTF8EncodeLength(m_pBuffer, nSrcLen);
2485   return m_iParsedBytes + nDstLen;
2486 }
2487 #ifdef _FDE_BLOCK_BUFFER
ParseTextChar(FX_WCHAR ch)2488 void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR ch) {
2489   if (m_iIndexInBlock == m_iAllocStep) {
2490     m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
2491     if (!m_pCurrentBlock) {
2492       return;
2493     }
2494   }
2495   m_pCurrentBlock[m_iIndexInBlock++] = ch;
2496   m_iDataLength++;
2497   if (m_iEntityStart > -1 && ch == L';') {
2498     CFX_WideString csEntity;
2499     m_BlockBuffer.GetTextData(csEntity, m_iEntityStart + 1,
2500                               (m_iDataLength - 1) - m_iEntityStart - 1);
2501     int32_t iLen = csEntity.GetLength();
2502     if (iLen > 0) {
2503       if (csEntity[0] == L'#') {
2504         ch = 0;
2505         FX_WCHAR w;
2506         if (iLen > 1 && csEntity[1] == L'x') {
2507           for (int32_t i = 2; i < iLen; i++) {
2508             w = csEntity[i];
2509             if (w >= L'0' && w <= L'9') {
2510               ch = (ch << 4) + w - L'0';
2511             } else if (w >= L'A' && w <= L'F') {
2512               ch = (ch << 4) + w - 55;
2513             } else if (w >= L'a' && w <= L'f') {
2514               ch = (ch << 4) + w - 87;
2515             } else {
2516               break;
2517             }
2518           }
2519         } else {
2520           for (int32_t i = 1; i < iLen; i++) {
2521             w = csEntity[i];
2522             if (w < L'0' || w > L'9') {
2523               break;
2524             }
2525             ch = ch * 10 + w - L'0';
2526           }
2527         }
2528         if (ch != 0) {
2529           m_BlockBuffer.SetTextChar(m_iEntityStart, ch);
2530           m_iEntityStart++;
2531         }
2532       } else {
2533         if (csEntity.Compare(L"amp") == 0) {
2534           m_BlockBuffer.SetTextChar(m_iEntityStart, L'&');
2535           m_iEntityStart++;
2536         } else if (csEntity.Compare(L"lt") == 0) {
2537           m_BlockBuffer.SetTextChar(m_iEntityStart, L'<');
2538           m_iEntityStart++;
2539         } else if (csEntity.Compare(L"gt") == 0) {
2540           m_BlockBuffer.SetTextChar(m_iEntityStart, L'>');
2541           m_iEntityStart++;
2542         } else if (csEntity.Compare(L"apos") == 0) {
2543           m_BlockBuffer.SetTextChar(m_iEntityStart, L'\'');
2544           m_iEntityStart++;
2545         } else if (csEntity.Compare(L"quot") == 0) {
2546           m_BlockBuffer.SetTextChar(m_iEntityStart, L'\"');
2547           m_iEntityStart++;
2548         }
2549       }
2550     }
2551     m_BlockBuffer.DeleteTextChars(m_iDataLength - m_iEntityStart, FALSE);
2552     m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock);
2553     m_iEntityStart = -1;
2554   } else {
2555     if (m_iEntityStart < 0 && ch == L'&') {
2556       m_iEntityStart = m_iDataLength - 1;
2557     }
2558   }
2559   m_pStart++;
2560 }
2561 #else
ParseTextChar(FX_WCHAR ch)2562 void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR ch) {
2563   if (m_iDataPos >= m_iTextDataSize) {
2564     ReallocTextDataBuffer();
2565   }
2566   m_pwsTextData[m_iDataPos] = ch;
2567   if (m_iEntityStart > -1 && ch == L';') {
2568     CFX_WideString csEntity(m_pwsTextData + m_iEntityStart + 1,
2569                             m_iDataPos - m_iEntityStart - 1);
2570     int32_t iLen = csEntity.GetLength();
2571     if (iLen > 0) {
2572       if (csEntity[0] == L'#') {
2573         ch = 0;
2574         FX_WCHAR w;
2575         if (iLen > 1 && csEntity[1] == L'x') {
2576           for (int32_t i = 2; i < iLen; i++) {
2577             w = csEntity[i];
2578             if (w >= L'0' && w <= L'9') {
2579               ch = (ch << 4) + w - L'0';
2580             } else if (w >= L'A' && w <= L'F') {
2581               ch = (ch << 4) + w - 55;
2582             } else if (w >= L'a' && w <= L'f') {
2583               ch = (ch << 4) + w - 87;
2584             } else {
2585               break;
2586             }
2587           }
2588         } else {
2589           for (int32_t i = 1; i < iLen; i++) {
2590             w = csEntity[i];
2591             if (w < L'0' || w > L'9') {
2592               break;
2593             }
2594             ch = ch * 10 + w - L'0';
2595           }
2596         }
2597         if (ch != 0) {
2598           m_pwsTextData[m_iEntityStart++] = ch;
2599         }
2600       } else {
2601         if (csEntity.Compare(L"amp") == 0) {
2602           m_pwsTextData[m_iEntityStart++] = L'&';
2603         } else if (csEntity.Compare(L"lt") == 0) {
2604           m_pwsTextData[m_iEntityStart++] = L'<';
2605         } else if (csEntity.Compare(L"gt") == 0) {
2606           m_pwsTextData[m_iEntityStart++] = L'>';
2607         } else if (csEntity.Compare(L"apos") == 0) {
2608           m_pwsTextData[m_iEntityStart++] = L'\'';
2609         } else if (csEntity.Compare(L"quot") == 0) {
2610           m_pwsTextData[m_iEntityStart++] = L'\"';
2611         }
2612       }
2613     }
2614     m_iDataPos = m_iEntityStart;
2615     m_iEntityStart = -1;
2616   } else {
2617     if (m_iEntityStart < 0 && ch == L'&') {
2618       m_iEntityStart = m_iDataPos;
2619     }
2620     m_iDataPos++;
2621   }
2622   m_pStart++;
2623 }
ReallocTextDataBuffer()2624 void CFDE_XMLSyntaxParser::ReallocTextDataBuffer() {
2625   FXSYS_assert(m_pwsTextData != NULL);
2626   if (m_iTextDataSize <= 1024 * 1024) {
2627     m_iTextDataSize *= 2;
2628   } else {
2629     m_iTextDataSize += 1024 * 1024;
2630   }
2631   m_pwsTextData = FX_Realloc(FX_WCHAR, m_pwsTextData, m_iTextDataSize);
2632 }
GetData(CFX_WideString & wsData) const2633 void CFDE_XMLSyntaxParser::GetData(CFX_WideString& wsData) const {
2634   FX_WCHAR* pBuf = wsData.GetBuffer(m_iTextDataLength);
2635   FXSYS_memcpy(pBuf, m_pwsTextData, m_iTextDataLength * sizeof(FX_WCHAR));
2636   wsData.ReleaseBuffer(m_iTextDataLength);
2637 }
2638 #endif
2639