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 | |
| parent | def8cb415354ac390b7e89052a50605285f1aca9 (diff) | |
Initial commit
Diffstat (limited to 'Minecraft.Client/Xbox/XML')
| -rw-r--r-- | Minecraft.Client/Xbox/XML/ATGXmlParser.cpp | 963 | ||||
| -rw-r--r-- | Minecraft.Client/Xbox/XML/ATGXmlParser.h | 156 | ||||
| -rw-r--r-- | Minecraft.Client/Xbox/XML/xmlFilesCallback.h | 339 |
3 files changed, 1458 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 diff --git a/Minecraft.Client/Xbox/XML/ATGXmlParser.h b/Minecraft.Client/Xbox/XML/ATGXmlParser.h new file mode 100644 index 00000000..75142e3e --- /dev/null +++ b/Minecraft.Client/Xbox/XML/ATGXmlParser.h @@ -0,0 +1,156 @@ +// 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.h +// +// XMLParser and SAX interface declaration +// +// Xbox Advanced Technology Group +// Copyright (C) Microsoft Corporation. All rights reserved. +//------------------------------------------------------------------------------------- + +#pragma once +#ifndef ATGXMLPARSER_H +#define ATGXMLPARSER_H + +namespace ATG +{ + +//----------------------------------------------------------------------------- +// error returns from XMLParse +//----------------------------------------------------------------------------- +#define _ATGFAC 0x61B +#define E_COULD_NOT_OPEN_FILE MAKE_HRESULT(1, _ATGFAC, 0x0001 ) +#define E_INVALID_XML_SYNTAX MAKE_HRESULT(1, _ATGFAC, 0x0002 ) + + +CONST UINT XML_MAX_ATTRIBUTES_PER_ELEMENT = 32; +CONST UINT XML_MAX_NAME_LENGTH = 128; +CONST UINT XML_READ_BUFFER_SIZE = 2048; +CONST UINT XML_WRITE_BUFFER_SIZE = 2048; + +// No tag can be longer than XML_WRITE_BUFFER_SIZE - an error will be returned if +// it is + +//------------------------------------------------------------------------------------- +struct XMLAttribute +{ + WCHAR* strName; + UINT NameLen; + WCHAR* strValue; + UINT ValueLen; +}; + +//------------------------------------------------------------------------------------- +class ISAXCallback +{ +friend class XMLParser; +public: + ISAXCallback() {}; + virtual ~ISAXCallback() {}; + + virtual HRESULT StartDocument() = 0; + virtual HRESULT EndDocument() = 0; + + virtual HRESULT ElementBegin( CONST WCHAR* strName, UINT NameLen, + CONST XMLAttribute *pAttributes, UINT NumAttributes ) = 0; + virtual HRESULT ElementContent( CONST WCHAR *strData, UINT DataLen, BOOL More ) = 0; + virtual HRESULT ElementEnd( CONST WCHAR *strName, UINT NameLen ) = 0; + + virtual HRESULT CDATABegin( ) = 0; + virtual HRESULT CDATAData( CONST WCHAR *strCDATA, UINT CDATALen, BOOL bMore ) = 0; + virtual HRESULT CDATAEnd( ) = 0; + + virtual VOID Error( HRESULT hError, CONST CHAR *strMessage ) = 0; + + virtual VOID SetParseProgress( DWORD dwProgress ) { } + + const CHAR* GetFilename() { return m_strFilename; } + UINT GetLineNumber() { return m_LineNum; } + UINT GetLinePosition() { return m_LinePos; } + +private: + CONST CHAR *m_strFilename; + UINT m_LineNum; + UINT m_LinePos; +}; + + +//------------------------------------------------------------------------------------- +class XMLParser +{ +public: + XMLParser(); + ~XMLParser(); + + // Register an interface inheiriting from ISAXCallback + VOID RegisterSAXCallbackInterface( ISAXCallback *pISAXCallback ); + + // Get the registered interface + ISAXCallback* GetSAXCallbackInterface(); + + // ParseXMLFile returns one of the following: + // E_COULD_NOT_OPEN_FILE - couldn't open the file + // E_INVALID_XML_SYNTAX - bad XML syntax according to this parser + // E_NOINTERFACE - RegisterSAXCallbackInterface not called + // E_ABORT - callback returned a fail code + // S_OK - file parsed and completed + + HRESULT ParseXMLFile( CONST CHAR *strFilename ); + + // Parses from a buffer- if you pass a WCHAR buffer (and cast it), it will + // correctly detect it and use unicode instead. Return codes are the + // same as for ParseXMLFile + + HRESULT ParseXMLBuffer( CONST CHAR* strBuffer, UINT uBufferSize ); + +private: + HRESULT MainParseLoop(); + + HRESULT AdvanceCharacter( BOOL bOkToFail = FALSE ); + VOID SkipNextAdvance(); + + HRESULT ConsumeSpace(); + HRESULT ConvertEscape(); + HRESULT AdvanceElement(); + HRESULT AdvanceName(); + HRESULT AdvanceAttrVal(); + HRESULT AdvanceCDATA(); + HRESULT AdvanceComment(); + + VOID FillBuffer(); + +#ifdef _Printf_format_string_ // VC++ 2008 and later support this annotation + VOID Error( HRESULT hRet, _In_z_ _Printf_format_string_ CONST CHAR* strFormat, ... ); +#else + VOID Error( HRESULT hRet, CONST CHAR* strFormat, ... ); +#endif + + ISAXCallback* m_pISAXCallback; + + HANDLE m_hFile; + CONST CHAR* m_pInXMLBuffer; + UINT m_uInXMLBufferCharsLeft; + DWORD m_dwCharsTotal; + DWORD m_dwCharsConsumed; + + BYTE m_pReadBuf[ XML_READ_BUFFER_SIZE + 2 ]; // room for a trailing NULL + WCHAR m_pWriteBuf[ XML_WRITE_BUFFER_SIZE ]; + + BYTE* m_pReadPtr; + WCHAR* m_pWritePtr; // write pointer within m_pBuf + + BOOL m_bUnicode; // TRUE = 16-bits, FALSE = 8-bits + BOOL m_bReverseBytes; // TRUE = reverse bytes, FALSE = don't reverse + + BOOL m_bSkipNextAdvance; + WCHAR m_Ch; // Current character being parsed +}; + +} // namespace ATG + +#endif diff --git a/Minecraft.Client/Xbox/XML/xmlFilesCallback.h b/Minecraft.Client/Xbox/XML/xmlFilesCallback.h new file mode 100644 index 00000000..2ea670df --- /dev/null +++ b/Minecraft.Client/Xbox/XML/xmlFilesCallback.h @@ -0,0 +1,339 @@ + +#pragma once +#ifndef XMLMOJANGCALLBACK_H +#define XMLMOJANGCALLBACK_H +// xml reading + +using namespace ATG; + +class xmlMojangCallback : public ATG::ISAXCallback +{ +public: + virtual HRESULT StartDocument() { return S_OK; }; + virtual HRESULT EndDocument() { return S_OK; }; + + virtual HRESULT ElementBegin( CONST WCHAR* strName, UINT NameLen, CONST XMLAttribute *pAttributes, UINT NumAttributes ) + { + WCHAR wTemp[35] = L""; + WCHAR wAttName[32] = L""; + WCHAR wNameXUID[32] = L""; + WCHAR wNameSkin[32] = L""; + WCHAR wNameCloak[32] = L""; + PlayerUID xuid=0LL; + + + if (NameLen >31) + return S_FALSE; + else + wcsncpy( wAttName, strName, NameLen); + + if ( _wcsicmp(wAttName,L"root") == 0) + { + return S_OK; + } + else if ( _wcsicmp(wAttName,L"data") == 0) + { + for(UINT i = 0; i < NumAttributes; i++) + { + wcsncpy_s( wAttName, pAttributes[i].strName, pAttributes[i].NameLen); + if (_wcsicmp(wAttName,L"name")==0) + { + if (pAttributes[i].ValueLen <= 32) + wcsncpy_s( wNameXUID, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + else if (_wcsicmp(wAttName,L"xuid")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + ZeroMemory(wTemp,sizeof(WCHAR)*35); + wcsncpy_s( wTemp, pAttributes[i].strValue, pAttributes[i].ValueLen); + xuid=_wcstoui64(wTemp,NULL,10); + } + } + else if (_wcsicmp(wAttName,L"cape")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wNameCloak, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + else if (_wcsicmp(wAttName,L"skin")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wNameSkin, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + + } + + // if the xuid hasn't been defined, then we can't use the data + if(xuid!=0LL) + { + return CConsoleMinecraftApp::RegisterMojangData(wNameXUID , xuid, wNameSkin, wNameCloak ); + } + else return S_FALSE; + } + else + { + return S_FALSE; + } + }; + + virtual HRESULT ElementContent( CONST WCHAR *strData, UINT DataLen, BOOL More ) { return S_OK; }; + + virtual HRESULT ElementEnd( CONST WCHAR *strName, UINT NameLen ){ return S_OK; }; + + virtual HRESULT CDATABegin( ) { return S_OK; }; + + virtual HRESULT CDATAData( CONST WCHAR *strCDATA, UINT CDATALen, BOOL bMore ){ return S_OK; }; + + virtual HRESULT CDATAEnd( ){ return S_OK; }; + + virtual VOID Error( HRESULT hError, CONST CHAR *strMessage ) { app.DebugPrintf("Error when Parsing xuids.XML\n"); }; + +}; + +class xmlConfigCallback : public ATG::ISAXCallback +{ +public: + virtual HRESULT StartDocument() { return S_OK; }; + virtual HRESULT EndDocument() { return S_OK; }; + + virtual HRESULT ElementBegin( CONST WCHAR* strName, UINT NameLen, CONST XMLAttribute *pAttributes, UINT NumAttributes ) + { + WCHAR wTemp[35] = L""; + WCHAR wType[32] = L""; + WCHAR wAttName[32] = L""; + WCHAR wValue[32] = L""; + int iValue=-1; + + if (NameLen >31) + return S_FALSE; + else + wcsncpy_s( wAttName, strName, NameLen); + + if ( _wcsicmp(wAttName,L"root") == 0) + { + return S_OK; + } + else if ( _wcsicmp(wAttName,L"data") == 0) + { + for(UINT i = 0; i < NumAttributes; i++) + { + wcsncpy_s( wAttName, pAttributes[i].strName, pAttributes[i].NameLen); + if (_wcsicmp(wAttName,L"Type")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wType, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + else if(_wcsicmp(wAttName,L"Value")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wValue, pAttributes[i].strValue, pAttributes[i].ValueLen); + +#ifdef _XBOX + iValue=_wtoi(wValue); +#else + iValue=wcstol(wValue, NULL, 10); +#endif + } + } + } + + // if the xuid hasn't been defined, then we can't use the data + if(iValue!=-1) + { + #ifdef _DEBUG + wprintf(L"Type - %s, Value - %d, ",wType, iValue); + #endif + + return CConsoleMinecraftApp::RegisterConfigValues(wType, iValue ); + } + else + { + return S_FALSE; + } + } + else + { + return S_FALSE; + } + } + + + virtual HRESULT ElementContent( CONST WCHAR *strData, UINT DataLen, BOOL More ) { return S_OK; }; + + virtual HRESULT ElementEnd( CONST WCHAR *strName, UINT NameLen ){ return S_OK; }; + + virtual HRESULT CDATABegin( ) { return S_OK; }; + + virtual HRESULT CDATAData( CONST WCHAR *strCDATA, UINT CDATALen, BOOL bMore ){ return S_OK; }; + + virtual HRESULT CDATAEnd( ){ return S_OK; }; + + virtual VOID Error( HRESULT hError, CONST CHAR *strMessage ) { app.DebugPrintf("Error when Parsing xuids.XML\n"); }; + +}; + +class xmlDLCInfoCallback : public ATG::ISAXCallback +{ +public: + virtual HRESULT StartDocument() { return S_OK; }; + virtual HRESULT EndDocument() { return S_OK; }; + + virtual HRESULT ElementBegin( CONST WCHAR* strName, UINT NameLen, CONST XMLAttribute *pAttributes, UINT NumAttributes ) + { + WCHAR wTemp[35] = L""; + WCHAR wAttName[32] = L""; + WCHAR wNameBanner[32] = L""; + WCHAR wDataFile[32] = L""; + WCHAR wType[32] = L""; + WCHAR wFirstSkin[32] = L""; + WCHAR wConfig[32] = L""; + ULONGLONG ullFull=0ll; + ULONGLONG ullTrial=0ll; + unsigned int uiSortIndex=0L; + int iGender=0; + int iConfig=0; + + if (NameLen >31) + return S_FALSE; + else + wcsncpy_s( wAttName, strName, NameLen); + + if ( _wcsicmp(wAttName,L"root") == 0) + { + return S_OK; + } + else if ( _wcsicmp(wAttName,L"data") == 0) + { + for(UINT i = 0; i < NumAttributes; i++) + { + wcsncpy_s( wAttName, pAttributes[i].strName, pAttributes[i].NameLen); + if (_wcsicmp(wAttName,L"SortIndex")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + ZeroMemory(wTemp,sizeof(WCHAR)*35); + wcsncpy_s( wTemp, pAttributes[i].strValue, pAttributes[i].ValueLen); + uiSortIndex=wcstoul(wTemp,NULL,16); + } + } + else if (_wcsicmp(wAttName,L"Banner")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wNameBanner, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + else if (_wcsicmp(wAttName,L"Full")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + ZeroMemory(wTemp,sizeof(WCHAR)*35); + wcsncpy_s( wTemp, pAttributes[i].strValue, pAttributes[i].ValueLen); + ullFull=_wcstoui64(wTemp,NULL,16); + } + } + else if (_wcsicmp(wAttName,L"Trial")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + ZeroMemory(wTemp,sizeof(WCHAR)*35); + wcsncpy_s( wTemp, pAttributes[i].strValue, pAttributes[i].ValueLen); + ullTrial=_wcstoui64(wTemp,NULL,16); + } + } + else if (_wcsicmp(wAttName,L"FirstSkin")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wFirstSkin, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + else if (_wcsicmp(wAttName,L"Type")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wType, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + else if (_wcsicmp(wAttName,L"Gender")==0) + { + if (_wcsicmp(wAttName,L"Male")==0) + { + iGender=1; + } + else if (_wcsicmp(wAttName,L"Female")==0) + { + iGender=2; + } + else + { + iGender=0; + } + } + else if(_wcsicmp(wAttName,L"Config")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wConfig, pAttributes[i].strValue, pAttributes[i].ValueLen); + +#ifdef _XBOX + iConfig=_wtoi(wConfig); +#else + iConfig=wcstol(wConfig, NULL, 10); +#endif + } + } + else if (_wcsicmp(wAttName,L"DataFile")==0) + { + if (pAttributes[i].ValueLen <= 32) + { + wcsncpy_s( wDataFile, pAttributes[i].strValue, pAttributes[i].ValueLen); + } + } + + } + + // if the xuid hasn't been defined, then we can't use the data + if(ullFull!=0LL) + { +#ifdef _DEBUG + wprintf(L"Type - %ls, Name - %ls, ",wType, wNameBanner); +#endif + app.DebugPrintf("Full = %lld, Trial %lld\n",ullFull,ullTrial); + + return CConsoleMinecraftApp::RegisterDLCData(wType, wNameBanner , iGender, ullFull, ullTrial, wFirstSkin, uiSortIndex, iConfig, wDataFile ); + } + else + { + return S_FALSE; + } + } + else + { + return S_FALSE; + } + }; + + virtual HRESULT ElementContent( CONST WCHAR *strData, UINT DataLen, BOOL More ) { return S_OK; }; + + virtual HRESULT ElementEnd( CONST WCHAR *strName, UINT NameLen ){ return S_OK; }; + + virtual HRESULT CDATABegin( ) { return S_OK; }; + + virtual HRESULT CDATAData( CONST WCHAR *strCDATA, UINT CDATALen, BOOL bMore ){ return S_OK; }; + + virtual HRESULT CDATAEnd( ){ return S_OK; }; + + virtual VOID Error( HRESULT hError, CONST CHAR *strMessage ) { app.DebugPrintf("Error when Parsing DLC.XML\n"); }; + +}; + + +#endif
\ No newline at end of file |
