📄 looseprs.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: looseprs.cpp,v 1.6.28.3 2004/07/09 01:44:10 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */#include "hxcom.h"#include "hxtypes.h"#include "hxstrutl.h"#include "hxmap.h"#include "xmlencod.h"#include "looseprs.h"#include <ctype.h>#include "hxheap.h"#ifdef _DEBUG#undef HX_THIS_FILE static const char HX_THIS_FILE[] = __FILE__;#endifstatic const int MAX_ERROR_LEN = 80;XMLParser::XMLParser(BOOL bStrictCompliance, const char* pEncoding, BOOL bAllowNonXMLComments): m_bStrictCompliance(bStrictCompliance), m_bAllowNonXMLComments(bAllowNonXMLComments), m_bCommentWasFound(FALSE), m_bXMLandSMIL10FullCompliance(FALSE), m_ulCurrentLine(1), m_ulCurrentCol(1), m_ulTagStartLine(1), m_ulTagStartCol(1), m_pLastError(0) , m_bStoreErrors(FALSE){ m_pCurrentFrame = new XMLFrame; m_comment_state = 0; m_comment_get_arg = 0; m_comment_pos = 0; if(pEncoding) { m_pEncoding = new_string(pEncoding); } else { m_pEncoding = new_string("US-ASCII"); // default encoding }}XMLParser::~XMLParser(){ HX_DELETE(m_pLastError); HX_VECTOR_DELETE(m_pEncoding); delete m_pCurrentFrame;}voidXMLParser::Reset(void){ if (m_pCurrentFrame != NULL) delete m_pCurrentFrame; m_pCurrentFrame = NULL;}// class function to get version/encoding of XML contentHX_RESULTXMLParser::GetPrologInfo(const char* pBuf, UINT32 ulBufLen, char*& pVersion, char*& pEncoding){ HX_RESULT rc = HXR_FAIL; const char* pCh = pBuf; enum { VERSION, ENCODING } nPrologAttribute = VERSION; char quoteType = '"'; BOOL bDone = FALSE; BOOL bInComment = FALSE; int state = 0; const char* pValueStart = NULL; while(!bDone && pCh < pBuf + ulBufLen) { switch(state) { case 0: // looking for either a comment open // or a prolog { if(*pCh == '<') { if(*(pCh + 1) == '!' && *(pCh + 2) == '-' && *(pCh + 3) == '-') { if(bInComment) { bDone = TRUE; // no nested comments } pCh += 4; // skip over bInComment = TRUE; state = 1; } else if(*(pCh + 1) == '?' && *(pCh + 2) == 'x' && *(pCh + 3) == 'm' && *(pCh + 4) == 'l') { pCh += 5; // skip over state = 2; } else { bDone = TRUE; // no prolog } } else if(isspace(*pCh)) { pCh++; } else { bDone = TRUE; // can't find prolog } } break; case 1: // comment end { if(*pCh == '-' && *(pCh + 1) == '-' && *(pCh + 2) == '>') { pCh += 3; bInComment = FALSE; state = 0; } else { pCh++; } } break; case 2: // known attribute in prolog { if(strncmp(pCh, "version", 7) == 0) { pCh += 7; nPrologAttribute = VERSION; state = 3; } else if(strncmp(pCh, "encoding", 8) == 0) { pCh += 8; nPrologAttribute = ENCODING; state = 3; } else { pCh++; } } break; case 3: // '=' { if(*pCh == '=') { state = 4; } pCh++; } break; case 4: // quote type { if(*pCh == '"') { quoteType = '"'; pValueStart = pCh + 1; state = 5; } else if(*pCh == '\'') { quoteType = '\''; pValueStart = pCh + 1; state = 5; } else { bDone = TRUE; // badly formed } pCh++; } break; case 5: // get value { if(*pCh == quoteType) { if (pValueStart) { INT32 lValLen = pCh - pValueStart; if (lValLen > 0) { char* pTmp = new char [lValLen + 1]; if (pTmp) { strncpy(pTmp, pValueStart, lValLen); pTmp[lValLen] = '\0'; if(nPrologAttribute == VERSION) { pVersion = pTmp; } else if(nPrologAttribute == ENCODING) { pEncoding = pTmp; } rc = HXR_OK; // got one! // reset for next string state = 2; } } } } pCh++; } break; } } return rc;}charXMLParser::GetEscapeMacro(const char*& ptr, const char* end){ char returnCh; if(*ptr != '&') { returnCh = *ptr; } else { int maxLen = end - ptr; if((maxLen > 5) && strncmp(ptr, "'", 6) == 0) { returnCh = '\''; ptr += 6; } else if((maxLen > 5) && strncmp(ptr, """, 6) == 0) { returnCh = '"'; ptr += 6; } else if((maxLen > 3) && strncmp(ptr, "<", 4) == 0) { returnCh = '<'; ptr += 4; } else if((maxLen > 3) && strncmp(ptr, ">", 4) == 0) { returnCh = '>'; ptr += 4; } else if((maxLen > 4) && strncmp(ptr, "&", 5) == 0) { returnCh = '&'; ptr += 5; } else { returnCh = '&'; ptr++; } } return returnCh;}GetStringResultXMLParser::GetString(const char*& ptr, const char* end, char*& val, UINT32 type){ GetStringResult retval = GSInvalid; CHXXMLEncode xmlStr(m_pEncoding, (BYTE*)ptr, end - ptr); UINT16 uLen = 0; ptr = (const char*)xmlStr.GetNextChar(uLen); while(isspace(*ptr) && ptr < end) { ptr = (const char*)xmlStr.GetNextChar(uLen); } if((const char*)ptr >= end) { return GSNoValue; } if(*ptr == '>') { ptr = (const char*)xmlStr.GetNextChar(uLen); return GSNoValue; } if(*ptr == '/' && *(ptr + 1) == '>') { xmlStr += 2; ptr = (const char*)xmlStr++; return GSNoValue; } // temp buffer to copy string value char* pVal = new char[end - ptr + 1]; char* pValPtr = pVal; char* pValStartPtr = pVal; switch(type) { case TagType: { // The main tag name, delimited by space if(*ptr == '/') { retval = GSEndTag; pValStartPtr++; } while(!isspace(*ptr) && *ptr != '>' && ptr < end) { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } ptr = (const char*)xmlStr.GetNextChar(uLen); } break; } case AttributeName: { // Delimited by whitespace or = while(!isspace(*ptr) && *ptr != '=' && *ptr != '>' && ptr < end) { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } ptr = (const char*)xmlStr.GetNextChar(uLen); } BOOL foundequals = FALSE; if(ptr < end) { // Set the ptr to past the = while((isspace(*ptr) || *ptr == '=') && ptr < end) { if(*ptr == '=') foundequals=TRUE; ptr = (const char*)xmlStr.GetNextChar(uLen); } } if(!foundequals) { retval = GSValueOnly; } break; } case AttributeValue: case AttributeValueNoQuote: case AttributeValueDirective: { if(*ptr == '"') { ptr = (const char*)xmlStr.GetNextChar(uLen); while(ptr<end && *ptr != '"') { if(*ptr == '&') { *pValPtr = GetEscapeMacro(ptr, end); pValPtr++; xmlStr.SetCurrent((BYTE*)ptr); } else { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } } ptr = (const char*)xmlStr.GetNextChar(uLen); } if(*ptr != '"') { return GSMissingQuote; } /* Skip the quote */ ptr = (const char*)xmlStr.GetNextChar(uLen); //Fixes 28799 (which is really an XML authoring error) // if m_bXMLandSMIL10FullCompliance is FALSE: if (m_bXMLandSMIL10FullCompliance && !isspace(*ptr) && '>' != *ptr && (('/' != *ptr && '?' != *ptr) || '>' != *(ptr+1)) ) { //[SMIL 1.0 Compliance] Fixes PR 23995. Junk following a // name="value" construct should be treated as an error, // e.g., the comma should be treated as an error in the // following: <region height="10", width="20"/> return GSInvalid; } } else if(*ptr == '\'') { ptr = (const char*)xmlStr.GetNextChar(uLen); while(*ptr != '\'' && ptr < end) { if(*ptr == '&') { *pValPtr = GetEscapeMacro(ptr, end); pValPtr++; xmlStr.SetCurrent((BYTE*)ptr); } else { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } } ptr = (const char*)xmlStr.GetNextChar(uLen); } if(*ptr != '\'') { delete [] pVal; return GSMissingQuote; } /* Skip the quote */ ptr = (const char*)xmlStr.GetNextChar(uLen); } else if(*ptr == '[' && type == AttributeValueDirective) { ptr = (const char*)xmlStr.GetNextChar(uLen); while(*ptr != ']' && ptr < end) { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } ptr = (const char*)xmlStr.GetNextChar(uLen); } if(*ptr != ']') { delete[] pVal; return GSMissingQuote; } /* skip the ']' */ ptr = (const char*)xmlStr.GetNextChar(uLen); } else { if(m_bStrictCompliance && type != AttributeValueNoQuote && type != AttributeValueDirective) { /* error - value must be quoted */ delete [] pVal; return GSMissingQuote; } else { /* don't care!!! */ while(!isspace(*ptr) && *ptr != '>' && ptr < end) { *pValPtr++ = *ptr; if(uLen == 2) { *pValPtr++ = *(ptr + 1); } ptr = (const char*)xmlStr.GetNextChar(uLen); } } } break; } } *pValPtr = '\0'; val = new_string(pValStartPtr); delete [] pVal; if(retval == GSInvalid) return GSFoundExpected; else return retval;}voidXMLParser::FindCommentClose(const char*& buf, const char* start, const char* end){ BOOL bResult = FALSE; UINT16 nCommentDepth = 1; CHXXMLEncode xmlStr(m_pEncoding, (BYTE*)start, end - start); UINT16 uLen = 0; const char* pos = (const char*)xmlStr.GetNextChar(uLen); while(pos < end && m_comment_state > 0) { switch(m_comment_state) { case 1: if(*pos == '-') m_comment_state = 2; else if (*pos == '<') m_comment_state = 4; else if (*pos == '>' && m_bAllowNonXMLComments) { nCommentDepth--; if (nCommentDepth == 0) { m_comment_state = 0; buf = (const char*)xmlStr.GetNextChar(uLen); } else m_comment_state = 1; } else if(m_comment_start) { if(*pos == '#')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -