?? parser.cpp
字號:
/*
* $Id: Parser.cpp,v 1.12 2006/10/20 11:36:39 matti Exp $
*
* EAXP - Lightweight XML SAX parser for Symbian Environments
* Copyright (C) 2004-2006 Matti Dahlbom
*
* 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.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact: Matti Dahlbom <matti at 777-team.org>
*/
#include "eaxp.h"
/////////////////////////////////////////////////
// global util functions
/////////////////////////////////////////////////
void XMLStringTrim(TPtr aPtr)
{
TInt len = aPtr.Length();
for( TInt i = 0; i < len; i++ ) {
if( (aPtr[i] == KNewline) || (aPtr[i] == KCarriageReturn) ) {
aPtr[i] = KWhitespace;
}
}
aPtr.TrimAll();
}
/////////////////////////////////////////////////
// class CAttribute
/////////////////////////////////////////////////
CAttribute* CAttribute::NewL(const TDesC &aName,
const TDesC &aNamespace,
const TDesC &aValue)
{
CAttribute *attr = new (ELeave) CAttribute();
CleanupStack::PushL(attr);
attr->ConstructL(aName, aNamespace, aValue);
CleanupStack::Pop(); // attr
return attr;
}
CAttribute::CAttribute()
{
}
CAttribute::~CAttribute()
{
delete iName;
delete iNamespace;
delete iValue;
}
void CAttribute::ConstructL(const TDesC &aName,
const TDesC &aNamespace,
const TDesC &aValue)
{
iName = aName.AllocL();
iNamespace = aNamespace.AllocL();
iValue = aValue.AllocL();
::XMLStringTrim(iValue->Des());
}
EXPORT_C const TDesC& CAttribute::GetName() const
{
return *iName;
}
EXPORT_C const TDesC& CAttribute::GetNamespace() const
{
return *iNamespace;
}
EXPORT_C const TDesC& CAttribute::GetValue() const
{
return *iValue;
}
/////////////////////////////////////////////////
// class CEAXPParser
/////////////////////////////////////////////////
EXPORT_C CEAXPParser* CEAXPParser::NewLC(MSAXEventListener &aListener)
{
CEAXPParser *parser = new (ELeave) CEAXPParser(aListener);
CleanupStack::PushL(parser);
parser->ConstructL();
return parser;
}
EXPORT_C CEAXPParser* CEAXPParser::NewL(MSAXEventListener &aListener)
{
CEAXPParser *parser = CEAXPParser::NewLC(aListener);
CleanupStack::Pop(); // parser
return parser;
}
CEAXPParser::CEAXPParser(MSAXEventListener &aListener)
: iListener(aListener),
iCoreState(ECoreNullState)
{
}
CEAXPParser::~CEAXPParser()
{
// dealloc buffers
delete iAttrName;
delete iAttrValue;
delete iFreeText;
delete iUnescapeBuffer;
delete[] iEscapedCharMap;
}
void CEAXPParser::ConstructL()
{
// construct default size buffers
AllocateDefaultSizeBuffersL();
// construct the escaped character mapping tables
iNumEscapeMappings = 0;
iEscapeMapCapacity = 10;
iEscapedCharMap = new (ELeave) TEscapedCharMapping[iEscapeMapCapacity];
AddEscapeMappingL(_L("amp"), '&');
AddEscapeMappingL(_L("lt"), '<');
AddEscapeMappingL(_L("gt"), '>');
AddEscapeMappingL(_L("quot"), '\"');
AddEscapeMappingL(_L("apos"), '\'');
}
void CEAXPParser::AllocateDefaultSizeBuffersL()
{
delete iAttrName;
iAttrName = NULL;
iAttrName = HBufC::NewL(32);
delete iAttrValue;
iAttrValue = NULL;
iAttrValue = HBufC::NewL(32);
delete iFreeText;
iFreeText = NULL;
iFreeText = HBufC::NewL(128);
delete iUnescapeBuffer;
iUnescapeBuffer = NULL;
iUnescapeBuffer = HBufC::NewL(128);
}
void CEAXPParser::AddEscapeMappingL(const TDesC &aEscape, TChar aChar)
{
if( iNumEscapeMappings == iEscapeMapCapacity ) {
iEscapeMapCapacity *= 2;
delete[] iEscapedCharMap;
iEscapedCharMap = NULL;
iEscapedCharMap = new (ELeave) TEscapedCharMapping[iEscapeMapCapacity];
}
TEscapedCharMapping *mapping = iEscapedCharMap + iNumEscapeMappings;
iNumEscapeMappings++;
mapping->iEscape.Copy(aEscape);
mapping->iChar = aChar;
}
void CEAXPParser::ValidateSizeAndCopyL(HBufC **aTo, const TDesC &aFrom)
{
// check if need to realloc
if( (*aTo)->Des().MaxLength() < aFrom.Length() ) {
delete *aTo;
*aTo = NULL;
*aTo = aFrom.AllocL();
} else {
// buffer large enough; just copy
(*aTo)->Des().Copy(aFrom);
}
}
void CEAXPParser::ValidateSizeL(HBufC **aBuf, TInt aSize)
{
if( (*aBuf)->Des().MaxLength() < aSize ) {
delete *aBuf;
*aBuf = NULL;
*aBuf = HBufC::NewL(aSize);
}
}
TChar CEAXPParser::FindEscapeL(const TPtrC &aEscape)
{
register TEscapedCharMapping *mapping = iEscapedCharMap;
for( register TInt i = 0; i < iNumEscapeMappings; i++ ) {
if( mapping->iEscape.Compare(aEscape) == 0 ) {
return mapping->iChar;
}
mapping++;
}
// escape not found!
_LIT(KNotSupportedEscape, "Not supported escape sequence &%S; on line %d!");
iErrorReason.Format(KNotSupportedEscape, &aEscape, iLineNum);
User::Leave(KErrParsingError);
// to suppress compiler warning
return 0;
}
void CEAXPParser::UnescapeL(const TPtrC &aFrom, TBool aTrim)
{
TLex lex(aFrom);
TChar esc_char;
TInt offset;
ValidateSizeL(&iUnescapeBuffer, aFrom.Length());
TPtr ptr = iUnescapeBuffer->Des();
ptr.Zero();
TBool parsing_escape = EFalse;
while( !lex.Eos() ) {
TChar peek = lex.Peek();
switch( peek ) {
case KAmpersand:
// consume ampersand and mark the start of escape
lex.Inc();
lex.Mark();
parsing_escape = ETrue;
break;
case KSemicolon:
if ( parsing_escape )
{
// consume semicolon and try to replace the escape sequence
offset = lex.Offset();
esc_char = FindEscapeL(aFrom.Mid(lex.MarkedOffset(),
offset - lex.MarkedOffset()));
ptr.Append(esc_char);
parsing_escape = EFalse;
}
else
{
// not parsing escape; append the semicolon normally
ptr.Append( KSemicolon );
}
lex.Inc();
break;
default:
// other char; consume and add to unescape buffer unless
// currently parsing an escape sequence
lex.Inc();
if( !parsing_escape ) {
ptr.Append(peek);
}
break;
}
}
if( aTrim ) {
iUnescapeBuffer->Des().Trim();
}
}
EXPORT_C TBool CEAXPParser::ParseL( const TDesC8& aDocument )
{
HBufC* buf = HBufC::NewLC( aDocument.Length() );
buf->Des().Copy( aDocument );
TBool ret = ParseL( *buf );
CleanupStack::PopAndDestroy( buf );
return ret;
}
EXPORT_C TBool CEAXPParser::ParseL(const TDesC &aDocument)
{
iDocument.Set(aDocument);
iLineNum = 1;
TRAPD(err, ParseImplL());
// after parsing is complete, make sure the buffers consume only the
// default amount of memory
AllocateDefaultSizeBuffersL();
if( err == KErrParsingError ) {
iListener.ParsingError(iErrorReason);
return EFalse;
} else if( err != KErrNone ) {
User::Leave(err);
}
return ETrue;
}
void CEAXPParser::ParseImplL()
{
TLex lex(iDocument);
TBool in_string = EFalse;
TInt start_offs = 0;
TPtrC ptr;
iCoreState = ECoreNullState;
// core parsing loop
while( !lex.Eos() ) {
TChar peek = lex.Peek();
switch( peek ) {
case KLessThan:
if( iCoreState == ECoreParsingElement ) {
IllegalCharacterMetL(peek);
} else if( iCoreState == ECoreParsingFreeText ) {
ValidateSizeAndCopyL(&iFreeText,
iDocument.Mid(lex.MarkedOffset(),
lex.Offset() - lex.MarkedOffset()));
::XMLStringTrim(iFreeText->Des());
if( iFreeText->Length() > 0 ) {
UnescapeL(*iFreeText, ETrue);
iListener.FreeText(*iUnescapeBuffer);
}
}
lex.Mark();
iCoreState = ECoreParsingElement;
break;
case KGreaterThan:
if( in_string || (iCoreState == ECoreParsingFreeText) ) {
IllegalCharacterMetL(peek);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -