⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gxml.cpp

📁 一个非常有用的开源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*	Copyright (C) 2006, Mike Gashler	This library is free software; you can redistribute it and/or	modify it under the terms of the GNU Lesser General Public	License as published by the Free Software Foundation; either	version 2.1 of the License, or (at your option) any later version.	see http://www.gnu.org/copyleft/lesser.html*/#include "GXML.h"#include <stdio.h>#include <string.h>#ifdef WIN32#include <io.h>#else // WIN32#endif // !WIN32// This is a helper class used by GXMLTag::ParseXMLFileclass GXMLParser{protected:	static const char* s_szCommentError;	GXMLTag* m_pRootTag;	GXMLTag* m_pCurrentTag;	int m_nPos;	const char* m_pFile;	int m_nLength;	int m_nLine;	int m_nLineStart;	const char* m_szErrorMessage;	int m_nErrorOffset;	int m_nErrorLine;	int m_nErrorColumn;public:	GXMLParser(const char* pFile, int nSize);	virtual ~GXMLParser();	GXMLTag* Parse(const char** pszErrorMessage, int* pnErrorOffset, int* pnErrorLine, int* pnErrorColumn);protected:	void SetError(const char* szMessage);	GXMLTag* ParseTag();	bool ParseCloser(int nNameStart, int nNameLength);	int ParseName();	void EatWhitespace();	GXMLAttribute* ParseAttribute();	bool UnescapeAttrValue(const char* pValue, int nLength, char* pBuffer);	void MoveIntoNextTag();	GXMLTag* ParseTagInternal();};/*static*/ const char* GXMLParser::s_szCommentError = "The tag is a comment";GXMLParser::GXMLParser(const char* pFile, int nSize){	m_pRootTag = NULL;	m_pCurrentTag = NULL;	m_nPos = 0;	m_nLineStart = 0;	m_pFile = pFile;	m_nLength = nSize;	m_nLine = 1;	m_szErrorMessage = NULL;	m_nErrorOffset = 0;	m_nErrorLine = 0;	m_nErrorColumn = 0;}GXMLParser::~GXMLParser(){}inline bool isWhitespace(char c){	return c <= ' ' ? true : false;}void GXMLParser::SetError(const char* szMessage){	GAssert(!m_szErrorMessage, "Error message already set");	m_szErrorMessage = szMessage;	m_nErrorOffset = m_nPos;	m_nErrorLine = m_nLine;	m_nErrorColumn = m_nPos - m_nLineStart;}void GXMLParser::EatWhitespace(){	char c;	while(true)	{		if(m_nPos >= m_nLength)			break;		c = m_pFile[m_nPos];		if(!isWhitespace(c))			break;		if(c == '\n')		{			m_nLine++;			m_nLineStart = m_nPos + 1;		}		m_nPos++;	}}GXMLTag* GXMLParser::Parse(const char** pszErrorMessage, int* pnErrorOffset, int* pnErrorLine, int* pnErrorColumn){	GXMLTag* pRoot = NULL;	m_szErrorMessage = s_szCommentError;	while(m_szErrorMessage == s_szCommentError)	{		m_szErrorMessage = NULL;		pRoot = ParseTag();	}	if(pszErrorMessage)		*pszErrorMessage = m_szErrorMessage;	if(pnErrorOffset)		*pnErrorOffset = m_nErrorOffset;	if(pnErrorLine)		*pnErrorLine = m_nErrorLine;	if(pnErrorColumn)		*pnErrorColumn = m_nErrorColumn;	return pRoot;}GXMLTag* GXMLParser::ParseTag(){	MoveIntoNextTag();	if(m_nPos >= m_nLength)	{		SetError("Expected a tag");		return NULL;	}	return ParseTagInternal();}void GXMLParser::MoveIntoNextTag(){	// Parse the name	while(m_nPos < m_nLength && m_pFile[m_nPos] != '<')		m_nPos++;	if(m_nPos < m_nLength)		m_nPos++;}GXMLTag* GXMLParser::ParseTagInternal(){	int nNameStart = m_nPos;	int nNameLength = ParseName();	if(nNameLength < 1)	{		SetError("Expected a tag name");		return NULL;	}	if(m_pFile[nNameStart] == '?')	{		while(true)		{			if(m_nPos >= m_nLength)				break;			if(m_pFile[m_nPos] == '>')				break;			else if(m_pFile[m_nPos] == '\n')			{				m_nLine++;				m_nLineStart = m_nPos + 1;			}			m_nPos++;		}		if(m_nPos < m_nLength)			m_nPos++;		SetError(s_szCommentError);		return NULL;	}	else if(nNameLength >= 3 && strncmp(&m_pFile[nNameStart], "!--", 3) == 0)	{		m_nPos -= nNameLength;		// Skip to the end of the comment		int nNests = 1;		while(true)		{			if(m_nPos + 3 >= m_nLength)				break;			if(strncmp(&m_pFile[m_nPos], "<!--", 4) == 0)				nNests++;			if(strncmp(&m_pFile[m_nPos], "-->", 3) == 0)			{				nNests--;				if(nNests <= 0)					break;			}			else if(m_pFile[m_nPos] == '\n')			{				m_nLine++;				m_nLineStart = m_nPos + 1;			}			m_nPos++;		}		m_nPos += 3;		SetError(s_szCommentError);		return NULL;	}	GXMLTag* pNewTag = new GXMLTag(&m_pFile[nNameStart], nNameLength);	Holder<GXMLTag*> hNewTag(pNewTag);	pNewTag->SetLineNumber(m_nLine);	int nStartColumn = m_nPos - m_nLineStart + 1;	// Parse Attributes	while(true)	{		EatWhitespace();		if(m_nPos >= m_nLength)		{			SetError("Expected an attribute, a '/', or a '>'");			return NULL;		}		if(m_pFile[m_nPos] == '/' || m_pFile[m_nPos] == '>')			break;		GXMLAttribute* pNewAttr = ParseAttribute();		if(!pNewAttr)			return NULL;		pNewTag->AddAttribute(pNewAttr);	}	int nEndColumn = m_nPos - m_nLineStart + 1;	pNewTag->SetColumnAndWidth(nStartColumn, nEndColumn - nStartColumn);	if(m_pFile[m_nPos] == '>')	{		// Parse the children		m_nPos++;		while(true)		{			MoveIntoNextTag();			if(m_nPos >= m_nLength)			{				SetError("Expected a closer tag");				return NULL;			}			if(m_pFile[m_nPos] == '/')			{				if(!ParseCloser(nNameStart, nNameLength))					return NULL;				break;			}			GXMLTag* pChildTag = ParseTagInternal();			if(!pChildTag)			{				if(m_szErrorMessage == s_szCommentError)				{					m_szErrorMessage = NULL;					continue;				}				else					return NULL;			}			pNewTag->AddChildTag(pChildTag);		}	}	else	{		// Parse the end of the tag		GAssert(m_pFile[m_nPos] == '/', "internal error");		m_nPos++;		EatWhitespace();		if(m_nPos >= m_nLength || m_pFile[m_nPos] != '>')		{			SetError("Expected a '>'");			return NULL;		}		m_nPos++;	}	return hNewTag.Drop();}int GXMLParser::ParseName(){	EatWhitespace();	char c;	int nLength = 0;	while(true)	{		if(m_nPos >= m_nLength)			break;		c = m_pFile[m_nPos];		if(c == '/' || c == '>' || c == '=')			break;		else if(c == '\n')		{			m_nLine++;			m_nLineStart = m_nPos + 1;			break;		}		else if(isWhitespace(c))			break;		m_nPos++;		nLength++;	}	return nLength;}bool GXMLParser::ParseCloser(int nNameStart, int nNameLength){	if(m_nPos >= m_nLength || m_pFile[m_nPos] != '/')	{		SetError("Expected a '/'");		return false;	}	m_nPos++;	EatWhitespace();	int nCloserStart = m_nPos;	int nCloserLength = ParseName();	if(nCloserLength != nNameLength || memcmp(&m_pFile[nNameStart], &m_pFile[nCloserStart], nCloserLength) != 0)	{		SetError("Closer name doesn't match tag name");		return false;	}	EatWhitespace();	if(m_nPos >= m_nLength || m_pFile[m_nPos] != '>')	{		SetError("Expected a '>'");		return false;	}	m_nPos++;	return true;}GXMLAttribute* GXMLParser::ParseAttribute(){	int nNameStart = m_nPos;	int nNameLength = ParseName();	if(nNameLength < 1)	{		SetError("Expected an attribute name");		return NULL;	}	EatWhitespace();	if(m_nPos >= m_nLength || m_pFile[m_nPos] != '=')	{		SetError("Expected a '='");		return NULL;	}	m_nPos++;	EatWhitespace();	if(m_nPos >= m_nLength || m_pFile[m_nPos] != '"')	{		SetError("Expected a '\"'");		return NULL;	}	m_nPos++;	int nValueStart = m_nPos;	char c;	int nValueLength = 0;	while(true)	{		if(m_nPos >= m_nLength)		{			SetError("Expected a '\"'");			return NULL;		}		c = m_pFile[m_nPos];		if(c == '"')			break;		else if(c == '\n')		{			SetError("Expected a '\"'");			return NULL;		}		m_nPos++;		nValueLength++;	}	if(m_nPos >= m_nLength || m_pFile[m_nPos] != '"')	{		SetError("Expected a '\"'");		return NULL;	}	m_nPos++;		char szTmp[512];	char* szBuff = szTmp;	if(nValueLength >= 512)		szBuff = new char[nValueLength + 1];	if(!UnescapeAttrValue(&m_pFile[nValueStart], nValueLength, szBuff))	{		SetError("Unrecognized escape sequence");		return NULL;	}	GXMLAttribute* pAttr = new GXMLAttribute(&m_pFile[nNameStart], nNameLength, szBuff);	if(szBuff != szTmp)		delete[] szBuff;	return pAttr;}bool GXMLParser::UnescapeAttrValue(const char* pValue, int nLength, char* pBuffer){	while(nLength > 0)	{		if(*pValue == '&')		{			pValue++;			nLength--;			switch(*pValue)			{			case '#':				{					pValue++;					nLength--;					if(UCHAR(*pValue) != 'X')						return false;					pValue++;					nLength--;					int nNum = 0;					while(*pValue != ';' && nLength > 0)					{						if(UCHAR(*pValue) < '0' || UCHAR(*pValue) > 'F')							return false;						if(UCHAR(*pValue) > '9' && UCHAR(*pValue) < 'A')							return false;						nNum <<= 4;						if(UCHAR(*pValue) <= '9')							nNum += UCHAR(*pValue) - '0';						else							nNum += UCHAR(*pValue) - 'A' + 10;						pValue++;						nLength--;					}					if(nLength < 1)						return false;					pValue++;					nLength--;					*pBuffer = nNum;				}				break;			case 'a':			case 'A':				pValue++;				nLength--;				if(UCHAR(*pValue) != 'M')					return false;				pValue++;				nLength--;				if(UCHAR(*pValue) != 'P')					return false;				pValue++;				nLength--;				if(*pValue != ';')					return false;				*pBuffer = '&';				pValue++;				nLength--;				break;			case 'g':			case 'G':				pValue++;				nLength--;				if(UCHAR(*pValue) != 'T')					return false;				pValue++;				nLength--;				if(*pValue != ';')					return false;				*pBuffer = '>';				pValue++;				nLength--;				break;			case 'l':			case 'L':				pValue++;				nLength--;				if(UCHAR(*pValue) != 'T')					return false;				pValue++;				nLength--;				if(*pValue != ';')					return false;				*pBuffer = '<';				pValue++;				nLength--;				break;			case 'q':			case 'Q':				pValue++;				nLength--;				if(UCHAR(*pValue) != 'U')					return false;				pValue++;				nLength--;				if(UCHAR(*pValue) != 'O')					return false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -