diff -r 000000000000 -r e35f40988205 xml/xmlexpatparser/src/xmlparserplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xml/xmlexpatparser/src/xmlparserplugin.cpp Thu Dec 17 09:29:21 2009 +0200 @@ -0,0 +1,203 @@ +// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of "Eclipse Public License v1.0" +// which accompanies this distribution, and is available +// at the URL "http://www.eclipse.org/legal/epl-v10.html". +// +// Initial Contributors: +// Nokia Corporation - initial contribution. +// +// Contributors: +// +// Description: +// + +#include +#include + +#include +#include + +#include "xmlparserplugin.h" + +using namespace Xml; + +const TInt KExpatBufferSize = 2048; + +MParser* CXmlParserPlugin::EcomNewL(TAny* aInitParams) + { + // The cast to the MParser interface is a particular to the Xml Framework. Ecom plug-ins usually + // return the pointer to the C class. + return static_cast(CXmlParserPlugin::NewL(aInitParams)); + } + +/* +CXmlParserPlugin::NewL is for testing and can only be accessed by linking directly to XmlParser.o + +aDebugFailCount is used to configure parser heap failure during construction testing - the +usual heap failure macros do not work for our purposes here as it is a private heap. See +CExpat for details. +*/ +CXmlParserPlugin* CXmlParserPlugin::NewL(TAny* aInitParams, TInt aDebugFailCount) + { + TParserInitParams* p = reinterpret_cast(aInitParams); + + CXmlParserPlugin* self = new(ELeave) CXmlParserPlugin(p->iContentHandler); + + CleanupStack::PushL(self); + self->ConstructL(p->iStringDictionaryCollection, p->iCharSetConverter, p->iElementStack, aDebugFailCount); + CleanupStack::Pop(self); + + return self; + } + +CXmlParserPlugin::CXmlParserPlugin(MContentHandler* aContentHandler) : + iContentHandler(*aContentHandler) + { + } + +void CXmlParserPlugin::ConstructL(RStringDictionaryCollection* aStringDictionaryCollection, CCharSetConverter* aCharSetConverter, + RElementStack* aElementStack, TInt aDebugFailCount) + { + iExpat = CExpat::NewL(iContentHandler, aStringDictionaryCollection->StringPool(), *aCharSetConverter, *aElementStack, aDebugFailCount); + } + +/* +Used by framework to delete this object +*/ +void CXmlParserPlugin::Release() + { + delete this; + } + +/* +Private destructor - only accessible from Release method +*/ +CXmlParserPlugin::~CXmlParserPlugin() + { + delete iExpat; + } + + +TInt CXmlParserPlugin::EnableFeature(TInt aParseMode) + { + return iExpat->EnableFeature(aParseMode); + } + +TInt CXmlParserPlugin::DisableFeature(TInt aParseMode) + { + return iExpat->DisableFeature(aParseMode); + } + +TBool CXmlParserPlugin::IsFeatureEnabled(TInt aParseMode) const + { + return iExpat->IsFeatureEnabled(aParseMode); + } + + +void CXmlParserPlugin::ParseChunkL(const TDesC8& aChunk) + { + // If a Reset failed, iExpatResetError will have been set. Here we report it by leaving with the error, + // which will in turn be passed to MContentHandler::OnError. + User::LeaveIfError(iExpatResetError); + ParseChunkInPartsL(aChunk); + } + +void CXmlParserPlugin::ParseLastChunkL(const TDesC8& aFinalChunk) + { + // If a Reset failed, iExpatResetError will have been set. Here we report it by leaving with the error, + // which will in turn be passed to MContentHandler::OnError. + User::LeaveIfError(iExpatResetError); + + // Could be that there is some enourmous piece of data here. + ParseChunkInPartsL(aFinalChunk); + + // We need a buffer even though we have nothing to parse, + // as any previous buffers are destroyed. + // We are just going through the sequence of completing the parsing gracefully. + TDes8& buf = iExpat->GetBufferL(1); + buf = _L8(""); + iExpat->ParseLastL(); + + // TRAP doesn't set its result variable unless a leave occurs - so reset it first. + iExpatResetError = KErrNone; + + // The Reset interface of the Xml Framework provides no mechanism for failure reporting. If iExpat.ResetL + // fails we set iExpatResetError. The error will be reported to MContentHandler::OnError when an attempt + // is made by the client to begin parsing (see RunL). + TRAP(iExpatResetError, iExpat->ResetL()); + } + +void CXmlParserPlugin::ParseChunkInPartsL(const TDesC8& aChunk) + { + // The Expat parser has a buffer of 64k that it stores its state variables in + // and allocates its heap memory from. + // We do this because we may need to upgrade the version of Expat later and this + // makes it easier. + // Beacuse of this we copy the buffer that could have a performance issue, + // we will address this if it later arises. + // We parse the descriptor in parts as we do not want to blow the buffer. + // Even though the descriptor may already be passed in chunks they may be too big. + + if (aChunk.Length() == 0) + { + return; + } + + TPtrC8 part; + TInt offset = 0; + TInt size = aChunk.Size(); + TInt partSize = size; + + do + { + TDes8& buf = iExpat->GetBufferL(KExpatBufferSize); + + if (partSize > KExpatBufferSize) + { + partSize = KExpatBufferSize; + } + + part.Set (aChunk.Mid(offset, partSize)); + + buf = part; + iExpat->ParseL(); + + // The remaining part stats. + offset += part.Length(); + partSize = size - offset; + + } while (partSize); + } + +void CXmlParserPlugin::SetContentSink(class MContentHandler &aContentSink) + { + iExpat->SetContentSink(aContentSink); + } + +RHeap* CXmlParserPlugin::GetInternalHeap() const + { + return iExpat->GetInternalHeap(); + } + +// +// Ecom implementation infrastructure +// + +// KUidXmlParserPlugin is the unique UID for our implementation of the MParser interface. This interface is +// 'published' as KParserInterfaceUid defined in Xml/FrameworkConstants.h. KUidXmlParserPlugin must be +// the same as the value of implementation_uid in the file 101faa0a.rss +const TInt KUidXmlParserPlugin = 0x101FAA0C; + +const TImplementationProxy ImplementationTable[] = { + IMPLEMENTATION_PROXY_ENTRY(KUidXmlParserPlugin, CXmlParserPlugin::EcomNewL) +}; + +EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount) + { + aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy); + + return ImplementationTable; + } +