codhandler/codeng/src/CodParser.cpp
changeset 0 dd21522fd290
child 10 a359256acfc6
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2002 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 the License "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: 
       
    15 *      Implementation of class TCodParser.   
       
    16 *      
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 
       
    23 #include "CodParser.h"
       
    24 #include "CodData.h"
       
    25 #include "CodError.h"
       
    26 #include "CodPanic.h"
       
    27 #include "CodLogger.h"
       
    28 
       
    29 // ================= CONSTANTS =======================
       
    30 
       
    31 // Characters.
       
    32 LOCAL_D const TText KCodSpace = 0x0020;         ///< Space.
       
    33 LOCAL_D const TText KCodHorizTab = 0x0009;      ///< Horizontal tab.
       
    34 LOCAL_D const TText KCodCarriageRet = 0x000d;   ///< Carriage return.
       
    35 LOCAL_D const TText KCodLineFeed = 0x000a;      ///< Line feed.
       
    36 LOCAL_D const TText KCodColon = ':';            ///< Colon.
       
    37 LOCAL_D const TText KCodLowControl = 0x001F;    ///< Lower Control characters.
       
    38 LOCAL_D const TText KCodUpControl = 0x007F;     ///< Upper Control character.
       
    39 
       
    40 // Attribute names.
       
    41 _LIT( KCodName, "COD-Name" );                       ///< COD-Name.
       
    42 _LIT( KCodVendor, "COD-Vendor" );                   ///< COD-Vendor.
       
    43 _LIT( KCodDescription, "COD-Description" );         ///< COD-Description.
       
    44 _LIT( KCodUrl, "COD-URL" );                         ///< COD-URL.
       
    45 _LIT( KCodSize, "COD-Size" );                       ///< COD-Size.
       
    46 _LIT( KCodType, "COD-Type" );                       ///< COD-Type.
       
    47 _LIT( KCodInstallNotify, "COD-Install-Notify" );    ///< COD-Install-Notify.
       
    48 _LIT( KCodNextUrl, "COD-Next-URL" );                ///< COD-Next-URL.
       
    49 _LIT( KCodNextUrlAtError, "COD-Next-URLatError" );  ///< COD-Next_URLatError.
       
    50 _LIT( KCodInfoUrl, "COD-Info-URL" );                ///< COD-Info-URL.
       
    51 _LIT( KCodPrice, "COD-Price" );                     ///< COD-Price.
       
    52 _LIT( KCodIcon, "COD-Icon" );                       ///< COD-Icon.
       
    53 
       
    54 // ================= MEMBER FUNCTIONS =======================
       
    55 
       
    56 // ---------------------------------------------------------
       
    57 // TCodParser::ParseL()
       
    58 // ---------------------------------------------------------
       
    59 //
       
    60 void TCodParser::ParseL( const TDesC& aBuf, CCodData& aData )
       
    61     {
       
    62     CLOG(( EParse, 2, _L("-> TCodParser::ParseL") ));
       
    63     CDUMP(( EParse, 2, _S("Buf:"), _S("    "), \
       
    64         (const TUint8*)aBuf.Ptr(), aBuf.Size() ));
       
    65     iError = KErrNone;
       
    66     iData = &aData;
       
    67     iBuf = &aBuf;
       
    68     iCurP = iBuf->Ptr();
       
    69     iEndP = iCurP + iBuf->Length();
       
    70     // Processing lines (attribute and value) until there is more lines to read.
       
    71     while ( AttrLineL() )
       
    72         {
       
    73         // Some compilers require empty controlled statement block instead of
       
    74         // just a semicolon.
       
    75         }
       
    76 
       
    77 #ifdef __TEST_COD_LOG
       
    78     TPtrC ptr16;
       
    79     TPtrC8 ptr8;
       
    80     CLOG(( EParse, 3, _L("TCodParser::ParseL data:") ));
       
    81     ptr16.Set( aData.Name() );
       
    82     CLOG(( EParse, 3, _L("  Name<%S>"), &ptr16 ));
       
    83     ptr16.Set( aData.Vendor() );
       
    84     CLOG(( EParse, 3, _L("  Vendor<%S>"), &ptr16 ));
       
    85     ptr16.Set( aData.Description() );
       
    86     CLOG(( EParse, 3, _L("  Desc<%S>"), &ptr16 ));
       
    87     CLOG(( EParse, 3, _L("  Size(%d)"), aData.Size() ));
       
    88     ptr8.Set( aData.InstallNotify() );
       
    89     CLOG(( EParse, 3, _L8("  InstNotif<%S>"), &ptr8 ));
       
    90     ptr8.Set( aData.NextUrl() );
       
    91     CLOG(( EParse, 3, _L8("  NextUrl<%S>"), &ptr8 ));
       
    92     ptr8.Set( aData.NextUrlAtError() );
       
    93     CLOG(( EParse, 3, _L8("  NextUrlAtErr<%S>"), &ptr8 ));
       
    94     ptr8.Set( aData.InfoUrl() );
       
    95     CLOG(( EParse, 3, _L8("  InfoUrl<%S>"), &ptr8 ));
       
    96     ptr16.Set( aData.Price() );
       
    97     CLOG(( EParse, 3, _L("  Price<%S>"), &ptr16 ));
       
    98     ptr8.Set( aData.Icon() );
       
    99     CLOG(( EParse, 3, _L8("  Icon<%S>"), &ptr8 ));
       
   100 #endif /* def __TEST_COD_LOG */
       
   101 
       
   102     // NULL data for clarity. These are never used later, but don't keep
       
   103     // pointers to objects which are out of reach.
       
   104     iBuf = NULL;
       
   105     iData = NULL;
       
   106     iCurP = NULL;
       
   107     iEndP = NULL;
       
   108     User::LeaveIfError( iError );
       
   109     CLOG(( EParse, 2, _L("<- TCodParser::ParseL") ));
       
   110     }
       
   111 
       
   112 // ---------------------------------------------------------
       
   113 // TCodParser::AttrLineL()
       
   114 // ---------------------------------------------------------
       
   115 //
       
   116 TBool TCodParser::AttrLineL()
       
   117     {
       
   118     SkipWhiteSpace();  // Skip lines which contain only WS and LF at the end.
       
   119     while ( IsEndOfLine() )
       
   120         {
       
   121         NextLine();
       
   122         SkipWhiteSpace();
       
   123         }
       
   124     TBool ok( ETrue );
       
   125     if ( iCurP < iEndP )
       
   126         {
       
   127         // Still has something to read.
       
   128         switch( AttrName() )
       
   129             {
       
   130             case ECodName:
       
   131                 {
       
   132                 if ( Colon() )
       
   133                     {
       
   134                     ok = iData->SetNameL( AttrValue() );
       
   135                     EndOfLine();
       
   136                     }
       
   137                 break;
       
   138                 }
       
   139 
       
   140             case ECodVendor:
       
   141                 {
       
   142                 if ( Colon() )
       
   143                     {
       
   144                     ok = iData->SetVendorL( AttrValue() );
       
   145                     EndOfLine();
       
   146                     }
       
   147                 break;
       
   148                 }
       
   149 
       
   150             case ECodDescription:
       
   151                 {
       
   152                 if ( Colon() )
       
   153                     {
       
   154                     ok = iData->SetDescriptionL( AttrValue() );
       
   155                     EndOfLine();
       
   156                     }
       
   157                 break;
       
   158                 }
       
   159 
       
   160             case ECodSize:
       
   161                 {
       
   162                 if ( Colon() )
       
   163                     {
       
   164                     // Parse as TUint - negative not allowed.
       
   165                     TUint size;
       
   166                     TLex lex( AttrValue() );
       
   167                     if ( !lex.Val( size ) )
       
   168                         {
       
   169                         iData->SetSize( size );
       
   170                         }
       
   171                     else
       
   172                         {
       
   173                         ok = EFalse;
       
   174                         }
       
   175                     EndOfLine();
       
   176                     }
       
   177                 break;
       
   178                 }
       
   179 
       
   180             case ECodInstallNotify:
       
   181                 {
       
   182                 if ( Colon() )
       
   183                     {
       
   184                     ok = iData->SetInstallNotifyL( AttrValue() );
       
   185                     EndOfLine();
       
   186                     }
       
   187                 break;
       
   188                 }
       
   189 
       
   190             case ECodNextUrl:
       
   191                 {
       
   192                 if ( Colon() )
       
   193                     {
       
   194                     ok = iData->SetNextUrlL( AttrValue() );
       
   195                     EndOfLine();
       
   196                     }
       
   197                 break;
       
   198                 }
       
   199 
       
   200             case ECodNextUrlAtError:
       
   201                 {
       
   202                 if ( Colon() )
       
   203                     {
       
   204                     ok = iData->SetNextUrlAtErrorL( AttrValue() );
       
   205                     EndOfLine();
       
   206                     }
       
   207                 break;
       
   208                 }
       
   209 
       
   210             case ECodInfoUrl:
       
   211                 {
       
   212                 if ( Colon() )
       
   213                     {
       
   214                     ok = iData->SetInfoUrlL( AttrValue() );
       
   215                     EndOfLine();
       
   216                     }
       
   217                 break;
       
   218                 }
       
   219 
       
   220             case ECodPrice:
       
   221                 {
       
   222                 if ( Colon() )
       
   223                     {
       
   224                     ok = iData->SetPriceL( AttrValue() );
       
   225                     EndOfLine();
       
   226                     }
       
   227                 break;
       
   228                 }
       
   229 
       
   230             case ECodIcon:
       
   231                 {
       
   232                 if ( Colon() )
       
   233                     {
       
   234                     ok = iData->SetIconL( AttrValue() );
       
   235                     EndOfLine();
       
   236                     }
       
   237                 break;
       
   238                 }
       
   239 
       
   240             case ECodUnknownAttr:
       
   241                 {
       
   242                 // Name unknown; check colon anyway (syntax check).
       
   243                 ok = Colon();
       
   244                 // Rest of the line goes unchecked.
       
   245                 break;
       
   246                 }
       
   247 
       
   248             default:
       
   249                 {
       
   250                 // Unexpected value.
       
   251                 CodPanic( ECodInternal );
       
   252                 }
       
   253 
       
   254             }
       
   255         if ( !ok )
       
   256             {
       
   257             Error( KErrCodInvalidDescriptor );
       
   258             }
       
   259         NextLine();     // Step past LF.
       
   260         return ETrue;   // More lines to go.
       
   261         }
       
   262     else
       
   263         {
       
   264         // EOF reached; done.
       
   265         // Note: not expecting EOF in any other place than here (well-formed
       
   266         // COD has complete attrlines. If EOF is found some other place, it
       
   267         // is a syntax error.
       
   268         return EFalse;
       
   269         }
       
   270     }
       
   271 
       
   272 // ---------------------------------------------------------
       
   273 // TCodParser::AttrName()
       
   274 // ---------------------------------------------------------
       
   275 //
       
   276 
       
   277 TCodParser::TCodAttr TCodParser::AttrName()
       
   278     {
       
   279     TCodAttr attr( ECodUnknownAttr );
       
   280 
       
   281     const TText* start = iCurP;
       
   282     while
       
   283         (
       
   284             iCurP < iEndP &&
       
   285             !IsControl() &&
       
   286             !IsSeparator() &&
       
   287             *iCurP != KCodCarriageRet &&
       
   288             *iCurP != KCodLineFeed
       
   289         )
       
   290         {
       
   291         iCurP++;
       
   292         }
       
   293 
       
   294     TPtrC token( start, iCurP - start );
       
   295     if ( !token.Length() )
       
   296         {
       
   297         Error( KErrCodInvalidDescriptor );
       
   298         }
       
   299     else if ( !token.Compare( KCodName ) )
       
   300         {
       
   301         attr = ECodName;
       
   302         }
       
   303     else if ( !token.Compare( KCodVendor ) )
       
   304         {
       
   305         attr = ECodVendor;
       
   306         }
       
   307     else if ( !token.Compare( KCodDescription ) )
       
   308         {
       
   309         attr = ECodDescription;
       
   310         }
       
   311     else if ( !token.Compare( KCodUrl ) )
       
   312         {
       
   313         attr = ECodUrl;
       
   314         }
       
   315     else if ( !token.Compare( KCodSize ) )
       
   316         {
       
   317         attr = ECodSize;
       
   318         }
       
   319     else if ( !token.Compare( KCodType ) )
       
   320         {
       
   321         attr = ECodType;
       
   322         }
       
   323     else if ( !token.Compare( KCodInstallNotify ) )
       
   324         {
       
   325         attr = ECodInstallNotify;
       
   326         }
       
   327     else if ( !token.Compare( KCodNextUrl ) )
       
   328         {
       
   329         attr = ECodNextUrl;
       
   330         }
       
   331     else if ( !token.Compare( KCodNextUrlAtError ) )
       
   332         {
       
   333         attr = ECodNextUrlAtError;
       
   334         }
       
   335     else if ( !token.Compare( KCodInfoUrl ) )
       
   336         {
       
   337         attr = ECodInfoUrl;
       
   338         }
       
   339     else if ( !token.Compare( KCodPrice ) )
       
   340         {
       
   341         attr = ECodPrice;
       
   342         }
       
   343     else if ( !token.Compare( KCodIcon ) )
       
   344         {
       
   345         attr = ECodIcon;
       
   346         }
       
   347 
       
   348     CLOG(( EParse, 4, _L("TCodParser::AttrName token<%S> attr(%d)"), \
       
   349         &token, attr ));
       
   350     return attr;
       
   351     }
       
   352 
       
   353 // ---------------------------------------------------------
       
   354 // TCodParser::AttrValue()
       
   355 // ---------------------------------------------------------
       
   356 //
       
   357 TPtrC TCodParser::AttrValue()
       
   358     {
       
   359     const TText* start = iCurP;
       
   360     const TText* trailingWs = NULL;
       
   361     while ( iCurP < iEndP && (IsValueChar() || IsWhiteSpace()) )
       
   362         {
       
   363         if ( IsWhiteSpace() && !trailingWs )
       
   364             {
       
   365             // Whitespace starts here; may be trailing WS.
       
   366             trailingWs = iCurP;
       
   367             }
       
   368         else if ( IsValueChar() )
       
   369             {
       
   370             // Possible previous WS is not trailing: value chars follow.
       
   371             trailingWs = NULL;
       
   372             }
       
   373         iCurP++;
       
   374         }
       
   375     if ( trailingWs )
       
   376         {
       
   377         // There was trailing WS. Back up to that position.
       
   378         iCurP = trailingWs;
       
   379         // Trailing WS should be trailing, not leading. This method expects
       
   380         // to be called with WS skipped first!
       
   381         __ASSERT_DEBUG( trailingWs > start, CodPanic( ECodInternal ) );
       
   382         }
       
   383     TPtrC token( start, iCurP - start );
       
   384     CLOG(( EParse, 4, _L("TCodParser::AttrValue token<%S>"), &token ));
       
   385     return token;
       
   386     }
       
   387 
       
   388 // ---------------------------------------------------------
       
   389 // TCodParser::SkipWhiteSpace()
       
   390 // ---------------------------------------------------------
       
   391 //
       
   392 void TCodParser::SkipWhiteSpace()
       
   393     {
       
   394     while ( iCurP < iEndP && IsWhiteSpace() )
       
   395         {
       
   396         iCurP++;
       
   397         }
       
   398     }
       
   399 
       
   400 // ---------------------------------------------------------
       
   401 // TCodParser::NextLine()
       
   402 // ---------------------------------------------------------
       
   403 //
       
   404 void TCodParser::NextLine()
       
   405     {
       
   406     while ( iCurP < iEndP && *iCurP != KCodLineFeed )
       
   407         {
       
   408         iCurP++;
       
   409         }
       
   410     if ( iCurP < iEndP ) // skip last LF.
       
   411         {
       
   412         iCurP++;
       
   413         }
       
   414     }
       
   415 
       
   416 // ---------------------------------------------------------
       
   417 // TCodParser::EndOfLine()
       
   418 // ---------------------------------------------------------
       
   419 //
       
   420 void TCodParser::EndOfLine()
       
   421     {
       
   422     while ( iCurP < iEndP )
       
   423         {
       
   424         if ( *iCurP == KCodLineFeed )
       
   425             {
       
   426             // LF found -> done. This is the lookahead.
       
   427             break;
       
   428             }
       
   429         else if ( *iCurP == KCodCarriageRet )
       
   430             {
       
   431             // CR found -> may be CR LF (that's OK) or CR alone (error).
       
   432             if ( iCurP + 1 < iEndP && *(iCurP + 1) == KCodLineFeed )
       
   433                 {
       
   434                 // CR LF found-> done. Lookahead is the LF.
       
   435                 iCurP ++;
       
   436                 break;
       
   437                 }
       
   438             // CR without LF is unexpected.
       
   439             Error( KErrCodInvalidDescriptor );
       
   440             }
       
   441         if ( IsValueChar() || IsControl() )
       
   442             {
       
   443             // Valuechar or CTL unexpected.
       
   444             Error( KErrCodInvalidDescriptor );
       
   445             }
       
   446         iCurP++;
       
   447         }
       
   448     }
       
   449 
       
   450 // ---------------------------------------------------------
       
   451 // TCodParser::Colon()
       
   452 // ---------------------------------------------------------
       
   453 //
       
   454 TBool TCodParser::Colon()
       
   455     {
       
   456     TBool colon( EFalse );
       
   457     SkipWhiteSpace();
       
   458     if ( iCurP < iEndP && *iCurP == KCodColon )
       
   459         {
       
   460         // OK it's a colon.
       
   461         colon = ETrue;
       
   462         iCurP++;
       
   463         }
       
   464     else
       
   465         {
       
   466         // Expected a colon.
       
   467         Error( KErrCodInvalidDescriptor );
       
   468         }
       
   469     SkipWhiteSpace();
       
   470     return colon;
       
   471     }
       
   472 
       
   473 // ---------------------------------------------------------
       
   474 // TCodParser::IsValueChar()
       
   475 // ---------------------------------------------------------
       
   476 //
       
   477 TBool TCodParser::IsValueChar() const
       
   478     {
       
   479     __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
       
   480     return ( !(IsControl() || IsWhiteSpace()) );
       
   481     }
       
   482 
       
   483 // ---------------------------------------------------------
       
   484 // TCodParser::IsControl()
       
   485 // ---------------------------------------------------------
       
   486 //
       
   487 TBool TCodParser::IsControl() const
       
   488     {
       
   489     __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
       
   490     return ( (*iCurP <= KCodLowControl) || (*iCurP == KCodUpControl) );
       
   491     }
       
   492 
       
   493 // ---------------------------------------------------------
       
   494 // TCodParser::IsWhiteSpace()
       
   495 // ---------------------------------------------------------
       
   496 //
       
   497 TBool TCodParser::IsWhiteSpace() const
       
   498     {
       
   499     __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
       
   500     return ( (*iCurP == KCodSpace) || (*iCurP == KCodHorizTab) );
       
   501     }
       
   502 
       
   503 // ---------------------------------------------------------
       
   504 // TCodParser::IsSeparator()
       
   505 // ---------------------------------------------------------
       
   506 //
       
   507 TBool TCodParser::IsSeparator() const
       
   508     {
       
   509     __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
       
   510     return
       
   511         (
       
   512             IsWhiteSpace()  ||
       
   513             *iCurP == '('   ||
       
   514             *iCurP == ')'   ||
       
   515             *iCurP == '<'   ||
       
   516             *iCurP == '>'   ||
       
   517             *iCurP == '@'   ||
       
   518             *iCurP == ','   ||
       
   519             *iCurP == ';'   ||
       
   520             *iCurP == ':'   ||
       
   521             *iCurP == '\''  ||
       
   522             *iCurP == '\"'  ||
       
   523             *iCurP == '/'   ||
       
   524             *iCurP == '['   ||
       
   525             *iCurP == ']'   ||
       
   526             *iCurP == '?'   ||
       
   527             *iCurP == '='   ||
       
   528             *iCurP == '{'   ||
       
   529             *iCurP == '}'
       
   530         );
       
   531     }
       
   532 
       
   533 // ---------------------------------------------------------
       
   534 // TCodParser::IsEndOfLine()
       
   535 // ---------------------------------------------------------
       
   536 //
       
   537 TBool TCodParser::IsEndOfLine() const
       
   538     {
       
   539     const TText* CurP = iCurP;
       
   540     if ( CurP < iEndP  && *CurP == KCodCarriageRet )
       
   541         {
       
   542         CurP++;
       
   543         }
       
   544     if ( CurP < iEndP  && *CurP == KCodLineFeed )
       
   545         {
       
   546         return ETrue;
       
   547         }
       
   548     return EFalse;
       
   549     }