www.pudn.com > uoth_src.zip > DataParser.h


#ifndef DSSI_DATAPARSER_H 
#define DSSI_DATAPARSER_H 
 
//----------------------------------------------------------------------------- 
//  
// @doc 
// 
// @module	DataParser.h - Data parser | 
// 
// This module contains the definition of the data parser 
// 
// Copyright (c) 2002 - Descartes Systems Sciences, Inc. 
// 
// All rights reserved. 
// 
// Redistribution and use in source and binary forms, with or without  
// modification, are permitted provided that the following conditions are  
// met: 
//  
// 1. Redistributions of source code must retain the above copyright notice,  
//    this list of conditions and the following disclaimer.  
// 2. Neither the name of Descartes Systems Sciences, Inc nor the names of  
//    its contributors may be used to endorse or promote products derived  
//    from this software without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR  
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,  
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED  
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR  
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING  
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS  
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
// 
// @end 
// 
// $History: ExpatImpl.h $ 
//       
//----------------------------------------------------------------------------- 
 
//----------------------------------------------------------------------------- 
// 
// Required include files 
// 
//----------------------------------------------------------------------------- 
 
#include  
#include "ExpatImpl.h" 
#include "uoth.h" 
#include "Level.h" 
#include "Region.h" 
#include "Treasure.h" 
#include "RuneBook.h" 
#include "RuneLibrary.h" 
#include "Character.h" 
 
//----------------------------------------------------------------------------- 
// 
// Forward definitions 
// 
//----------------------------------------------------------------------------- 
 
//----------------------------------------------------------------------------- 
// 
// Template class definition 
// 
//----------------------------------------------------------------------------- 
 
class CDataParser : public CExpatImpl   
{ 
public: 
 
	enum _State 
	{ 
		Start			= 0, 
		InData			= 1, 
		InTreasure		= 2, 
		InRegion		= 3, 
		InLevel			= 4, 
		InRuneLibrary	= 5, 
		InRuneBook		= 6, 
		InCharacter		= 7, 
	}; 
 
public: 
 
	// Constructor  
	 
	CDataParser ()  
	{ 
		m_nState = Start; 
		m_nTextLength = 0; 
	} 
	 
	// Invoked by CExpatImpl after the parser is created 
	 
	void OnPostCreate () 
	{ 
		// Enable all the event routines we want 
		EnableStartElementHandler (); 
		EnableEndElementHandler (); 
		// Note: EnableElementHandler will do both start and end 
		EnableCharacterDataHandler (); 
	} 
	 
	// @cmember Start element handler 
 
	void OnStartElement (const XML_Char *pszName, const XML_Char **papszAttrs) 
	{ 
 
		// 
		// If we have already failed, return 
		// 
 
		if (!m_strError .IsEmpty ()) 
			return; 
 
		// 
		// Reset the text length 
		// 
 
		m_nTextLength = 0; 
 
		// 
		// Switch based on the state 
		// 
 
		switch (m_nState) 
		{ 
 
			// 
			// If this is the start element 
			// 
 
			case Start: 
 
				// 
				// If the data element 
				// 
 
				if (stricmp (pszName, "uoth-data") == 0) 
				{ 
 
					// 
					// No attributes are allowed 
					// 
 
					if (papszAttrs [0] != NULL) 
					{ 
						SetError (IDS_ERR_XML_NO_ATTRS); 
						return; 
					} 
 
					// 
					// Set the state 
					// 
 
					m_nState = InData; 
				} 
 
				// 
				// Otherwise, all other elements are invalid 
				// 
 
				else 
				{ 
					SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
					return; 
				} 
				break; 
 
			// 
			// If we are already in data 
			// 
 
			case InData: 
				{ 
					if (stricmp (pszName, "Treasure") == 0) 
						m_sTreasure .OnStart (this, papszAttrs); 
					else if (stricmp (pszName, "Region") == 0) 
						m_sRegion .OnStart (this, papszAttrs); 
					else if (stricmp (pszName, "Level") == 0) 
						m_sLevel .OnStart (this, papszAttrs); 
					else if (stricmp (pszName, "RuneLibrary") == 0) 
						m_sRuneLibrary .OnStart (this, papszAttrs); 
					else if (stricmp (pszName, "Character") == 0) 
						m_sCharacter .OnStart (this, papszAttrs); 
					else 
					{ 
						SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
						return; 
					} 
				} 
				break; 
 
			case InTreasure: 
				m_sTreasure .OnStartElement (this, pszName, papszAttrs); 
				break; 
 
			case InRegion: 
				m_sRegion .OnStartElement (this, pszName, papszAttrs); 
				break; 
 
			case InLevel: 
				m_sLevel .OnStartElement (this, pszName, papszAttrs); 
				break; 
 
			case InRuneLibrary: 
				m_sRuneLibrary .OnStartElement (this, pszName, papszAttrs); 
				break; 
 
			case InRuneBook: 
				m_sRuneBook .OnStartElement (this, pszName, papszAttrs); 
				break; 
 
			case InCharacter: 
				m_sCharacter .OnStartElement (this, pszName, papszAttrs); 
				break; 
		} 
		return; 
	} 
 
	// End element handler 
 
	void OnEndElement (const XML_Char *pszName) 
	{ 
 
		// 
		// If we have already failed, return 
		// 
 
		if (!m_strError .IsEmpty ()) 
			return; 
 
		// 
		// Switch based on the state 
		// 
 
		switch (m_nState) 
		{ 
			case Start: 
				SetError (IDS_ERR_XML_UNEXPECTED); 
				return; 
 
			case InData: 
				if (stricmp (pszName, "uoth-data") == 0) 
				{ 
					m_nState = Start; 
				} 
				else 
				{ 
					SetError (IDS_ERR_XML_UNEXPECTED_ELEMENT); 
					return; 
				} 
				break; 
 
			case InTreasure: 
				m_sTreasure .OnEndElement (this, pszName); 
				break; 
 
			case InRegion: 
				m_sRegion .OnEndElement (this, pszName); 
				break; 
 
			case InLevel: 
				m_sLevel .OnEndElement (this, pszName); 
				break; 
 
			case InRuneLibrary: 
				m_sRuneLibrary .OnEndElement (this, pszName); 
				break; 
 
			case InRuneBook: 
				m_sRuneBook .OnEndElement (this, pszName); 
				break; 
 
			case InCharacter: 
				m_sCharacter .OnEndElement (this, pszName); 
				break; 
		} 
		return; 
	} 
 
	// Character data handler 
 
	void OnCharacterData (const XML_Char *pszData, int nLength) 
	{ 
 
		// 
		// If we have already failed, return 
		// 
 
		if (!m_strError .IsEmpty ()) 
			return; 
 
		// 
		// Add the text 
		// 
 
		if (nLength + m_nTextLength > _countof (m_szText) - 1) 
			nLength = _countof (m_szText) - 1 - m_nTextLength; 
		memcpy (&m_szText [m_nTextLength], pszData,  
			nLength * sizeof (XML_Char)); 
		m_nTextLength += nLength; 
		return; 
	} 
 
// @access Public methods 
public: 
 
	// @cmember Set the current state 
	 
	void SetState (_State nState) 
	{ 
		m_nState = nState; 
	} 
 
	// @cmember Return the text  
 
	XML_Char *GetText (bool fRemoveWhitespace) 
	{ 
		if (fRemoveWhitespace) 
			RemoveWhitespace (); 
		else 
			m_szText [m_nTextLength] = 0; 
		return m_szText; 
	} 
 
	// @cmember Set the error string 
 
	void SetError (LPCTSTR pszError) 
	{ 
		m_strError = pszError; 
		m_nLineNumber = GetCurrentLineNumber (); 
		m_nColumnNumber = GetCurrentColumnNumber (); 
	} 
 
	// @cmember Set the error string 
 
	void SetError (UINT nID) 
	{ 
		m_strError .LoadString (nID); 
		m_nLineNumber = GetCurrentLineNumber (); 
		m_nColumnNumber = GetCurrentColumnNumber (); 
	} 
 
	// @cmember Convert coords 
 
	void GetCoord (int *px, int *py) 
	{ 
		RemoveWhitespace (); 
		XML_Char *pcomma = strchr (m_szText, ','); 
		if (pcomma == NULL) 
		{ 
			SetError (IDS_ERR_XML_INVALID_COORD); 
			return; 
		} 
		*pcomma++ = 0; 
		*px = atol (m_szText); 
		*py = atol (pcomma); 
	} 
 
	// @cmember Add the current rune book to the library 
 
	void AddRuneBookToLibrary () 
	{ 
		m_sRuneLibrary .AddRuneBook (m_sRuneBook); 
	} 
 
// @access Protected methods 
protected: 
 
	// @cmember Remove whitespace 
	 
	void RemoveWhitespace () 
	{ 
		int nOut = 0; 
		bool fHaveWhite = true; 
		int nIn = 0; 
		while (nIn < m_nTextLength) 
		{ 
			XML_Char c = m_szText [nIn++]; 
			if (isspace (c)) 
			{ 
				if (!fHaveWhite) 
				{ 
					fHaveWhite = true; 
				} 
			} 
			else 
			{ 
				if (fHaveWhite) 
				{ 
					fHaveWhite = false; 
					if (nOut != 0) 
						m_szText [nOut++] = ' '; 
				} 
				m_szText [nOut++] = c; 
			} 
		} 
		m_szText [nOut] = 0; 
		m_nTextLength = nOut; 
	} 
 
// @access Public data 
public: 
 
	// @cmember Current state 
 
	_State				m_nState; 
 
	// @cmember Current text buffer 
 
	XML_Char			m_szText [1024]; //FIXME 
 
	// @cmember Current text length 
 
	int					m_nTextLength; 
 
	// @cmember If set, the process has failed 
 
	CString				m_strError; 
 
	// @cmember Scratch region space 
	 
	CRegion				m_sRegion; 
 
	// @cmember Scratch treasure space 
 
	CTreasure			m_sTreasure; 
 
	// @cmember Scratch level space 
 
	CLevel				m_sLevel; 
 
	// @cmember Scratch rune library space 
 
	CRuneLibrary		m_sRuneLibrary; 
 
	// @cmember Scratch rune book space 
 
	CRuneBook			m_sRuneBook; 
 
	// @cmember Scratch character space 
 
	CCharacter			m_sCharacter; 
 
	// @cmember Scratch map index 
 
	int					m_nMapIndex; 
 
	// @cmember Error line number 
 
	int					m_nLineNumber; 
 
	// @cmember column number 
 
	int					m_nColumnNumber; 
}; 
 
#endif // DSSI_DATAPARSER_H