| OLD | NEW |
| (Empty) |
| 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 "xfa/src/fde/xml/fde_xml_imp.h" | |
| 8 | |
| 9 #include <algorithm> | |
| 10 | |
| 11 #include "xfa/src/fgas/crt/fgas_system.h" | |
| 12 #include "xfa/src/fgas/crt/fgas_codepage.h" | |
| 13 | |
| 14 #define FDE_XMLVALIDCHARRANGENUM 5 | |
| 15 | |
| 16 static const FX_WCHAR g_XMLValidCharRange[FDE_XMLVALIDCHARRANGENUM][2] = { | |
| 17 {0x09, 0x09}, | |
| 18 {0x0A, 0x0A}, | |
| 19 {0x0D, 0x0D}, | |
| 20 {0x20, 0xD7FF}, | |
| 21 {0xE000, 0xFFFD}}; | |
| 22 | |
| 23 FX_BOOL FDE_IsXMLValidChar(FX_WCHAR ch) { | |
| 24 int32_t iStart = 0, iEnd = FDE_XMLVALIDCHARRANGENUM - 1, iMid; | |
| 25 while (iStart <= iEnd) { | |
| 26 iMid = (iStart + iEnd) / 2; | |
| 27 if (ch < g_XMLValidCharRange[iMid][0]) { | |
| 28 iEnd = iMid - 1; | |
| 29 } else if (ch > g_XMLValidCharRange[iMid][1]) { | |
| 30 iStart = iMid + 1; | |
| 31 } else { | |
| 32 return TRUE; | |
| 33 } | |
| 34 } | |
| 35 return FALSE; | |
| 36 } | |
| 37 FX_BOOL FDE_IsXMLWhiteSpace(FX_WCHAR ch) { | |
| 38 return ch == L' ' || ch == 0x0A || ch == 0x0D || ch == 0x09; | |
| 39 } | |
| 40 | |
| 41 struct FDE_XMLNAMECHAR { | |
| 42 FX_WCHAR wStart; | |
| 43 FX_WCHAR wEnd; | |
| 44 FX_BOOL bStartChar; | |
| 45 }; | |
| 46 | |
| 47 #define FDE_XMLNAMECHARSNUM 20 | |
| 48 static FDE_XMLNAMECHAR g_XMLNameChars[FDE_XMLNAMECHARSNUM] = { | |
| 49 {L'-', L'.', FALSE}, {L'0', L'9', FALSE}, {L':', L':', FALSE}, | |
| 50 {L'A', L'Z', TRUE}, {L'_', L'_', TRUE}, {L'a', L'z', TRUE}, | |
| 51 {0xB7, 0xB7, FALSE}, {0xC0, 0xD6, TRUE}, {0xD8, 0xF6, TRUE}, | |
| 52 {0xF8, 0x02FF, TRUE}, {0x0300, 0x036F, FALSE}, {0x0370, 0x037D, TRUE}, | |
| 53 {0x037F, 0x1FFF, TRUE}, {0x200C, 0x200D, TRUE}, {0x203F, 0x2040, FALSE}, | |
| 54 {0x2070, 0x218F, TRUE}, {0x2C00, 0x2FEF, TRUE}, {0x3001, 0xD7FF, TRUE}, | |
| 55 {0xF900, 0xFDCF, TRUE}, {0xFDF0, 0xFFFD, TRUE}, | |
| 56 }; | |
| 57 | |
| 58 FX_BOOL FDE_IsXMLNameChar(FX_WCHAR ch, FX_BOOL bFirstChar) { | |
| 59 int32_t iStart = 0, iEnd = FDE_XMLNAMECHARSNUM - 1, iMid; | |
| 60 while (iStart <= iEnd) { | |
| 61 iMid = (iStart + iEnd) / 2; | |
| 62 if (ch < g_XMLNameChars[iMid].wStart) { | |
| 63 iEnd = iMid - 1; | |
| 64 } else if (ch > g_XMLNameChars[iMid].wEnd) { | |
| 65 iStart = iMid + 1; | |
| 66 } else { | |
| 67 if (bFirstChar) { | |
| 68 return g_XMLNameChars[iMid].bStartChar; | |
| 69 } | |
| 70 return TRUE; | |
| 71 } | |
| 72 } | |
| 73 return FALSE; | |
| 74 } | |
| 75 | |
| 76 CFDE_XMLNode::CFDE_XMLNode() | |
| 77 : m_pParent(NULL), m_pChild(NULL), m_pPrior(NULL), m_pNext(NULL) {} | |
| 78 CFDE_XMLNode::~CFDE_XMLNode() { | |
| 79 DeleteChildren(); | |
| 80 } | |
| 81 void CFDE_XMLNode::DeleteChildren() { | |
| 82 CFDE_XMLNode *pChild = m_pChild, *pTemp; | |
| 83 while (pChild != NULL) { | |
| 84 pTemp = pChild->m_pNext; | |
| 85 pChild->Release(); | |
| 86 pChild = pTemp; | |
| 87 } | |
| 88 m_pChild = NULL; | |
| 89 } | |
| 90 int32_t CFDE_XMLNode::CountChildNodes() const { | |
| 91 int32_t iCount = 0; | |
| 92 CFDE_XMLNode* pChild = m_pChild; | |
| 93 while (pChild != NULL) { | |
| 94 iCount++; | |
| 95 pChild = pChild->m_pNext; | |
| 96 } | |
| 97 return iCount; | |
| 98 } | |
| 99 CFDE_XMLNode* CFDE_XMLNode::GetChildNode(int32_t index) const { | |
| 100 CFDE_XMLNode* pChild = m_pChild; | |
| 101 while (pChild != NULL) { | |
| 102 if (index == 0) { | |
| 103 return pChild; | |
| 104 } | |
| 105 index--; | |
| 106 pChild = pChild->m_pNext; | |
| 107 } | |
| 108 return NULL; | |
| 109 } | |
| 110 int32_t CFDE_XMLNode::GetChildNodeIndex(CFDE_XMLNode* pNode) const { | |
| 111 int32_t index = 0; | |
| 112 CFDE_XMLNode* pChild = m_pChild; | |
| 113 while (pChild != NULL) { | |
| 114 if (pChild == pNode) { | |
| 115 return index; | |
| 116 } | |
| 117 index++; | |
| 118 pChild = pChild->m_pNext; | |
| 119 } | |
| 120 return -1; | |
| 121 } | |
| 122 CFDE_XMLNode* CFDE_XMLNode::GetPath(const FX_WCHAR* pPath, | |
| 123 int32_t iLength, | |
| 124 FX_BOOL bQualifiedName) const { | |
| 125 FXSYS_assert(pPath != NULL); | |
| 126 if (iLength < 0) { | |
| 127 iLength = FXSYS_wcslen(pPath); | |
| 128 } | |
| 129 if (iLength == 0) { | |
| 130 return NULL; | |
| 131 } | |
| 132 CFX_WideString csPath; | |
| 133 const FX_WCHAR* pStart = pPath; | |
| 134 const FX_WCHAR* pEnd = pPath + iLength; | |
| 135 FX_WCHAR ch; | |
| 136 while (pStart < pEnd) { | |
| 137 ch = *pStart++; | |
| 138 if (ch == L'/') { | |
| 139 break; | |
| 140 } else { | |
| 141 csPath += ch; | |
| 142 } | |
| 143 } | |
| 144 iLength -= pStart - pPath; | |
| 145 CFDE_XMLNode* pFind = NULL; | |
| 146 if (csPath.GetLength() < 1) { | |
| 147 pFind = GetNodeItem(IFDE_XMLNode::Root); | |
| 148 } else if (csPath.Compare(L"..") == 0) { | |
| 149 pFind = m_pParent; | |
| 150 } else if (csPath.Compare(L".") == 0) { | |
| 151 pFind = (CFDE_XMLNode*)this; | |
| 152 } else { | |
| 153 CFX_WideString wsTag; | |
| 154 CFDE_XMLNode* pNode = m_pChild; | |
| 155 while (pNode != NULL) { | |
| 156 if (pNode->GetType() == FDE_XMLNODE_Element) { | |
| 157 if (bQualifiedName) { | |
| 158 ((CFDE_XMLElement*)pNode)->GetTagName(wsTag); | |
| 159 } else { | |
| 160 ((CFDE_XMLElement*)pNode)->GetLocalTagName(wsTag); | |
| 161 } | |
| 162 if (wsTag.Compare(csPath) == 0) { | |
| 163 if (iLength < 1) { | |
| 164 pFind = pNode; | |
| 165 } else { | |
| 166 pFind = pNode->GetPath(pStart, iLength, bQualifiedName); | |
| 167 } | |
| 168 if (pFind != NULL) { | |
| 169 return pFind; | |
| 170 } | |
| 171 } | |
| 172 } | |
| 173 pNode = pNode->m_pNext; | |
| 174 } | |
| 175 } | |
| 176 if (pFind == NULL || iLength < 1) { | |
| 177 return pFind; | |
| 178 } | |
| 179 return pFind->GetPath(pStart, iLength, bQualifiedName); | |
| 180 } | |
| 181 int32_t CFDE_XMLNode::InsertChildNode(CFDE_XMLNode* pNode, int32_t index) { | |
| 182 FXSYS_assert(pNode != NULL); | |
| 183 pNode->m_pParent = this; | |
| 184 if (m_pChild == NULL) { | |
| 185 m_pChild = pNode; | |
| 186 pNode->m_pPrior = NULL; | |
| 187 pNode->m_pNext = NULL; | |
| 188 return 0; | |
| 189 } else if (index == 0) { | |
| 190 pNode->m_pNext = m_pChild; | |
| 191 pNode->m_pPrior = NULL; | |
| 192 m_pChild->m_pPrior = pNode; | |
| 193 m_pChild = pNode; | |
| 194 return 0; | |
| 195 } | |
| 196 int32_t iCount = 0; | |
| 197 CFDE_XMLNode* pFind = m_pChild; | |
| 198 while (++iCount != index && pFind->m_pNext != NULL) { | |
| 199 pFind = pFind->m_pNext; | |
| 200 } | |
| 201 pNode->m_pPrior = pFind; | |
| 202 pNode->m_pNext = pFind->m_pNext; | |
| 203 if (pFind->m_pNext != NULL) { | |
| 204 pFind->m_pNext->m_pPrior = pNode; | |
| 205 } | |
| 206 pFind->m_pNext = pNode; | |
| 207 return iCount; | |
| 208 } | |
| 209 void CFDE_XMLNode::RemoveChildNode(CFDE_XMLNode* pNode) { | |
| 210 FXSYS_assert(m_pChild != NULL && pNode != NULL); | |
| 211 if (m_pChild == pNode) { | |
| 212 m_pChild = pNode->m_pNext; | |
| 213 } else { | |
| 214 pNode->m_pPrior->m_pNext = pNode->m_pNext; | |
| 215 } | |
| 216 if (pNode->m_pNext != NULL) { | |
| 217 pNode->m_pNext->m_pPrior = pNode->m_pPrior; | |
| 218 } | |
| 219 pNode->m_pParent = NULL; | |
| 220 pNode->m_pNext = NULL; | |
| 221 pNode->m_pPrior = NULL; | |
| 222 } | |
| 223 CFDE_XMLNode* CFDE_XMLNode::GetNodeItem(IFDE_XMLNode::NodeItem eItem) const { | |
| 224 switch (eItem) { | |
| 225 case IFDE_XMLNode::Root: { | |
| 226 CFDE_XMLNode* pParent = (CFDE_XMLNode*)this; | |
| 227 while (pParent->m_pParent != NULL) { | |
| 228 pParent = pParent->m_pParent; | |
| 229 } | |
| 230 return pParent; | |
| 231 } | |
| 232 case IFDE_XMLNode::Parent: | |
| 233 return m_pParent; | |
| 234 case IFDE_XMLNode::FirstSibling: { | |
| 235 CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; | |
| 236 while (pItem->m_pPrior != NULL) { | |
| 237 pItem = pItem->m_pPrior; | |
| 238 } | |
| 239 return pItem == (CFDE_XMLNode*)this ? NULL : pItem; | |
| 240 } | |
| 241 case IFDE_XMLNode::PriorSibling: | |
| 242 return m_pPrior; | |
| 243 case IFDE_XMLNode::NextSibling: | |
| 244 return m_pNext; | |
| 245 case IFDE_XMLNode::LastSibling: { | |
| 246 CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; | |
| 247 while (pItem->m_pNext != NULL) { | |
| 248 pItem = pItem->m_pNext; | |
| 249 } | |
| 250 return pItem == (CFDE_XMLNode*)this ? NULL : pItem; | |
| 251 } | |
| 252 case IFDE_XMLNode::FirstNeighbor: { | |
| 253 CFDE_XMLNode* pParent = (CFDE_XMLNode*)this; | |
| 254 while (pParent->m_pParent != NULL) { | |
| 255 pParent = pParent->m_pParent; | |
| 256 } | |
| 257 return pParent == (CFDE_XMLNode*)this ? NULL : pParent; | |
| 258 } | |
| 259 case IFDE_XMLNode::PriorNeighbor: { | |
| 260 if (m_pPrior == NULL) { | |
| 261 return m_pParent; | |
| 262 } | |
| 263 CFDE_XMLNode* pItem = m_pPrior; | |
| 264 while (CFDE_XMLNode* pTemp = pItem->m_pChild) { | |
| 265 pItem = pTemp; | |
| 266 while ((pTemp = pItem->m_pNext) != NULL) { | |
| 267 pItem = pTemp; | |
| 268 } | |
| 269 } | |
| 270 return pItem; | |
| 271 } | |
| 272 case IFDE_XMLNode::NextNeighbor: { | |
| 273 if (m_pChild != NULL) { | |
| 274 return m_pChild; | |
| 275 } | |
| 276 if (m_pNext != NULL) { | |
| 277 return m_pNext; | |
| 278 } | |
| 279 CFDE_XMLNode* pItem = m_pParent; | |
| 280 while (pItem != NULL) { | |
| 281 if (pItem->m_pNext != NULL) { | |
| 282 return pItem->m_pNext; | |
| 283 } | |
| 284 pItem = pItem->m_pParent; | |
| 285 } | |
| 286 return NULL; | |
| 287 } | |
| 288 case IFDE_XMLNode::LastNeighbor: { | |
| 289 CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; | |
| 290 while (pItem->m_pParent != NULL) { | |
| 291 pItem = pItem->m_pParent; | |
| 292 } | |
| 293 while (TRUE) { | |
| 294 while (pItem->m_pNext != NULL) { | |
| 295 pItem = pItem->m_pNext; | |
| 296 } | |
| 297 if (pItem->m_pChild == NULL) { | |
| 298 break; | |
| 299 } | |
| 300 pItem = pItem->m_pChild; | |
| 301 } | |
| 302 return pItem == (CFDE_XMLNode*)this ? NULL : pItem; | |
| 303 } | |
| 304 case IFDE_XMLNode::FirstChild: | |
| 305 return m_pChild; | |
| 306 case IFDE_XMLNode::LastChild: { | |
| 307 if (m_pChild == NULL) { | |
| 308 return NULL; | |
| 309 } | |
| 310 CFDE_XMLNode* pChild = m_pChild; | |
| 311 while (pChild->m_pNext != NULL) { | |
| 312 pChild = pChild->m_pNext; | |
| 313 } | |
| 314 return pChild; | |
| 315 } | |
| 316 default: | |
| 317 break; | |
| 318 } | |
| 319 return NULL; | |
| 320 } | |
| 321 int32_t CFDE_XMLNode::GetNodeLevel() const { | |
| 322 int32_t iLevel = 0; | |
| 323 CFDE_XMLNode* pItem = (CFDE_XMLNode*)this; | |
| 324 while ((pItem = pItem->m_pParent) != NULL) { | |
| 325 iLevel++; | |
| 326 } | |
| 327 return iLevel; | |
| 328 } | |
| 329 FX_BOOL CFDE_XMLNode::InsertNodeItem(IFDE_XMLNode::NodeItem eItem, | |
| 330 CFDE_XMLNode* pNode) { | |
| 331 FXSYS_assert(pNode != NULL); | |
| 332 switch (eItem) { | |
| 333 case IFDE_XMLNode::NextSibling: { | |
| 334 pNode->m_pParent = m_pParent; | |
| 335 pNode->m_pNext = m_pNext; | |
| 336 pNode->m_pPrior = this; | |
| 337 if (m_pNext) { | |
| 338 m_pNext->m_pPrior = pNode; | |
| 339 } | |
| 340 m_pNext = pNode; | |
| 341 return TRUE; | |
| 342 } | |
| 343 case IFDE_XMLNode::PriorSibling: { | |
| 344 pNode->m_pParent = m_pParent; | |
| 345 pNode->m_pNext = this; | |
| 346 pNode->m_pPrior = m_pPrior; | |
| 347 if (m_pPrior) { | |
| 348 m_pPrior->m_pNext = pNode; | |
| 349 } else if (m_pParent) { | |
| 350 m_pParent->m_pChild = pNode; | |
| 351 } | |
| 352 m_pPrior = pNode; | |
| 353 return TRUE; | |
| 354 } | |
| 355 default: | |
| 356 return FALSE; | |
| 357 } | |
| 358 return FALSE; | |
| 359 } | |
| 360 CFDE_XMLNode* CFDE_XMLNode::RemoveNodeItem(IFDE_XMLNode::NodeItem eItem) { | |
| 361 CFDE_XMLNode* pNode = NULL; | |
| 362 switch (eItem) { | |
| 363 case IFDE_XMLNode::NextSibling: | |
| 364 if (m_pNext) { | |
| 365 pNode = m_pNext; | |
| 366 m_pNext = pNode->m_pNext; | |
| 367 if (m_pNext) { | |
| 368 m_pNext->m_pPrior = this; | |
| 369 } | |
| 370 pNode->m_pParent = NULL; | |
| 371 pNode->m_pNext = NULL; | |
| 372 pNode->m_pPrior = NULL; | |
| 373 } | |
| 374 break; | |
| 375 default: | |
| 376 break; | |
| 377 } | |
| 378 return pNode; | |
| 379 } | |
| 380 CFDE_XMLNode* CFDE_XMLNode::Clone(FX_BOOL bRecursive) { | |
| 381 return NULL; | |
| 382 } | |
| 383 void CFDE_XMLNode::SaveXMLNode(IFX_Stream* pXMLStream) { | |
| 384 CFDE_XMLNode* pNode = (CFDE_XMLNode*)this; | |
| 385 FXSYS_assert(pXMLStream != NULL && pNode != NULL); | |
| 386 switch (pNode->GetType()) { | |
| 387 case FDE_XMLNODE_Instruction: { | |
| 388 CFX_WideString ws; | |
| 389 CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode; | |
| 390 if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) { | |
| 391 ws = L"<?xml version=\"1.0\" encoding=\""; | |
| 392 FX_WORD wCodePage = pXMLStream->GetCodePage(); | |
| 393 if (wCodePage == FX_CODEPAGE_UTF16LE) { | |
| 394 ws += L"UTF-16"; | |
| 395 } else if (wCodePage == FX_CODEPAGE_UTF16BE) { | |
| 396 ws += L"UTF-16be"; | |
| 397 } else { | |
| 398 ws += L"UTF-8"; | |
| 399 } | |
| 400 ws += L"\"?>"; | |
| 401 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 402 } else { | |
| 403 ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget); | |
| 404 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 405 CFX_WideStringArray& attributes = pInstruction->m_Attributes; | |
| 406 int32_t i, iCount = attributes.GetSize(); | |
| 407 CFX_WideString wsValue; | |
| 408 for (i = 0; i < iCount; i += 2) { | |
| 409 ws = L" "; | |
| 410 ws += attributes[i]; | |
| 411 ws += L"=\""; | |
| 412 wsValue = attributes[i + 1]; | |
| 413 wsValue.Replace(L"&", L"&"); | |
| 414 wsValue.Replace(L"<", L"<"); | |
| 415 wsValue.Replace(L">", L">"); | |
| 416 wsValue.Replace(L"\'", L"'"); | |
| 417 wsValue.Replace(L"\"", L"""); | |
| 418 ws += wsValue; | |
| 419 ws += L"\""; | |
| 420 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 421 } | |
| 422 CFX_WideStringArray& targetdata = pInstruction->m_TargetData; | |
| 423 iCount = targetdata.GetSize(); | |
| 424 for (i = 0; i < iCount; i++) { | |
| 425 ws = L" \""; | |
| 426 ws += targetdata[i]; | |
| 427 ws += L"\""; | |
| 428 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 429 } | |
| 430 ws = L"?>"; | |
| 431 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 432 } | |
| 433 } break; | |
| 434 case FDE_XMLNODE_Element: { | |
| 435 CFX_WideString ws; | |
| 436 ws = L"<"; | |
| 437 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 438 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 439 CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes; | |
| 440 int32_t iCount = attributes.GetSize(); | |
| 441 CFX_WideString wsValue; | |
| 442 for (int32_t i = 0; i < iCount; i += 2) { | |
| 443 ws = L" "; | |
| 444 ws += attributes[i]; | |
| 445 ws += L"=\""; | |
| 446 wsValue = attributes[i + 1]; | |
| 447 wsValue.Replace(L"&", L"&"); | |
| 448 wsValue.Replace(L"<", L"<"); | |
| 449 wsValue.Replace(L">", L">"); | |
| 450 wsValue.Replace(L"\'", L"'"); | |
| 451 wsValue.Replace(L"\"", L"""); | |
| 452 ws += wsValue; | |
| 453 ws += L"\""; | |
| 454 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 455 } | |
| 456 if (pNode->m_pChild == NULL) { | |
| 457 ws = L"\n/>"; | |
| 458 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 459 } else { | |
| 460 ws = L"\n>"; | |
| 461 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 462 CFDE_XMLNode* pChild = pNode->m_pChild; | |
| 463 while (pChild != NULL) { | |
| 464 pChild->SaveXMLNode(pXMLStream); | |
| 465 pChild = pChild->m_pNext; | |
| 466 } | |
| 467 ws = L"</"; | |
| 468 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 469 ws += L"\n>"; | |
| 470 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 471 } | |
| 472 } break; | |
| 473 case FDE_XMLNODE_Text: { | |
| 474 CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; | |
| 475 ws.Replace(L"&", L"&"); | |
| 476 ws.Replace(L"<", L"<"); | |
| 477 ws.Replace(L">", L">"); | |
| 478 ws.Replace(L"\'", L"'"); | |
| 479 ws.Replace(L"\"", L"""); | |
| 480 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 481 } break; | |
| 482 case FDE_XMLNODE_CharData: { | |
| 483 CFX_WideString ws = L"<![CDATA["; | |
| 484 ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; | |
| 485 ws += L"]]>"; | |
| 486 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 487 } break; | |
| 488 case FDE_XMLNODE_Unknown: | |
| 489 break; | |
| 490 default: | |
| 491 break; | |
| 492 } | |
| 493 } | |
| 494 void CFDE_XMLNode::CloneChildren(CFDE_XMLNode* pClone) { | |
| 495 if (!m_pChild) { | |
| 496 return; | |
| 497 } | |
| 498 CFDE_XMLNode* pNext = m_pChild; | |
| 499 CFDE_XMLNode* pCloneNext = pNext->Clone(TRUE); | |
| 500 pClone->InsertChildNode(pCloneNext); | |
| 501 pNext = pNext->m_pNext; | |
| 502 while (pNext) { | |
| 503 CFDE_XMLNode* pChild = pNext->Clone(TRUE); | |
| 504 pCloneNext->InsertNodeItem(IFDE_XMLNode::NextSibling, pChild); | |
| 505 pCloneNext = pChild; | |
| 506 pNext = pNext->m_pNext; | |
| 507 } | |
| 508 } | |
| 509 IFDE_XMLInstruction* IFDE_XMLInstruction::Create( | |
| 510 const CFX_WideString& wsTarget) { | |
| 511 return (IFDE_XMLInstruction*)new CFDE_XMLInstruction(wsTarget); | |
| 512 } | |
| 513 CFDE_XMLInstruction::CFDE_XMLInstruction(const CFX_WideString& wsTarget) | |
| 514 : m_wsTarget(wsTarget) { | |
| 515 FXSYS_assert(m_wsTarget.GetLength() > 0); | |
| 516 } | |
| 517 CFDE_XMLNode* CFDE_XMLInstruction::Clone(FX_BOOL bRecursive) { | |
| 518 CFDE_XMLInstruction* pClone = new CFDE_XMLInstruction(m_wsTarget); | |
| 519 if (!pClone) { | |
| 520 return pClone; | |
| 521 } | |
| 522 pClone->m_Attributes.Copy(m_Attributes); | |
| 523 pClone->m_TargetData.Copy(m_TargetData); | |
| 524 if (bRecursive) { | |
| 525 CloneChildren(pClone); | |
| 526 } | |
| 527 return pClone; | |
| 528 } | |
| 529 int32_t CFDE_XMLInstruction::CountAttributes() const { | |
| 530 return m_Attributes.GetSize() / 2; | |
| 531 } | |
| 532 FX_BOOL CFDE_XMLInstruction::GetAttribute(int32_t index, | |
| 533 CFX_WideString& wsAttriName, | |
| 534 CFX_WideString& wsAttriValue) const { | |
| 535 int32_t iCount = m_Attributes.GetSize(); | |
| 536 FXSYS_assert(index > -1 && index < iCount / 2); | |
| 537 for (int32_t i = 0; i < iCount; i += 2) { | |
| 538 if (index == 0) { | |
| 539 wsAttriName = m_Attributes[i]; | |
| 540 wsAttriValue = m_Attributes[i + 1]; | |
| 541 return TRUE; | |
| 542 } | |
| 543 index--; | |
| 544 } | |
| 545 return FALSE; | |
| 546 } | |
| 547 FX_BOOL CFDE_XMLInstruction::HasAttribute(const FX_WCHAR* pwsAttriName) const { | |
| 548 int32_t iCount = m_Attributes.GetSize(); | |
| 549 for (int32_t i = 0; i < iCount; i += 2) { | |
| 550 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 551 return TRUE; | |
| 552 } | |
| 553 } | |
| 554 return FALSE; | |
| 555 } | |
| 556 void CFDE_XMLInstruction::GetString(const FX_WCHAR* pwsAttriName, | |
| 557 CFX_WideString& wsAttriValue, | |
| 558 const FX_WCHAR* pwsDefValue) const { | |
| 559 int32_t iCount = m_Attributes.GetSize(); | |
| 560 for (int32_t i = 0; i < iCount; i += 2) { | |
| 561 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 562 wsAttriValue = m_Attributes[i + 1]; | |
| 563 return; | |
| 564 } | |
| 565 } | |
| 566 wsAttriValue = pwsDefValue; | |
| 567 } | |
| 568 void CFDE_XMLInstruction::SetString(const CFX_WideString& wsAttriName, | |
| 569 const CFX_WideString& wsAttriValue) { | |
| 570 FXSYS_assert(wsAttriName.GetLength() > 0); | |
| 571 int32_t iCount = m_Attributes.GetSize(); | |
| 572 for (int32_t i = 0; i < iCount; i += 2) { | |
| 573 if (m_Attributes[i].Compare(wsAttriName) == 0) { | |
| 574 m_Attributes[i] = wsAttriName; | |
| 575 m_Attributes[i + 1] = wsAttriValue; | |
| 576 return; | |
| 577 } | |
| 578 } | |
| 579 m_Attributes.Add(wsAttriName); | |
| 580 m_Attributes.Add(wsAttriValue); | |
| 581 } | |
| 582 int32_t CFDE_XMLInstruction::GetInteger(const FX_WCHAR* pwsAttriName, | |
| 583 int32_t iDefValue) const { | |
| 584 int32_t iCount = m_Attributes.GetSize(); | |
| 585 for (int32_t i = 0; i < iCount; i += 2) { | |
| 586 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 587 return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]); | |
| 588 } | |
| 589 } | |
| 590 return iDefValue; | |
| 591 } | |
| 592 void CFDE_XMLInstruction::SetInteger(const FX_WCHAR* pwsAttriName, | |
| 593 int32_t iAttriValue) { | |
| 594 CFX_WideString wsValue; | |
| 595 wsValue.Format(L"%d", iAttriValue); | |
| 596 SetString(pwsAttriName, wsValue); | |
| 597 } | |
| 598 FX_FLOAT CFDE_XMLInstruction::GetFloat(const FX_WCHAR* pwsAttriName, | |
| 599 FX_FLOAT fDefValue) const { | |
| 600 int32_t iCount = m_Attributes.GetSize(); | |
| 601 for (int32_t i = 0; i < iCount; i += 2) { | |
| 602 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 603 return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]); | |
| 604 } | |
| 605 } | |
| 606 return fDefValue; | |
| 607 } | |
| 608 void CFDE_XMLInstruction::SetFloat(const FX_WCHAR* pwsAttriName, | |
| 609 FX_FLOAT fAttriValue) { | |
| 610 CFX_WideString wsValue; | |
| 611 wsValue.Format(L"%f", fAttriValue); | |
| 612 SetString(pwsAttriName, wsValue); | |
| 613 } | |
| 614 void CFDE_XMLInstruction::RemoveAttribute(const FX_WCHAR* pwsAttriName) { | |
| 615 int32_t iCount = m_Attributes.GetSize(); | |
| 616 for (int32_t i = 0; i < iCount; i += 2) { | |
| 617 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 618 m_Attributes.RemoveAt(i + 1); | |
| 619 m_Attributes.RemoveAt(i); | |
| 620 return; | |
| 621 } | |
| 622 } | |
| 623 } | |
| 624 int32_t CFDE_XMLInstruction::CountData() const { | |
| 625 return m_TargetData.GetSize(); | |
| 626 } | |
| 627 FX_BOOL CFDE_XMLInstruction::GetData(int32_t index, | |
| 628 CFX_WideString& wsData) const { | |
| 629 if (index < 0 || index >= m_TargetData.GetSize()) { | |
| 630 return FALSE; | |
| 631 } | |
| 632 wsData = m_TargetData[index]; | |
| 633 return TRUE; | |
| 634 } | |
| 635 void CFDE_XMLInstruction::AppendData(const CFX_WideString& wsData) { | |
| 636 m_TargetData.Add(wsData); | |
| 637 } | |
| 638 void CFDE_XMLInstruction::RemoveData(int32_t index) { | |
| 639 m_TargetData.RemoveAt(index); | |
| 640 } | |
| 641 IFDE_XMLElement* IFDE_XMLElement::Create(const CFX_WideString& wsTag) { | |
| 642 return (IFDE_XMLElement*)new CFDE_XMLElement(wsTag); | |
| 643 } | |
| 644 CFDE_XMLElement::CFDE_XMLElement(const CFX_WideString& wsTag) | |
| 645 : CFDE_XMLNode(), m_wsTag(wsTag), m_Attributes() { | |
| 646 FXSYS_assert(m_wsTag.GetLength() > 0); | |
| 647 } | |
| 648 CFDE_XMLElement::~CFDE_XMLElement() { | |
| 649 m_Attributes.RemoveAll(); | |
| 650 } | |
| 651 CFDE_XMLNode* CFDE_XMLElement::Clone(FX_BOOL bRecursive) { | |
| 652 CFDE_XMLElement* pClone = new CFDE_XMLElement(m_wsTag); | |
| 653 if (!pClone) { | |
| 654 return NULL; | |
| 655 } | |
| 656 pClone->m_Attributes.Copy(m_Attributes); | |
| 657 if (bRecursive) { | |
| 658 CloneChildren(pClone); | |
| 659 } else { | |
| 660 CFX_WideString wsText; | |
| 661 CFDE_XMLNode* pChild = m_pChild; | |
| 662 while (pChild != NULL) { | |
| 663 switch (pChild->GetType()) { | |
| 664 case FDE_XMLNODE_Text: | |
| 665 wsText += ((CFDE_XMLText*)pChild)->m_wsText; | |
| 666 break; | |
| 667 default: | |
| 668 break; | |
| 669 } | |
| 670 pChild = pChild->m_pNext; | |
| 671 } | |
| 672 pClone->SetTextData(wsText); | |
| 673 } | |
| 674 return pClone; | |
| 675 } | |
| 676 void CFDE_XMLElement::GetTagName(CFX_WideString& wsTag) const { | |
| 677 wsTag = m_wsTag; | |
| 678 } | |
| 679 void CFDE_XMLElement::GetLocalTagName(CFX_WideString& wsTag) const { | |
| 680 FX_STRSIZE iFind = m_wsTag.Find(L':', 0); | |
| 681 if (iFind < 0) { | |
| 682 wsTag = m_wsTag; | |
| 683 } else { | |
| 684 wsTag = m_wsTag.Right(m_wsTag.GetLength() - iFind - 1); | |
| 685 } | |
| 686 } | |
| 687 void CFDE_XMLElement::GetNamespacePrefix(CFX_WideString& wsPrefix) const { | |
| 688 FX_STRSIZE iFind = m_wsTag.Find(L':', 0); | |
| 689 if (iFind < 0) { | |
| 690 wsPrefix.Empty(); | |
| 691 } else { | |
| 692 wsPrefix = m_wsTag.Left(iFind); | |
| 693 } | |
| 694 } | |
| 695 void CFDE_XMLElement::GetNamespaceURI(CFX_WideString& wsNamespace) const { | |
| 696 CFX_WideString wsAttri(L"xmlns"), wsPrefix; | |
| 697 GetNamespacePrefix(wsPrefix); | |
| 698 if (wsPrefix.GetLength() > 0) { | |
| 699 wsAttri += L":"; | |
| 700 wsAttri += wsPrefix; | |
| 701 } | |
| 702 wsNamespace.Empty(); | |
| 703 CFDE_XMLNode* pNode = (CFDE_XMLNode*)this; | |
| 704 while (pNode != NULL) { | |
| 705 if (pNode->GetType() != FDE_XMLNODE_Element) { | |
| 706 break; | |
| 707 } | |
| 708 CFDE_XMLElement* pElement = (CFDE_XMLElement*)pNode; | |
| 709 if (!pElement->HasAttribute(wsAttri)) { | |
| 710 pNode = pNode->GetNodeItem(IFDE_XMLNode::Parent); | |
| 711 continue; | |
| 712 } | |
| 713 pElement->GetString(wsAttri, wsNamespace); | |
| 714 break; | |
| 715 } | |
| 716 } | |
| 717 int32_t CFDE_XMLElement::CountAttributes() const { | |
| 718 return m_Attributes.GetSize() / 2; | |
| 719 } | |
| 720 FX_BOOL CFDE_XMLElement::GetAttribute(int32_t index, | |
| 721 CFX_WideString& wsAttriName, | |
| 722 CFX_WideString& wsAttriValue) const { | |
| 723 int32_t iCount = m_Attributes.GetSize(); | |
| 724 FXSYS_assert(index > -1 && index < iCount / 2); | |
| 725 for (int32_t i = 0; i < iCount; i += 2) { | |
| 726 if (index == 0) { | |
| 727 wsAttriName = m_Attributes[i]; | |
| 728 wsAttriValue = m_Attributes[i + 1]; | |
| 729 return TRUE; | |
| 730 } | |
| 731 index--; | |
| 732 } | |
| 733 return FALSE; | |
| 734 } | |
| 735 FX_BOOL CFDE_XMLElement::HasAttribute(const FX_WCHAR* pwsAttriName) const { | |
| 736 int32_t iCount = m_Attributes.GetSize(); | |
| 737 for (int32_t i = 0; i < iCount; i += 2) { | |
| 738 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 739 return TRUE; | |
| 740 } | |
| 741 } | |
| 742 return FALSE; | |
| 743 } | |
| 744 void CFDE_XMLElement::GetString(const FX_WCHAR* pwsAttriName, | |
| 745 CFX_WideString& wsAttriValue, | |
| 746 const FX_WCHAR* pwsDefValue) const { | |
| 747 int32_t iCount = m_Attributes.GetSize(); | |
| 748 for (int32_t i = 0; i < iCount; i += 2) { | |
| 749 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 750 wsAttriValue = m_Attributes[i + 1]; | |
| 751 return; | |
| 752 } | |
| 753 } | |
| 754 wsAttriValue = pwsDefValue; | |
| 755 } | |
| 756 void CFDE_XMLElement::SetString(const CFX_WideString& wsAttriName, | |
| 757 const CFX_WideString& wsAttriValue) { | |
| 758 FXSYS_assert(wsAttriName.GetLength() > 0); | |
| 759 int32_t iCount = m_Attributes.GetSize(); | |
| 760 for (int32_t i = 0; i < iCount; i += 2) { | |
| 761 if (m_Attributes[i].Compare(wsAttriName) == 0) { | |
| 762 m_Attributes[i] = wsAttriName; | |
| 763 m_Attributes[i + 1] = wsAttriValue; | |
| 764 return; | |
| 765 } | |
| 766 } | |
| 767 m_Attributes.Add(wsAttriName); | |
| 768 m_Attributes.Add(wsAttriValue); | |
| 769 } | |
| 770 int32_t CFDE_XMLElement::GetInteger(const FX_WCHAR* pwsAttriName, | |
| 771 int32_t iDefValue) const { | |
| 772 int32_t iCount = m_Attributes.GetSize(); | |
| 773 for (int32_t i = 0; i < iCount; i += 2) { | |
| 774 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 775 return FXSYS_wtoi((const FX_WCHAR*)m_Attributes[i + 1]); | |
| 776 } | |
| 777 } | |
| 778 return iDefValue; | |
| 779 } | |
| 780 void CFDE_XMLElement::SetInteger(const FX_WCHAR* pwsAttriName, | |
| 781 int32_t iAttriValue) { | |
| 782 CFX_WideString wsValue; | |
| 783 wsValue.Format(L"%d", iAttriValue); | |
| 784 SetString(pwsAttriName, wsValue); | |
| 785 } | |
| 786 FX_FLOAT CFDE_XMLElement::GetFloat(const FX_WCHAR* pwsAttriName, | |
| 787 FX_FLOAT fDefValue) const { | |
| 788 int32_t iCount = m_Attributes.GetSize(); | |
| 789 for (int32_t i = 0; i < iCount; i += 2) { | |
| 790 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 791 return FX_wcstof((const FX_WCHAR*)m_Attributes[i + 1]); | |
| 792 } | |
| 793 } | |
| 794 return fDefValue; | |
| 795 } | |
| 796 void CFDE_XMLElement::SetFloat(const FX_WCHAR* pwsAttriName, | |
| 797 FX_FLOAT fAttriValue) { | |
| 798 CFX_WideString wsValue; | |
| 799 wsValue.Format(L"%f", fAttriValue); | |
| 800 SetString(pwsAttriName, wsValue); | |
| 801 } | |
| 802 void CFDE_XMLElement::RemoveAttribute(const FX_WCHAR* pwsAttriName) { | |
| 803 int32_t iCount = m_Attributes.GetSize(); | |
| 804 for (int32_t i = 0; i < iCount; i += 2) { | |
| 805 if (m_Attributes[i].Compare(pwsAttriName) == 0) { | |
| 806 m_Attributes.RemoveAt(i + 1); | |
| 807 m_Attributes.RemoveAt(i); | |
| 808 return; | |
| 809 } | |
| 810 } | |
| 811 } | |
| 812 void CFDE_XMLElement::GetTextData(CFX_WideString& wsText) const { | |
| 813 CFX_WideTextBuf buffer; | |
| 814 CFDE_XMLNode* pChild = m_pChild; | |
| 815 while (pChild != NULL) { | |
| 816 switch (pChild->GetType()) { | |
| 817 case FDE_XMLNODE_Text: | |
| 818 buffer << ((CFDE_XMLText*)pChild)->m_wsText; | |
| 819 break; | |
| 820 case FDE_XMLNODE_CharData: | |
| 821 buffer << ((CFDE_XMLCharData*)pChild)->m_wsCharData; | |
| 822 break; | |
| 823 default: | |
| 824 break; | |
| 825 } | |
| 826 pChild = pChild->m_pNext; | |
| 827 } | |
| 828 wsText = buffer.GetWideString(); | |
| 829 } | |
| 830 void CFDE_XMLElement::SetTextData(const CFX_WideString& wsText) { | |
| 831 if (wsText.GetLength() < 1) { | |
| 832 return; | |
| 833 } | |
| 834 InsertChildNode(new CFDE_XMLText(wsText)); | |
| 835 } | |
| 836 IFDE_XMLText* IFDE_XMLText::Create(const CFX_WideString& wsText) { | |
| 837 return (IFDE_XMLText*)new CFDE_XMLText(wsText); | |
| 838 } | |
| 839 CFDE_XMLText::CFDE_XMLText(const CFX_WideString& wsText) | |
| 840 : CFDE_XMLNode(), m_wsText(wsText) {} | |
| 841 CFDE_XMLNode* CFDE_XMLText::Clone(FX_BOOL bRecursive) { | |
| 842 CFDE_XMLText* pClone = new CFDE_XMLText(m_wsText); | |
| 843 return pClone; | |
| 844 } | |
| 845 IFDE_XMLCharData* IFDE_XMLCharData::Create(const CFX_WideString& wsCData) { | |
| 846 return (IFDE_XMLCharData*)new CFDE_XMLCharData(wsCData); | |
| 847 } | |
| 848 CFDE_XMLCharData::CFDE_XMLCharData(const CFX_WideString& wsCData) | |
| 849 : CFDE_XMLDeclaration(), m_wsCharData(wsCData) {} | |
| 850 CFDE_XMLNode* CFDE_XMLCharData::Clone(FX_BOOL bRecursive) { | |
| 851 CFDE_XMLCharData* pClone = new CFDE_XMLCharData(m_wsCharData); | |
| 852 return pClone; | |
| 853 } | |
| 854 IFDE_XMLDoc* IFDE_XMLDoc::Create() { | |
| 855 return (IFDE_XMLDoc*)new CFDE_XMLDoc; | |
| 856 } | |
| 857 CFDE_XMLDoc::CFDE_XMLDoc() | |
| 858 : m_pRoot(NULL), m_pSyntaxParser(NULL), m_pXMLParser(NULL) { | |
| 859 Reset(TRUE); | |
| 860 CFDE_XMLInstruction* pXML = new CFDE_XMLInstruction(L"xml"); | |
| 861 m_pRoot->InsertChildNode(pXML); | |
| 862 } | |
| 863 CFDE_XMLDoc::~CFDE_XMLDoc() { | |
| 864 Reset(FALSE); | |
| 865 } | |
| 866 void CFDE_XMLDoc::Reset(FX_BOOL bInitRoot) { | |
| 867 m_iStatus = 0; | |
| 868 m_pStream = NULL; | |
| 869 if (bInitRoot) { | |
| 870 if (m_pRoot == NULL) { | |
| 871 m_pRoot = new CFDE_XMLNode; | |
| 872 } else { | |
| 873 m_pRoot->DeleteChildren(); | |
| 874 } | |
| 875 } else { | |
| 876 if (m_pRoot != NULL) { | |
| 877 m_pRoot->Release(); | |
| 878 m_pRoot = NULL; | |
| 879 } | |
| 880 } | |
| 881 ReleaseParser(); | |
| 882 } | |
| 883 void CFDE_XMLDoc::ReleaseParser() { | |
| 884 if (m_pXMLParser != NULL) { | |
| 885 m_pXMLParser->Release(); | |
| 886 m_pXMLParser = NULL; | |
| 887 } | |
| 888 if (m_pSyntaxParser != NULL) { | |
| 889 m_pSyntaxParser->Release(); | |
| 890 m_pSyntaxParser = NULL; | |
| 891 } | |
| 892 } | |
| 893 FX_BOOL CFDE_XMLDoc::LoadXML(IFX_Stream* pXMLStream, | |
| 894 int32_t iXMLPlaneSize, | |
| 895 int32_t iTextDataSize, | |
| 896 FDE_XMLREADERHANDLER* pHandler) { | |
| 897 if (pXMLStream == NULL) { | |
| 898 return FALSE; | |
| 899 } | |
| 900 Reset(TRUE); | |
| 901 iXMLPlaneSize = iXMLPlaneSize / 1024; | |
| 902 if (iXMLPlaneSize < 1) { | |
| 903 iXMLPlaneSize = 1; | |
| 904 } | |
| 905 iXMLPlaneSize *= 1024; | |
| 906 if (iXMLPlaneSize < 4096) { | |
| 907 iXMLPlaneSize = 4096; | |
| 908 } | |
| 909 iTextDataSize = iTextDataSize / 128; | |
| 910 if (iTextDataSize < 1) { | |
| 911 iTextDataSize = 1; | |
| 912 } | |
| 913 iTextDataSize *= 128; | |
| 914 if (iTextDataSize < 128) { | |
| 915 iTextDataSize = 128; | |
| 916 } | |
| 917 m_pStream = pXMLStream; | |
| 918 FX_WORD wCodePage = m_pStream->GetCodePage(); | |
| 919 if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && | |
| 920 wCodePage != FX_CODEPAGE_UTF8) { | |
| 921 m_pStream->SetCodePage(FX_CODEPAGE_UTF8); | |
| 922 } | |
| 923 m_pSyntaxParser = IFDE_XMLSyntaxParser::Create(); | |
| 924 if (m_pSyntaxParser == NULL) { | |
| 925 return FALSE; | |
| 926 } | |
| 927 m_pSyntaxParser->Init(m_pStream, iXMLPlaneSize, iTextDataSize); | |
| 928 if (pHandler == NULL) { | |
| 929 m_pXMLParser = new CFDE_XMLDOMParser(m_pRoot, m_pSyntaxParser); | |
| 930 } else { | |
| 931 m_pXMLParser = new CFDE_XMLSAXParser(pHandler, m_pSyntaxParser); | |
| 932 } | |
| 933 return TRUE; | |
| 934 } | |
| 935 FX_BOOL CFDE_XMLDoc::LoadXML(IFDE_XMLParser* pXMLParser) { | |
| 936 if (pXMLParser == NULL) { | |
| 937 return FALSE; | |
| 938 } | |
| 939 Reset(TRUE); | |
| 940 m_pXMLParser = pXMLParser; | |
| 941 return m_pXMLParser != NULL; | |
| 942 } | |
| 943 int32_t CFDE_XMLDoc::DoLoad(IFX_Pause* pPause) { | |
| 944 if (m_iStatus >= 100) { | |
| 945 return m_iStatus; | |
| 946 } | |
| 947 FXSYS_assert(m_pXMLParser != NULL); | |
| 948 return m_iStatus = m_pXMLParser->DoParser(pPause); | |
| 949 } | |
| 950 void CFDE_XMLDoc::CloseXML() { | |
| 951 ReleaseParser(); | |
| 952 } | |
| 953 void CFDE_XMLDoc::SaveXMLNode(IFX_Stream* pXMLStream, IFDE_XMLNode* pINode) { | |
| 954 CFDE_XMLNode* pNode = (CFDE_XMLNode*)pINode; | |
| 955 FXSYS_assert(pXMLStream != NULL && pNode != NULL); | |
| 956 switch (pNode->GetType()) { | |
| 957 case FDE_XMLNODE_Instruction: { | |
| 958 CFX_WideString ws; | |
| 959 CFDE_XMLInstruction* pInstruction = (CFDE_XMLInstruction*)pNode; | |
| 960 if (pInstruction->m_wsTarget.CompareNoCase(L"xml") == 0) { | |
| 961 ws = L"<?xml version=\"1.0\" encoding=\""; | |
| 962 FX_WORD wCodePage = pXMLStream->GetCodePage(); | |
| 963 if (wCodePage == FX_CODEPAGE_UTF16LE) { | |
| 964 ws += L"UTF-16"; | |
| 965 } else if (wCodePage == FX_CODEPAGE_UTF16BE) { | |
| 966 ws += L"UTF-16be"; | |
| 967 } else { | |
| 968 ws += L"UTF-8"; | |
| 969 } | |
| 970 ws += L"\"?>"; | |
| 971 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 972 } else { | |
| 973 ws.Format(L"<?%s", (const FX_WCHAR*)pInstruction->m_wsTarget); | |
| 974 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 975 CFX_WideStringArray& attributes = pInstruction->m_Attributes; | |
| 976 int32_t i, iCount = attributes.GetSize(); | |
| 977 CFX_WideString wsValue; | |
| 978 for (i = 0; i < iCount; i += 2) { | |
| 979 ws = L" "; | |
| 980 ws += attributes[i]; | |
| 981 ws += L"=\""; | |
| 982 wsValue = attributes[i + 1]; | |
| 983 wsValue.Replace(L"&", L"&"); | |
| 984 wsValue.Replace(L"<", L"<"); | |
| 985 wsValue.Replace(L">", L">"); | |
| 986 wsValue.Replace(L"\'", L"'"); | |
| 987 wsValue.Replace(L"\"", L"""); | |
| 988 ws += wsValue; | |
| 989 ws += L"\""; | |
| 990 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 991 } | |
| 992 CFX_WideStringArray& targetdata = pInstruction->m_TargetData; | |
| 993 iCount = targetdata.GetSize(); | |
| 994 for (i = 0; i < iCount; i++) { | |
| 995 ws = L" \""; | |
| 996 ws += targetdata[i]; | |
| 997 ws += L"\""; | |
| 998 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 999 } | |
| 1000 ws = L"?>"; | |
| 1001 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1002 } | |
| 1003 } break; | |
| 1004 case FDE_XMLNODE_Element: { | |
| 1005 CFX_WideString ws; | |
| 1006 ws = L"<"; | |
| 1007 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 1008 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1009 CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes; | |
| 1010 int32_t iCount = attributes.GetSize(); | |
| 1011 CFX_WideString wsValue; | |
| 1012 for (int32_t i = 0; i < iCount; i += 2) { | |
| 1013 ws = L" "; | |
| 1014 ws += attributes[i]; | |
| 1015 ws += L"=\""; | |
| 1016 wsValue = attributes[i + 1]; | |
| 1017 wsValue.Replace(L"&", L"&"); | |
| 1018 wsValue.Replace(L"<", L"<"); | |
| 1019 wsValue.Replace(L">", L">"); | |
| 1020 wsValue.Replace(L"\'", L"'"); | |
| 1021 wsValue.Replace(L"\"", L"""); | |
| 1022 ws += wsValue; | |
| 1023 ws += L"\""; | |
| 1024 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1025 } | |
| 1026 if (pNode->m_pChild == NULL) { | |
| 1027 ws = L"\n/>"; | |
| 1028 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1029 } else { | |
| 1030 ws = L"\n>"; | |
| 1031 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1032 CFDE_XMLNode* pChild = pNode->m_pChild; | |
| 1033 while (pChild != NULL) { | |
| 1034 SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pChild); | |
| 1035 pChild = pChild->m_pNext; | |
| 1036 } | |
| 1037 ws = L"</"; | |
| 1038 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 1039 ws += L"\n>"; | |
| 1040 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1041 } | |
| 1042 } break; | |
| 1043 case FDE_XMLNODE_Text: { | |
| 1044 CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; | |
| 1045 ws.Replace(L"&", L"&"); | |
| 1046 ws.Replace(L"<", L"<"); | |
| 1047 ws.Replace(L">", L">"); | |
| 1048 ws.Replace(L"\'", L"'"); | |
| 1049 ws.Replace(L"\"", L"""); | |
| 1050 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1051 } break; | |
| 1052 case FDE_XMLNODE_CharData: { | |
| 1053 CFX_WideString ws = L"<![CDATA["; | |
| 1054 ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; | |
| 1055 ws += L"]]>"; | |
| 1056 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1057 } break; | |
| 1058 case FDE_XMLNODE_Unknown: | |
| 1059 break; | |
| 1060 default: | |
| 1061 break; | |
| 1062 } | |
| 1063 } | |
| 1064 void CFDE_XMLDoc::SaveXML(IFX_Stream* pXMLStream, FX_BOOL bSaveBOM) { | |
| 1065 if (pXMLStream == NULL || pXMLStream == m_pStream) { | |
| 1066 m_pStream->Seek(FX_STREAMSEEK_Begin, 0); | |
| 1067 pXMLStream = m_pStream; | |
| 1068 } | |
| 1069 FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Text) != 0); | |
| 1070 FXSYS_assert((pXMLStream->GetAccessModes() & FX_STREAMACCESS_Write) != 0); | |
| 1071 FX_WORD wCodePage = pXMLStream->GetCodePage(); | |
| 1072 if (wCodePage != FX_CODEPAGE_UTF16LE && wCodePage != FX_CODEPAGE_UTF16BE && | |
| 1073 wCodePage != FX_CODEPAGE_UTF8) { | |
| 1074 wCodePage = FX_CODEPAGE_UTF8; | |
| 1075 pXMLStream->SetCodePage(wCodePage); | |
| 1076 } | |
| 1077 if (bSaveBOM) { | |
| 1078 pXMLStream->WriteString(L"\xFEFF", 1); | |
| 1079 } | |
| 1080 CFDE_XMLNode* pNode = m_pRoot->m_pChild; | |
| 1081 while (pNode != NULL) { | |
| 1082 SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pNode); | |
| 1083 pNode = pNode->m_pNext; | |
| 1084 } | |
| 1085 if (pXMLStream == m_pStream) { | |
| 1086 int32_t iPos = pXMLStream->GetPosition(); | |
| 1087 pXMLStream->SetLength(iPos); | |
| 1088 } | |
| 1089 } | |
| 1090 CFDE_XMLDOMParser::CFDE_XMLDOMParser(CFDE_XMLNode* pRoot, | |
| 1091 IFDE_XMLSyntaxParser* pParser) | |
| 1092 : m_pParser(pParser), | |
| 1093 m_pParent(pRoot), | |
| 1094 m_pChild(NULL), | |
| 1095 m_NodeStack(16), | |
| 1096 m_ws1(), | |
| 1097 m_ws2() { | |
| 1098 m_NodeStack.Push(m_pParent); | |
| 1099 } | |
| 1100 CFDE_XMLDOMParser::~CFDE_XMLDOMParser() { | |
| 1101 m_NodeStack.RemoveAll(); | |
| 1102 m_ws1.Empty(); | |
| 1103 m_ws2.Empty(); | |
| 1104 } | |
| 1105 int32_t CFDE_XMLDOMParser::DoParser(IFX_Pause* pPause) { | |
| 1106 FX_DWORD dwRet; | |
| 1107 int32_t iCount = 0; | |
| 1108 while (TRUE) { | |
| 1109 dwRet = m_pParser->DoSyntaxParse(); | |
| 1110 switch (dwRet) { | |
| 1111 case FDE_XMLSYNTAXSTATUS_InstructionOpen: | |
| 1112 break; | |
| 1113 case FDE_XMLSYNTAXSTATUS_InstructionClose: | |
| 1114 if (m_pChild->GetType() != FDE_XMLNODE_Instruction) { | |
| 1115 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1116 break; | |
| 1117 } | |
| 1118 m_pChild = m_pParent; | |
| 1119 break; | |
| 1120 case FDE_XMLSYNTAXSTATUS_ElementOpen: | |
| 1121 case FDE_XMLSYNTAXSTATUS_ElementBreak: | |
| 1122 break; | |
| 1123 case FDE_XMLSYNTAXSTATUS_ElementClose: | |
| 1124 if (m_pChild->GetType() != FDE_XMLNODE_Element) { | |
| 1125 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1126 break; | |
| 1127 } | |
| 1128 m_pParser->GetTagName(m_ws1); | |
| 1129 ((CFDE_XMLElement*)m_pChild)->GetTagName(m_ws2); | |
| 1130 if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_ws2) != 0) { | |
| 1131 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1132 break; | |
| 1133 } | |
| 1134 m_NodeStack.Pop(); | |
| 1135 if (m_NodeStack.GetSize() < 1) { | |
| 1136 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1137 break; | |
| 1138 } | |
| 1139 m_pParent = (CFDE_XMLNode*)*m_NodeStack.GetTopElement(); | |
| 1140 m_pChild = m_pParent; | |
| 1141 iCount++; | |
| 1142 break; | |
| 1143 case FDE_XMLSYNTAXSTATUS_TargetName: | |
| 1144 m_pParser->GetTargetName(m_ws1); | |
| 1145 m_pChild = new CFDE_XMLInstruction(m_ws1); | |
| 1146 m_pParent->InsertChildNode(m_pChild); | |
| 1147 m_ws1.Empty(); | |
| 1148 break; | |
| 1149 case FDE_XMLSYNTAXSTATUS_TagName: | |
| 1150 m_pParser->GetTagName(m_ws1); | |
| 1151 m_pChild = new CFDE_XMLElement(m_ws1); | |
| 1152 m_pParent->InsertChildNode(m_pChild); | |
| 1153 m_NodeStack.Push(m_pChild); | |
| 1154 m_pParent = m_pChild; | |
| 1155 break; | |
| 1156 case FDE_XMLSYNTAXSTATUS_AttriName: | |
| 1157 m_pParser->GetAttributeName(m_ws1); | |
| 1158 break; | |
| 1159 case FDE_XMLSYNTAXSTATUS_AttriValue: | |
| 1160 if (m_pChild == NULL) { | |
| 1161 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1162 break; | |
| 1163 } | |
| 1164 m_pParser->GetAttributeName(m_ws2); | |
| 1165 if (m_pChild->GetType() == FDE_XMLNODE_Element) { | |
| 1166 ((CFDE_XMLElement*)m_pChild)->SetString(m_ws1, m_ws2); | |
| 1167 } else if (m_pChild->GetType() == FDE_XMLNODE_Instruction) { | |
| 1168 ((CFDE_XMLInstruction*)m_pChild)->SetString(m_ws1, m_ws2); | |
| 1169 } | |
| 1170 m_ws1.Empty(); | |
| 1171 break; | |
| 1172 case FDE_XMLSYNTAXSTATUS_Text: | |
| 1173 m_pParser->GetTextData(m_ws1); | |
| 1174 m_pChild = new CFDE_XMLText(m_ws1); | |
| 1175 m_pParent->InsertChildNode(m_pChild); | |
| 1176 m_pChild = m_pParent; | |
| 1177 break; | |
| 1178 case FDE_XMLSYNTAXSTATUS_CData: | |
| 1179 m_pParser->GetTextData(m_ws1); | |
| 1180 m_pChild = new CFDE_XMLCharData(m_ws1); | |
| 1181 m_pParent->InsertChildNode(m_pChild); | |
| 1182 m_pChild = m_pParent; | |
| 1183 break; | |
| 1184 case FDE_XMLSYNTAXSTATUS_TargetData: | |
| 1185 if (m_pChild == NULL || | |
| 1186 m_pChild->GetType() != FDE_XMLNODE_Instruction) { | |
| 1187 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1188 break; | |
| 1189 } | |
| 1190 if (!m_ws1.IsEmpty()) { | |
| 1191 ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1); | |
| 1192 } | |
| 1193 m_pParser->GetTargetData(m_ws1); | |
| 1194 ((CFDE_XMLInstruction*)m_pChild)->AppendData(m_ws1); | |
| 1195 m_ws1.Empty(); | |
| 1196 break; | |
| 1197 default: | |
| 1198 break; | |
| 1199 } | |
| 1200 if (dwRet == FDE_XMLSYNTAXSTATUS_Error || | |
| 1201 dwRet == FDE_XMLSYNTAXSTATUS_EOS) { | |
| 1202 break; | |
| 1203 } | |
| 1204 if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) { | |
| 1205 break; | |
| 1206 } | |
| 1207 } | |
| 1208 return m_pParser->GetStatus(); | |
| 1209 } | |
| 1210 CFDE_XMLSAXParser::CFDE_XMLSAXParser(FDE_XMLREADERHANDLER* pHandler, | |
| 1211 IFDE_XMLSyntaxParser* pParser) | |
| 1212 : m_pHandler(pHandler), | |
| 1213 m_pParser(pParser), | |
| 1214 m_TagStack(16), | |
| 1215 m_pTagTop(NULL), | |
| 1216 m_ws1(), | |
| 1217 m_ws2() {} | |
| 1218 CFDE_XMLSAXParser::~CFDE_XMLSAXParser() { | |
| 1219 m_TagStack.RemoveAll(); | |
| 1220 m_ws1.Empty(); | |
| 1221 m_ws2.Empty(); | |
| 1222 } | |
| 1223 int32_t CFDE_XMLSAXParser::DoParser(IFX_Pause* pPause) { | |
| 1224 FX_DWORD dwRet = 0; | |
| 1225 int32_t iCount = 0; | |
| 1226 while (TRUE) { | |
| 1227 dwRet = m_pParser->DoSyntaxParse(); | |
| 1228 switch (dwRet) { | |
| 1229 case FDE_XMLSYNTAXSTATUS_ElementBreak: | |
| 1230 if (m_pTagTop == NULL) { | |
| 1231 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1232 break; | |
| 1233 } | |
| 1234 if (m_pTagTop->eType == FDE_XMLNODE_Element) { | |
| 1235 m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName); | |
| 1236 } | |
| 1237 break; | |
| 1238 case FDE_XMLSYNTAXSTATUS_ElementClose: | |
| 1239 if (m_pTagTop == NULL || m_pTagTop->eType != FDE_XMLNODE_Element) { | |
| 1240 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1241 break; | |
| 1242 } | |
| 1243 m_pParser->GetTagName(m_ws1); | |
| 1244 if (m_ws1.GetLength() > 0 && m_ws1.Compare(m_pTagTop->wsTagName) != 0) { | |
| 1245 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1246 break; | |
| 1247 } else if (m_ws1.GetLength() == 0) { | |
| 1248 m_pHandler->OnTagBreak(m_pHandler, m_pTagTop->wsTagName); | |
| 1249 } | |
| 1250 m_pHandler->OnTagClose(m_pHandler, m_pTagTop->wsTagName); | |
| 1251 Pop(); | |
| 1252 iCount++; | |
| 1253 break; | |
| 1254 case FDE_XMLSYNTAXSTATUS_TargetName: { | |
| 1255 m_pParser->GetTargetName(m_ws1); | |
| 1256 CFDE_XMLTAG xmlTag; | |
| 1257 xmlTag.wsTagName = m_ws1; | |
| 1258 xmlTag.eType = FDE_XMLNODE_Instruction; | |
| 1259 Push(xmlTag); | |
| 1260 m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Instruction, | |
| 1261 m_pTagTop->wsTagName); | |
| 1262 m_ws1.Empty(); | |
| 1263 } break; | |
| 1264 case FDE_XMLSYNTAXSTATUS_TagName: { | |
| 1265 m_pParser->GetTargetName(m_ws1); | |
| 1266 CFDE_XMLTAG xmlTag; | |
| 1267 xmlTag.wsTagName = m_ws1; | |
| 1268 xmlTag.eType = FDE_XMLNODE_Element; | |
| 1269 Push(xmlTag); | |
| 1270 m_pHandler->OnTagEnter(m_pHandler, FDE_XMLNODE_Element, | |
| 1271 m_pTagTop->wsTagName); | |
| 1272 } break; | |
| 1273 case FDE_XMLSYNTAXSTATUS_AttriName: | |
| 1274 m_pParser->GetTargetName(m_ws1); | |
| 1275 break; | |
| 1276 case FDE_XMLSYNTAXSTATUS_AttriValue: | |
| 1277 m_pParser->GetAttributeName(m_ws2); | |
| 1278 if (m_pTagTop == NULL) { | |
| 1279 dwRet = FDE_XMLSYNTAXSTATUS_Error; | |
| 1280 break; | |
| 1281 } | |
| 1282 if (m_pTagTop->eType == FDE_XMLNODE_Element) { | |
| 1283 m_pHandler->OnAttribute(m_pHandler, m_ws1, m_ws2); | |
| 1284 } | |
| 1285 m_ws1.Empty(); | |
| 1286 break; | |
| 1287 case FDE_XMLSYNTAXSTATUS_CData: | |
| 1288 m_pParser->GetTextData(m_ws1); | |
| 1289 m_pHandler->OnData(m_pHandler, FDE_XMLNODE_CharData, m_ws1); | |
| 1290 break; | |
| 1291 case FDE_XMLSYNTAXSTATUS_Text: | |
| 1292 m_pParser->GetTextData(m_ws1); | |
| 1293 m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Text, m_ws1); | |
| 1294 break; | |
| 1295 case FDE_XMLSYNTAXSTATUS_TargetData: | |
| 1296 m_pParser->GetTargetData(m_ws1); | |
| 1297 m_pHandler->OnData(m_pHandler, FDE_XMLNODE_Instruction, m_ws1); | |
| 1298 m_ws1.Empty(); | |
| 1299 break; | |
| 1300 default: | |
| 1301 break; | |
| 1302 } | |
| 1303 if (dwRet == FDE_XMLSYNTAXSTATUS_Error || | |
| 1304 dwRet == FDE_XMLSYNTAXSTATUS_EOS) { | |
| 1305 break; | |
| 1306 } | |
| 1307 if (pPause != NULL && iCount > 500 && pPause->NeedToPauseNow()) { | |
| 1308 break; | |
| 1309 } | |
| 1310 } | |
| 1311 return m_pParser->GetStatus(); | |
| 1312 } | |
| 1313 inline void CFDE_XMLSAXParser::Push(const CFDE_XMLTAG& xmlTag) { | |
| 1314 m_TagStack.Push(xmlTag); | |
| 1315 m_pTagTop = m_TagStack.GetTopElement(); | |
| 1316 } | |
| 1317 inline void CFDE_XMLSAXParser::Pop() { | |
| 1318 m_TagStack.Pop(); | |
| 1319 m_pTagTop = m_TagStack.GetTopElement(); | |
| 1320 } | |
| 1321 | |
| 1322 CFDE_BlockBuffer::CFDE_BlockBuffer(int32_t iAllocStep) | |
| 1323 : m_iDataLength(0), | |
| 1324 m_iBufferSize(0), | |
| 1325 m_iAllocStep(iAllocStep), | |
| 1326 m_iStartPosition(0) {} | |
| 1327 CFDE_BlockBuffer::~CFDE_BlockBuffer() { | |
| 1328 ClearBuffer(); | |
| 1329 } | |
| 1330 FX_WCHAR* CFDE_BlockBuffer::GetAvailableBlock(int32_t& iIndexInBlock) { | |
| 1331 iIndexInBlock = 0; | |
| 1332 if (!m_BlockArray.GetSize()) { | |
| 1333 return nullptr; | |
| 1334 } | |
| 1335 int32_t iRealIndex = m_iStartPosition + m_iDataLength; | |
| 1336 if (iRealIndex == m_iBufferSize) { | |
| 1337 FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep); | |
| 1338 m_BlockArray.Add(pBlock); | |
| 1339 m_iBufferSize += m_iAllocStep; | |
| 1340 return pBlock; | |
| 1341 } | |
| 1342 iIndexInBlock = iRealIndex % m_iAllocStep; | |
| 1343 return (FX_WCHAR*)m_BlockArray[iRealIndex / m_iAllocStep]; | |
| 1344 } | |
| 1345 FX_BOOL CFDE_BlockBuffer::InitBuffer(int32_t iBufferSize) { | |
| 1346 ClearBuffer(); | |
| 1347 int32_t iNumOfBlock = (iBufferSize - 1) / m_iAllocStep + 1; | |
| 1348 for (int32_t i = 0; i < iNumOfBlock; i++) { | |
| 1349 m_BlockArray.Add(FX_Alloc(FX_WCHAR, m_iAllocStep)); | |
| 1350 } | |
| 1351 m_iBufferSize = iNumOfBlock * m_iAllocStep; | |
| 1352 return TRUE; | |
| 1353 } | |
| 1354 void CFDE_BlockBuffer::SetTextChar(int32_t iIndex, FX_WCHAR ch) { | |
| 1355 if (iIndex < 0) { | |
| 1356 return; | |
| 1357 } | |
| 1358 int32_t iRealIndex = m_iStartPosition + iIndex; | |
| 1359 int32_t iBlockIndex = iRealIndex / m_iAllocStep; | |
| 1360 int32_t iInnerIndex = iRealIndex % m_iAllocStep; | |
| 1361 int32_t iBlockSize = m_BlockArray.GetSize(); | |
| 1362 if (iBlockIndex >= iBlockSize) { | |
| 1363 int32_t iNewBlocks = iBlockIndex - iBlockSize + 1; | |
| 1364 do { | |
| 1365 FX_WCHAR* pBlock = FX_Alloc(FX_WCHAR, m_iAllocStep); | |
| 1366 m_BlockArray.Add(pBlock); | |
| 1367 m_iBufferSize += m_iAllocStep; | |
| 1368 } while (--iNewBlocks); | |
| 1369 } | |
| 1370 FX_WCHAR* pTextData = (FX_WCHAR*)m_BlockArray[iBlockIndex]; | |
| 1371 *(pTextData + iInnerIndex) = ch; | |
| 1372 if (m_iDataLength <= iIndex) { | |
| 1373 m_iDataLength = iIndex + 1; | |
| 1374 } | |
| 1375 } | |
| 1376 int32_t CFDE_BlockBuffer::DeleteTextChars(int32_t iCount, FX_BOOL bDirection) { | |
| 1377 if (iCount <= 0) { | |
| 1378 return m_iDataLength; | |
| 1379 } | |
| 1380 if (iCount >= m_iDataLength) { | |
| 1381 Reset(FALSE); | |
| 1382 return 0; | |
| 1383 } | |
| 1384 if (bDirection) { | |
| 1385 m_iStartPosition += iCount; | |
| 1386 m_iDataLength -= iCount; | |
| 1387 } else { | |
| 1388 m_iDataLength -= iCount; | |
| 1389 } | |
| 1390 return m_iDataLength; | |
| 1391 } | |
| 1392 void CFDE_BlockBuffer::GetTextData(CFX_WideString& wsTextData, | |
| 1393 int32_t iStart, | |
| 1394 int32_t iLength) const { | |
| 1395 wsTextData.Empty(); | |
| 1396 int32_t iMaybeDataLength = m_iBufferSize - 1 - m_iStartPosition; | |
| 1397 if (iStart < 0 || iStart > iMaybeDataLength) { | |
| 1398 return; | |
| 1399 } | |
| 1400 if (iLength == -1 || iLength > iMaybeDataLength) { | |
| 1401 iLength = iMaybeDataLength; | |
| 1402 } | |
| 1403 if (iLength <= 0) { | |
| 1404 return; | |
| 1405 } | |
| 1406 FX_WCHAR* pBuf = wsTextData.GetBuffer(iLength); | |
| 1407 if (!pBuf) { | |
| 1408 return; | |
| 1409 } | |
| 1410 int32_t iStartBlockIndex = 0; | |
| 1411 int32_t iStartInnerIndex = 0; | |
| 1412 TextDataIndex2BufIndex(iStart, iStartBlockIndex, iStartInnerIndex); | |
| 1413 int32_t iEndBlockIndex = 0; | |
| 1414 int32_t iEndInnerIndex = 0; | |
| 1415 TextDataIndex2BufIndex(iStart + iLength, iEndBlockIndex, iEndInnerIndex); | |
| 1416 int32_t iPointer = 0; | |
| 1417 for (int32_t i = iStartBlockIndex; i <= iEndBlockIndex; i++) { | |
| 1418 int32_t iBufferPointer = 0; | |
| 1419 int32_t iCopyLength = m_iAllocStep; | |
| 1420 if (i == iStartBlockIndex) { | |
| 1421 iCopyLength -= iStartInnerIndex; | |
| 1422 iBufferPointer = iStartInnerIndex; | |
| 1423 } | |
| 1424 if (i == iEndBlockIndex) { | |
| 1425 iCopyLength -= ((m_iAllocStep - 1) - iEndInnerIndex); | |
| 1426 } | |
| 1427 FX_WCHAR* pBlockBuf = (FX_WCHAR*)m_BlockArray[i]; | |
| 1428 FXSYS_memcpy(pBuf + iPointer, pBlockBuf + iBufferPointer, | |
| 1429 iCopyLength * sizeof(FX_WCHAR)); | |
| 1430 iPointer += iCopyLength; | |
| 1431 } | |
| 1432 wsTextData.ReleaseBuffer(iLength); | |
| 1433 } | |
| 1434 void CFDE_BlockBuffer::TextDataIndex2BufIndex(const int32_t iIndex, | |
| 1435 int32_t& iBlockIndex, | |
| 1436 int32_t& iInnerIndex) const { | |
| 1437 FXSYS_assert(iIndex >= 0); | |
| 1438 int32_t iRealIndex = m_iStartPosition + iIndex; | |
| 1439 iBlockIndex = iRealIndex / m_iAllocStep; | |
| 1440 iInnerIndex = iRealIndex % m_iAllocStep; | |
| 1441 } | |
| 1442 void CFDE_BlockBuffer::ClearBuffer() { | |
| 1443 m_iBufferSize = 0; | |
| 1444 int32_t iSize = m_BlockArray.GetSize(); | |
| 1445 for (int32_t i = 0; i < iSize; i++) { | |
| 1446 FX_Free(m_BlockArray[i]); | |
| 1447 m_BlockArray[i] = NULL; | |
| 1448 } | |
| 1449 m_BlockArray.RemoveAll(); | |
| 1450 } | |
| 1451 | |
| 1452 IFDE_XMLSyntaxParser* IFDE_XMLSyntaxParser::Create() { | |
| 1453 return new CFDE_XMLSyntaxParser; | |
| 1454 } | |
| 1455 | |
| 1456 CFDE_XMLSyntaxParser::CFDE_XMLSyntaxParser() | |
| 1457 : m_pStream(nullptr), | |
| 1458 m_iXMLPlaneSize(-1), | |
| 1459 m_iCurrentPos(0), | |
| 1460 m_iCurrentNodeNum(-1), | |
| 1461 m_iLastNodeNum(-1), | |
| 1462 m_iParsedChars(0), | |
| 1463 m_iParsedBytes(0), | |
| 1464 m_pBuffer(nullptr), | |
| 1465 m_iBufferChars(0), | |
| 1466 m_bEOS(FALSE), | |
| 1467 m_pStart(nullptr), | |
| 1468 m_pEnd(nullptr), | |
| 1469 m_XMLNodeStack(16), | |
| 1470 m_iAllocStep(m_BlockBuffer.GetAllocStep()), | |
| 1471 m_iDataLength(m_BlockBuffer.GetDataLengthRef()), | |
| 1472 m_pCurrentBlock(nullptr), | |
| 1473 m_iIndexInBlock(0), | |
| 1474 m_iTextDataLength(0), | |
| 1475 m_dwStatus(FDE_XMLSYNTAXSTATUS_None), | |
| 1476 m_dwMode(FDE_XMLSYNTAXMODE_Text), | |
| 1477 m_wQuotationMark(0), | |
| 1478 m_iEntityStart(-1), | |
| 1479 m_SkipStack(16) { | |
| 1480 m_CurNode.iNodeNum = -1; | |
| 1481 m_CurNode.eNodeType = FDE_XMLNODE_Unknown; | |
| 1482 } | |
| 1483 void CFDE_XMLSyntaxParser::Init(IFX_Stream* pStream, | |
| 1484 int32_t iXMLPlaneSize, | |
| 1485 int32_t iTextDataSize) { | |
| 1486 FXSYS_assert(m_pStream == NULL && m_pBuffer == NULL); | |
| 1487 FXSYS_assert(pStream != NULL && iXMLPlaneSize > 0); | |
| 1488 int32_t iStreamLength = pStream->GetLength(); | |
| 1489 FXSYS_assert(iStreamLength > 0); | |
| 1490 m_pStream = pStream; | |
| 1491 m_iXMLPlaneSize = std::min(iXMLPlaneSize, iStreamLength); | |
| 1492 uint8_t bom[4]; | |
| 1493 m_iCurrentPos = m_pStream->GetBOM(bom); | |
| 1494 FXSYS_assert(m_pBuffer == NULL); | |
| 1495 m_pBuffer = FX_Alloc(FX_WCHAR, m_iXMLPlaneSize); | |
| 1496 m_pStart = m_pEnd = m_pBuffer; | |
| 1497 FXSYS_assert(!m_BlockBuffer.IsInitialized()); | |
| 1498 m_BlockBuffer.InitBuffer(); | |
| 1499 m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); | |
| 1500 m_iParsedBytes = m_iParsedChars = 0; | |
| 1501 m_iBufferChars = 0; | |
| 1502 } | |
| 1503 FX_DWORD CFDE_XMLSyntaxParser::DoSyntaxParse() { | |
| 1504 if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error || | |
| 1505 m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) { | |
| 1506 return m_dwStatus; | |
| 1507 } | |
| 1508 FXSYS_assert(m_pStream && m_pBuffer && m_BlockBuffer.IsInitialized()); | |
| 1509 int32_t iStreamLength = m_pStream->GetLength(); | |
| 1510 int32_t iPos; | |
| 1511 FX_WCHAR ch; | |
| 1512 FX_DWORD dwStatus = FDE_XMLSYNTAXSTATUS_None; | |
| 1513 while (TRUE) { | |
| 1514 if (m_pStart >= m_pEnd) { | |
| 1515 if (m_bEOS || m_iCurrentPos >= iStreamLength) { | |
| 1516 m_dwStatus = FDE_XMLSYNTAXSTATUS_EOS; | |
| 1517 return m_dwStatus; | |
| 1518 } | |
| 1519 m_iParsedChars += (m_pEnd - m_pBuffer); | |
| 1520 m_iParsedBytes = m_iCurrentPos; | |
| 1521 if (m_pStream->GetPosition() != m_iCurrentPos) { | |
| 1522 m_pStream->Seek(FX_STREAMSEEK_Begin, m_iCurrentPos); | |
| 1523 } | |
| 1524 m_iBufferChars = | |
| 1525 m_pStream->ReadString(m_pBuffer, m_iXMLPlaneSize, m_bEOS); | |
| 1526 iPos = m_pStream->GetPosition(); | |
| 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_XMLNODE* 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_XMLNODE* 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 | |
| 1973 CFDE_XMLSyntaxParser::~CFDE_XMLSyntaxParser() { | |
| 1974 if (m_pCurrentBlock) { | |
| 1975 m_pCurrentBlock = NULL; | |
| 1976 } | |
| 1977 FX_Free(m_pBuffer); | |
| 1978 } | |
| 1979 | |
| 1980 int32_t CFDE_XMLSyntaxParser::GetStatus() const { | |
| 1981 if (m_pStream == NULL) { | |
| 1982 return -1; | |
| 1983 } | |
| 1984 int32_t iStreamLength = m_pStream->GetLength(); | |
| 1985 if (iStreamLength < 1) { | |
| 1986 return 100; | |
| 1987 } | |
| 1988 if (m_dwStatus == FDE_XMLSYNTAXSTATUS_Error) { | |
| 1989 return -1; | |
| 1990 } | |
| 1991 if (m_dwStatus == FDE_XMLSYNTAXSTATUS_EOS) { | |
| 1992 return 100; | |
| 1993 } | |
| 1994 return m_iParsedBytes * 100 / iStreamLength; | |
| 1995 } | |
| 1996 static int32_t FX_GetUTF8EncodeLength(const FX_WCHAR* pSrc, int32_t iSrcLen) { | |
| 1997 FX_DWORD unicode = 0; | |
| 1998 int32_t iDstNum = 0; | |
| 1999 while (iSrcLen-- > 0) { | |
| 2000 unicode = *pSrc++; | |
| 2001 int nbytes = 0; | |
| 2002 if ((FX_DWORD)unicode < 0x80) { | |
| 2003 nbytes = 1; | |
| 2004 } else if ((FX_DWORD)unicode < 0x800) { | |
| 2005 nbytes = 2; | |
| 2006 } else if ((FX_DWORD)unicode < 0x10000) { | |
| 2007 nbytes = 3; | |
| 2008 } else if ((FX_DWORD)unicode < 0x200000) { | |
| 2009 nbytes = 4; | |
| 2010 } else if ((FX_DWORD)unicode < 0x4000000) { | |
| 2011 nbytes = 5; | |
| 2012 } else { | |
| 2013 nbytes = 6; | |
| 2014 } | |
| 2015 iDstNum += nbytes; | |
| 2016 } | |
| 2017 return iDstNum; | |
| 2018 } | |
| 2019 FX_FILESIZE CFDE_XMLSyntaxParser::GetCurrentBinaryPos() const { | |
| 2020 if (m_pStream == NULL) { | |
| 2021 return 0; | |
| 2022 } | |
| 2023 int32_t nSrcLen = m_pStart - m_pBuffer; | |
| 2024 int32_t nDstLen = FX_GetUTF8EncodeLength(m_pBuffer, nSrcLen); | |
| 2025 return m_iParsedBytes + nDstLen; | |
| 2026 } | |
| 2027 | |
| 2028 void CFDE_XMLSyntaxParser::ParseTextChar(FX_WCHAR ch) { | |
| 2029 if (m_iIndexInBlock == m_iAllocStep) { | |
| 2030 m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); | |
| 2031 if (!m_pCurrentBlock) { | |
| 2032 return; | |
| 2033 } | |
| 2034 } | |
| 2035 m_pCurrentBlock[m_iIndexInBlock++] = ch; | |
| 2036 m_iDataLength++; | |
| 2037 if (m_iEntityStart > -1 && ch == L';') { | |
| 2038 CFX_WideString csEntity; | |
| 2039 m_BlockBuffer.GetTextData(csEntity, m_iEntityStart + 1, | |
| 2040 (m_iDataLength - 1) - m_iEntityStart - 1); | |
| 2041 int32_t iLen = csEntity.GetLength(); | |
| 2042 if (iLen > 0) { | |
| 2043 if (csEntity[0] == L'#') { | |
| 2044 ch = 0; | |
| 2045 FX_WCHAR w; | |
| 2046 if (iLen > 1 && csEntity[1] == L'x') { | |
| 2047 for (int32_t i = 2; i < iLen; i++) { | |
| 2048 w = csEntity[i]; | |
| 2049 if (w >= L'0' && w <= L'9') { | |
| 2050 ch = (ch << 4) + w - L'0'; | |
| 2051 } else if (w >= L'A' && w <= L'F') { | |
| 2052 ch = (ch << 4) + w - 55; | |
| 2053 } else if (w >= L'a' && w <= L'f') { | |
| 2054 ch = (ch << 4) + w - 87; | |
| 2055 } else { | |
| 2056 break; | |
| 2057 } | |
| 2058 } | |
| 2059 } else { | |
| 2060 for (int32_t i = 1; i < iLen; i++) { | |
| 2061 w = csEntity[i]; | |
| 2062 if (w < L'0' || w > L'9') { | |
| 2063 break; | |
| 2064 } | |
| 2065 ch = ch * 10 + w - L'0'; | |
| 2066 } | |
| 2067 } | |
| 2068 if (ch != 0) { | |
| 2069 m_BlockBuffer.SetTextChar(m_iEntityStart, ch); | |
| 2070 m_iEntityStart++; | |
| 2071 } | |
| 2072 } else { | |
| 2073 if (csEntity.Compare(L"amp") == 0) { | |
| 2074 m_BlockBuffer.SetTextChar(m_iEntityStart, L'&'); | |
| 2075 m_iEntityStart++; | |
| 2076 } else if (csEntity.Compare(L"lt") == 0) { | |
| 2077 m_BlockBuffer.SetTextChar(m_iEntityStart, L'<'); | |
| 2078 m_iEntityStart++; | |
| 2079 } else if (csEntity.Compare(L"gt") == 0) { | |
| 2080 m_BlockBuffer.SetTextChar(m_iEntityStart, L'>'); | |
| 2081 m_iEntityStart++; | |
| 2082 } else if (csEntity.Compare(L"apos") == 0) { | |
| 2083 m_BlockBuffer.SetTextChar(m_iEntityStart, L'\''); | |
| 2084 m_iEntityStart++; | |
| 2085 } else if (csEntity.Compare(L"quot") == 0) { | |
| 2086 m_BlockBuffer.SetTextChar(m_iEntityStart, L'\"'); | |
| 2087 m_iEntityStart++; | |
| 2088 } | |
| 2089 } | |
| 2090 } | |
| 2091 m_BlockBuffer.DeleteTextChars(m_iDataLength - m_iEntityStart, FALSE); | |
| 2092 m_pCurrentBlock = m_BlockBuffer.GetAvailableBlock(m_iIndexInBlock); | |
| 2093 m_iEntityStart = -1; | |
| 2094 } else { | |
| 2095 if (m_iEntityStart < 0 && ch == L'&') { | |
| 2096 m_iEntityStart = m_iDataLength - 1; | |
| 2097 } | |
| 2098 } | |
| 2099 m_pStart++; | |
| 2100 } | |
| OLD | NEW |