syncmlfw/common/xml/src/XMLParser.cpp
changeset 0 b497e44ab2fc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/syncmlfw/common/xml/src/XMLParser.cpp	Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,416 @@
+/*
+* Copyright (c) 2002 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:  XML parser
+*
+*/
+
+
+// ------------------------------------------------------------------------------------------------
+// Includes
+// ------------------------------------------------------------------------------------------------
+#include <s32mem.h>
+
+#include "XMLParser.h"
+#include "WBXMLAttributes.h"
+
+// ------------------------------------------------------------------------------------------------
+// Local functions
+// ------------------------------------------------------------------------------------------------
+LOCAL_D void doPanic( const TDesC& aMsg, TInt aReason )
+	{
+	User::Panic(aMsg, aReason);
+	}
+
+// ------------------------------------------------------------------------------------------------
+// CXMLParser
+// ------------------------------------------------------------------------------------------------
+EXPORT_C CXMLParser* CXMLParser::NewL()
+	{
+	CXMLParser* self = new (ELeave) CXMLParser();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(); // self
+	return self;
+	}
+
+// ------------------------------------------------------------------------------------------------
+void CXMLParser::ConstructL()
+	{
+	iBuffer = CBufFlat::NewL(32);
+	}
+
+// ------------------------------------------------------------------------------------------------
+EXPORT_C CXMLParser::~CXMLParser()
+	{
+	delete iBuffer;
+	delete iStringTable;
+	iStack.Reset();
+	}
+
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CXMLParser::SetDocumentHandler( MWBXMLDocumentHandler* aHandler )
+	{
+	iDocHandler = aHandler;
+	}
+
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CXMLParser::SetExtensionHandler( MWBXMLExtensionHandler* aHandler )
+	{
+	iExtHandler = aHandler;
+	}
+
+// ------------------------------------------------------------------------------------------------
+EXPORT_C void CXMLParser::SetDocumentL( RReadStream& aInput )
+	{
+	iInput = aInput;
+	iStack.Reset();
+	iDocHdrParsed = EFalse;
+	if( iDocHandler )
+		{
+		iDocHandler->DocumentChangedL();
+		}
+	}
+
+// ------------------------------------------------------------------------------------------------
+EXPORT_C TWBXMLParserError CXMLParser::ParseL()
+	{
+	__ASSERT_ALWAYS(iDocHandler, doPanic(KXMLNoDocHandler, KErrGeneral));
+	__ASSERT_ALWAYS(iExtHandler, doPanic(KXMLNoExtHandler, KErrGeneral));
+	if( !iDocHdrParsed )
+		{
+		TWBXMLParserError result(KWBXMLParserErrorOk);
+		TRAPD(err, 	result = doParseDocumentHeaderL());
+		if( err == KErrEof )
+			{
+			return KWBXMLParserErrorEofTooEarly;
+			}
+		return result;
+		}
+	return doParseDocumentBodyL();
+	}
+
+// ------------------------------------------------------------------------------------------------
+TWBXMLParserError CXMLParser::doParseDocumentHeaderL()
+	{
+	iDocHdrParsed = ETrue;
+
+	// Version
+	TUint8 version = readUint8L();
+	
+	// PublicId
+	TInt32 publicId = readMUint32L();
+
+	if( publicId == 0 )
+		{
+		publicId = readMUint32L();
+		}
+	else
+		{
+		publicId = -publicId;
+		}
+
+	// Charset
+	TUint32 charSet = readMUint32L();
+
+	// String table
+	readStringTableL();
+
+	// Document begings now
+	if( publicId < 0 )
+		{
+		iDocHandler->StartDocumentL(version, -publicId, charSet);
+		}
+	else
+		{
+		iDocHandler->StartDocumentL(version, stringTableString(publicId), charSet);
+		}
+
+	return KWBXMLParserErrorOk;
+	}
+
+// ------------------------------------------------------------------------------------------------
+TWBXMLParserError CXMLParser::doParseDocumentBodyL()
+	{
+	TUint8 id(0);
+	
+	TRAPD(err, id = readUint8L());
+
+	if( err != KErrNone )
+		{
+		if( err == KErrEof )
+			{
+			iDocHandler->EndDocumentL();
+			if( iStack.Count() > 0 )
+				{
+				return KWBXMLParserErrorEofTooEarly;
+				}
+			return KWBXMLParserErrorEof;
+			}
+		User::Leave(err);
+		}
+	
+	switch (id) 
+		{
+		case SWITCH_PAGE: 
+			{
+			TUint8 cp = readUint8L();
+			if( cp != iCodePage )
+				{
+				iDocHandler->CodePageSwitchL(cp);
+				iCodePage = cp;
+				}
+			}
+			break;
+	
+		case END:
+			{
+			if( !iStack.Count() )
+				{
+				User::Leave(KErrParserErrorInvalidDocument);
+				}
+			TXMLStackItem si(iStack.operator[](iStack.Count() - 1));
+			if( si.CodePage() != iCodePage )
+				{
+				iDocHandler->CodePageSwitchL(si.CodePage());
+				iCodePage = si.CodePage();
+				}
+			iDocHandler->EndElementL(si.Tag());
+			iStack.Remove(iStack.Count() - 1);
+			}
+			break;
+	
+		case ENTITY:
+			{
+			TUint8 b = readUint8L();
+			iDocHandler->CharactersL(TPtrC8(&b, 1));
+			}
+			break;
+
+		case STR_I: 
+			{
+			iDocHandler->CharactersL(readStrIL());
+			}
+			break;
+
+		case EXT_I_0: 
+		case EXT_I_1: 
+		case EXT_I_2:
+		case EXT_T_0: 
+		case EXT_T_1: 
+		case EXT_T_2:
+		case EXT_0:   
+		case EXT_1:   
+		case EXT_2:
+		case OPAQUE:
+			handleExtensionsL(id);
+			break;
+
+		case STR_T: 
+			iDocHandler->CharactersL(stringTableString(readMUint32L()));
+			break;
+
+		case PI:
+			User::Leave(KErrNotSupported);
+			break;
+
+		default: 
+			handleElementL(id);
+			break;
+	    }
+
+	return KWBXMLParserErrorOk;
+	}
+
+// ------------------------------------------------------------------------------------------------
+TUint32 CXMLParser::readMUint32L()
+	{
+	TUint32 result = 0;
+	TUint8 c;
+	
+	do 	{
+		c = readUint8L();
+		result = (result << 7) | (c & 0x7f);
+		} while ( c & 0x80 );
+
+	return result;
+	}
+
+// ------------------------------------------------------------------------------------------------
+TUint8 CXMLParser::readUint8L()
+	{
+	return iInput.ReadUint8L();
+	}
+
+// ------------------------------------------------------------------------------------------------
+TPtrC8 CXMLParser::readStrIL()
+	{
+	iBuffer->Reset();
+	RBufWriteStream bws(*iBuffer);
+	TUint8 c;
+	while( (c = readUint8L()) != 0 )
+		{
+		bws.WriteUint8L(c);
+		}
+	bws.CommitL();
+	return iBuffer->Ptr(0);
+	}
+
+// ------------------------------------------------------------------------------------------------
+TPtrC8 CXMLParser::readOpaqueL()
+	{
+	iBuffer->Reset();
+	RBufWriteStream bws(*iBuffer);
+	bws.WriteL(iInput, readMUint32L());
+	bws.CommitL();
+	return iBuffer->Ptr(0);
+	}
+
+// ------------------------------------------------------------------------------------------------
+TPtrC8 CXMLParser::stringTableString( TUint32 aIndex )
+	{
+	TPtrC8 temp(iStringTable->Mid(aIndex));
+	TInt pos = temp.Find(KXMLNull());
+	if( pos != KErrNotFound )
+		{
+		return temp.Mid(0, pos);
+		}
+	return temp;
+	}
+
+// ------------------------------------------------------------------------------------------------
+void CXMLParser::readStringTableL()
+	{
+	delete iStringTable;
+	iStringTable = 0;
+	TUint32 strTblLen = readMUint32L();
+	if( strTblLen > 0 )
+		{
+		iStringTable = HBufC8::NewL(strTblLen);
+		TPtr8 ptr = iStringTable->Des();
+		iInput.ReadL(ptr, strTblLen);
+		}
+	}
+
+// ------------------------------------------------------------------------------------------------
+void CXMLParser::handleExtensionsL( TUint8 aId )
+	{
+	switch( aId ) 
+		{
+		case EXT_I_0: 
+		case EXT_I_1: 
+		case EXT_I_2:     
+			iExtHandler->Ext_IL(TUint8(aId - EXT_I_0), readStrIL());
+			break;
+			
+		case EXT_T_0: 
+		case EXT_T_1: 
+		case EXT_T_2:
+			iExtHandler->Ext_TL(TUint8(aId - EXT_T_0), readMUint32L());
+			break;
+			
+		case EXT_0:   
+		case EXT_1: 
+		case EXT_2:
+			iExtHandler->ExtL(TUint8(aId - EXT_0));
+			break;
+			
+		case OPAQUE: 
+			iExtHandler->OpaqueL(readOpaqueL());
+			break;
+
+		default:
+			User::Leave( KWBXMLParserErrorInvalidTag );
+		}
+	}
+
+// ------------------------------------- -----------------------------------------------------------
+void CXMLParser::handleElementL( TUint8 aId )
+	{
+	TUint8 aTag = TUint8(aId & 0x3f);
+
+	CWBXMLAttributes* attr = CWBXMLAttributes::NewLC();
+	
+	if( aId & 0x80 )
+		{
+		readAttributesL(attr);
+		}
+
+	iDocHandler->StartElementL(aTag, *attr);
+
+	if( aId & 0x40 ) 
+		{
+		TXMLStackItem si(aTag, iCodePage);
+	    iStack.Append(si);
+		}
+	else 
+		{
+	    iDocHandler->EndElementL(aTag);
+		}
+
+	CleanupStack::PopAndDestroy(); // attr
+	}
+
+// ------------------------------------------------------------------------------------------------
+void CXMLParser::readAttributesL( CWBXMLAttributes* aAttributes )
+	{
+	TUint8 id = readUint8L();
+	while( id != END ) 
+		{	    
+		iBuffer->Reset();
+		RBufWriteStream bws(*iBuffer);
+		TUint8 name = id;
+	    id = readUint8L();
+	    while( id > 0x80 || id == ENTITY || id == STR_I || id == STR_T || (id >= EXT_I_0 && id <= EXT_I_2) || (id >= EXT_T_0 && id <= EXT_T_2) ) 
+			{		
+			switch (id) 
+				{
+				case ENTITY: 
+					bws.WriteUint8L(readUint8L());
+					break;
+
+				case STR_I: 
+					bws.WriteL(readStrIL());
+					break;
+			
+				case EXT_I_0: 
+				case EXT_I_1: 
+				case EXT_I_2:     
+				case EXT_T_0: 
+				case EXT_T_1: 
+				case EXT_T_2:
+				case EXT_0:   
+				case EXT_1: 
+				case EXT_2:
+				case OPAQUE: 
+					handleExtensionsL(id);
+					break;
+ 
+				case STR_T: 
+					bws.WriteL(stringTableString(readUint8L()));
+					break;
+			   
+				default:
+					bws.WriteUint8L(id);
+					break;
+				}
+			id = readUint8L();
+			}
+		bws.CommitL();
+		aAttributes->AddAttributeL(name, iBuffer->Ptr(0));
+		}
+	}
+
+//End of File
+
+