--- /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);
+ }