--- /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 <e32std.h>
+#include <ecom/implementationproxy.h>
+
+#include <xml/contenthandler.h>
+#include <xml/stringdictionarycollection.h>
+
+#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<MParser*>(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<TParserInitParams*>(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;
+ }
+