the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1// 4J-PB -
2// The ATG Framework is a common set of C++ class libraries that is used by the samples in the XDK, and was developed by the Advanced Technology Group (ATG).
3// The ATG Framework offers a clean and consistent format for the samples. These classes define functions used by all the samples.
4// The ATG Framework together with the samples demonstrates best practices and innovative techniques for Xbox 360. There are many useful sections of code in the samples.
5// You are encouraged to incorporate this code into your titles.
6
7
8//-------------------------------------------------------------------------------------
9// AtgXmlParser.cpp
10//
11// Simple callback non-validating XML parser implementation.
12//
13// Xbox Advanced Technology Group.
14// Copyright (C) Microsoft Corporation. All rights reserved.
15//-------------------------------------------------------------------------------------
16
17#include "stdafx.h"
18#include "AtgXmlParser.h"
19
20namespace ATG
21{
22
23//-------------------------------------------------------------------------------------
24// Name: XMLParser::XMLParser
25//-------------------------------------------------------------------------------------
26XMLParser::XMLParser()
27{
28 m_pWritePtr = m_pWriteBuf;
29 m_pReadPtr = m_pReadBuf;
30 m_pISAXCallback = NULL;
31 m_hFile = INVALID_HANDLE_VALUE;
32}
33
34//-------------------------------------------------------------------------------------
35// Name: XMLParser::~XMLParser
36//-------------------------------------------------------------------------------------
37XMLParser::~XMLParser()
38{
39}
40
41
42//-------------------------------------------------------------------------------------
43// Name: XMLParser::FillBuffer
44// Desc: Reads a block from the current open file
45//-------------------------------------------------------------------------------------
46VOID XMLParser::FillBuffer()
47{
48 DWORD NChars;
49
50 m_pReadPtr = m_pReadBuf;
51
52 if( m_hFile == NULL )
53 {
54 if( m_uInXMLBufferCharsLeft > XML_READ_BUFFER_SIZE )
55 NChars = XML_READ_BUFFER_SIZE;
56 else
57 NChars = m_uInXMLBufferCharsLeft;
58
59 CopyMemory( m_pReadBuf, m_pInXMLBuffer, NChars );
60 m_uInXMLBufferCharsLeft -= NChars;
61 m_pInXMLBuffer += NChars;
62 }
63 else
64 {
65 if( !ReadFile( m_hFile, m_pReadBuf, XML_READ_BUFFER_SIZE, &NChars, NULL ))
66 {
67 return;
68 }
69 }
70
71 m_dwCharsConsumed += NChars;
72 __int64 iProgress = m_dwCharsTotal ? (( (__int64)m_dwCharsConsumed * 1000 ) / (__int64)m_dwCharsTotal) : 0;
73 m_pISAXCallback->SetParseProgress( (DWORD)iProgress );
74
75 m_pReadBuf[ NChars ] = '\0';
76 m_pReadBuf[ NChars + 1] = '\0';
77}
78
79
80//-------------------------------------------------------------------------------------
81// Name: XMLParser::SkipNextAdvance
82// Desc: Puts the last character read back on the input stream
83//-------------------------------------------------------------------------------------
84VOID XMLParser::SkipNextAdvance()
85{
86 m_bSkipNextAdvance = TRUE;
87}
88
89
90//-------------------------------------------------------------------------------------
91// Name: XMLParser::ConsumeSpace
92// Desc: Skips spaces in the current stream
93//-------------------------------------------------------------------------------------
94HRESULT XMLParser::ConsumeSpace()
95{
96 HRESULT hr;
97
98 // Skip spaces
99 if( FAILED( hr = AdvanceCharacter() ) )
100 return hr;
101
102 while ( ( m_Ch == ' ' ) || ( m_Ch == '\t' ) ||
103 ( m_Ch == '\n' ) || ( m_Ch == '\r' ) )
104 {
105 if( FAILED( hr = AdvanceCharacter() ) )
106 return hr;
107 }
108 SkipNextAdvance();
109 return S_OK;
110}
111
112
113//-------------------------------------------------------------------------------------
114// Name: XMLParser::ConvertEscape
115// Desc: Copies and converts an escape sequence into m_pWriteBuf
116//-------------------------------------------------------------------------------------
117HRESULT XMLParser::ConvertEscape()
118{
119 HRESULT hr;
120 WCHAR wVal = 0;
121
122 if( FAILED( hr = AdvanceCharacter() ) )
123 return hr;
124
125 // all escape sequences start with &, so ignore the first character
126
127 if( FAILED( hr = AdvanceCharacter() ) )
128 return hr;
129
130 if ( m_Ch == '#' ) // character as hex or decimal
131 {
132 if( FAILED( hr = AdvanceCharacter() ) )
133 return hr;
134 if ( m_Ch == 'x' ) // hex number
135 {
136 if( FAILED( hr = AdvanceCharacter() ) )
137 return hr;
138
139 while ( m_Ch != ';' )
140 {
141 wVal *= 16;
142
143 if ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) )
144 {
145 wVal += m_Ch - '0';
146 }
147 else if ( ( m_Ch >= 'a' ) && ( m_Ch <= 'f' ) )
148 {
149 wVal += m_Ch - 'a' + 10;
150 }
151 else if ( ( m_Ch >= 'A' ) && ( m_Ch <= 'F' ) )
152 {
153 wVal += m_Ch - 'A' + 10;
154 }
155 else
156 {
157 Error( E_INVALID_XML_SYNTAX, "Expected hex digit as part of &#x escape sequence" );
158 return E_INVALID_XML_SYNTAX;
159 }
160
161 if( FAILED( hr = AdvanceCharacter() ) )
162 return hr;
163 }
164 }
165 else // decimal number
166 {
167 while ( m_Ch != ';' )
168 {
169 wVal *= 10;
170
171 if ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) )
172 {
173 wVal += m_Ch - '0';
174 }
175 else
176 {
177 Error( E_INVALID_XML_SYNTAX, "Expected decimal digit as part of &# escape sequence" );
178 return E_INVALID_XML_SYNTAX;
179 }
180
181 if( FAILED( hr = AdvanceCharacter() ) )
182 return hr;
183 }
184 }
185
186 // copy character into the buffer
187 m_Ch = wVal;
188
189 return S_OK;
190 }
191
192 // must be an entity reference
193
194 WCHAR *pEntityRefVal = m_pWritePtr;
195 UINT EntityRefLen;
196
197 SkipNextAdvance();
198 if( FAILED( hr = AdvanceName() ) )
199 return hr;
200
201 EntityRefLen = (UINT)( m_pWritePtr - pEntityRefVal );
202 m_pWritePtr = pEntityRefVal;
203
204 if ( EntityRefLen == 0 )
205 {
206 Error( E_INVALID_XML_SYNTAX, "Expecting entity name after &" );
207 return E_INVALID_XML_SYNTAX;
208 }
209
210 if( !wcsncmp( pEntityRefVal, L"lt", EntityRefLen ) )
211 wVal = '<';
212 else if( !wcsncmp( pEntityRefVal, L"gt", EntityRefLen ) )
213 wVal = '>';
214 else if( !wcsncmp( pEntityRefVal, L"amp", EntityRefLen ) )
215 wVal = '&';
216 else if( !wcsncmp( pEntityRefVal, L"apos", EntityRefLen ) )
217 wVal = '\'';
218 else if( !wcsncmp( pEntityRefVal, L"quot", EntityRefLen ) )
219 wVal = '"';
220 else
221 {
222 Error( E_INVALID_XML_SYNTAX, "Unrecognized entity name after & - (should be lt, gt, amp, apos, or quot)" );
223 return E_INVALID_XML_SYNTAX; // return false if unrecognized token sequence
224 }
225
226 if( FAILED( hr = AdvanceCharacter() ) )
227 return hr;
228
229 if( m_Ch != ';' )
230 {
231 Error( E_INVALID_XML_SYNTAX, "Expected terminating ; for entity reference" );
232 return E_INVALID_XML_SYNTAX; // malformed reference - needs terminating ;
233 }
234
235 m_Ch = wVal;
236 return S_OK;
237}
238
239
240//-------------------------------------------------------------------------------------
241// Name: XMLParser::AdvanceAttrVal
242// Desc: Copies an attribute value into m_pWrite buf, skipping surrounding quotes
243//-------------------------------------------------------------------------------------
244HRESULT XMLParser::AdvanceAttrVal()
245{
246 HRESULT hr;
247 WCHAR wQuoteChar;
248
249 if( FAILED( hr = AdvanceCharacter() ) )
250 return hr;
251
252 if( ( m_Ch != '"' ) && ( m_Ch != '\'' ) )
253 {
254 Error( E_INVALID_XML_SYNTAX, "Attribute values must be enclosed in quotes" );
255 return E_INVALID_XML_SYNTAX;
256 }
257
258 wQuoteChar = m_Ch;
259
260 for( ;; )
261 {
262 if( FAILED( hr = AdvanceCharacter() ) )
263 return hr;
264 else if( m_Ch == wQuoteChar )
265 break;
266 else if( m_Ch == '&' )
267 {
268 SkipNextAdvance();
269 if( FAILED( hr = ConvertEscape() ) )
270 return hr;
271 }
272 else if( m_Ch == '<' )
273 {
274 Error( E_INVALID_XML_SYNTAX, "Illegal character '<' in element tag" );
275 return E_INVALID_XML_SYNTAX;
276 }
277
278 // copy character into the buffer
279
280 if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE )
281 {
282 Error( E_INVALID_XML_SYNTAX, "Total element tag size may not be more than %d characters", XML_WRITE_BUFFER_SIZE );
283 return E_INVALID_XML_SYNTAX;
284 }
285
286 *m_pWritePtr = m_Ch;
287 m_pWritePtr++;
288 }
289 return S_OK;
290}
291
292
293//-------------------------------------------------------------------------------------
294// Name: XMLParser::AdvanceName
295// Desc: Copies a name into the m_pWriteBuf - returns TRUE on success, FALSE on failure
296// Ignores leading whitespace. Currently does not support unicode names
297//-------------------------------------------------------------------------------------
298HRESULT XMLParser::AdvanceName()
299{
300 HRESULT hr;
301
302 if( FAILED( hr = AdvanceCharacter() ) )
303 return hr;
304
305 if( ( ( m_Ch < 'A' ) || ( m_Ch > 'Z' ) ) &&
306 ( ( m_Ch < 'a' ) || ( m_Ch > 'z' ) ) &&
307 ( m_Ch != '_' ) && ( m_Ch != ':' ) )
308 {
309 Error( E_INVALID_XML_SYNTAX, "Names must start with an alphabetic character or _ or :" );
310 return E_INVALID_XML_SYNTAX;
311 }
312
313 while( ( ( m_Ch >= 'A' ) && ( m_Ch <= 'Z' ) ) ||
314 ( ( m_Ch >= 'a' ) && ( m_Ch <= 'z' ) ) ||
315 ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) ) ||
316 ( m_Ch == '_' ) || ( m_Ch == ':' ) ||
317 ( m_Ch == '-' ) || ( m_Ch == '.' ) )
318 {
319
320 if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE )
321 {
322 Error( E_INVALID_XML_SYNTAX, "Total element tag size may not be more than %d characters", XML_WRITE_BUFFER_SIZE );
323 return E_INVALID_XML_SYNTAX;
324 }
325
326 *m_pWritePtr = m_Ch;
327 m_pWritePtr++;
328
329 if( FAILED( hr = AdvanceCharacter() ) )
330 return hr;
331 }
332
333 SkipNextAdvance();
334 return S_OK;
335}
336
337
338//-------------------------------------------------------------------------------------
339// Name: XMLParser::AdvanceCharacter
340// Desc: Copies the character at *m_pReadPtr to m_Ch
341// handling difference in UTF16 / UTF8, and big/little endian
342// and getting another chunk of the file if needed
343// Returns S_OK if there are more characters, E_ABORT for no characters to read
344//-------------------------------------------------------------------------------------
345HRESULT XMLParser::AdvanceCharacter( BOOL bOkToFail )
346{
347 if( m_bSkipNextAdvance )
348 {
349 m_bSkipNextAdvance = FALSE;
350 return S_OK;
351 }
352
353 // If we hit EOF in the middle of a character,
354 // it's ok-- we'll just have a corrupt last character
355 // (the buffer is padded with double NULLs )
356
357 if ( ( m_pReadPtr[0] == '\0' ) && ( m_pReadPtr[1] == '\0' ) )
358 {
359 // Read more from the file
360 FillBuffer();
361
362 // We are at EOF if it is still NULL
363 if ( ( m_pReadPtr[0] == '\0' ) && ( m_pReadPtr[1] == '\0' ) )
364 {
365 if( !bOkToFail )
366 {
367 Error( E_INVALID_XML_SYNTAX, "Unexpected EOF while parsing XML file" );
368 return E_INVALID_XML_SYNTAX;
369 }
370 else
371 {
372 return E_FAIL;
373 }
374 }
375 }
376
377 if( m_bUnicode == FALSE )
378 {
379 m_Ch = *((CHAR *)m_pReadPtr);
380 m_pReadPtr++;
381 }
382 else // if( m_bUnicode == TRUE )
383 {
384 m_Ch = *((WCHAR *)m_pReadPtr);
385
386 if( m_bReverseBytes )
387 {
388 m_Ch = ( m_Ch << 8 ) + ( m_Ch >> 8 );
389 }
390
391 m_pReadPtr += 2;
392 }
393
394 if( m_Ch == '\n' )
395 {
396 m_pISAXCallback->m_LineNum++;
397 m_pISAXCallback->m_LinePos = 0;
398 }
399 else if( m_Ch != '\r' )
400 m_pISAXCallback->m_LinePos++;
401
402 return S_OK;
403}
404
405
406//-------------------------------------------------------------------------------------
407// Name: XMLParser::AdvanceElement
408// Desc: Builds <element> data, calls callback
409//-------------------------------------------------------------------------------------
410HRESULT XMLParser::AdvanceElement()
411{
412 HRESULT hr;
413
414 // write ptr at the beginning of the buffer
415 m_pWritePtr = m_pWriteBuf;
416
417 if( FAILED( hr = AdvanceCharacter() ) )
418 return hr;
419
420 // if first character wasn't '<', we wouldn't be here
421
422 if( FAILED( hr = AdvanceCharacter() ) )
423 return hr;
424
425 if( m_Ch == '!' )
426 {
427 if( FAILED( hr = AdvanceCharacter() ) )
428 return hr;
429 if ( m_Ch == '-' )
430 {
431 if( FAILED( hr = AdvanceCharacter() ) )
432 return hr;
433 if( m_Ch != '-' )
434 {
435 Error( E_INVALID_XML_SYNTAX, "Expecting '-' after '<!-'" );
436 return E_INVALID_XML_SYNTAX;
437 }
438 if( FAILED( hr = AdvanceComment() ) )
439 return hr;
440 return S_OK;
441 }
442
443 if( m_Ch != '[' )
444 {
445 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
446 return E_INVALID_XML_SYNTAX;
447 }
448 if( FAILED( hr = AdvanceCharacter() ) )
449 return hr;
450 if( m_Ch != 'C' )
451 {
452 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
453 return E_INVALID_XML_SYNTAX;
454 }
455 if( FAILED( hr = AdvanceCharacter() ) )
456 return hr;
457 if( m_Ch != 'D' )
458 {
459 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
460 return E_INVALID_XML_SYNTAX;
461 }
462 if( FAILED( hr = AdvanceCharacter() ) )
463 return hr;
464 if( m_Ch != 'A' )
465 {
466 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
467 return E_INVALID_XML_SYNTAX;
468 }
469 if( FAILED( hr = AdvanceCharacter() ) )
470 return hr;
471 if( m_Ch != 'T' )
472 {
473 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
474 return E_INVALID_XML_SYNTAX;
475 }
476 if( FAILED( hr = AdvanceCharacter() ) )
477 return hr;
478 if( m_Ch != 'A' )
479 {
480 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
481 return E_INVALID_XML_SYNTAX;
482 }
483 if( FAILED( hr = AdvanceCharacter() ) )
484 return hr;
485 if( m_Ch != '[' )
486 {
487 Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" );
488 return E_INVALID_XML_SYNTAX;
489 }
490 if( FAILED( hr = AdvanceCDATA() ) )
491 return hr;
492 }
493 else if( m_Ch == '/' )
494 {
495 WCHAR *pEntityRefVal = m_pWritePtr;
496
497 if( FAILED( hr = AdvanceName() ) )
498 return hr;
499
500 if( FAILED( m_pISAXCallback->ElementEnd( pEntityRefVal,
501 (UINT) ( m_pWritePtr - pEntityRefVal ) ) ) )
502 return E_ABORT;
503
504 if( FAILED( hr = ConsumeSpace() ) )
505 return hr;
506
507 if( FAILED( hr = AdvanceCharacter() ) )
508 return hr;
509
510 if( m_Ch != '>' )
511 {
512 Error( E_INVALID_XML_SYNTAX, "Expecting '>' after name for closing entity reference" );
513 return E_INVALID_XML_SYNTAX;
514 }
515 }
516 else if( m_Ch == '?' )
517 {
518 // just skip any xml header tag since not really important after identifying character set
519 for( ;; )
520 {
521 if( FAILED( hr = AdvanceCharacter() ) )
522 return hr;
523
524 if ( m_Ch == '>' )
525 return S_OK;
526 }
527 }
528 else
529 {
530 XMLAttribute Attributes[ XML_MAX_ATTRIBUTES_PER_ELEMENT ];
531 UINT NumAttrs;
532
533 WCHAR *pEntityRefVal = m_pWritePtr;
534 UINT EntityRefLen;
535
536 NumAttrs = 0;
537
538 SkipNextAdvance();
539
540 // Entity tag
541 if( FAILED( hr = AdvanceName() ) )
542 return hr;
543
544 EntityRefLen = (UINT)( m_pWritePtr - pEntityRefVal );
545
546 if( FAILED( hr = ConsumeSpace() ) )
547 return hr;
548
549 if( FAILED( hr = AdvanceCharacter() ) )
550 return hr;
551
552 // read attributes
553 while( ( m_Ch != '>' ) && ( m_Ch != '/' ) )
554 {
555 SkipNextAdvance();
556
557 if ( NumAttrs >= XML_MAX_ATTRIBUTES_PER_ELEMENT )
558 {
559 Error( E_INVALID_XML_SYNTAX, "Elements may not have more than %d attributes", XML_MAX_ATTRIBUTES_PER_ELEMENT );
560 return E_INVALID_XML_SYNTAX;
561 }
562
563 Attributes[ NumAttrs ].strName = m_pWritePtr;
564
565 // Attribute name
566 if( FAILED( hr = AdvanceName() ) )
567 return hr;
568
569 Attributes[ NumAttrs ].NameLen = (UINT)( m_pWritePtr - Attributes[ NumAttrs ].strName );
570
571 if( FAILED( hr = ConsumeSpace() ) )
572 return hr;
573
574 if( FAILED( hr = AdvanceCharacter() ) )
575 return hr;
576
577 if( m_Ch != '=' )
578 {
579 Error( E_INVALID_XML_SYNTAX, "Expecting '=' character after attribute name" );
580 return E_INVALID_XML_SYNTAX;
581 }
582
583 if( FAILED( hr = ConsumeSpace() ) )
584 return hr;
585
586 Attributes[ NumAttrs ].strValue = m_pWritePtr;
587
588 if( FAILED( hr = AdvanceAttrVal() ) )
589 return hr;
590
591 Attributes[ NumAttrs ].ValueLen = (UINT)( m_pWritePtr -
592 Attributes[ NumAttrs ].strValue );
593
594 ++NumAttrs;
595
596 if( FAILED( hr = ConsumeSpace() ) )
597 return hr;
598
599 if( FAILED( hr = AdvanceCharacter() ) )
600 return hr;
601 }
602
603 if( m_Ch == '/' )
604 {
605 if( FAILED( hr = AdvanceCharacter() ) )
606 return hr;
607 if( m_Ch != '>' )
608 {
609 Error( E_INVALID_XML_SYNTAX, "Expecting '>' after '/' in element tag" );
610 return E_INVALID_XML_SYNTAX;
611 }
612
613 if( FAILED( m_pISAXCallback->ElementBegin( pEntityRefVal, EntityRefLen,
614 Attributes, NumAttrs ) ) )
615 return E_ABORT;
616
617 if( FAILED( m_pISAXCallback->ElementEnd( pEntityRefVal, EntityRefLen ) ) )
618 return E_ABORT;
619 }
620 else
621 {
622 if( FAILED( m_pISAXCallback->ElementBegin( pEntityRefVal, EntityRefLen,
623 Attributes, NumAttrs ) ) )
624 return E_ABORT;
625 }
626 }
627
628 return S_OK;
629}
630
631
632//-------------------------------------------------------------------------------------
633// Name: XMLParser::AdvanceCDATA
634// Desc: Read a CDATA section
635//-------------------------------------------------------------------------------------
636HRESULT XMLParser::AdvanceCDATA()
637{
638 HRESULT hr;
639 WORD wStage = 0;
640
641 if( FAILED( m_pISAXCallback->CDATABegin() ) )
642 return E_ABORT;
643
644 for( ;; )
645 {
646 if( FAILED( hr = AdvanceCharacter() ) )
647 return hr;
648
649 *m_pWritePtr = m_Ch;
650 m_pWritePtr++;
651
652 if( ( m_Ch == ']' ) && ( wStage == 0 ) )
653 wStage = 1;
654 else if( ( m_Ch == ']' ) && ( wStage == 1 ) )
655 wStage = 2;
656 else if( ( m_Ch == '>' ) && ( wStage == 2 ) )
657 {
658 m_pWritePtr -= 3;
659 break;
660 }
661 else
662 wStage = 0;
663
664 if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE )
665 {
666 if( FAILED( m_pISAXCallback->CDATAData( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), TRUE ) ) )
667 return E_ABORT;
668 m_pWritePtr = m_pWriteBuf;
669 }
670 }
671
672 if( FAILED( m_pISAXCallback->CDATAData( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) )
673 return E_ABORT;
674
675 m_pWritePtr = m_pWriteBuf;
676
677 if( FAILED( m_pISAXCallback->CDATAEnd() ) )
678 return E_ABORT;
679
680 return S_OK;
681}
682
683//-------------------------------------------------------------------------------------
684// Name: XMLParser::AdvanceComment
685// Desk: Skips over a comment
686//-------------------------------------------------------------------------------------
687HRESULT XMLParser::AdvanceComment()
688{
689 HRESULT hr;
690 WORD wStage;
691
692 wStage = 0;
693 for( ;; )
694 {
695 if( FAILED( hr = AdvanceCharacter() ) )
696 return hr;
697
698 if (( m_Ch == '-' ) && ( wStage == 0 ))
699 wStage = 1;
700 else if (( m_Ch == '-' ) && ( wStage == 1 ))
701 wStage = 2;
702 else if (( m_Ch == '>' ) && ( wStage == 2 ))
703 break;
704 else
705 wStage = 0;
706 }
707
708 return S_OK;
709}
710
711
712//-------------------------------------------------------------------------------------
713// Name: XMLParser::RegisterSAXCallbackInterface
714// Desc: Registers callback interface
715//-------------------------------------------------------------------------------------
716VOID XMLParser::RegisterSAXCallbackInterface( ISAXCallback *pISAXCallback )
717{
718 m_pISAXCallback = pISAXCallback;
719}
720
721
722//-------------------------------------------------------------------------------------
723// Name: XMLParser::GetSAXCallbackInterface
724// Desc: Returns current callback interface
725//-------------------------------------------------------------------------------------
726ISAXCallback* XMLParser::GetSAXCallbackInterface()
727{
728 return m_pISAXCallback;
729}
730
731
732//-------------------------------------------------------------------------------------
733// Name: XMLParser::MainParseLoop
734// Desc: Main Loop to Parse Data - source agnostic
735//-------------------------------------------------------------------------------------
736HRESULT XMLParser::MainParseLoop()
737{
738 BOOL bWhiteSpaceOnly = TRUE;
739 HRESULT hr = S_OK;
740
741 if( FAILED( m_pISAXCallback->StartDocument() ) )
742 return E_ABORT;
743
744 m_pWritePtr = m_pWriteBuf;
745
746 FillBuffer();
747
748 if ( *((WCHAR *) m_pReadBuf ) == 0xFEFF )
749 {
750 m_bUnicode = TRUE;
751 m_bReverseBytes = FALSE;
752 m_pReadPtr += 2;
753 }
754 else if ( *((WCHAR *) m_pReadBuf ) == 0xFFFE )
755 {
756 m_bUnicode = TRUE;
757 m_bReverseBytes = TRUE;
758 m_pReadPtr += 2;
759 }
760 else if ( *((WCHAR *) m_pReadBuf ) == 0x003C )
761 {
762 m_bUnicode = TRUE;
763 m_bReverseBytes = FALSE;
764 }
765 else if ( *((WCHAR *) m_pReadBuf ) == 0x3C00 )
766 {
767 m_bUnicode = TRUE;
768 m_bReverseBytes = TRUE;
769 }
770 else if ( m_pReadBuf[ 0 ] == 0x3C )
771 {
772 m_bUnicode = FALSE;
773 m_bReverseBytes = FALSE;
774 }
775 else
776 {
777 Error( E_INVALID_XML_SYNTAX, "Unrecognized encoding (parser does not support UTF-8 language encodings)" );
778 return E_INVALID_XML_SYNTAX;
779 }
780
781 for( ;; )
782 {
783 if( FAILED( AdvanceCharacter( TRUE ) ) )
784 {
785 if ( ( (UINT) ( m_pWritePtr - m_pWriteBuf ) != 0 ) && ( !bWhiteSpaceOnly ) )
786 {
787 if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) )
788 return E_ABORT;
789
790 bWhiteSpaceOnly = TRUE;
791 }
792
793 if( FAILED( m_pISAXCallback->EndDocument() ) )
794 return E_ABORT;
795
796 return S_OK;
797 }
798
799 if( m_Ch == '<' )
800 {
801 if( ( (UINT) ( m_pWritePtr - m_pWriteBuf ) != 0 ) && ( !bWhiteSpaceOnly ) )
802 {
803 if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) )
804 return E_ABORT;
805
806 bWhiteSpaceOnly = TRUE;
807 }
808
809 SkipNextAdvance();
810
811 m_pWritePtr = m_pWriteBuf;
812
813 if( FAILED( hr = AdvanceElement() ) )
814 return hr;
815
816 m_pWritePtr = m_pWriteBuf;
817 }
818 else
819 {
820 if( m_Ch == '&' )
821 {
822 SkipNextAdvance();
823 if( FAILED( hr = ConvertEscape() ) )
824 return hr;
825 }
826
827 if( bWhiteSpaceOnly && ( m_Ch != ' ' ) && ( m_Ch != '\n' ) && ( m_Ch != '\r' ) &&
828 ( m_Ch != '\t' ) )
829 {
830 bWhiteSpaceOnly = FALSE;
831 }
832
833 *m_pWritePtr = m_Ch;
834 m_pWritePtr++;
835
836 if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE )
837 {
838 if( !bWhiteSpaceOnly )
839 {
840 if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf,
841 ( UINT ) ( m_pWritePtr - m_pWriteBuf ),
842 TRUE ) ) )
843 {
844 return E_ABORT;
845 }
846 }
847
848 m_pWritePtr = m_pWriteBuf;
849 bWhiteSpaceOnly = TRUE;
850 }
851 }
852 }
853}
854
855
856//-------------------------------------------------------------------------------------
857// Name: XMLParser::ParseXMLFile
858// Desc: Builds element data
859//-------------------------------------------------------------------------------------
860HRESULT XMLParser::ParseXMLFile( CONST CHAR *strFilename )
861{
862 HRESULT hr;
863
864 if( m_pISAXCallback == NULL )
865 return E_NOINTERFACE;
866
867 m_pISAXCallback->m_LineNum = 1;
868 m_pISAXCallback->m_LinePos = 0;
869 m_pISAXCallback->m_strFilename = strFilename; // save this off only while we parse the file
870
871 m_bSkipNextAdvance = FALSE;
872 m_pReadPtr = m_pReadBuf;
873
874 m_pReadBuf[ 0 ] = '\0';
875 m_pReadBuf[ 1 ] = '\0';
876
877 m_pInXMLBuffer = NULL;
878 m_uInXMLBufferCharsLeft = 0;
879 m_hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL );
880
881 if( m_hFile == INVALID_HANDLE_VALUE )
882 {
883 Error( E_COULD_NOT_OPEN_FILE, "Error opening file" );
884 hr = E_COULD_NOT_OPEN_FILE;
885
886 }
887 else
888 {
889 LARGE_INTEGER iFileSize;
890 GetFileSizeEx( m_hFile, &iFileSize );
891 m_dwCharsTotal = (DWORD)iFileSize.QuadPart;
892 m_dwCharsConsumed = 0;
893 hr = MainParseLoop();
894 }
895
896 // Close the file
897 if( m_hFile != INVALID_HANDLE_VALUE )
898 CloseHandle( m_hFile );
899 m_hFile = INVALID_HANDLE_VALUE;
900
901 // we no longer own strFilename, so un-set it
902 m_pISAXCallback->m_strFilename = NULL;
903
904 return hr;
905}
906
907//-------------------------------------------------------------------------------------
908// Name: XMLParser::ParseXMLFile
909// Desc: Builds element data
910//-------------------------------------------------------------------------------------
911HRESULT XMLParser::ParseXMLBuffer( CONST CHAR *strBuffer, UINT uBufferSize )
912{
913 HRESULT hr;
914
915 if( m_pISAXCallback == NULL )
916 return E_NOINTERFACE;
917
918 m_pISAXCallback->m_LineNum = 1;
919 m_pISAXCallback->m_LinePos = 0;
920 m_pISAXCallback->m_strFilename = ""; // save this off only while we parse the file
921
922 m_bSkipNextAdvance = FALSE;
923 m_pReadPtr = m_pReadBuf;
924
925 m_pReadBuf[ 0 ] = '\0';
926 m_pReadBuf[ 1 ] = '\0';
927
928 m_hFile = NULL;
929 m_pInXMLBuffer = strBuffer;
930 m_uInXMLBufferCharsLeft = uBufferSize;
931 m_dwCharsTotal = uBufferSize;
932 m_dwCharsConsumed = 0;
933
934 hr = MainParseLoop();
935
936 // we no longer own strFilename, so un-set it
937 m_pISAXCallback->m_strFilename = NULL;
938
939 return hr;
940}
941
942//-------------------------------------------------------------------------------------
943// XMLParser::Error()
944// Logs an error through the callback interface
945//-------------------------------------------------------------------------------------
946#ifdef _Printf_format_string_ // VC++ 2008 and later support this annotation
947VOID XMLParser::Error( HRESULT hErr, _In_z_ _Printf_format_string_ CONST CHAR* strFormat, ... )
948#else
949VOID XMLParser::Error( HRESULT hErr, CONST CHAR* strFormat, ... )
950#endif
951{
952 CONST INT MAX_OUTPUT_STR = 160;
953 CHAR strBuffer[ MAX_OUTPUT_STR ];
954 va_list pArglist;
955 va_start( pArglist, strFormat );
956
957 vsprintf( strBuffer, strFormat, pArglist );
958
959 m_pISAXCallback->Error( hErr, strBuffer );
960 va_end( pArglist );
961}
962
963} // namespace ATG