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/fgas/src/fgas_base.h"
10 #include "fx_sax_imp.h"
11 
12 namespace {
13 
14 const FX_DWORD kSaxFileBufSize = 32768;
15 
16 }  // namespace
17 
FX_SAXReader_Create()18 IFX_SAXReader* FX_SAXReader_Create() {
19   return new CFX_SAXReader;
20 }
CFX_SAXFile()21 CFX_SAXFile::CFX_SAXFile()
22     : m_pFile(NULL),
23       m_dwStart(0),
24       m_dwEnd(0),
25       m_dwCur(0),
26       m_pBuf(NULL),
27       m_dwBufSize(0),
28       m_dwBufIndex(0) {}
StartFile(IFX_FileRead * pFile,FX_DWORD dwStart,FX_DWORD dwLen)29 FX_BOOL CFX_SAXFile::StartFile(IFX_FileRead* pFile,
30                                FX_DWORD dwStart,
31                                FX_DWORD dwLen) {
32   FXSYS_assert(m_pFile == NULL && pFile != NULL);
33   FX_DWORD dwSize = pFile->GetSize();
34   if (dwStart >= dwSize) {
35     return FALSE;
36   }
37   if (dwLen == -1 || dwStart + dwLen > dwSize) {
38     dwLen = dwSize - dwStart;
39   }
40   if (dwLen == 0) {
41     return FALSE;
42   }
43   m_dwBufSize = std::min(dwLen, kSaxFileBufSize);
44   m_pBuf = FX_Alloc(uint8_t, m_dwBufSize);
45   if (!pFile->ReadBlock(m_pBuf, dwStart, m_dwBufSize)) {
46     return FALSE;
47   }
48   m_dwStart = dwStart;
49   m_dwEnd = dwStart + dwLen;
50   m_dwCur = dwStart;
51   m_pFile = pFile;
52   m_dwBufIndex = 0;
53   return TRUE;
54 }
ReadNextBlock()55 FX_BOOL CFX_SAXFile::ReadNextBlock() {
56   FXSYS_assert(m_pFile != NULL);
57   FX_DWORD dwSize = m_dwEnd - m_dwCur;
58   if (dwSize == 0) {
59     return FALSE;
60   }
61   m_dwBufSize = std::min(dwSize, kSaxFileBufSize);
62   if (!m_pFile->ReadBlock(m_pBuf, m_dwCur, m_dwBufSize)) {
63     return FALSE;
64   }
65   m_dwBufIndex = 0;
66   return TRUE;
67 }
Reset()68 void CFX_SAXFile::Reset() {
69   if (m_pBuf) {
70     FX_Free(m_pBuf);
71     m_pBuf = NULL;
72   }
73   m_pFile = NULL;
74 }
CFX_SAXReader()75 CFX_SAXReader::CFX_SAXReader()
76     : m_File(),
77       m_pHandler(nullptr),
78       m_iState(-1),
79       m_pRoot(nullptr),
80       m_pCurItem(nullptr),
81       m_dwItemID(0),
82       m_iDataSize(256),
83       m_iNameSize(256),
84       m_dwParseMode(0),
85       m_pCommentContext(nullptr) {
86   m_pszData = FX_Alloc(uint8_t, m_iDataSize);
87   m_pszName = FX_Alloc(uint8_t, m_iNameSize);
88 }
~CFX_SAXReader()89 CFX_SAXReader::~CFX_SAXReader() {
90   Reset();
91   if (m_pszData) {
92     FX_Free(m_pszData);
93     m_pszData = NULL;
94   }
95   if (m_pszName) {
96     FX_Free(m_pszName);
97     m_pszName = NULL;
98   }
99 }
Reset()100 void CFX_SAXReader::Reset() {
101   m_File.Reset();
102   CFX_SAXItem* pItem = m_pRoot;
103   while (pItem) {
104     CFX_SAXItem* pNext = pItem->m_pNext;
105     delete pItem;
106     pItem = pNext;
107   }
108   m_pRoot = NULL;
109   m_pCurItem = NULL;
110   m_dwItemID = 0;
111   m_SkipStack.RemoveAll();
112   m_SkipChar = 0;
113   m_iDataLength = 0;
114   m_iEntityStart = -1;
115   m_iNameLength = 0;
116   m_iDataPos = 0;
117   if (m_pCommentContext) {
118     delete m_pCommentContext;
119     m_pCommentContext = NULL;
120   }
121 }
Push()122 inline void CFX_SAXReader::Push() {
123   CFX_SAXItem* pNew = new CFX_SAXItem;
124   pNew->m_dwID = ++m_dwItemID;
125   pNew->m_bSkip = m_pCurItem->m_bSkip;
126   pNew->m_pPrev = m_pCurItem;
127   m_pCurItem->m_pNext = pNew;
128   m_pCurItem = pNew;
129 }
Pop()130 inline void CFX_SAXReader::Pop() {
131   if (!m_pCurItem) {
132     return;
133   }
134   CFX_SAXItem* pPrev = m_pCurItem->m_pPrev;
135   pPrev->m_pNext = NULL;
136   delete m_pCurItem;
137   m_pCurItem = pPrev;
138 }
AppendData(uint8_t ch)139 inline void CFX_SAXReader::AppendData(uint8_t ch) {
140   ReallocDataBuffer();
141   m_pszData[m_iDataPos++] = ch;
142 }
AppendName(uint8_t ch)143 inline void CFX_SAXReader::AppendName(uint8_t ch) {
144   ReallocNameBuffer();
145   m_pszName[m_iDataPos++] = ch;
146 }
ReallocDataBuffer()147 void CFX_SAXReader::ReallocDataBuffer() {
148   if (m_iDataPos < m_iDataSize) {
149     return;
150   }
151   if (m_iDataSize <= 1024 * 1024) {
152     m_iDataSize *= 2;
153   } else {
154     m_iDataSize += 1024 * 1024;
155   }
156   m_pszData = (uint8_t*)FX_Realloc(uint8_t, m_pszData, m_iDataSize);
157 }
ReallocNameBuffer()158 void CFX_SAXReader::ReallocNameBuffer() {
159   if (m_iDataPos < m_iNameSize) {
160     return;
161   }
162   if (m_iNameSize <= 1024 * 1024) {
163     m_iNameSize *= 2;
164   } else {
165     m_iNameSize += 1024 * 1024;
166   }
167   m_pszName = (uint8_t*)FX_Realloc(uint8_t, m_pszName, m_iNameSize);
168 }
SkipSpace(uint8_t ch)169 inline FX_BOOL CFX_SAXReader::SkipSpace(uint8_t ch) {
170   return (m_dwParseMode & FX_SAXPARSEMODE_NotSkipSpace) == 0 && ch < 0x21;
171 }
StartParse(IFX_FileRead * pFile,FX_DWORD dwStart,FX_DWORD dwLen,FX_DWORD dwParseMode)172 int32_t CFX_SAXReader::StartParse(IFX_FileRead* pFile,
173                                   FX_DWORD dwStart,
174                                   FX_DWORD dwLen,
175                                   FX_DWORD dwParseMode) {
176   m_iState = -1;
177   Reset();
178   if (!m_File.StartFile(pFile, dwStart, dwLen)) {
179     return -1;
180   }
181   m_iState = 0;
182   m_eMode = FX_SAXMODE_Text;
183   m_ePrevMode = FX_SAXMODE_Text;
184   m_bCharData = FALSE;
185   m_dwDataOffset = 0;
186   m_pRoot = m_pCurItem = new CFX_SAXItem;
187   m_pCurItem->m_dwID = ++m_dwItemID;
188   m_dwParseMode = dwParseMode;
189   return 0;
190 }
191 typedef void (CFX_SAXReader::*FX_SAXReader_LPFParse)();
192 static const FX_SAXReader_LPFParse g_FX_SAXReader_LPFParse[FX_SAXMODE_MAX] = {
193     &CFX_SAXReader::ParseText,
194     &CFX_SAXReader::ParseNodeStart,
195     &CFX_SAXReader::ParseDeclOrComment,
196     &CFX_SAXReader::ParseDeclNode,
197     &CFX_SAXReader::ParseComment,
198     &CFX_SAXReader::ParseCommentContent,
199     &CFX_SAXReader::ParseTagName,
200     &CFX_SAXReader::ParseTagAttributeName,
201     &CFX_SAXReader::ParseTagAttributeEqual,
202     &CFX_SAXReader::ParseTagAttributeValue,
203     &CFX_SAXReader::ParseMaybeClose,
204     &CFX_SAXReader::ParseTagClose,
205     &CFX_SAXReader::ParseTagEnd,
206     &CFX_SAXReader::ParseTargetData,
207 };
ContinueParse(IFX_Pause * pPause)208 int32_t CFX_SAXReader::ContinueParse(IFX_Pause* pPause) {
209   if (m_iState < 0 || m_iState > 99) {
210     return m_iState;
211   }
212   while (m_File.m_dwCur < m_File.m_dwEnd) {
213     FX_DWORD& index = m_File.m_dwBufIndex;
214     FX_DWORD size = m_File.m_dwBufSize;
215     const uint8_t* pBuf = m_File.m_pBuf;
216     while (index < size) {
217       m_CurByte = pBuf[index];
218       (this->*g_FX_SAXReader_LPFParse[m_eMode])();
219       index++;
220     }
221     m_File.m_dwCur += index;
222     m_iState = (m_File.m_dwCur - m_File.m_dwStart) * 100 /
223                (m_File.m_dwEnd - m_File.m_dwStart);
224     if (m_File.m_dwCur >= m_File.m_dwEnd) {
225       break;
226     }
227     if (!m_File.ReadNextBlock()) {
228       m_iState = -2;
229       break;
230     }
231     m_dwDataOffset = 0;
232     if (pPause && pPause->NeedToPauseNow()) {
233       break;
234     }
235   }
236   return m_iState;
237 }
ParseChar(uint8_t ch)238 void CFX_SAXReader::ParseChar(uint8_t ch) {
239   ReallocDataBuffer();
240   m_pszData[m_iDataPos] = ch;
241   if (m_iEntityStart > -1 && ch == ';') {
242     int32_t iSaveEntityStart = m_iEntityStart;
243     CFX_ByteString csEntity(m_pszData + m_iEntityStart + 1,
244                             m_iDataPos - m_iEntityStart - 1);
245     int32_t iLen = csEntity.GetLength();
246     if (iLen > 0) {
247       if (csEntity[0] == '#') {
248         if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_sharp) == 0) {
249           ch = 0;
250           uint8_t w;
251           if (iLen > 1 && csEntity[1] == 'x') {
252             for (int32_t i = 2; i < iLen; i++) {
253               w = csEntity[i];
254               if (w >= '0' && w <= '9') {
255                 ch = (ch << 4) + w - '0';
256               } else if (w >= 'A' && w <= 'F') {
257                 ch = (ch << 4) + w - 55;
258               } else if (w >= 'a' && w <= 'f') {
259                 ch = (ch << 4) + w - 87;
260               } else {
261                 break;
262               }
263             }
264           } else {
265             for (int32_t i = 1; i < iLen; i++) {
266               w = csEntity[i];
267               if (w < '0' || w > '9') {
268                 break;
269               }
270               ch = ch * 10 + w - '0';
271             }
272           }
273           if (ch != 0) {
274             m_pszData[m_iEntityStart++] = ch;
275           }
276         }
277       } else {
278         if (csEntity.Compare("amp") == 0) {
279           if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_amp) == 0) {
280             m_pszData[m_iEntityStart++] = '&';
281           }
282         } else if (csEntity.Compare("lt") == 0) {
283           if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_lt) == 0) {
284             m_pszData[m_iEntityStart++] = '<';
285           }
286         } else if (csEntity.Compare("gt") == 0) {
287           if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_gt) == 0) {
288             m_pszData[m_iEntityStart++] = '>';
289           }
290         } else if (csEntity.Compare("apos") == 0) {
291           if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_apos) == 0) {
292             m_pszData[m_iEntityStart++] = '\'';
293           }
294         } else if (csEntity.Compare("quot") == 0) {
295           if ((m_dwParseMode & FX_SAXPARSEMODE_NotConvert_quot) == 0) {
296             m_pszData[m_iEntityStart++] = '\"';
297           }
298         }
299       }
300     }
301     if (iSaveEntityStart != m_iEntityStart) {
302       m_iDataPos = m_iEntityStart;
303       m_iEntityStart = -1;
304     } else {
305       m_iDataPos++;
306       m_iEntityStart = -1;
307     }
308   } else {
309     if (m_iEntityStart < 0 && ch == '&') {
310       m_iEntityStart = m_iDataPos;
311     }
312     m_iDataPos++;
313   }
314 }
ParseText()315 void CFX_SAXReader::ParseText() {
316   if (m_CurByte == '<') {
317     if (m_iDataPos > 0) {
318       m_iDataLength = m_iDataPos;
319       m_iDataPos = 0;
320       if (m_pHandler) {
321         NotifyData();
322       }
323     }
324     Push();
325     m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
326     m_eMode = FX_SAXMODE_NodeStart;
327     return;
328   }
329   if (m_iDataPos < 1 && SkipSpace(m_CurByte)) {
330     return;
331   }
332   ParseChar(m_CurByte);
333 }
ParseNodeStart()334 void CFX_SAXReader::ParseNodeStart() {
335   if (m_CurByte == '?') {
336     m_pCurItem->m_eNode = FX_SAXNODE_Instruction;
337     m_eMode = FX_SAXMODE_TagName;
338     return;
339   }
340   if (m_CurByte == '!') {
341     m_eMode = FX_SAXMODE_DeclOrComment;
342     return;
343   }
344   if (m_CurByte == '/') {
345     m_eMode = FX_SAXMODE_TagEnd;
346     return;
347   }
348   if (m_CurByte == '>') {
349     Pop();
350     m_eMode = FX_SAXMODE_Text;
351     return;
352   }
353   if (m_CurByte > 0x20) {
354     m_dwDataOffset = m_File.m_dwBufIndex;
355     m_pCurItem->m_eNode = FX_SAXNODE_Tag;
356     m_eMode = FX_SAXMODE_TagName;
357     AppendData(m_CurByte);
358   }
359 }
ParseDeclOrComment()360 void CFX_SAXReader::ParseDeclOrComment() {
361   if (m_CurByte == '-') {
362     m_eMode = FX_SAXMODE_Comment;
363     m_pCurItem->m_eNode = FX_SAXNODE_Comment;
364     if (m_pCommentContext == NULL) {
365       m_pCommentContext = new CFX_SAXCommentContext;
366     }
367     m_pCommentContext->m_iHeaderCount = 1;
368     m_pCommentContext->m_iTailCount = 0;
369   } else {
370     m_eMode = FX_SAXMODE_DeclNode;
371     m_dwDataOffset = m_File.m_dwBufIndex;
372     m_SkipChar = '>';
373     m_SkipStack.Add('>');
374     SkipNode();
375   }
376 }
ParseComment()377 void CFX_SAXReader::ParseComment() {
378   m_pCommentContext->m_iHeaderCount = 2;
379   m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
380   m_eMode = FX_SAXMODE_CommentContent;
381 }
ParseCommentContent()382 void CFX_SAXReader::ParseCommentContent() {
383   if (m_CurByte == '-') {
384     m_pCommentContext->m_iTailCount++;
385   } else if (m_CurByte == '>' && m_pCommentContext->m_iTailCount == 2) {
386     m_iDataLength = m_iDataPos;
387     m_iDataPos = 0;
388     if (m_pHandler) {
389       NotifyTargetData();
390     }
391     Pop();
392     m_eMode = FX_SAXMODE_Text;
393   } else {
394     while (m_pCommentContext->m_iTailCount > 0) {
395       AppendData('-');
396       m_pCommentContext->m_iTailCount--;
397     }
398     AppendData(m_CurByte);
399   }
400 }
ParseDeclNode()401 void CFX_SAXReader::ParseDeclNode() {
402   SkipNode();
403 }
ParseTagName()404 void CFX_SAXReader::ParseTagName() {
405   if (m_CurByte < 0x21 || m_CurByte == '/' || m_CurByte == '>' ||
406       m_CurByte == '?') {
407     m_iDataLength = m_iDataPos;
408     m_iDataPos = 0;
409     if (m_pHandler) {
410       NotifyEnter();
411     }
412     if (m_CurByte < 0x21) {
413       m_eMode = FX_SAXMODE_TagAttributeName;
414     } else if (m_CurByte == '/' || m_CurByte == '?') {
415       m_ePrevMode = m_eMode;
416       m_eMode = FX_SAXMODE_TagMaybeClose;
417     } else {
418       if (m_pHandler) {
419         NotifyBreak();
420       }
421       m_eMode = FX_SAXMODE_Text;
422     }
423   } else {
424     AppendData(m_CurByte);
425   }
426 }
ParseTagAttributeName()427 void CFX_SAXReader::ParseTagAttributeName() {
428   if (m_CurByte < 0x21 || m_CurByte == '=') {
429     if (m_iDataPos < 1 && m_CurByte < 0x21) {
430       return;
431     }
432     m_iNameLength = m_iDataPos;
433     m_iDataPos = 0;
434     m_SkipChar = 0;
435     m_eMode = m_CurByte == '=' ? FX_SAXMODE_TagAttributeValue
436                                : FX_SAXMODE_TagAttributeEqual;
437     return;
438   }
439   if (m_CurByte == '/' || m_CurByte == '>' || m_CurByte == '?') {
440     if (m_CurByte == '/' || m_CurByte == '?') {
441       m_ePrevMode = m_eMode;
442       m_eMode = FX_SAXMODE_TagMaybeClose;
443     } else {
444       if (m_pHandler) {
445         NotifyBreak();
446       }
447       m_eMode = FX_SAXMODE_Text;
448     }
449     return;
450   }
451   if (m_iDataPos < 1) {
452     m_dwDataOffset = m_File.m_dwBufIndex;
453   }
454   AppendName(m_CurByte);
455 }
ParseTagAttributeEqual()456 void CFX_SAXReader::ParseTagAttributeEqual() {
457   if (m_CurByte == '=') {
458     m_SkipChar = 0;
459     m_eMode = FX_SAXMODE_TagAttributeValue;
460     return;
461   } else if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
462     m_iDataPos = m_iNameLength;
463     AppendName(0x20);
464     m_eMode = FX_SAXMODE_TargetData;
465     ParseTargetData();
466   }
467 }
ParseTagAttributeValue()468 void CFX_SAXReader::ParseTagAttributeValue() {
469   if (m_SkipChar) {
470     if (m_SkipChar == m_CurByte) {
471       {
472         m_iDataLength = m_iDataPos;
473         m_iDataPos = 0;
474         if (m_pHandler) {
475           NotifyAttribute();
476         }
477       }
478       m_SkipChar = 0;
479       m_eMode = FX_SAXMODE_TagAttributeName;
480       return;
481     }
482     ParseChar(m_CurByte);
483     return;
484   }
485   if (m_CurByte < 0x21) {
486     return;
487   }
488   if (m_iDataPos < 1) {
489     if (m_CurByte == '\'' || m_CurByte == '\"') {
490       m_SkipChar = m_CurByte;
491     }
492   }
493 }
ParseMaybeClose()494 void CFX_SAXReader::ParseMaybeClose() {
495   if (m_CurByte == '>') {
496     if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
497       m_iNameLength = m_iDataPos;
498       m_iDataPos = 0;
499       if (m_pHandler) {
500         NotifyTargetData();
501       }
502     }
503     ParseTagClose();
504     m_eMode = FX_SAXMODE_Text;
505   } else if (m_ePrevMode == FX_SAXMODE_TagName) {
506     AppendData('/');
507     m_eMode = FX_SAXMODE_TagName;
508     m_ePrevMode = FX_SAXMODE_Text;
509     ParseTagName();
510   } else if (m_ePrevMode == FX_SAXMODE_TagAttributeName) {
511     AppendName('/');
512     m_eMode = FX_SAXMODE_TagAttributeName;
513     m_ePrevMode = FX_SAXMODE_Text;
514     ParseTagAttributeName();
515   } else if (m_ePrevMode == FX_SAXMODE_TargetData) {
516     AppendName('?');
517     m_eMode = FX_SAXMODE_TargetData;
518     m_ePrevMode = FX_SAXMODE_Text;
519     ParseTargetData();
520   }
521 }
ParseTagClose()522 void CFX_SAXReader::ParseTagClose() {
523   m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
524   if (m_pHandler) {
525     NotifyClose();
526   }
527   Pop();
528 }
ParseTagEnd()529 void CFX_SAXReader::ParseTagEnd() {
530   if (m_CurByte < 0x21) {
531     return;
532   }
533   if (m_CurByte == '>') {
534     Pop();
535     m_dwNodePos = m_File.m_dwCur + m_File.m_dwBufIndex;
536     m_iDataLength = m_iDataPos;
537     m_iDataPos = 0;
538     if (m_pHandler) {
539       NotifyEnd();
540     }
541     Pop();
542     m_eMode = FX_SAXMODE_Text;
543   } else {
544     ParseChar(m_CurByte);
545   }
546 }
ParseTargetData()547 void CFX_SAXReader::ParseTargetData() {
548   if (m_CurByte == '?') {
549     m_ePrevMode = m_eMode;
550     m_eMode = FX_SAXMODE_TagMaybeClose;
551   } else {
552     AppendName(m_CurByte);
553   }
554 }
SkipNode()555 void CFX_SAXReader::SkipNode() {
556   int32_t iLen = m_SkipStack.GetSize();
557   if (m_SkipChar == '\'' || m_SkipChar == '\"') {
558     if (m_CurByte != m_SkipChar) {
559       return;
560     }
561     iLen--;
562     FXSYS_assert(iLen > -1);
563     m_SkipStack.RemoveAt(iLen, 1);
564     m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
565     return;
566   }
567   switch (m_CurByte) {
568     case '<':
569       m_SkipChar = '>';
570       m_SkipStack.Add('>');
571       break;
572     case '[':
573       m_SkipChar = ']';
574       m_SkipStack.Add(']');
575       break;
576     case '(':
577       m_SkipChar = ')';
578       m_SkipStack.Add(')');
579       break;
580     case '\'':
581       m_SkipChar = '\'';
582       m_SkipStack.Add('\'');
583       break;
584     case '\"':
585       m_SkipChar = '\"';
586       m_SkipStack.Add('\"');
587       break;
588     default:
589       if (m_CurByte == m_SkipChar) {
590         iLen--;
591         m_SkipStack.RemoveAt(iLen, 1);
592         m_SkipChar = iLen ? m_SkipStack[iLen - 1] : 0;
593         if (iLen == 0 && m_CurByte == '>') {
594           m_iDataLength = m_iDataPos;
595           m_iDataPos = 0;
596           if (m_iDataLength >= 9 &&
597               FXSYS_memcmp(m_pszData, "[CDATA[", 7 * sizeof(uint8_t)) == 0 &&
598               FXSYS_memcmp(m_pszData + m_iDataLength - 2, "]]",
599                            2 * sizeof(uint8_t)) == 0) {
600             Pop();
601             m_iDataLength -= 9;
602             m_dwDataOffset += 7;
603             FXSYS_memmove(m_pszData, m_pszData + 7,
604                           m_iDataLength * sizeof(uint8_t));
605             m_bCharData = TRUE;
606             if (m_pHandler) {
607               NotifyData();
608             }
609             m_bCharData = FALSE;
610           } else {
611             Pop();
612           }
613           m_eMode = FX_SAXMODE_Text;
614         }
615       }
616       break;
617   }
618   if (iLen > 0) {
619     ParseChar(m_CurByte);
620   }
621 }
NotifyData()622 void CFX_SAXReader::NotifyData() {
623   FXSYS_assert(m_pHandler != NULL);
624   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag)
625     m_pHandler->OnTagData(m_pCurItem->m_pNode,
626                           m_bCharData ? FX_SAXNODE_CharData : FX_SAXNODE_Text,
627                           CFX_ByteStringC(m_pszData, m_iDataLength),
628                           m_File.m_dwCur + m_dwDataOffset);
629 }
NotifyEnter()630 void CFX_SAXReader::NotifyEnter() {
631   FXSYS_assert(m_pHandler != NULL);
632   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag ||
633       m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
634     m_pCurItem->m_pNode =
635         m_pHandler->OnTagEnter(CFX_ByteStringC(m_pszData, m_iDataLength),
636                                m_pCurItem->m_eNode, m_dwNodePos);
637   }
638 }
NotifyAttribute()639 void CFX_SAXReader::NotifyAttribute() {
640   FXSYS_assert(m_pHandler != NULL);
641   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag ||
642       m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
643     m_pHandler->OnTagAttribute(m_pCurItem->m_pNode,
644                                CFX_ByteStringC(m_pszName, m_iNameLength),
645                                CFX_ByteStringC(m_pszData, m_iDataLength));
646   }
647 }
NotifyBreak()648 void CFX_SAXReader::NotifyBreak() {
649   FXSYS_assert(m_pHandler != NULL);
650   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag) {
651     m_pHandler->OnTagBreak(m_pCurItem->m_pNode);
652   }
653 }
NotifyClose()654 void CFX_SAXReader::NotifyClose() {
655   FXSYS_assert(m_pHandler != NULL);
656   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag ||
657       m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
658     m_pHandler->OnTagClose(m_pCurItem->m_pNode, m_dwNodePos);
659   }
660 }
NotifyEnd()661 void CFX_SAXReader::NotifyEnd() {
662   FXSYS_assert(m_pHandler != NULL);
663   if (m_pCurItem->m_eNode == FX_SAXNODE_Tag) {
664     m_pHandler->OnTagEnd(m_pCurItem->m_pNode,
665                          CFX_ByteStringC(m_pszData, m_iDataLength),
666                          m_dwNodePos);
667   }
668 }
NotifyTargetData()669 void CFX_SAXReader::NotifyTargetData() {
670   FXSYS_assert(m_pHandler != NULL);
671   if (m_pCurItem->m_eNode == FX_SAXNODE_Instruction) {
672     m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode,
673                              CFX_ByteStringC(m_pszName, m_iNameLength),
674                              m_dwNodePos);
675   } else if (m_pCurItem->m_eNode == FX_SAXNODE_Comment) {
676     m_pHandler->OnTargetData(m_pCurItem->m_pNode, m_pCurItem->m_eNode,
677                              CFX_ByteStringC(m_pszData, m_iDataLength),
678                              m_dwNodePos);
679   }
680 }
SkipCurrentNode()681 void CFX_SAXReader::SkipCurrentNode() {
682   if (!m_pCurItem) {
683     return;
684   }
685   m_pCurItem->m_bSkip = TRUE;
686 }
SetHandler(IFX_SAXReaderHandler * pHandler)687 void CFX_SAXReader::SetHandler(IFX_SAXReaderHandler* pHandler) {
688   m_pHandler = pHandler;
689 }
690