diff options
| author | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
|---|---|---|
| committer | daoge_cmd <3523206925@qq.com> | 2026-03-01 12:16:08 +0800 |
| commit | b691c43c44ff180d10e7d4a9afc83b98551ff586 (patch) | |
| tree | 3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Xbox/XML/ATGXmlParser.cpp | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.Client/Xbox/XML/ATGXmlParser.cpp')
| -rw-r--r-- | Minecraft.Client/Xbox/XML/ATGXmlParser.cpp | 963 |
1 files changed, 963 insertions, 0 deletions
diff --git a/Minecraft.Client/Xbox/XML/ATGXmlParser.cpp b/Minecraft.Client/Xbox/XML/ATGXmlParser.cpp new file mode 100644 index 00000000..5366e721 --- /dev/null +++ b/Minecraft.Client/Xbox/XML/ATGXmlParser.cpp @@ -0,0 +1,963 @@ +// 4J-PB - +// 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). +// The ATG Framework offers a clean and consistent format for the samples. These classes define functions used by all the samples. +// 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. +// You are encouraged to incorporate this code into your titles. + + +//------------------------------------------------------------------------------------- +// AtgXmlParser.cpp +// +// Simple callback non-validating XML parser implementation. +// +// Xbox Advanced Technology Group. +// Copyright (C) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#include "stdafx.h" +#include "AtgXmlParser.h" + +namespace ATG +{ + +//------------------------------------------------------------------------------------- +// Name: XMLParser::XMLParser +//------------------------------------------------------------------------------------- +XMLParser::XMLParser() +{ + m_pWritePtr = m_pWriteBuf; + m_pReadPtr = m_pReadBuf; + m_pISAXCallback = NULL; + m_hFile = INVALID_HANDLE_VALUE; +} + +//------------------------------------------------------------------------------------- +// Name: XMLParser::~XMLParser +//------------------------------------------------------------------------------------- +XMLParser::~XMLParser() +{ +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::FillBuffer +// Desc: Reads a block from the current open file +//------------------------------------------------------------------------------------- +VOID XMLParser::FillBuffer() +{ + DWORD NChars; + + m_pReadPtr = m_pReadBuf; + + if( m_hFile == NULL ) + { + if( m_uInXMLBufferCharsLeft > XML_READ_BUFFER_SIZE ) + NChars = XML_READ_BUFFER_SIZE; + else + NChars = m_uInXMLBufferCharsLeft; + + CopyMemory( m_pReadBuf, m_pInXMLBuffer, NChars ); + m_uInXMLBufferCharsLeft -= NChars; + m_pInXMLBuffer += NChars; + } + else + { + if( !ReadFile( m_hFile, m_pReadBuf, XML_READ_BUFFER_SIZE, &NChars, NULL )) + { + return; + } + } + + m_dwCharsConsumed += NChars; + __int64 iProgress = m_dwCharsTotal ? (( (__int64)m_dwCharsConsumed * 1000 ) / (__int64)m_dwCharsTotal) : 0; + m_pISAXCallback->SetParseProgress( (DWORD)iProgress ); + + m_pReadBuf[ NChars ] = '\0'; + m_pReadBuf[ NChars + 1] = '\0'; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::SkipNextAdvance +// Desc: Puts the last character read back on the input stream +//------------------------------------------------------------------------------------- +VOID XMLParser::SkipNextAdvance() +{ + m_bSkipNextAdvance = TRUE; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::ConsumeSpace +// Desc: Skips spaces in the current stream +//------------------------------------------------------------------------------------- +HRESULT XMLParser::ConsumeSpace() +{ + HRESULT hr; + + // Skip spaces + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + while ( ( m_Ch == ' ' ) || ( m_Ch == '\t' ) || + ( m_Ch == '\n' ) || ( m_Ch == '\r' ) ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + } + SkipNextAdvance(); + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::ConvertEscape +// Desc: Copies and converts an escape sequence into m_pWriteBuf +//------------------------------------------------------------------------------------- +HRESULT XMLParser::ConvertEscape() +{ + HRESULT hr; + WCHAR wVal = 0; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + // all escape sequences start with &, so ignore the first character + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if ( m_Ch == '#' ) // character as hex or decimal + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if ( m_Ch == 'x' ) // hex number + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + while ( m_Ch != ';' ) + { + wVal *= 16; + + if ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) ) + { + wVal += m_Ch - '0'; + } + else if ( ( m_Ch >= 'a' ) && ( m_Ch <= 'f' ) ) + { + wVal += m_Ch - 'a' + 10; + } + else if ( ( m_Ch >= 'A' ) && ( m_Ch <= 'F' ) ) + { + wVal += m_Ch - 'A' + 10; + } + else + { + Error( E_INVALID_XML_SYNTAX, "Expected hex digit as part of &#x escape sequence" ); + return E_INVALID_XML_SYNTAX; + } + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + } + } + else // decimal number + { + while ( m_Ch != ';' ) + { + wVal *= 10; + + if ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) ) + { + wVal += m_Ch - '0'; + } + else + { + Error( E_INVALID_XML_SYNTAX, "Expected decimal digit as part of &# escape sequence" ); + return E_INVALID_XML_SYNTAX; + } + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + } + } + + // copy character into the buffer + m_Ch = wVal; + + return S_OK; + } + + // must be an entity reference + + WCHAR *pEntityRefVal = m_pWritePtr; + UINT EntityRefLen; + + SkipNextAdvance(); + if( FAILED( hr = AdvanceName() ) ) + return hr; + + EntityRefLen = (UINT)( m_pWritePtr - pEntityRefVal ); + m_pWritePtr = pEntityRefVal; + + if ( EntityRefLen == 0 ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting entity name after &" ); + return E_INVALID_XML_SYNTAX; + } + + if( !wcsncmp( pEntityRefVal, L"lt", EntityRefLen ) ) + wVal = '<'; + else if( !wcsncmp( pEntityRefVal, L"gt", EntityRefLen ) ) + wVal = '>'; + else if( !wcsncmp( pEntityRefVal, L"amp", EntityRefLen ) ) + wVal = '&'; + else if( !wcsncmp( pEntityRefVal, L"apos", EntityRefLen ) ) + wVal = '\''; + else if( !wcsncmp( pEntityRefVal, L"quot", EntityRefLen ) ) + wVal = '"'; + else + { + Error( E_INVALID_XML_SYNTAX, "Unrecognized entity name after & - (should be lt, gt, amp, apos, or quot)" ); + return E_INVALID_XML_SYNTAX; // return false if unrecognized token sequence + } + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( m_Ch != ';' ) + { + Error( E_INVALID_XML_SYNTAX, "Expected terminating ; for entity reference" ); + return E_INVALID_XML_SYNTAX; // malformed reference - needs terminating ; + } + + m_Ch = wVal; + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceAttrVal +// Desc: Copies an attribute value into m_pWrite buf, skipping surrounding quotes +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceAttrVal() +{ + HRESULT hr; + WCHAR wQuoteChar; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( ( m_Ch != '"' ) && ( m_Ch != '\'' ) ) + { + Error( E_INVALID_XML_SYNTAX, "Attribute values must be enclosed in quotes" ); + return E_INVALID_XML_SYNTAX; + } + + wQuoteChar = m_Ch; + + for( ;; ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + else if( m_Ch == wQuoteChar ) + break; + else if( m_Ch == '&' ) + { + SkipNextAdvance(); + if( FAILED( hr = ConvertEscape() ) ) + return hr; + } + else if( m_Ch == '<' ) + { + Error( E_INVALID_XML_SYNTAX, "Illegal character '<' in element tag" ); + return E_INVALID_XML_SYNTAX; + } + + // copy character into the buffer + + if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE ) + { + Error( E_INVALID_XML_SYNTAX, "Total element tag size may not be more than %d characters", XML_WRITE_BUFFER_SIZE ); + return E_INVALID_XML_SYNTAX; + } + + *m_pWritePtr = m_Ch; + m_pWritePtr++; + } + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceName +// Desc: Copies a name into the m_pWriteBuf - returns TRUE on success, FALSE on failure +// Ignores leading whitespace. Currently does not support unicode names +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceName() +{ + HRESULT hr; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( ( ( m_Ch < 'A' ) || ( m_Ch > 'Z' ) ) && + ( ( m_Ch < 'a' ) || ( m_Ch > 'z' ) ) && + ( m_Ch != '_' ) && ( m_Ch != ':' ) ) + { + Error( E_INVALID_XML_SYNTAX, "Names must start with an alphabetic character or _ or :" ); + return E_INVALID_XML_SYNTAX; + } + + while( ( ( m_Ch >= 'A' ) && ( m_Ch <= 'Z' ) ) || + ( ( m_Ch >= 'a' ) && ( m_Ch <= 'z' ) ) || + ( ( m_Ch >= '0' ) && ( m_Ch <= '9' ) ) || + ( m_Ch == '_' ) || ( m_Ch == ':' ) || + ( m_Ch == '-' ) || ( m_Ch == '.' ) ) + { + + if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE ) + { + Error( E_INVALID_XML_SYNTAX, "Total element tag size may not be more than %d characters", XML_WRITE_BUFFER_SIZE ); + return E_INVALID_XML_SYNTAX; + } + + *m_pWritePtr = m_Ch; + m_pWritePtr++; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + } + + SkipNextAdvance(); + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceCharacter +// Desc: Copies the character at *m_pReadPtr to m_Ch +// handling difference in UTF16 / UTF8, and big/little endian +// and getting another chunk of the file if needed +// Returns S_OK if there are more characters, E_ABORT for no characters to read +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceCharacter( BOOL bOkToFail ) +{ + if( m_bSkipNextAdvance ) + { + m_bSkipNextAdvance = FALSE; + return S_OK; + } + + // If we hit EOF in the middle of a character, + // it's ok-- we'll just have a corrupt last character + // (the buffer is padded with double NULLs ) + + if ( ( m_pReadPtr[0] == '\0' ) && ( m_pReadPtr[1] == '\0' ) ) + { + // Read more from the file + FillBuffer(); + + // We are at EOF if it is still NULL + if ( ( m_pReadPtr[0] == '\0' ) && ( m_pReadPtr[1] == '\0' ) ) + { + if( !bOkToFail ) + { + Error( E_INVALID_XML_SYNTAX, "Unexpected EOF while parsing XML file" ); + return E_INVALID_XML_SYNTAX; + } + else + { + return E_FAIL; + } + } + } + + if( m_bUnicode == FALSE ) + { + m_Ch = *((CHAR *)m_pReadPtr); + m_pReadPtr++; + } + else // if( m_bUnicode == TRUE ) + { + m_Ch = *((WCHAR *)m_pReadPtr); + + if( m_bReverseBytes ) + { + m_Ch = ( m_Ch << 8 ) + ( m_Ch >> 8 ); + } + + m_pReadPtr += 2; + } + + if( m_Ch == '\n' ) + { + m_pISAXCallback->m_LineNum++; + m_pISAXCallback->m_LinePos = 0; + } + else if( m_Ch != '\r' ) + m_pISAXCallback->m_LinePos++; + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceElement +// Desc: Builds <element> data, calls callback +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceElement() +{ + HRESULT hr; + + // write ptr at the beginning of the buffer + m_pWritePtr = m_pWriteBuf; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + // if first character wasn't '<', we wouldn't be here + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( m_Ch == '!' ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if ( m_Ch == '-' ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != '-' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '-' after '<!-'" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceComment() ) ) + return hr; + return S_OK; + } + + if( m_Ch != '[' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != 'C' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != 'D' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != 'A' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != 'T' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != 'A' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != '[' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '<![CDATA['" ); + return E_INVALID_XML_SYNTAX; + } + if( FAILED( hr = AdvanceCDATA() ) ) + return hr; + } + else if( m_Ch == '/' ) + { + WCHAR *pEntityRefVal = m_pWritePtr; + + if( FAILED( hr = AdvanceName() ) ) + return hr; + + if( FAILED( m_pISAXCallback->ElementEnd( pEntityRefVal, + (UINT) ( m_pWritePtr - pEntityRefVal ) ) ) ) + return E_ABORT; + + if( FAILED( hr = ConsumeSpace() ) ) + return hr; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( m_Ch != '>' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '>' after name for closing entity reference" ); + return E_INVALID_XML_SYNTAX; + } + } + else if( m_Ch == '?' ) + { + // just skip any xml header tag since not really important after identifying character set + for( ;; ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if ( m_Ch == '>' ) + return S_OK; + } + } + else + { + XMLAttribute Attributes[ XML_MAX_ATTRIBUTES_PER_ELEMENT ]; + UINT NumAttrs; + + WCHAR *pEntityRefVal = m_pWritePtr; + UINT EntityRefLen; + + NumAttrs = 0; + + SkipNextAdvance(); + + // Entity tag + if( FAILED( hr = AdvanceName() ) ) + return hr; + + EntityRefLen = (UINT)( m_pWritePtr - pEntityRefVal ); + + if( FAILED( hr = ConsumeSpace() ) ) + return hr; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + // read attributes + while( ( m_Ch != '>' ) && ( m_Ch != '/' ) ) + { + SkipNextAdvance(); + + if ( NumAttrs >= XML_MAX_ATTRIBUTES_PER_ELEMENT ) + { + Error( E_INVALID_XML_SYNTAX, "Elements may not have more than %d attributes", XML_MAX_ATTRIBUTES_PER_ELEMENT ); + return E_INVALID_XML_SYNTAX; + } + + Attributes[ NumAttrs ].strName = m_pWritePtr; + + // Attribute name + if( FAILED( hr = AdvanceName() ) ) + return hr; + + Attributes[ NumAttrs ].NameLen = (UINT)( m_pWritePtr - Attributes[ NumAttrs ].strName ); + + if( FAILED( hr = ConsumeSpace() ) ) + return hr; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if( m_Ch != '=' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '=' character after attribute name" ); + return E_INVALID_XML_SYNTAX; + } + + if( FAILED( hr = ConsumeSpace() ) ) + return hr; + + Attributes[ NumAttrs ].strValue = m_pWritePtr; + + if( FAILED( hr = AdvanceAttrVal() ) ) + return hr; + + Attributes[ NumAttrs ].ValueLen = (UINT)( m_pWritePtr - + Attributes[ NumAttrs ].strValue ); + + ++NumAttrs; + + if( FAILED( hr = ConsumeSpace() ) ) + return hr; + + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + } + + if( m_Ch == '/' ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + if( m_Ch != '>' ) + { + Error( E_INVALID_XML_SYNTAX, "Expecting '>' after '/' in element tag" ); + return E_INVALID_XML_SYNTAX; + } + + if( FAILED( m_pISAXCallback->ElementBegin( pEntityRefVal, EntityRefLen, + Attributes, NumAttrs ) ) ) + return E_ABORT; + + if( FAILED( m_pISAXCallback->ElementEnd( pEntityRefVal, EntityRefLen ) ) ) + return E_ABORT; + } + else + { + if( FAILED( m_pISAXCallback->ElementBegin( pEntityRefVal, EntityRefLen, + Attributes, NumAttrs ) ) ) + return E_ABORT; + } + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceCDATA +// Desc: Read a CDATA section +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceCDATA() +{ + HRESULT hr; + WORD wStage = 0; + + if( FAILED( m_pISAXCallback->CDATABegin() ) ) + return E_ABORT; + + for( ;; ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + *m_pWritePtr = m_Ch; + m_pWritePtr++; + + if( ( m_Ch == ']' ) && ( wStage == 0 ) ) + wStage = 1; + else if( ( m_Ch == ']' ) && ( wStage == 1 ) ) + wStage = 2; + else if( ( m_Ch == '>' ) && ( wStage == 2 ) ) + { + m_pWritePtr -= 3; + break; + } + else + wStage = 0; + + if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE ) + { + if( FAILED( m_pISAXCallback->CDATAData( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), TRUE ) ) ) + return E_ABORT; + m_pWritePtr = m_pWriteBuf; + } + } + + if( FAILED( m_pISAXCallback->CDATAData( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) ) + return E_ABORT; + + m_pWritePtr = m_pWriteBuf; + + if( FAILED( m_pISAXCallback->CDATAEnd() ) ) + return E_ABORT; + + return S_OK; +} + +//------------------------------------------------------------------------------------- +// Name: XMLParser::AdvanceComment +// Desk: Skips over a comment +//------------------------------------------------------------------------------------- +HRESULT XMLParser::AdvanceComment() +{ + HRESULT hr; + WORD wStage; + + wStage = 0; + for( ;; ) + { + if( FAILED( hr = AdvanceCharacter() ) ) + return hr; + + if (( m_Ch == '-' ) && ( wStage == 0 )) + wStage = 1; + else if (( m_Ch == '-' ) && ( wStage == 1 )) + wStage = 2; + else if (( m_Ch == '>' ) && ( wStage == 2 )) + break; + else + wStage = 0; + } + + return S_OK; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::RegisterSAXCallbackInterface +// Desc: Registers callback interface +//------------------------------------------------------------------------------------- +VOID XMLParser::RegisterSAXCallbackInterface( ISAXCallback *pISAXCallback ) +{ + m_pISAXCallback = pISAXCallback; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::GetSAXCallbackInterface +// Desc: Returns current callback interface +//------------------------------------------------------------------------------------- +ISAXCallback* XMLParser::GetSAXCallbackInterface() +{ + return m_pISAXCallback; +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::MainParseLoop +// Desc: Main Loop to Parse Data - source agnostic +//------------------------------------------------------------------------------------- +HRESULT XMLParser::MainParseLoop() +{ + BOOL bWhiteSpaceOnly = TRUE; + HRESULT hr = S_OK; + + if( FAILED( m_pISAXCallback->StartDocument() ) ) + return E_ABORT; + + m_pWritePtr = m_pWriteBuf; + + FillBuffer(); + + if ( *((WCHAR *) m_pReadBuf ) == 0xFEFF ) + { + m_bUnicode = TRUE; + m_bReverseBytes = FALSE; + m_pReadPtr += 2; + } + else if ( *((WCHAR *) m_pReadBuf ) == 0xFFFE ) + { + m_bUnicode = TRUE; + m_bReverseBytes = TRUE; + m_pReadPtr += 2; + } + else if ( *((WCHAR *) m_pReadBuf ) == 0x003C ) + { + m_bUnicode = TRUE; + m_bReverseBytes = FALSE; + } + else if ( *((WCHAR *) m_pReadBuf ) == 0x3C00 ) + { + m_bUnicode = TRUE; + m_bReverseBytes = TRUE; + } + else if ( m_pReadBuf[ 0 ] == 0x3C ) + { + m_bUnicode = FALSE; + m_bReverseBytes = FALSE; + } + else + { + Error( E_INVALID_XML_SYNTAX, "Unrecognized encoding (parser does not support UTF-8 language encodings)" ); + return E_INVALID_XML_SYNTAX; + } + + for( ;; ) + { + if( FAILED( AdvanceCharacter( TRUE ) ) ) + { + if ( ( (UINT) ( m_pWritePtr - m_pWriteBuf ) != 0 ) && ( !bWhiteSpaceOnly ) ) + { + if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) ) + return E_ABORT; + + bWhiteSpaceOnly = TRUE; + } + + if( FAILED( m_pISAXCallback->EndDocument() ) ) + return E_ABORT; + + return S_OK; + } + + if( m_Ch == '<' ) + { + if( ( (UINT) ( m_pWritePtr - m_pWriteBuf ) != 0 ) && ( !bWhiteSpaceOnly ) ) + { + if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf, (UINT)( m_pWritePtr - m_pWriteBuf ), FALSE ) ) ) + return E_ABORT; + + bWhiteSpaceOnly = TRUE; + } + + SkipNextAdvance(); + + m_pWritePtr = m_pWriteBuf; + + if( FAILED( hr = AdvanceElement() ) ) + return hr; + + m_pWritePtr = m_pWriteBuf; + } + else + { + if( m_Ch == '&' ) + { + SkipNextAdvance(); + if( FAILED( hr = ConvertEscape() ) ) + return hr; + } + + if( bWhiteSpaceOnly && ( m_Ch != ' ' ) && ( m_Ch != '\n' ) && ( m_Ch != '\r' ) && + ( m_Ch != '\t' ) ) + { + bWhiteSpaceOnly = FALSE; + } + + *m_pWritePtr = m_Ch; + m_pWritePtr++; + + if( m_pWritePtr - m_pWriteBuf >= XML_WRITE_BUFFER_SIZE ) + { + if( !bWhiteSpaceOnly ) + { + if( FAILED( m_pISAXCallback->ElementContent( m_pWriteBuf, + ( UINT ) ( m_pWritePtr - m_pWriteBuf ), + TRUE ) ) ) + { + return E_ABORT; + } + } + + m_pWritePtr = m_pWriteBuf; + bWhiteSpaceOnly = TRUE; + } + } + } +} + + +//------------------------------------------------------------------------------------- +// Name: XMLParser::ParseXMLFile +// Desc: Builds element data +//------------------------------------------------------------------------------------- +HRESULT XMLParser::ParseXMLFile( CONST CHAR *strFilename ) +{ + HRESULT hr; + + if( m_pISAXCallback == NULL ) + return E_NOINTERFACE; + + m_pISAXCallback->m_LineNum = 1; + m_pISAXCallback->m_LinePos = 0; + m_pISAXCallback->m_strFilename = strFilename; // save this off only while we parse the file + + m_bSkipNextAdvance = FALSE; + m_pReadPtr = m_pReadBuf; + + m_pReadBuf[ 0 ] = '\0'; + m_pReadBuf[ 1 ] = '\0'; + + m_pInXMLBuffer = NULL; + m_uInXMLBufferCharsLeft = 0; + m_hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL ); + + if( m_hFile == INVALID_HANDLE_VALUE ) + { + Error( E_COULD_NOT_OPEN_FILE, "Error opening file" ); + hr = E_COULD_NOT_OPEN_FILE; + + } + else + { + LARGE_INTEGER iFileSize; + GetFileSizeEx( m_hFile, &iFileSize ); + m_dwCharsTotal = (DWORD)iFileSize.QuadPart; + m_dwCharsConsumed = 0; + hr = MainParseLoop(); + } + + // Close the file + if( m_hFile != INVALID_HANDLE_VALUE ) + CloseHandle( m_hFile ); + m_hFile = INVALID_HANDLE_VALUE; + + // we no longer own strFilename, so un-set it + m_pISAXCallback->m_strFilename = NULL; + + return hr; +} + +//------------------------------------------------------------------------------------- +// Name: XMLParser::ParseXMLFile +// Desc: Builds element data +//------------------------------------------------------------------------------------- +HRESULT XMLParser::ParseXMLBuffer( CONST CHAR *strBuffer, UINT uBufferSize ) +{ + HRESULT hr; + + if( m_pISAXCallback == NULL ) + return E_NOINTERFACE; + + m_pISAXCallback->m_LineNum = 1; + m_pISAXCallback->m_LinePos = 0; + m_pISAXCallback->m_strFilename = ""; // save this off only while we parse the file + + m_bSkipNextAdvance = FALSE; + m_pReadPtr = m_pReadBuf; + + m_pReadBuf[ 0 ] = '\0'; + m_pReadBuf[ 1 ] = '\0'; + + m_hFile = NULL; + m_pInXMLBuffer = strBuffer; + m_uInXMLBufferCharsLeft = uBufferSize; + m_dwCharsTotal = uBufferSize; + m_dwCharsConsumed = 0; + + hr = MainParseLoop(); + + // we no longer own strFilename, so un-set it + m_pISAXCallback->m_strFilename = NULL; + + return hr; +} + +//------------------------------------------------------------------------------------- +// XMLParser::Error() +// Logs an error through the callback interface +//------------------------------------------------------------------------------------- +#ifdef _Printf_format_string_ // VC++ 2008 and later support this annotation +VOID XMLParser::Error( HRESULT hErr, _In_z_ _Printf_format_string_ CONST CHAR* strFormat, ... ) +#else +VOID XMLParser::Error( HRESULT hErr, CONST CHAR* strFormat, ... ) +#endif +{ + CONST INT MAX_OUTPUT_STR = 160; + CHAR strBuffer[ MAX_OUTPUT_STR ]; + va_list pArglist; + va_start( pArglist, strFormat ); + + vsprintf( strBuffer, strFormat, pArglist ); + + m_pISAXCallback->Error( hErr, strBuffer ); + va_end( pArglist ); +} + +} // namespace ATG |
