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