--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/codhandler/codeng/src/CodParser.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,549 @@
+/*
+* 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 the License "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:
+* Implementation of class TCodParser.
+*
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "CodParser.h"
+#include "CodData.h"
+#include "CodError.h"
+#include "CodPanic.h"
+#include "CodLogger.h"
+
+// ================= CONSTANTS =======================
+
+// Characters.
+LOCAL_D const TText KCodSpace = 0x0020; ///< Space.
+LOCAL_D const TText KCodHorizTab = 0x0009; ///< Horizontal tab.
+LOCAL_D const TText KCodCarriageRet = 0x000d; ///< Carriage return.
+LOCAL_D const TText KCodLineFeed = 0x000a; ///< Line feed.
+LOCAL_D const TText KCodColon = ':'; ///< Colon.
+LOCAL_D const TText KCodLowControl = 0x001F; ///< Lower Control characters.
+LOCAL_D const TText KCodUpControl = 0x007F; ///< Upper Control character.
+
+// Attribute names.
+_LIT( KCodName, "COD-Name" ); ///< COD-Name.
+_LIT( KCodVendor, "COD-Vendor" ); ///< COD-Vendor.
+_LIT( KCodDescription, "COD-Description" ); ///< COD-Description.
+_LIT( KCodUrl, "COD-URL" ); ///< COD-URL.
+_LIT( KCodSize, "COD-Size" ); ///< COD-Size.
+_LIT( KCodType, "COD-Type" ); ///< COD-Type.
+_LIT( KCodInstallNotify, "COD-Install-Notify" ); ///< COD-Install-Notify.
+_LIT( KCodNextUrl, "COD-Next-URL" ); ///< COD-Next-URL.
+_LIT( KCodNextUrlAtError, "COD-Next-URLatError" ); ///< COD-Next_URLatError.
+_LIT( KCodInfoUrl, "COD-Info-URL" ); ///< COD-Info-URL.
+_LIT( KCodPrice, "COD-Price" ); ///< COD-Price.
+_LIT( KCodIcon, "COD-Icon" ); ///< COD-Icon.
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// TCodParser::ParseL()
+// ---------------------------------------------------------
+//
+void TCodParser::ParseL( const TDesC& aBuf, CCodData& aData )
+ {
+ CLOG(( EParse, 2, _L("-> TCodParser::ParseL") ));
+ CDUMP(( EParse, 2, _S("Buf:"), _S(" "), \
+ (const TUint8*)aBuf.Ptr(), aBuf.Size() ));
+ iError = KErrNone;
+ iData = &aData;
+ iBuf = &aBuf;
+ iCurP = iBuf->Ptr();
+ iEndP = iCurP + iBuf->Length();
+ // Processing lines (attribute and value) until there is more lines to read.
+ while ( AttrLineL() )
+ {
+ // Some compilers require empty controlled statement block instead of
+ // just a semicolon.
+ }
+
+#ifdef __TEST_COD_LOG
+ TPtrC ptr16;
+ TPtrC8 ptr8;
+ CLOG(( EParse, 3, _L("TCodParser::ParseL data:") ));
+ ptr16.Set( aData.Name() );
+ CLOG(( EParse, 3, _L(" Name<%S>"), &ptr16 ));
+ ptr16.Set( aData.Vendor() );
+ CLOG(( EParse, 3, _L(" Vendor<%S>"), &ptr16 ));
+ ptr16.Set( aData.Description() );
+ CLOG(( EParse, 3, _L(" Desc<%S>"), &ptr16 ));
+ CLOG(( EParse, 3, _L(" Size(%d)"), aData.Size() ));
+ ptr8.Set( aData.InstallNotify() );
+ CLOG(( EParse, 3, _L8(" InstNotif<%S>"), &ptr8 ));
+ ptr8.Set( aData.NextUrl() );
+ CLOG(( EParse, 3, _L8(" NextUrl<%S>"), &ptr8 ));
+ ptr8.Set( aData.NextUrlAtError() );
+ CLOG(( EParse, 3, _L8(" NextUrlAtErr<%S>"), &ptr8 ));
+ ptr8.Set( aData.InfoUrl() );
+ CLOG(( EParse, 3, _L8(" InfoUrl<%S>"), &ptr8 ));
+ ptr16.Set( aData.Price() );
+ CLOG(( EParse, 3, _L(" Price<%S>"), &ptr16 ));
+ ptr8.Set( aData.Icon() );
+ CLOG(( EParse, 3, _L8(" Icon<%S>"), &ptr8 ));
+#endif /* def __TEST_COD_LOG */
+
+ // NULL data for clarity. These are never used later, but don't keep
+ // pointers to objects which are out of reach.
+ iBuf = NULL;
+ iData = NULL;
+ iCurP = NULL;
+ iEndP = NULL;
+ User::LeaveIfError( iError );
+ CLOG(( EParse, 2, _L("<- TCodParser::ParseL") ));
+ }
+
+// ---------------------------------------------------------
+// TCodParser::AttrLineL()
+// ---------------------------------------------------------
+//
+TBool TCodParser::AttrLineL()
+ {
+ SkipWhiteSpace(); // Skip lines which contain only WS and LF at the end.
+ while ( IsEndOfLine() )
+ {
+ NextLine();
+ SkipWhiteSpace();
+ }
+ TBool ok( ETrue );
+ if ( iCurP < iEndP )
+ {
+ // Still has something to read.
+ switch( AttrName() )
+ {
+ case ECodName:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetNameL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodVendor:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetVendorL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodDescription:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetDescriptionL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodSize:
+ {
+ if ( Colon() )
+ {
+ // Parse as TUint - negative not allowed.
+ TUint size;
+ TLex lex( AttrValue() );
+ if ( !lex.Val( size ) )
+ {
+ iData->SetSize( size );
+ }
+ else
+ {
+ ok = EFalse;
+ }
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodInstallNotify:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetInstallNotifyL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodNextUrl:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetNextUrlL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodNextUrlAtError:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetNextUrlAtErrorL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodInfoUrl:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetInfoUrlL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodPrice:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetPriceL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodIcon:
+ {
+ if ( Colon() )
+ {
+ ok = iData->SetIconL( AttrValue() );
+ EndOfLine();
+ }
+ break;
+ }
+
+ case ECodUnknownAttr:
+ {
+ // Name unknown; check colon anyway (syntax check).
+ ok = Colon();
+ // Rest of the line goes unchecked.
+ break;
+ }
+
+ default:
+ {
+ // Unexpected value.
+ CodPanic( ECodInternal );
+ }
+
+ }
+ if ( !ok )
+ {
+ Error( KErrCodInvalidDescriptor );
+ }
+ NextLine(); // Step past LF.
+ return ETrue; // More lines to go.
+ }
+ else
+ {
+ // EOF reached; done.
+ // Note: not expecting EOF in any other place than here (well-formed
+ // COD has complete attrlines. If EOF is found some other place, it
+ // is a syntax error.
+ return EFalse;
+ }
+ }
+
+// ---------------------------------------------------------
+// TCodParser::AttrName()
+// ---------------------------------------------------------
+//
+
+TCodParser::TCodAttr TCodParser::AttrName()
+ {
+ TCodAttr attr( ECodUnknownAttr );
+
+ const TText* start = iCurP;
+ while
+ (
+ iCurP < iEndP &&
+ !IsControl() &&
+ !IsSeparator() &&
+ *iCurP != KCodCarriageRet &&
+ *iCurP != KCodLineFeed
+ )
+ {
+ iCurP++;
+ }
+
+ TPtrC token( start, iCurP - start );
+ if ( !token.Length() )
+ {
+ Error( KErrCodInvalidDescriptor );
+ }
+ else if ( !token.Compare( KCodName ) )
+ {
+ attr = ECodName;
+ }
+ else if ( !token.Compare( KCodVendor ) )
+ {
+ attr = ECodVendor;
+ }
+ else if ( !token.Compare( KCodDescription ) )
+ {
+ attr = ECodDescription;
+ }
+ else if ( !token.Compare( KCodUrl ) )
+ {
+ attr = ECodUrl;
+ }
+ else if ( !token.Compare( KCodSize ) )
+ {
+ attr = ECodSize;
+ }
+ else if ( !token.Compare( KCodType ) )
+ {
+ attr = ECodType;
+ }
+ else if ( !token.Compare( KCodInstallNotify ) )
+ {
+ attr = ECodInstallNotify;
+ }
+ else if ( !token.Compare( KCodNextUrl ) )
+ {
+ attr = ECodNextUrl;
+ }
+ else if ( !token.Compare( KCodNextUrlAtError ) )
+ {
+ attr = ECodNextUrlAtError;
+ }
+ else if ( !token.Compare( KCodInfoUrl ) )
+ {
+ attr = ECodInfoUrl;
+ }
+ else if ( !token.Compare( KCodPrice ) )
+ {
+ attr = ECodPrice;
+ }
+ else if ( !token.Compare( KCodIcon ) )
+ {
+ attr = ECodIcon;
+ }
+
+ CLOG(( EParse, 4, _L("TCodParser::AttrName token<%S> attr(%d)"), \
+ &token, attr ));
+ return attr;
+ }
+
+// ---------------------------------------------------------
+// TCodParser::AttrValue()
+// ---------------------------------------------------------
+//
+TPtrC TCodParser::AttrValue()
+ {
+ const TText* start = iCurP;
+ const TText* trailingWs = NULL;
+ while ( iCurP < iEndP && (IsValueChar() || IsWhiteSpace()) )
+ {
+ if ( IsWhiteSpace() && !trailingWs )
+ {
+ // Whitespace starts here; may be trailing WS.
+ trailingWs = iCurP;
+ }
+ else if ( IsValueChar() )
+ {
+ // Possible previous WS is not trailing: value chars follow.
+ trailingWs = NULL;
+ }
+ iCurP++;
+ }
+ if ( trailingWs )
+ {
+ // There was trailing WS. Back up to that position.
+ iCurP = trailingWs;
+ // Trailing WS should be trailing, not leading. This method expects
+ // to be called with WS skipped first!
+ __ASSERT_DEBUG( trailingWs > start, CodPanic( ECodInternal ) );
+ }
+ TPtrC token( start, iCurP - start );
+ CLOG(( EParse, 4, _L("TCodParser::AttrValue token<%S>"), &token ));
+ return token;
+ }
+
+// ---------------------------------------------------------
+// TCodParser::SkipWhiteSpace()
+// ---------------------------------------------------------
+//
+void TCodParser::SkipWhiteSpace()
+ {
+ while ( iCurP < iEndP && IsWhiteSpace() )
+ {
+ iCurP++;
+ }
+ }
+
+// ---------------------------------------------------------
+// TCodParser::NextLine()
+// ---------------------------------------------------------
+//
+void TCodParser::NextLine()
+ {
+ while ( iCurP < iEndP && *iCurP != KCodLineFeed )
+ {
+ iCurP++;
+ }
+ if ( iCurP < iEndP ) // skip last LF.
+ {
+ iCurP++;
+ }
+ }
+
+// ---------------------------------------------------------
+// TCodParser::EndOfLine()
+// ---------------------------------------------------------
+//
+void TCodParser::EndOfLine()
+ {
+ while ( iCurP < iEndP )
+ {
+ if ( *iCurP == KCodLineFeed )
+ {
+ // LF found -> done. This is the lookahead.
+ break;
+ }
+ else if ( *iCurP == KCodCarriageRet )
+ {
+ // CR found -> may be CR LF (that's OK) or CR alone (error).
+ if ( iCurP + 1 < iEndP && *(iCurP + 1) == KCodLineFeed )
+ {
+ // CR LF found-> done. Lookahead is the LF.
+ iCurP ++;
+ break;
+ }
+ // CR without LF is unexpected.
+ Error( KErrCodInvalidDescriptor );
+ }
+ if ( IsValueChar() || IsControl() )
+ {
+ // Valuechar or CTL unexpected.
+ Error( KErrCodInvalidDescriptor );
+ }
+ iCurP++;
+ }
+ }
+
+// ---------------------------------------------------------
+// TCodParser::Colon()
+// ---------------------------------------------------------
+//
+TBool TCodParser::Colon()
+ {
+ TBool colon( EFalse );
+ SkipWhiteSpace();
+ if ( iCurP < iEndP && *iCurP == KCodColon )
+ {
+ // OK it's a colon.
+ colon = ETrue;
+ iCurP++;
+ }
+ else
+ {
+ // Expected a colon.
+ Error( KErrCodInvalidDescriptor );
+ }
+ SkipWhiteSpace();
+ return colon;
+ }
+
+// ---------------------------------------------------------
+// TCodParser::IsValueChar()
+// ---------------------------------------------------------
+//
+TBool TCodParser::IsValueChar() const
+ {
+ __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
+ return ( !(IsControl() || IsWhiteSpace()) );
+ }
+
+// ---------------------------------------------------------
+// TCodParser::IsControl()
+// ---------------------------------------------------------
+//
+TBool TCodParser::IsControl() const
+ {
+ __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
+ return ( (*iCurP <= KCodLowControl) || (*iCurP == KCodUpControl) );
+ }
+
+// ---------------------------------------------------------
+// TCodParser::IsWhiteSpace()
+// ---------------------------------------------------------
+//
+TBool TCodParser::IsWhiteSpace() const
+ {
+ __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
+ return ( (*iCurP == KCodSpace) || (*iCurP == KCodHorizTab) );
+ }
+
+// ---------------------------------------------------------
+// TCodParser::IsSeparator()
+// ---------------------------------------------------------
+//
+TBool TCodParser::IsSeparator() const
+ {
+ __ASSERT_DEBUG( iCurP < iEndP, CodPanic( ECodBufferOverread ) );
+ return
+ (
+ IsWhiteSpace() ||
+ *iCurP == '(' ||
+ *iCurP == ')' ||
+ *iCurP == '<' ||
+ *iCurP == '>' ||
+ *iCurP == '@' ||
+ *iCurP == ',' ||
+ *iCurP == ';' ||
+ *iCurP == ':' ||
+ *iCurP == '\'' ||
+ *iCurP == '\"' ||
+ *iCurP == '/' ||
+ *iCurP == '[' ||
+ *iCurP == ']' ||
+ *iCurP == '?' ||
+ *iCurP == '=' ||
+ *iCurP == '{' ||
+ *iCurP == '}'
+ );
+ }
+
+// ---------------------------------------------------------
+// TCodParser::IsEndOfLine()
+// ---------------------------------------------------------
+//
+TBool TCodParser::IsEndOfLine() const
+ {
+ const TText* CurP = iCurP;
+ if ( CurP < iEndP && *CurP == KCodCarriageRet )
+ {
+ CurP++;
+ }
+ if ( CurP < iEndP && *CurP == KCodLineFeed )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }