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