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