ncdengine/provider/protocol/src/ncdparserimpl.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   CNcdParserImpl implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <xml/parser.h>
       
    20 #include <xml/documentparameters.h>
       
    21 #include <xml/taginfo.h>
       
    22 #include <xml/attribute.h>
       
    23 
       
    24 #include <s32file.h>
       
    25 
       
    26 #include "ncdparserimpl.h"
       
    27 #include "ncdparserobserverbundleimpl.h"
       
    28 #include "ncdtoplevelparser.h"
       
    29 #include "ncdprotocolutils.h"
       
    30 #include "catalogsdebug.h"
       
    31 #include "ncdprotocoldefaultobserver.h"
       
    32 
       
    33 
       
    34 // Input buffer grow size for CBufSeg when appending new xml data in async mode
       
    35 const TInt KInputBufferGrowSize( 4096 );
       
    36 
       
    37 // Size of the buffer for the data to be processed in one async step.
       
    38 // This is an important figure as it determines the time used in the parser
       
    39 // in each step. Too big -> too unresponsive a system, too small --> too slow
       
    40 // a parsing operation.
       
    41 const TInt KFeedBufferSize( 1024 );
       
    42 
       
    43 CNcdParserImpl* CNcdParserImpl::NewL( 
       
    44     MNcdProtocolDefaultObserver* aDefaultObserver )
       
    45     {
       
    46     CNcdParserImpl* self = new(ELeave) CNcdParserImpl( aDefaultObserver );
       
    47     CleanupStack::PushL( self );
       
    48     self->ConstructL();
       
    49     CleanupStack::Pop( self );
       
    50     return self;
       
    51     }
       
    52 
       
    53 
       
    54 CNcdParserImpl::CNcdParserImpl( 
       
    55     MNcdProtocolDefaultObserver* aDefaultObserver  )
       
    56     : CActive( EPriorityStandard ), 
       
    57       iDefaultObserver( aDefaultObserver )
       
    58     {
       
    59     CActiveScheduler::Add( this );
       
    60     }
       
    61 
       
    62 CNcdParserImpl::~CNcdParserImpl()
       
    63     {
       
    64     DLTRACEIN((""));
       
    65     CancelParsing();
       
    66     
       
    67     delete iXmlParser;
       
    68     
       
    69     DLINFO((""));
       
    70     delete iSubParser;
       
    71     
       
    72     DLINFO((""));
       
    73     delete iInputBuffer;
       
    74     DLINFO((""));
       
    75     delete iFeedBuffer;
       
    76     DLINFO((""));
       
    77     delete iObservers;
       
    78     DLINFO((""));
       
    79     delete iDefaultObserver;
       
    80     DLTRACEOUT((""));
       
    81     }
       
    82 
       
    83 void CNcdParserImpl::ConstructL()
       
    84     {
       
    85     iObservers = CNcdParserObserverBundleImpl::NewL( iDefaultObserver );
       
    86     }
       
    87 
       
    88 
       
    89 
       
    90 MNcdParserObserverBundle& CNcdParserImpl::Observers() const
       
    91     {
       
    92     return *iObservers;
       
    93     }
       
    94 
       
    95 MNcdProtocolDefaultObserver& CNcdParserImpl::DefaultObserver() const
       
    96     {
       
    97     return *iDefaultObserver;
       
    98     }
       
    99 
       
   100 
       
   101 void CNcdParserImpl::BeginSyncL()
       
   102     {
       
   103     DLTRACEIN((""));    
       
   104     BeginSyncL( NULL );
       
   105     }
       
   106 
       
   107 
       
   108 void CNcdParserImpl::BeginSyncL( CNcdSubParser* aSubParser )
       
   109     {
       
   110     DLTRACEIN((""));
       
   111     iSynchronous = ETrue;
       
   112     BeginL( aSubParser );
       
   113     }
       
   114 
       
   115 
       
   116 void CNcdParserImpl::BeginAsyncL()
       
   117     {
       
   118     DLTRACEIN((""));
       
   119     BeginAsyncL( NULL );
       
   120     }
       
   121     
       
   122     
       
   123 void CNcdParserImpl::BeginAsyncL( CNcdSubParser* aSubParser )
       
   124     {
       
   125     DLTRACEIN((""));
       
   126     iSynchronous = EFalse;
       
   127     iPleaseFinish = EFalse;
       
   128     CleanupStack::PushL( aSubParser );
       
   129     delete iFeedBuffer;
       
   130     iFeedBuffer = 0;
       
   131     iFeedBuffer = HBufC8::NewL( KFeedBufferSize );
       
   132     CleanupStack::Pop( aSubParser );
       
   133     
       
   134     BeginL( aSubParser );
       
   135     }
       
   136     
       
   137     
       
   138 void CNcdParserImpl::BeginL( CNcdSubParser* aSubParser )
       
   139     {
       
   140     DLTRACEIN(("begin"));
       
   141 
       
   142     DASSERT( iObservers->ParserObserver() );
       
   143 
       
   144     iCancelled = EFalse;
       
   145 
       
   146     delete iSubParser;
       
   147     iSubParser = 0;
       
   148     
       
   149     if ( aSubParser ) 
       
   150         {
       
   151         DLTRACE(("Using given subparser"));
       
   152         iSubParser = aSubParser;
       
   153         }
       
   154     else 
       
   155         {   
       
   156         DLTRACE(("Using toplevel parser"));     
       
   157         iSubParser = CNcdTopLevelParser::NewL( 
       
   158             *iObservers, *this, 0 /*initial depth=0*/ );
       
   159         }
       
   160 
       
   161     delete iInputBuffer;
       
   162     iInputBuffer = 0;
       
   163     iInputBuffer = CBufSeg::NewL( KInputBufferGrowSize );
       
   164 
       
   165     delete iXmlParser;
       
   166     iXmlParser = 0;
       
   167 
       
   168     _LIT8( KXmlType, "text/xml" );
       
   169     iXmlParser = Xml::CParser::NewL( KXmlType, *iSubParser );
       
   170     iXmlParser->ParseBeginL();
       
   171     }
       
   172 
       
   173 void CNcdParserImpl::EndL()
       
   174     {
       
   175     DLTRACEIN(("data left=%d",iInputBuffer->Size()));
       
   176 
       
   177     if( iSynchronous || ( !IsActive() && iInputBuffer->Size() == 0 ) )
       
   178         {
       
   179         DLINFO(("sync end"));
       
   180         // After ParseEndL() OnError() call may come if the end of the data
       
   181         // is screwed.
       
   182         iXmlParser->ParseEndL();
       
   183 
       
   184         // Cancel callback removed according to users' wishes.
       
   185         if ( !iCancelled ) 
       
   186             iObservers->ParserObserver()->ParseCompleteL( KErrNone );
       
   187         }
       
   188     else
       
   189         {
       
   190         DLINFO(("please finish"));
       
   191         iPleaseFinish = ETrue;
       
   192         }
       
   193     DLTRACEOUT((""));
       
   194     }
       
   195 
       
   196 void CNcdParserImpl::SetOriginL( const TDesC& aOrigin )
       
   197     {
       
   198     iObservers->SetSessionOriginL( aOrigin );
       
   199     }
       
   200 
       
   201 void CNcdParserImpl::ParseL( const TDesC8& aData )
       
   202     {
       
   203     DLTRACEIN(("8-bit parse, length=%d",aData.Length()));
       
   204     DLINFO(("data=%S",&aData));
       
   205 
       
   206     if( iSynchronous )
       
   207         {
       
   208         iXmlParser->ParseL( aData );
       
   209         }
       
   210     else
       
   211         {
       
   212         DLINFO(("inserting, buffer size=%d",iInputBuffer->Size()));
       
   213         // Compress to free some memory if possible.
       
   214         iInputBuffer->Compress();
       
   215         iInputBuffer->InsertL( iInputBuffer->Size(), aData );
       
   216         if( ! IsActive() )
       
   217             {
       
   218             DLINFO(("activating"));
       
   219             iStatus = KRequestPending;
       
   220             SetActive();
       
   221             TRequestStatus* status = &iStatus;
       
   222             User::RequestComplete( status, KErrNone );
       
   223             }
       
   224         }
       
   225     }
       
   226 
       
   227 void CNcdParserImpl::ParseL( const TDesC16& aData )
       
   228     {
       
   229     DLTRACEIN(("16-bit parse, length=%d",aData.Length()));
       
   230     HBufC8* utf8 = NcdProtocolUtils::ConvertUnicodeToUtf8L( aData );
       
   231     CleanupStack::PushL( utf8 );
       
   232     ParseL( *utf8 );
       
   233     CleanupStack::PopAndDestroy( utf8 );
       
   234     }
       
   235 
       
   236 
       
   237 void CNcdParserImpl::SubParserFinishedL( const TDesC8& /*aTag*/, TInt /*aErrorCode*/ )
       
   238     {
       
   239     DLTRACE((""));
       
   240     }
       
   241 
       
   242 
       
   243 void CNcdParserImpl::CancelParsing()
       
   244     {
       
   245     DLTRACE(("active=%d", IsActive() ));
       
   246     if( !IsActive() )
       
   247         {
       
   248         iCancelled = ETrue;
       
   249         }
       
   250     
       
   251     // Prevent another Cancel-call while handling the first one
       
   252     if ( !iCancelled ) 
       
   253         {
       
   254         Cancel();
       
   255         }
       
   256     }
       
   257 
       
   258 void CNcdParserImpl::DoCancel()
       
   259     {
       
   260     DLTRACE(("iCancelled=%d", iCancelled ));
       
   261 
       
   262     // iCancelled is never ETrue when coming here unless someone
       
   263     // errorneously calls CNcdParserImpl::Cancel() from outside this class
       
   264     iCancelled = ETrue;
       
   265     TRAP_IGNORE( 
       
   266         {
       
   267         // this usually causes a parse error callback to the observer
       
   268         iXmlParser->ParseEndL();
       
   269         } );
       
   270     }
       
   271 
       
   272 TInt CNcdParserImpl::RunError( TInt aError )
       
   273     {
       
   274     DLERROR(("Fatal parser error %d",aError));
       
   275     iObservers->ParserObserver()->ParseError( aError );
       
   276     return KErrNone;
       
   277     }
       
   278 
       
   279 void CNcdParserImpl::RunL()
       
   280     {
       
   281     TRequestStatus* status = &iStatus;
       
   282     DLTRACEIN(("data left=%d status=%d",iInputBuffer->Size(),status->Int()));
       
   283 
       
   284     if( iCancelled )
       
   285         {
       
   286         DLINFO(("user cancelled!"));
       
   287         return;
       
   288         }
       
   289 
       
   290     // @ Is it even possible to get != KErrNone here?
       
   291     if( status->Int() != KErrNone )
       
   292         {
       
   293         DLERROR(("RunL() error, canceling!"));
       
   294         CancelParsing();
       
   295         return;
       
   296         }
       
   297 
       
   298     if( iInputBuffer->Size() == 0 )
       
   299         {
       
   300         // All done.
       
   301         DLINFO(("all done"));
       
   302         if( iPleaseFinish )
       
   303             {
       
   304             EndL();
       
   305             }
       
   306         return;
       
   307         }
       
   308 
       
   309     TPtr8 buf = iFeedBuffer->Des();
       
   310     TInt length = buf.MaxSize();
       
   311     if( iInputBuffer->Size() < length )
       
   312         {
       
   313         length = iInputBuffer->Size();
       
   314         }
       
   315     iInputBuffer->Read( 0, buf, length );
       
   316     iInputBuffer->Delete( 0, buf.Length() );
       
   317     iXmlParser->ParseL( buf );
       
   318 
       
   319     // Next step
       
   320     
       
   321     // Check again if the parser is cancelled. It is possible since callbacks occur
       
   322     // as consequence of calling ParseL.
       
   323     if ( iCancelled ) 
       
   324         {
       
   325         return;
       
   326         }
       
   327         
       
   328     iStatus = KRequestPending;
       
   329     SetActive();
       
   330     User::RequestComplete( status, KErrNone );
       
   331 
       
   332     }
       
   333 
       
   334 
       
   335