📄 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__;
#endif
static 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;
}
void
XMLParser::Reset(void)
{
if (m_pCurrentFrame != NULL) delete m_pCurrentFrame;
m_pCurrentFrame = NULL;
}
// class function to get version/encoding of XML content
HX_RESULT
XMLParser::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;
}
char
XMLParser::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;
}
GetStringResult
XMLParser::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;
}
void
XMLParser::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 + -