diff -r 000000000000 -r 307788aac0a8 realtimenetprots/sipfw/SIP/Codec/src/CSIPTokenizer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/realtimenetprots/sipfw/SIP/Codec/src/CSIPTokenizer.cpp Tue Feb 02 01:03:15 2010 +0200 @@ -0,0 +1,329 @@ +// Copyright (c) 2004-2009 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: +// Name : CSIPTokenizer.cpp +// Part of : Codec +// Version : SIP/3.0 +// + + + + +#include "CSIPTokenizer.h" +#include "sipcodecerr.h" + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::NewL +// ----------------------------------------------------------------------------- +// +CSIPTokenizer* CSIPTokenizer::NewL( + const TDesC8& aValue, + const TChar& aSeparator, + TBool aIgnoreParenthesis, + TBool aIgnoreLastEmptyValue, + TBool aSkipSeparatorsBeforeAt) + { + CSIPTokenizer* self = + CSIPTokenizer::NewLC( aValue,aSeparator, aIgnoreParenthesis, + aIgnoreLastEmptyValue, aSkipSeparatorsBeforeAt ); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::NewLC +// ----------------------------------------------------------------------------- +// +CSIPTokenizer* CSIPTokenizer::NewLC( + const TDesC8& aValue, + const TChar& aSeparator, + TBool aIgnoreParenthesis, + TBool aIgnoreLastEmptyValue, + TBool aSkipSeparatorsBeforeAt) + { + __ASSERT_ALWAYS (aValue.Length() > 0, User::Leave (KErrSipCodecTokenizer)); + __ASSERT_ALWAYS (aSeparator != '\\', User::Leave (KErrSipCodecTokenizer)); + __ASSERT_ALWAYS (aSeparator != '"', User::Leave (KErrSipCodecTokenizer)); + __ASSERT_ALWAYS (aSeparator != '<', User::Leave (KErrSipCodecTokenizer)); + __ASSERT_ALWAYS (aSeparator != '>', User::Leave (KErrSipCodecTokenizer)); + if(!aIgnoreParenthesis) + { + __ASSERT_ALWAYS (aSeparator != '(', User::Leave(KErrSipCodecTokenizer)); + __ASSERT_ALWAYS (aSeparator != ')', User::Leave(KErrSipCodecTokenizer)); + } + + CSIPTokenizer* self = + new(ELeave)CSIPTokenizer(aValue,aSeparator,aIgnoreParenthesis, + aIgnoreLastEmptyValue, + aSkipSeparatorsBeforeAt ); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::CSIPTokenizer +// ----------------------------------------------------------------------------- +// +CSIPTokenizer::CSIPTokenizer(const TDesC8& aValue, + const TChar& aSeparator, + TBool aIgnoreParenthesis, + TBool aIgnoreLastEmptyValue, + TBool aSkipSeparatorsBeforeAt) +: iOriginalValue (aValue), + iLexer( aValue ), + iSeparator (aSeparator), + iPreviousWasBackSlash (EFalse), + iInQuotes (EFalse), + iInAngleBrackets (EFalse), + iInParenthesis (EFalse), + iIgnoreParenthesis (aIgnoreParenthesis), + iIgnoreLastEmptyValue ( aIgnoreLastEmptyValue ), + iSkipSeparatorsBeforeAt ( aSkipSeparatorsBeforeAt ) + { + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::ConstructL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::ConstructL() + { + iTokens = new(ELeave)CPtrC8Array(1); + TokenizeL(); + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::~CSIPTokenizer +// ----------------------------------------------------------------------------- +// +CSIPTokenizer::~CSIPTokenizer() + { + delete iTokens; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::Tokens +// ----------------------------------------------------------------------------- +// +CPtrC8Array& CSIPTokenizer::Tokens() + { + return *iTokens; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::TokenizeL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::TokenizeL() + { + TChar chr = iLexer.Get(); + + while (chr) + { + iParsedSoFar++; iTokenLength++; + if (chr == '\\') + { + // If the previous character was already a backslash, + // then it is quoting the current backslash. + iPreviousWasBackSlash = !iPreviousWasBackSlash; + } + else + { + switch (chr) + { + case '"' : HandleQuote(); break; + case '<' : HandleOpeningAngleBracketL(); break; + case '>' : HandleClosingAngleBracketL(); break; + case '(' : HandleOpeningParenthesis(); break; + case ')' : HandleClosingParenthesis(); break; + default: HandleOtherCharacterL(chr); break; + } + iPreviousWasBackSlash = EFalse; + } + chr = iLexer.Get(); + } + + CheckMatchingQuotesBracketsL(); + AddLastTokenL(); // Add the last token after all the other tokens. + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleQuote +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleQuote() + { + if (iPreviousWasBackSlash) + { + return; + } + + iInQuotes = !iInQuotes; + iQuoteCount++; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleOpeningAngleBracketL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleOpeningAngleBracketL() + { + if (iInQuotes) + { + return; // ignore + } + + // Nested angle brackets are not allowed + __ASSERT_ALWAYS (!iInAngleBrackets, + User::Leave (KErrSipCodecTokenizer)); + + iInAngleBrackets = ETrue; + iAngleBracketCount++; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleClosingAngleBracketL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleClosingAngleBracketL() + { + if (iInQuotes) + { + return; // ignore + } + + // Matching opening angle bracket has to exist + __ASSERT_ALWAYS (iInAngleBrackets, + User::Leave (KErrSipCodecTokenizer)); + + iInAngleBrackets = EFalse; + iAngleBracketCount++; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleOpeningParenthesis +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleOpeningParenthesis() + { + if (iInQuotes) + { + return; // ignore + } + + iInParenthesis = ETrue; + iParenthesisCount++; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleClosingParenthesis +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleClosingParenthesis() + { + if (iInQuotes) + { + return; // ignore + } + + iInParenthesis = EFalse; + iParenthesisCount++; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::CheckMatchingQuotesBracketsL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::CheckMatchingQuotesBracketsL() + { + __ASSERT_ALWAYS (iQuoteCount%2 == 0, + User::Leave (KErrSipCodecTokenizer)); + + __ASSERT_ALWAYS (iAngleBracketCount%2 == 0, + User::Leave (KErrSipCodecTokenizer)); + + if(!iIgnoreParenthesis) + { + __ASSERT_ALWAYS (iParenthesisCount%2 == 0, + User::Leave (KErrSipCodecTokenizer)); + } + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::HandleOtherCharacterL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::HandleOtherCharacterL(const TChar& aChr) + { + __ASSERT_ALWAYS (iTokenLength > 0, + User::Leave (KErrSipCodecTokenizer)); + + if (iInQuotes || + iInAngleBrackets || + (iInParenthesis && !iIgnoreParenthesis)) + { + return; + } + + if (aChr != iSeparator) + { + return; + } + + TPtrC8 remainder(iLexer.Remainder()); + if (aChr == iSeparator && + iSkipSeparatorsBeforeAt && + remainder.Locate('@') >= 0) + { + CSIPTokenizer* atChrTokenizer = + CSIPTokenizer::NewLC( + remainder, '@', EFalse, ETrue, EFalse); + + TInt atCount = atChrTokenizer->Tokens().Count() - 1; + + CleanupStack::PopAndDestroy(atChrTokenizer); + + if (atCount > 0) + { + return; // skip the separators before '@' + } + } + + TUint startPos = iParsedSoFar - iTokenLength; + TPtrC8 token (iOriginalValue.Mid(startPos, iTokenLength-1)); + iTokens->AppendL(token); + + // Start a new token + iTokenLength = 0; + } + +// ----------------------------------------------------------------------------- +// CSIPTokenizer::AddLastTokenL +// ----------------------------------------------------------------------------- +// +void CSIPTokenizer::AddLastTokenL() + { + if ( iIgnoreLastEmptyValue && !(iTokenLength > 0)) + { + return; + } + + __ASSERT_ALWAYS (iTokenLength > 0, + User::Leave (KErrSipCodecTokenizer)); + + TUint startPos = iParsedSoFar - iTokenLength; + TPtrC8 token (iOriginalValue.Mid(startPos, iTokenLength)); + + iTokens->AppendL(token); + }