upnpavcontroller/upnpxmlparser/src/upnpxmlparserlite.cpp
changeset 0 7f85d04be362
child 34 eab116a48b80
child 38 5360b7ddc251
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpavcontroller/upnpxmlparser/src/upnpxmlparserlite.cpp	Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,507 @@
+/*
+* Copyright (c) 2008 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 SAX Parser for UPnP.
+*
+*/
+
+
+
+
+
+
+// INCLUDE FILES
+// xml parser
+#include <xml/parser.h>
+#include <xml/parserfeature.h>
+#include <xml/matchdata.h>
+
+// upnp stack api
+#include <upnpstring.h>
+
+// upnpframework / xmlparser api
+#include "upnpxmlparserlite.h"
+#include "upnpobjectlite.h"
+
+// xmlparser internal
+#include "upnpobjectstacklite.h"
+
+
+_LIT( KComponentLogfile, "upnpxmlparser.txt");
+#include "upnplog.h"
+
+_LIT8( KXmlMimeType,    "text/xml"     );
+_LIT8( KLIB2XML,        "libxml2" );
+
+_LIT8( KContainer,      "container"    );
+_LIT8( KItem,           "item"         );
+_LIT8( KTitle,          "title"        );
+_LIT8( KClass,          "class"        );
+_LIT8( KId,             "id"           );
+//_LIT8( KComma,          ":"            );
+_LIT8( KDIDL,           "DIDL-Lite"    );
+_LIT8( KDesc,           "desc"         );
+_LIT8( KDlnaDoc,        "X_DLNADOC"    );
+
+_LIT( KIndexContainer,  "1" );
+_LIT( KIndexAudio,      "2" );
+_LIT( KIndexVideo,      "3" );
+_LIT( KIndexImage,      "4" );
+_LIT( KIndexOther,      "5" );
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::CUPnPXMLParserLite()
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+CUPnPXMLParserLite::CUPnPXMLParserLite()
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::ConstructL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::ConstructL()
+    {
+    __LOG( "CUPnPXMLParserLite::CostructL" );
+    iStack = CUPnPObjectStackLite::NewL();
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::NewL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+EXPORT_C CUPnPXMLParserLite* CUPnPXMLParserLite::NewL()
+    {
+    CUPnPXMLParserLite* self = CUPnPXMLParserLite::NewLC();
+    CleanupStack::Pop( self );    
+    return self;
+    }
+
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::NewLC
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+EXPORT_C CUPnPXMLParserLite* CUPnPXMLParserLite::NewLC()
+    {   
+    CUPnPXMLParserLite* self = new( ELeave ) CUPnPXMLParserLite();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+    
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::~CUPnPXMLParserLite
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+CUPnPXMLParserLite::~CUPnPXMLParserLite()
+    {
+    __LOG( "CUPnPXMLParserLite::~CUPnPXMLParserLite" );
+    if ( iStack )
+        {
+        iStack->ResetAndDestroy();
+        delete iStack;
+        }
+    
+    delete iElementValue;
+    delete iFormatString;
+    delete iTitleBuf;
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::ParseResultDataL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+EXPORT_C void CUPnPXMLParserLite::ParseResultDataL(
+    RPointerArray<CUpnpObjectLite>& aResultArray, const TDesC8& aData,
+    const TDesC& aFormatString )
+    {
+    __LOG( "CUPnPXMLParserLite::ParseResultDataL, begin" );
+    
+    delete iFormatString; iFormatString = NULL;
+    if( aFormatString != KNullDesC )
+        {
+        iFormatString = aFormatString.AllocL();
+        }
+    
+    if ( !aData.Length() )
+        {
+        User::Leave( KErrArgument );
+        }
+        
+    iResultRoot = &aResultArray;
+
+    // Create parser 
+    CMatchData* matchData = CMatchData::NewLC();
+    matchData->SetMimeTypeL( KXmlMimeType ); 
+    matchData->SetVariantL( KLIB2XML ); 
+    CParser* parser = CParser::NewLC( *matchData, *this ); 
+    parser->EnableFeature( Xml::EReportNamespaceMapping );
+    
+    Xml::ParseL( *parser, aData );    
+    
+    CleanupStack::PopAndDestroy( parser );
+    CleanupStack::PopAndDestroy( matchData );
+    
+    iResultRoot = NULL;           
+    __LOG( "CUPnPXMLParserLite::ParseResultDataL, end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnStartDocumentL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnStartDocumentL( 
+                                const RDocumentParameters& /*aDocParam*/, 
+                                TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnEndDocumentL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnEndDocumentL( TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnStartElementL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnStartElementL( const RTagInfo& aElement, 
+                                      const RAttributeArray& aAttributes,
+                                      TInt aErrorCode )
+    {
+    __LOG1( "CUPnPXMLParserLite::OnStartElementL, error code: %d", aErrorCode );
+    if ( aErrorCode != KErrNone )
+        {
+        return;
+        }
+    const TDesC8& desName = aElement.LocalName().DesC();
+    const TDesC8& prefix = aElement.Prefix().DesC();
+    
+    // Delete content, since there may be some stuff between the elements
+    // (comments, whitespace etc.)
+    delete iElementValue; iElementValue = NULL;    
+      
+    if ( !desName.CompareF( KContainer ) ) // Container element
+        {
+        CUpnpObjectLite* tmpContainer = CUpnpObjectLite::NewL();
+        CleanupStack::PushL( tmpContainer );
+
+        SetAttributesL( *tmpContainer, aAttributes );
+        //push into the stack, ownership is transferred                      
+        iStack->PushL( tmpContainer ); 
+        
+        CleanupStack::Pop( tmpContainer );
+        }
+    else if ( !desName.CompareF( KItem ) ) // Item element
+        {
+        CUpnpObjectLite* tmpItem = CUpnpObjectLite::NewL();
+        CleanupStack::PushL( tmpItem );
+
+        SetAttributesL( *tmpItem, aAttributes );                      
+        //push into the stack, ownership is transferred                      
+        iStack->PushL( tmpItem );
+        
+        CleanupStack::Pop( tmpItem );
+        }
+    else if( !desName.CompareF( KTitle ) ) // Title element
+        {
+        // check that we have item or container. cause leave if not
+        if ( iStack->Count() == 0)
+            {
+            User::Leave( KErrArgument );
+            }
+        // We should have an item or a container already!
+        //__ASSERTD( iStack->Top(), __FILE__, __LINE__ );
+        iTitle = ETrue;
+        }
+    else if( !desName.CompareF( KClass ) ) // Object class element
+        {
+        // check that we have item or container. cause leave if not
+        if ( iStack->Count() == 0)
+            {
+            User::Leave( KErrArgument );
+            }
+        // We should have an item or a container already!
+        //__ASSERTD( iStack->Top(), __FILE__, __LINE__ );
+        iObjectClass = ETrue;
+        }
+    // Ignore DIDL-Lite, desc and X_DLNADOC -elements (DLNA req)
+    else if( desName.Compare( KDIDL ) == KErrNone ||
+             desName.Compare( KDesc ) == KErrNone ||
+             desName.Compare( KDlnaDoc ) == KErrNone    
+           )
+        {
+        // Ignore
+        }
+    else 
+        {
+        // check that we have item or container. cause leave if not
+        if ( iStack->Count() == 0)
+            {
+            User::Leave( KErrArgument );
+            }
+        // Ignore rest of the elements
+                }
+    __LOG( "CUPnPXMLParserLite::OnStartElementL, end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnEndElementL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnEndElementL( const RTagInfo& aElement, 
+                                    TInt aErrorCode )
+    {
+    __LOG( "CUPnPXMLParserLite::OnEndElementL(), begin" );
+    if ( aErrorCode != KErrNone )
+        {
+        return;
+        }
+        
+    const TDesC8& desName = aElement.LocalName().DesC();    
+    if ( !desName.CompareF( KContainer ) || !desName.CompareF( KItem ) )
+        {
+        if( iTitleBuf )
+            {
+            CUpnpObjectLite* obj = iStack->Top();
+            __ASSERTD( obj, __FILE__, __LINE__ );
+
+            if( iFormatString )
+                {
+                HBufC* tempBuf = UpnpString::ToUnicodeL( *iTitleBuf );
+                CleanupStack::PushL( tempBuf );
+                HBufC* buf = HBufC::NewL( iFormatString->Length() +
+                    tempBuf->Length() );
+                buf->Des().Format( *iFormatString, tempBuf );
+                CleanupStack::PopAndDestroy( tempBuf );
+                obj->SetTitleL( buf );
+                }
+            else
+                {
+                HBufC* buf = HBufC::NewL( iTitleBuf->Length() );
+                buf->Des().Copy( *iTitleBuf );
+                obj->SetTitleL( buf );
+                }
+            delete iTitleBuf; iTitleBuf = NULL;
+            }
+               
+        iResultRoot->AppendL( iStack->Top() );
+        iStack->Pop(); // Remove object from stack.
+        }
+    else if( KErrNone != desName.CompareF( KDIDL ))
+        {        
+        CUpnpObjectLite* obj = iStack->Top();
+        __ASSERTD( obj, __FILE__, __LINE__ );
+             
+        if ( iElementValue )
+            {
+            if( !desName.CompareF( KTitle ) )
+                {
+                delete iTitleBuf; iTitleBuf = NULL;
+                iTitleBuf = iElementValue;
+                iElementValue = NULL;
+                }
+            else if( !desName.CompareF( KClass ) )
+                {
+                obj->SetObjectClass( *iElementValue );                
+                iObjectClass = EFalse;
+                if( iFormatString )
+                    {
+                    SetIconIndex( *obj );
+                    }                
+                }
+            else
+                {               
+                }          
+            }
+        else
+            {
+            }    
+        
+        delete iElementValue; iElementValue = NULL;    
+        }    
+    __LOG( "CUPnPXMLParserLite::OnEndElementL(), end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnContentL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnContentL( const TDesC8& aBytes, TInt aErrorCode )
+    {
+    __LOG( "CUPnPXMLParserLite::OnContentL(), begin" );
+    if ( !iStack->Count() || aErrorCode != KErrNone )
+        {
+        return;
+        }
+    
+    if( iTitle || iObjectClass ) // We are only interested in title or
+                                 // object class!
+        {
+        if( !iElementValue ) //if 1st time
+            {
+            iElementValue = HBufC8::NewL(aBytes.Length());
+            iElementValue->Des().Copy(aBytes); 
+            }
+        else
+            {
+            HBufC8* previousValue = iElementValue;
+            iElementValue = HBufC8::NewL( previousValue->Des().Length() +
+                                          aBytes.Length() );
+            iElementValue->Des().Append( *previousValue );
+            iElementValue->Des().Append( aBytes );
+            delete previousValue;
+            }         
+        }
+    
+    __LOG( "CUPnPXMLParserLite::OnContentL(), end" );
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnStartPrefixMappingL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnStartPrefixMappingL( const RString& /*aPrefix*/, 
+                                               const RString& /*aUri*/, 
+                                               TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnEndPrefixMappingL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnEndPrefixMappingL( const RString& /*aPrefix*/, 
+                                             TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnIgnorableWhiteSpaceL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, 
+                                                TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnSkippedEntityL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnSkippedEntityL( const RString& /*aName*/, 
+                                          TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnProcessingInstructionL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnProcessingInstructionL( const TDesC8& /*aTarget*/, 
+                                                  const TDesC8& /*aData*/, 
+                                                  TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::OnError
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::OnError( TInt /*aErrorCode*/ )
+    {
+    // No implementation needed
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::GetExtendedInterface
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+TAny* CUPnPXMLParserLite::GetExtendedInterface( const TInt32 /*aUid*/ )
+    {    
+    // No implementation needed
+    return NULL;
+    }
+
+// --------------------------------------------------------------------------
+// CUPnPXMLParserLite::SetAttributesL
+// See upnpxmlparser.h
+// --------------------------------------------------------------------------
+void CUPnPXMLParserLite::SetAttributesL( CUpnpObjectLite& aObject, 
+    const RAttributeArray& aAttributes )
+    {
+    __LOG( "CUPnPXMLParserLite::SetAttributesL" );
+    
+    if ( iStack->Count() )
+        {
+        // Object has a parent.
+        // Should not really happen
+        __LOG( "Object has a parent!" );
+        __PANICD(__FILE__, __LINE__);      
+        }
+        
+    RAttribute attribute;
+    TInt count = aAttributes.Count();
+    for ( TInt i = 0 ; i < count; i++ ) // Read attributes.
+        {
+        attribute = aAttributes[ i ];
+        const TDesC8& name = attribute.Attribute().LocalName().DesC();
+        
+        if( !name.CompareF( KId ) )
+            {
+            aObject.SetObjectIdL( attribute.Value().DesC() );
+            }
+        }
+    __LOG( "CUPnPXMLParserLite::SetAttributesL - End" );
+    }
+
+void CUPnPXMLParserLite::SetIconIndex( const CUpnpObjectLite& aObject )
+    {
+    if( aObject.IsTypeOf( CUpnpObjectLite::EContainer ) )
+        {
+        iFormatString->Des().Replace( 0, 1, KIndexContainer );
+        }
+    else if( aObject.IsTypeOf( CUpnpObjectLite::EMusicItem ) )
+        {
+        iFormatString->Des().Replace( 0, 1, KIndexAudio );
+        }
+    else if( aObject.IsTypeOf( CUpnpObjectLite::EImageItem ) )
+        {
+        iFormatString->Des().Replace( 0, 1, KIndexImage );
+        }
+    else if( aObject.IsTypeOf( CUpnpObjectLite::EVideoItem ) )
+        {
+        iFormatString->Des().Replace( 0, 1, KIndexVideo );
+        }
+    else
+        {
+        // Other
+        iFormatString->Des().Replace( 0, 1, KIndexOther );
+        }    
+    }
+        
+// end of file
+
+