diff -r 000000000000 -r dd21522fd290 codhandler/codeng/src/CodParser.cpp --- /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; + }