| 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 <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"&"); | |
| 411 wsValue.Replace(L"<", L"<"); | |
| 412 wsValue.Replace(L">", L">"); | |
| 413 wsValue.Replace(L"\'", L"'"); | |
| 414 wsValue.Replace(L"\"", L"""); | |
| 415 ws += wsValue; | |
| 416 ws += L"\""; | |
| 417 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 418 } | |
| 419 CFX_WideStringArray& targetdata = pInstruction->m_TargetData; | |
| 420 iCount = targetdata.GetSize(); | |
| 421 for (i = 0; i < iCount; i++) { | |
| 422 ws = L" \""; | |
| 423 ws += targetdata[i]; | |
| 424 ws += L"\""; | |
| 425 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 426 } | |
| 427 ws = L"?>"; | |
| 428 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 429 } | |
| 430 } break; | |
| 431 case FDE_XMLNODE_Element: { | |
| 432 CFX_WideString ws; | |
| 433 ws = L"<"; | |
| 434 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 435 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 436 CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes; | |
| 437 int32_t iCount = attributes.GetSize(); | |
| 438 CFX_WideString wsValue; | |
| 439 for (int32_t i = 0; i < iCount; i += 2) { | |
| 440 ws = L" "; | |
| 441 ws += attributes[i]; | |
| 442 ws += L"=\""; | |
| 443 wsValue = attributes[i + 1]; | |
| 444 wsValue.Replace(L"&", L"&"); | |
| 445 wsValue.Replace(L"<", L"<"); | |
| 446 wsValue.Replace(L">", L">"); | |
| 447 wsValue.Replace(L"\'", L"'"); | |
| 448 wsValue.Replace(L"\"", L"""); | |
| 449 ws += wsValue; | |
| 450 ws += L"\""; | |
| 451 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 452 } | |
| 453 if (pNode->m_pChild == NULL) { | |
| 454 ws = L"\n/>"; | |
| 455 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 456 } else { | |
| 457 ws = L"\n>"; | |
| 458 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 459 CFDE_XMLNode* pChild = pNode->m_pChild; | |
| 460 while (pChild != NULL) { | |
| 461 pChild->SaveXMLNode(pXMLStream); | |
| 462 pChild = pChild->m_pNext; | |
| 463 } | |
| 464 ws = L"</"; | |
| 465 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 466 ws += L"\n>"; | |
| 467 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 468 } | |
| 469 } break; | |
| 470 case FDE_XMLNODE_Text: { | |
| 471 CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; | |
| 472 ws.Replace(L"&", L"&"); | |
| 473 ws.Replace(L"<", L"<"); | |
| 474 ws.Replace(L">", L">"); | |
| 475 ws.Replace(L"\'", L"'"); | |
| 476 ws.Replace(L"\"", L"""); | |
| 477 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 478 } break; | |
| 479 case FDE_XMLNODE_CharData: { | |
| 480 CFX_WideString ws = L"<![CDATA["; | |
| 481 ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; | |
| 482 ws += L"]]>"; | |
| 483 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 484 } break; | |
| 485 case FDE_XMLNODE_Unknown: | |
| 486 break; | |
| 487 default: | |
| 488 break; | |
| 489 } | |
| 490 } | |
| 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"&"); | |
| 981 wsValue.Replace(L"<", L"<"); | |
| 982 wsValue.Replace(L">", L">"); | |
| 983 wsValue.Replace(L"\'", L"'"); | |
| 984 wsValue.Replace(L"\"", L"""); | |
| 985 ws += wsValue; | |
| 986 ws += L"\""; | |
| 987 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 988 } | |
| 989 CFX_WideStringArray& targetdata = pInstruction->m_TargetData; | |
| 990 iCount = targetdata.GetSize(); | |
| 991 for (i = 0; i < iCount; i++) { | |
| 992 ws = L" \""; | |
| 993 ws += targetdata[i]; | |
| 994 ws += L"\""; | |
| 995 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 996 } | |
| 997 ws = L"?>"; | |
| 998 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 999 } | |
| 1000 } break; | |
| 1001 case FDE_XMLNODE_Element: { | |
| 1002 CFX_WideString ws; | |
| 1003 ws = L"<"; | |
| 1004 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 1005 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1006 CFX_WideStringArray& attributes = ((CFDE_XMLElement*)pNode)->m_Attributes; | |
| 1007 int32_t iCount = attributes.GetSize(); | |
| 1008 CFX_WideString wsValue; | |
| 1009 for (int32_t i = 0; i < iCount; i += 2) { | |
| 1010 ws = L" "; | |
| 1011 ws += attributes[i]; | |
| 1012 ws += L"=\""; | |
| 1013 wsValue = attributes[i + 1]; | |
| 1014 wsValue.Replace(L"&", L"&"); | |
| 1015 wsValue.Replace(L"<", L"<"); | |
| 1016 wsValue.Replace(L">", L">"); | |
| 1017 wsValue.Replace(L"\'", L"'"); | |
| 1018 wsValue.Replace(L"\"", L"""); | |
| 1019 ws += wsValue; | |
| 1020 ws += L"\""; | |
| 1021 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1022 } | |
| 1023 if (pNode->m_pChild == NULL) { | |
| 1024 ws = L"\n/>"; | |
| 1025 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1026 } else { | |
| 1027 ws = L"\n>"; | |
| 1028 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1029 CFDE_XMLNode* pChild = pNode->m_pChild; | |
| 1030 while (pChild != NULL) { | |
| 1031 SaveXMLNode(pXMLStream, (IFDE_XMLNode*)pChild); | |
| 1032 pChild = pChild->m_pNext; | |
| 1033 } | |
| 1034 ws = L"</"; | |
| 1035 ws += ((CFDE_XMLElement*)pNode)->m_wsTag; | |
| 1036 ws += L"\n>"; | |
| 1037 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1038 } | |
| 1039 } break; | |
| 1040 case FDE_XMLNODE_Text: { | |
| 1041 CFX_WideString ws = ((CFDE_XMLText*)pNode)->m_wsText; | |
| 1042 ws.Replace(L"&", L"&"); | |
| 1043 ws.Replace(L"<", L"<"); | |
| 1044 ws.Replace(L">", L">"); | |
| 1045 ws.Replace(L"\'", L"'"); | |
| 1046 ws.Replace(L"\"", L"""); | |
| 1047 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1048 } break; | |
| 1049 case FDE_XMLNODE_CharData: { | |
| 1050 CFX_WideString ws = L"<![CDATA["; | |
| 1051 ws += ((CFDE_XMLCharData*)pNode)->m_wsCharData; | |
| 1052 ws += L"]]>"; | |
| 1053 pXMLStream->WriteString(ws, ws.GetLength()); | |
| 1054 } break; | |
| 1055 case FDE_XMLNODE_Unknown: | |
| 1056 break; | |
| 1057 default: | |
| 1058 break; | |
| 1059 } | |
| 1060 } | |
| 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 | |
| OLD | NEW |