realtimenetprots/sipfw/SIP/Codec/src/CSIPTokenizer.cpp
changeset 0 307788aac0a8
--- /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);
+	}