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