Home | History | Annotate | Download | only in xml
      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}};
     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 }
     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 };
     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
     73 CFDE_XMLNode::CFDE_XMLNode()
     74     : m_pParent(NULL), m_pChild(NULL), m_pPrior(NULL), m_pNext(NULL) {}
     75 CFDE_XMLNode::~CFDE_XMLNode() {
     76   DeleteChildren();
     77 }
     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 }
     87 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 }
     96 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 }
    107 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 }
    119 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 }
    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 }
    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 }
    220 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 }
    318 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 }
    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 }
    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 }
    377 CFDE_XMLNode* CFDE_XMLNode::Clone(FX_BOOL bRecursive) {
    378   return NULL;
    379 }
    380 void CFDE_XMLNode::SaveXMLNode(IFX_Stream* pXMLStream) {
    381   CFDE_XMLNode* pNode = (CFDE_XMLNode*)this;
    382   FXSYS_assert(pXMLStream != NULL && pNode != NULL);
    383   switch (pNode->GetType()) {
    384     case FDE_XMLNODE_Instruction: {
    385       CFX_WideString ws;
    386       CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode;
    387       if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
    388         ws = L"<?xml version=\"1.0\" encoding=\"";
    389         FX_WORD wCodePage = pXMLStream->GetCodePage();
    390         if (wCodePage == FX_CODEPAGE_UTF16LE) {
    391           ws += L"UTF-16";
    392         } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
    393           ws += L"UTF-16be";
    394         } else {
    395           ws += L"UTF-8";
    396         }
    397         ws += L"\"?>";
    398         pXMLStream->WriteString(ws, ws.GetLength());
    399       } else {
    400         ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
    401         pXMLStream->WriteString(ws, ws.GetLength());
    402         CFX_WideStringArray& attributes = pInstruction->m_Attributes;
    403         int32_t i, iCount = attributes.GetSize();
    404         CFX_WideString wsValue;
    405         for (i = 0; i < iCount; i += 2) {
    406           ws = L" ";
    407           ws += attributes[i];
    408           ws += L"=\"";
    409           wsValue = attributes[i + 1];
    410           wsValue.Replace(L"&", L"&amp;");
    411           wsValue.Replace(L"<", L"&lt;");
    412           wsValue.Replace(L">", L"&gt;");
    413           wsValue.Replace(L"\'", L"&apos;");
    414           wsValue.Replace(L"\"", L"&quot;");
    415           ws += wsValue;
    416           ws += L"\"";
    417           pXMLStream->WriteString(ws, ws.GetLength());
    418         }
    419         CFX_WideStringArray& targetdata = pInstruction->m_TargetData;
    420         iCount = targetdata.GetSize();
    421         for (i = 0; i < iCount; i++) {
    422           ws = L" \"";
    423           ws += targetdata[i];
    424           ws += L"\"";
    425           pXMLStream->WriteString(ws, ws.GetLength());
    426         }
    427         ws = L"?>";
    428         pXMLStream->WriteString(ws, ws.GetLength());
    429       }
    430     } break;
    431     case FDE_XMLNODE_Element: {
    432       CFX_WideString ws;
    433       ws = L"<";
    434       ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
    435       pXMLStream->WriteString(ws, ws.GetLength());
    436       CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
    437       int32_t iCount = attributes.GetSize();
    438       CFX_WideString wsValue;
    439       for (int32_t i = 0; i < iCount; i += 2) {
    440         ws = L" ";
    441         ws += attributes[i];
    442         ws += L"=\"";
    443         wsValue = attributes[i + 1];
    444         wsValue.Replace(L"&", L"&amp;");
    445         wsValue.Replace(L"<", L"&lt;");
    446         wsValue.Replace(L">", L"&gt;");
    447         wsValue.Replace(L"\'", L"&apos;");
    448         wsValue.Replace(L"\"", L"&quot;");
    449         ws += wsValue;
    450         ws += L"\"";
    451         pXMLStream->WriteString(ws, ws.GetLength());
    452       }
    453       if (pNode->m_pChild == NULL) {
    454         ws = L"\n/>";
    455         pXMLStream->WriteString(ws, ws.GetLength());
    456       } else {
    457         ws = L"\n>";
    458         pXMLStream->WriteString(ws, ws.GetLength());
    459         CFDE_XMLNode* pChild = pNode->m_pChild;
    460         while (pChild != NULL) {
    461           pChild->SaveXMLNode(pXMLStream);
    462           pChild = pChild->m_pNext;
    463         }
    464         ws = L"</";
    465         ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
    466         ws += L"\n>";
    467         pXMLStream->WriteString(ws, ws.GetLength());
    468       }
    469     } break;
    470     case FDE_XMLNODE_Text: {
    471       CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
    472       ws.Replace(L"&", L"&amp;");
    473       ws.Replace(L"<", L"&lt;");
    474       ws.Replace(L">", L"&gt;");
    475       ws.Replace(L"\'", L"&apos;");
    476       ws.Replace(L"\"", L"&quot;");
    477       pXMLStream->WriteString(ws, ws.GetLength());
    478     } break;
    479     case FDE_XMLNODE_CharData: {
    480       CFX_WideString ws = L"<![CDATA[";
    481       ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
    482       ws += L"]]>";
    483       pXMLStream->WriteString(ws, ws.GetLength());
    484     } break;
    485     case FDE_XMLNODE_Unknown:
    486       break;
    487     default:
    488       break;
    489   }
    490 }
    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 }
    506 IFDE_XMLInstruction* IFDE_XMLInstruction::Create(
    507     const CFX_WideString& wsTarget) {
    508   return (IFDE_XMLInstruction*)new CFDE_XMLInstruction(wsTarget);
    509 }
    510 CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString& wsTarget)
    511     : m_wsTarget(wsTarget) {
    512   FXSYS_assert(m_wsTarget.GetLength() > 0);
    513 }
    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 }
    526 int32_t CFDE_XMLInstruction::CountAttributes() const {
    527   return m_Attributes.GetSize() / 2;
    528 }
    529 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 }
    544 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 }
    553 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 }
    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 }
    579 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 }
    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 }
    595 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 }
    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 }
    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 }
    621 int32_t CFDE_XMLInstruction::CountData() const {
    622   return m_TargetData.GetSize();
    623 }
    624 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 }
    632 void CFDE_XMLInstruction::AppendData(const CFX_WideString& wsData) {
    633   m_TargetData.Add(wsData);
    634 }
    635 void CFDE_XMLInstruction::RemoveData(int32_t index) {
    636   m_TargetData.RemoveAt(index);
    637 }
    638 IFDE_XMLElement* IFDE_XMLElement::Create(const CFX_WideString& wsTag) {
    639   return (IFDE_XMLElement*)new CFDE_XMLElement(wsTag);
    640 }
    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 }
    645 CFDE_XMLElement::~CFDE_XMLElement() {
    646   m_Attributes.RemoveAll();
    647 }
    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 }
    673 void CFDE_XMLElement::GetTagName(CFX_WideString& wsTag) const {
    674   wsTag = m_wsTag;
    675 }
    676 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 }
    684 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 }
    692 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 }
    714 int32_t CFDE_XMLElement::CountAttributes() const {
    715   return m_Attributes.GetSize() / 2;
    716 }
    717 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 }
    732 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 }
    741 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 }
    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 }
    767 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 }
    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 }
    783 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 }
    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 }
    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 }
    809 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 }
    827 void CFDE_XMLElement::SetTextData(const CFX_WideString& wsText) {
    828   if (wsText.GetLength() < 1) {
    829     return;
    830   }
    831   InsertChildNode(new CFDE_XMLText(wsText));
    832 }
    833 IFDE_XMLText* IFDE_XMLText::Create(const CFX_WideString& wsText) {
    834   return (IFDE_XMLText*)new CFDE_XMLText(wsText);
    835 }
    836 CFDE_XMLText::CFDE_XMLText(const CFX_WideString& wsText)
    837     : CFDE_XMLNode(), m_wsText(wsText) {}
    838 CFDE_XMLNode* CFDE_XMLText::Clone(FX_BOOL bRecursive) {
    839   CFDE_XMLText* pClone = new CFDE_XMLText(m_wsText);
    840   return pClone;
    841 }
    842 IFDE_XMLCharData* IFDE_XMLCharData::Create(const CFX_WideString& wsCData) {
    843   return (IFDE_XMLCharData*)new CFDE_XMLCharData(wsCData);
    844 }
    845 CFDE_XMLCharData::CFDE_XMLCharData(const CFX_WideString& wsCData)
    846     : CFDE_XMLDeclaration(), m_wsCharData(wsCData) {}
    847 CFDE_XMLNode* CFDE_XMLCharData::Clone(FX_BOOL bRecursive) {
    848   CFDE_XMLCharData* pClone = new CFDE_XMLCharData(m_wsCharData);
    849   return pClone;
    850 }
    851 IFDE_XMLDoc* IFDE_XMLDoc::Create() {
    852   return (IFDE_XMLDoc*)new CFDE_XMLDoc;
    853 }
    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 }
    860 CFDE_XMLDoc::~CFDE_XMLDoc() {
    861   Reset(FALSE);
    862 }
    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 }
    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 }
    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 }
    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 }
    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 }
    947 void CFDE_XMLDoc::CloseXML() {
    948   ReleaseParser();
    949 }
    950 void CFDE_XMLDoc::SaveXMLNode(IFX_Stream* pXMLStream, IFDE_XMLNode* pINode) {
    951   CFDE_XMLNode* pNode = (CFDE_XMLNode*)pINode;
    952   FXSYS_assert(pXMLStream != NULL && pNode != NULL);
    953   switch (pNode->GetType()) {
    954     case FDE_XMLNODE_Instruction: {
    955       CFX_WideString ws;
    956       CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode;
    957       if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) {
    958         ws = L"<?xml version=\"1.0\" encoding=\"";
    959         FX_WORD wCodePage = pXMLStream->GetCodePage();
    960         if (wCodePage == FX_CODEPAGE_UTF16LE) {
    961           ws += L"UTF-16";
    962         } else if (wCodePage == FX_CODEPAGE_UTF16BE) {
    963           ws += L"UTF-16be";
    964         } else {
    965           ws += L"UTF-8";
    966         }
    967         ws += L"\"?>";
    968         pXMLStream->WriteString(ws, ws.GetLength());
    969       } else {
    970         ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget);
    971         pXMLStream->WriteString(ws, ws.GetLength());
    972         CFX_WideStringArray& attributes = pInstruction->m_Attributes;
    973         int32_t i, iCount = attributes.GetSize();
    974         CFX_WideString wsValue;
    975         for (i = 0; i < iCount; i += 2) {
    976           ws = L" ";
    977           ws += attributes[i];
    978           ws += L"=\"";
    979           wsValue = attributes[i + 1];
    980           wsValue.Replace(L"&", L"&amp;");
    981           wsValue.Replace(L"<", L"&lt;");
    982           wsValue.Replace(L">", L"&gt;");
    983           wsValue.Replace(L"\'", L"&apos;");
    984           wsValue.Replace(L"\"", L"&quot;");
    985           ws += wsValue;
    986           ws += L"\"";
    987           pXMLStream->WriteString(ws, ws.GetLength());
    988         }
    989         CFX_WideStringArray& targetdata = pInstruction->m_TargetData;
    990         iCount = targetdata.GetSize();
    991         for (i = 0; i < iCount; i++) {
    992           ws = L" \"";
    993           ws += targetdata[i];
    994           ws += L"\"";
    995           pXMLStream->WriteString(ws, ws.GetLength());
    996         }
    997         ws = L"?>";
    998         pXMLStream->WriteString(ws, ws.GetLength());
    999       }
   1000     } break;
   1001     case FDE_XMLNODE_Element: {
   1002       CFX_WideString ws;
   1003       ws = L"<";
   1004       ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
   1005       pXMLStream->WriteString(ws, ws.GetLength());
   1006       CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes;
   1007       int32_t iCount = attributes.GetSize();
   1008       CFX_WideString wsValue;
   1009       for (int32_t i = 0; i < iCount; i += 2) {
   1010         ws = L" ";
   1011         ws += attributes[i];
   1012         ws += L"=\"";
   1013         wsValue = attributes[i + 1];
   1014         wsValue.Replace(L"&", L"&amp;");
   1015         wsValue.Replace(L"<", L"&lt;");
   1016         wsValue.Replace(L">", L"&gt;");
   1017         wsValue.Replace(L"\'", L"&apos;");
   1018         wsValue.Replace(L"\"", L"&quot;");
   1019         ws += wsValue;
   1020         ws += L"\"";
   1021         pXMLStream->WriteString(ws, ws.GetLength());
   1022       }
   1023       if (pNode->m_pChild == NULL) {
   1024         ws = L"\n/>";
   1025         pXMLStream->WriteString(ws, ws.GetLength());
   1026       } else {
   1027         ws = L"\n>";
   1028         pXMLStream->WriteString(ws, ws.GetLength());
   1029         CFDE_XMLNode* pChild = pNode->m_pChild;
   1030         while (pChild != NULL) {
   1031           SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pChild);
   1032           pChild = pChild->m_pNext;
   1033         }
   1034         ws = L"</";
   1035         ws += ((CFDE_XMLElement*)pNode)->m_wsTag;
   1036         ws += L"\n>";
   1037         pXMLStream->WriteString(ws, ws.GetLength());
   1038       }
   1039     } break;
   1040     case FDE_XMLNODE_Text: {
   1041       CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText;
   1042       ws.Replace(L"&", L"&amp;");
   1043       ws.Replace(L"<", L"&lt;");
   1044       ws.Replace(L">", L"&gt;");
   1045       ws.Replace(L"\'", L"&apos;");
   1046       ws.Replace(L"\"", L"&quot;");
   1047       pXMLStream->WriteString(ws, ws.GetLength());
   1048     } break;
   1049     case FDE_XMLNODE_CharData: {
   1050       CFX_WideString ws = L"<![CDATA[";
   1051       ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData;
   1052       ws += L"]]>";
   1053       pXMLStream->WriteString(ws, ws.GetLength());
   1054     } break;
   1055     case FDE_XMLNODE_Unknown:
   1056       break;
   1057     default:
   1058       break;
   1059   }
   1060 }
   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 }
   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 }
   1097 CFDE_XMLDOMParser::~CFDE_XMLDOMParser() {
   1098   m_NodeStack.RemoveAll();
   1099   m_ws1.Empty();
   1100   m_ws2.Empty();
   1101 }
   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 }
   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() {}
   1215 CFDE_XMLSAXParser::~CFDE_XMLSAXParser() {
   1216   m_TagStack.RemoveAll();
   1217   m_ws1.Empty();
   1218   m_ws2.Empty();
   1219 }
   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 }
   1310 inline void CFDE_XMLSAXParser::Push(const CFDE_XMLTAG& xmlTag) {
   1311   m_TagStack.Push(xmlTag);
   1312   m_pTagTop = m_TagStack.GetTopElement();
   1313 }
   1314 inline void CFDE_XMLSAXParser::Pop() {
   1315   m_TagStack.Pop();
   1316   m_pTagTop = m_TagStack.GetTopElement();
   1317 }
   1318 #ifdef _FDE_BLOCK_BUFFER
   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 }
   1325 CFDE_BlockBuffer::~CFDE_BlockBuffer() {
   1326   ClearBuffer();
   1327 }
   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 }
   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 }
   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 }
   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 }
   1390 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 }
   1432 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 }
   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
   1450 IFDE_XMLSyntaxParser* IFDE_XMLSyntaxParser::Create() {
   1451   return new CFDE_XMLSyntaxParser;
   1452 }
   1453 #ifdef _FDE_BLOCK_BUFFER
   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 }
   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 }
   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
   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 }
   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 }
   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
   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 }
   2440 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 }
   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 }
   2479 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
   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
   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 }
   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 }
   2633 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