contentmgmt/referencedrmagent/RefTestAgent/localsdp/src/sdputil.cpp
changeset 66 8873e6835f7b
equal deleted inserted replaced
62:b23410e29e22 66:8873e6835f7b
       
     1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Name          : SdpUtil.cpp
       
    15 // Part of       : Local SDP Codec
       
    16 // Version       : 1.0
       
    17 //
       
    18 
       
    19 
       
    20 
       
    21 #include <s32strm.h>
       
    22 #include <in_sock.h>
       
    23 #include "sdputil.h"
       
    24 #include "sdpcodecstringconstants.h"
       
    25 #include "sdpcodecstringpool.h"
       
    26 #include "sdpcodecconstants.h"
       
    27 #include "_sdpdefs.h"
       
    28 
       
    29 // LOCAL CONSTANTS
       
    30 const TInt KMaxAddressLength = 256;
       
    31 _LIT8(KInvalidTokenCharacters, "\0\r\n\t ()<>@,;:");
       
    32 _LIT8(KInvalidByteStringCharacters, "\0\r\n");
       
    33 _LIT8(KWhitespaceCharacters, "\0\r\n \t");
       
    34 _LIT16(KWildAddr, "0.0.0.0");
       
    35     
       
    36 // -----------------------------------------------------------------------------
       
    37 // SdpUtil::IsValidCharSet
       
    38 // Generic checker to validate that string has only valid characters
       
    39 // -----------------------------------------------------------------------------
       
    40 //
       
    41 TBool SdpUtil::IsValidCharSet(
       
    42     const TDesC8& aIllegalChars,
       
    43     const TDesC8& aValue,
       
    44     TInt aStart,
       
    45     TInt aEnd)
       
    46 	{
       
    47 	TBool result = EFalse;
       
    48 	
       
    49 	if ( aIllegalChars.Length() > 0 && aStart >= 0 && 
       
    50          aEnd <= aValue.Length() && aStart < aEnd )
       
    51 		{
       
    52 		TInt comp = KErrNotFound;
       
    53 		while (comp == KErrNotFound && aStart < aEnd)
       
    54 			{
       
    55 			comp = aIllegalChars.Locate( aValue[aStart] );
       
    56 			++aStart;
       
    57 			}
       
    58 		result = ( comp == KErrNotFound );
       
    59 		}
       
    60 	else 
       
    61 		{
       
    62 		result = ( ( aStart < aEnd ) && 
       
    63                    ( aIllegalChars.Length() == 0 || aValue.Length() == 0 ) );
       
    64 		}
       
    65 
       
    66 	return result;
       
    67 	}
       
    68 
       
    69 // -----------------------------------------------------------------------------
       
    70 // SdpUtil::IsTokenList
       
    71 // Checks that token list is valid
       
    72 // -----------------------------------------------------------------------------
       
    73 //
       
    74 TBool SdpUtil::IsTokenList(
       
    75     const TDesC8& aValue )
       
    76 	{	
       
    77 	TBool atError = ( aValue.Length() == 0 );
       
    78     
       
    79     // Check that we are starting with valid character, not e.g. with space
       
    80     if ( !atError && 
       
    81          KInvalidTokenCharacters().Locate( aValue[0] ) != KErrNotFound )
       
    82         {
       
    83         atError = ETrue;
       
    84         }
       
    85     
       
    86     TLex8 lexer( aValue );
       
    87     // Go through the tokens to see that they are valid
       
    88     while ( !atError && !lexer.Eos() )
       
    89         {
       
    90         if ( !IsToken( lexer.NextToken() ) )
       
    91             {
       
    92             atError = ETrue;
       
    93             }   
       
    94         }
       
    95 
       
    96 	return !atError;
       
    97 	}
       
    98 
       
    99 // -----------------------------------------------------------------------------
       
   100 // SdpUtil::IsToken
       
   101 // Checks if aValue is valid token
       
   102 // -----------------------------------------------------------------------------
       
   103 //
       
   104 TBool SdpUtil::IsToken( 
       
   105     const TDesC8& aValue, 
       
   106     TInt aStart, 
       
   107     TInt aEnd)
       
   108 	{
       
   109 	return IsValidCharSet( KInvalidTokenCharacters, aValue, aStart, aEnd );
       
   110 	}
       
   111 
       
   112 // -----------------------------------------------------------------------------
       
   113 // SdpUtil::IsToken
       
   114 // Checks if aValue is valid token
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 TBool SdpUtil::IsToken(
       
   118     const TDesC8& aValue )
       
   119 	{
       
   120 	return IsValidCharSet( KInvalidTokenCharacters, aValue, 0, aValue.Length() );
       
   121 	}
       
   122 
       
   123 // -----------------------------------------------------------------------------
       
   124 // SdpUtil::IsByteString
       
   125 // Checks if aValue is valid byte string
       
   126 // -----------------------------------------------------------------------------
       
   127 //
       
   128 TBool SdpUtil::IsByteString(
       
   129     const TDesC8& aValue, 
       
   130     TInt aStart, 
       
   131     TInt aEnd )
       
   132 	{
       
   133 	return IsValidCharSet( KInvalidByteStringCharacters, aValue, aStart, aEnd );
       
   134 	}
       
   135 
       
   136 // -----------------------------------------------------------------------------
       
   137 // SdpUtil::IsByteString
       
   138 // Checks if aValue is valid byte string
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 TBool SdpUtil::IsByteString(
       
   142     const TDesC8& aValue )
       
   143 	{
       
   144 	return IsValidCharSet( KInvalidByteStringCharacters, aValue, 0, 
       
   145                            aValue.Length() );
       
   146 	}
       
   147 
       
   148 // -----------------------------------------------------------------------------
       
   149 // SdpUtil::IsTokenTextPair
       
   150 // Checks if aValue is valid pair ("valid token":"valid byte-string")
       
   151 // -----------------------------------------------------------------------------
       
   152 //
       
   153 TBool SdpUtil::IsTokenTextPair(
       
   154     const TDesC8& aValue, 
       
   155     TInt aStart,
       
   156     TInt aEnd )
       
   157 	{
       
   158 	// token ":" text
       
   159 	TBool result = EFalse;
       
   160 	if ( aStart >= 0 && aEnd <= aValue.Length() && aStart < aEnd )
       
   161 		{
       
   162 		TPtrC8 subVal = aValue.Mid( aStart, aEnd - aStart );
       
   163 		TInt colonPos = subVal.Locate( KColonChar );
       
   164 		result = colonPos != KErrNone &&
       
   165                  IsToken( subVal, 0, colonPos ) &&
       
   166                  IsByteString( subVal, colonPos + 1, subVal.Length() );
       
   167 		}
       
   168 	return result;
       
   169 	}
       
   170 
       
   171 // -----------------------------------------------------------------------------
       
   172 // SdpUtil::IsTokenTextPair
       
   173 // Checks if aValue is valid pair ("valid token":"valid byte-string")
       
   174 // -----------------------------------------------------------------------------
       
   175 //
       
   176 TBool SdpUtil::IsTokenTextPair(
       
   177     const TDesC8& aValue )
       
   178 	{
       
   179 	return IsTokenTextPair( aValue, 0, aValue.Length() );
       
   180 	}
       
   181 
       
   182 // -----------------------------------------------------------------------------
       
   183 // SdpUtil::IsNonWhitepce
       
   184 // Checks if aValue contains only non-whitespace characters
       
   185 // -----------------------------------------------------------------------------
       
   186 //
       
   187 TBool SdpUtil::IsNonWhitespace(
       
   188     const TDesC8& aValue )
       
   189 	{
       
   190 	return IsValidCharSet( KWhitespaceCharacters, aValue, 0, aValue.Length() );
       
   191 	}
       
   192 
       
   193 // -----------------------------------------------------------------------------
       
   194 // SdpUtil::IsValidNtpTime
       
   195 // Checks if aValue contains only non-whitespace characters
       
   196 // -----------------------------------------------------------------------------
       
   197 //
       
   198 TBool SdpUtil::IsValidNtpTime(
       
   199     const TDesC8& aValue )
       
   200 	{
       
   201 	// POS-DIGIT 9*DIGIT
       
   202 	TUint len = aValue.Length();
       
   203 	TBool result = len >= 10 && TChar( aValue[0] ) != TChar('0');
       
   204 	if ( result )
       
   205 		{
       
   206 		for ( TUint i( 0 ); result && i < len; i++)
       
   207 			{
       
   208 			TInt tmp = aValue[i] - '0';
       
   209 			result = ( tmp >= 0 && tmp <= 9 );
       
   210 			}
       
   211 		}
       
   212 	return result;
       
   213 	}
       
   214 
       
   215 // -----------------------------------------------------------------------------
       
   216 // SdpUtil::DivideToLinesL
       
   217 // Divides descriptor into a number of lines that are separated by
       
   218 // CRLF or LF marks
       
   219 // -----------------------------------------------------------------------------
       
   220 //
       
   221 RArray<TPtrC8> SdpUtil::DivideToLinesL( 
       
   222     const TDesC8& aLines,
       
   223     TInt aErrCode )
       
   224     {
       
   225     RArray<TPtrC8> lineArray;
       
   226     CleanupClosePushL( lineArray );
       
   227     
       
   228     TInt lineStartPos( 0 );
       
   229     TInt lineEndPos( aLines.Length() );
       
   230     TInt pos( 0 );
       
   231     
       
   232     TPtrC8 parsedPart( aLines.Right( lineEndPos - lineStartPos ) );
       
   233     // Splits aLines to number of TPtrC8s, each ending to CRLF/LF
       
   234     while ( lineStartPos < lineEndPos && 
       
   235            ( pos = parsedPart.Find( KLFStr ) ) != KErrNotFound )
       
   236         {  
       
   237         if ( ! ( pos == 0 || 
       
   238                 ( pos == ( KCRLFStr().Length() - 1 ) && 
       
   239                   parsedPart.Find( KCRLFStr ) == 0 ) ) )
       
   240             {
       
   241             // Lines that contain only CRLF or LF are ignored
       
   242             // Put the valid lines to the array
       
   243             User::LeaveIfError( 
       
   244                 lineArray.Append( 
       
   245                     TPtrC8( parsedPart.Left( pos + KLFStr().Length() ) ) ) );
       
   246             }
       
   247         // Advance the start of the line after LF mark
       
   248         lineStartPos += pos + KLFStr().Length();
       
   249         parsedPart.Set( aLines.Right( lineEndPos - lineStartPos ) );
       
   250         }    
       
   251     
       
   252     // This method expects that last line of aLines ends _always_ 
       
   253     // to LF not to '\0'
       
   254     if ( aLines.Length() == 0 ||
       
   255         ( aLines.Length() > 0 && aLines[aLines.Length() - 1] != '\n' ) )
       
   256         {
       
   257         User::Leave( aErrCode );
       
   258         }
       
   259 
       
   260     CleanupStack::Pop();    // lineArray
       
   261     return lineArray;    
       
   262     }
       
   263 
       
   264 // -----------------------------------------------------------------------------
       
   265 // SdpUtil::GetElementsFromLineL
       
   266 // Gets all the elements from a single line
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 RArray<TPtrC8> SdpUtil::GetElementsFromLineL(
       
   270     const TDesC8& aLine, 
       
   271     TInt aErrCode )
       
   272     {
       
   273     TLex8 lexer( aLine );
       
   274     RArray<TPtrC8> lineArray = 
       
   275         SdpUtil::GetElementsFromLineL( lexer, KSPChar, aErrCode );    
       
   276     return lineArray;
       
   277     }
       
   278 
       
   279 // -----------------------------------------------------------------------------
       
   280 // SdpUtil::GetElementsFromLineL
       
   281 // Gets all the elements from a single line
       
   282 // -----------------------------------------------------------------------------
       
   283 //
       
   284 RArray<TPtrC8> SdpUtil::GetElementsFromLineL( 
       
   285     const TDesC8& aLine, 
       
   286     TChar aDelimiter,
       
   287     TInt aErrCode )
       
   288     {
       
   289     TLex8 lexer( aLine );
       
   290     RArray<TPtrC8> lineArray = 
       
   291         SdpUtil::GetElementsFromLineL( lexer, aDelimiter, aErrCode );
       
   292     return lineArray;
       
   293     }
       
   294 
       
   295 // -----------------------------------------------------------------------------
       
   296 // SdpUtil::GetElementsFromLineL
       
   297 // Gets all the elements from a single line
       
   298 // -----------------------------------------------------------------------------
       
   299 //
       
   300 RArray<TPtrC8> SdpUtil::GetElementsFromLineL( 
       
   301     TLex8& aLexer, 
       
   302     TChar aDelimiter,
       
   303     TInt aErrCode )
       
   304     {
       
   305     RArray<TPtrC8> lineArray;    
       
   306     CleanupClosePushL( lineArray );
       
   307    
       
   308     // Header is special case, because it is joined _without_
       
   309     // space character with the first attribute, so it must be
       
   310     // parsed separately        
       
   311             
       
   312     aLexer.Mark();
       
   313     // curChar must be != KEqualChar at first comparison
       
   314     for ( TChar curChar( KSPChar ); curChar != KEqualChar; )
       
   315         {
       
   316         curChar = aLexer.Peek();
       
   317         // Syntax check      
       
   318         if ( curChar == KEofChar || curChar == KLFChar ||
       
   319              curChar == KCRChar )
       
   320             {
       
   321             User::Leave( aErrCode );
       
   322             }        
       
   323         aLexer.Inc();       
       
   324         }
       
   325     // Append header to array
       
   326     User::LeaveIfError( lineArray.Append( aLexer.MarkedToken() ) );
       
   327     
       
   328     // Whitespace MUST NOT be used after the "=" sign
       
   329     if (aLexer.Peek() == KSPChar) 
       
   330 	    {
       
   331 		User::Leave( aErrCode );	    	 
       
   332 	    }
       
   333 
       
   334     // Get the other elements from the string to the array
       
   335     ChopElementsFromLineL( lineArray, aLexer, aDelimiter, aErrCode );
       
   336 
       
   337     CleanupStack::Pop();    // lineArray
       
   338     return lineArray;
       
   339     }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // SdpUtil::IsPosDigit
       
   343 // Checks if all the charcaters on the descriptor are POS-DIGITs
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 TBool SdpUtil::IsPosDigit( 
       
   347     const TDesC8& aDes )
       
   348     {
       
   349     // POS-DIGIT = %x31-39 ; 1 - 9
       
   350     _LIT8( KValidPosDigits, "123456789" );
       
   351     return SdpUtil::IsValidChars( KValidPosDigits, aDes );
       
   352     }
       
   353 
       
   354 // -----------------------------------------------------------------------------
       
   355 // SdpUtil::IsDigit
       
   356 // Checks if all the charcaters on the descriptor are DIGITs
       
   357 // -----------------------------------------------------------------------------
       
   358 //
       
   359 TBool SdpUtil::IsDigit( 
       
   360     const TDesC8& aDes )
       
   361     {
       
   362     // DIGIT = "0" / "1" / "2" / "3" / "4" / "5" / "6" /
       
   363     //         "7" / "8" / "9"
       
   364     _LIT8( KValidDigits, "0123456789" );
       
   365 
       
   366     return SdpUtil::IsValidChars( KValidDigits, aDes );
       
   367     }
       
   368 
       
   369 // -----------------------------------------------------------------------------
       
   370 // SdpUtil::IsValidChars
       
   371 // Checks if all the charcaters on the descriptor are from valid charset
       
   372 // -----------------------------------------------------------------------------
       
   373 //
       
   374 TBool SdpUtil::IsValidChars( 
       
   375     const TDesC8& aValidChars, 
       
   376     const TDesC8& aDes )
       
   377     {
       
   378     TBool valid( aDes.Length() > 0 );
       
   379     for ( TInt i( 0 ); i < aDes.Length() && valid; i++ )
       
   380         {
       
   381         if ( aValidChars.Locate( aDes[i] ) == KErrNotFound )
       
   382             {
       
   383             valid = EFalse;
       
   384             }
       
   385         }
       
   386 
       
   387     return valid;
       
   388     }
       
   389         
       
   390 // -----------------------------------------------------------------------------
       
   391 // SdpUtil::IsTokenCharWithSpacesL
       
   392 // Checks if all the elements on the string are valid tokens
       
   393 // -----------------------------------------------------------------------------
       
   394 //
       
   395 TBool SdpUtil::IsTokenCharWithSpacesL(
       
   396     const TDesC8& aValue )
       
   397 	{
       
   398 	TLex8 lex( aValue );
       
   399 	lex.SkipSpace();
       
   400 
       
   401 	if( lex.Remainder().Length() == 0 )
       
   402 		{
       
   403 		User::Leave( KErrArgument );
       
   404 		}
       
   405 
       
   406 	while ( !lex.Eos() )
       
   407 		{
       
   408 		if ( !IsTokenChar( lex.NextToken() ) )
       
   409 			{
       
   410 			return EFalse;
       
   411 			}
       
   412 		lex.SkipSpace();
       
   413 		}
       
   414 	return ETrue;
       
   415 	}
       
   416 
       
   417 // -----------------------------------------------------------------------------
       
   418 // SdpUtil::IsTokenCharWithOptionalSlash
       
   419 // Checks if all the possible two elements divided by slash are valid tokens
       
   420 // -----------------------------------------------------------------------------
       
   421 //
       
   422 TBool SdpUtil::IsTokenCharWithOptionalSlash(const TDesC8& aValue)
       
   423 	{
       
   424 	TInt lineEndPosition = aValue.Locate('/');
       
   425 
       
   426 	if ( lineEndPosition != KErrNotFound )
       
   427 		{
       
   428 		TPtrC8 firstToken( aValue.Left( lineEndPosition ) );
       
   429 		if( !IsTokenChar( firstToken ) ||
       
   430 		    !IsTokenChar( aValue.Mid( lineEndPosition + 1 ) ) )
       
   431 			{
       
   432 			return EFalse;
       
   433 			}
       
   434 		}
       
   435 	else
       
   436 		{
       
   437 		return IsTokenChar( aValue );
       
   438 		}
       
   439 	return ETrue;
       
   440 	}
       
   441 
       
   442 // -----------------------------------------------------------------------------
       
   443 // SdpUtil::IsTokenChar
       
   444 // Checks if all the elements on the string are valid tokens
       
   445 // -----------------------------------------------------------------------------
       
   446 //
       
   447 TBool SdpUtil::IsTokenChar(
       
   448     const TDesC8& aValue )
       
   449 	{	
       
   450     TLex8 lex( aValue );
       
   451 	while( !lex.Eos() )
       
   452 		{
       
   453 		TChar ch = lex.Get();
       
   454 		lex.Inc();
       
   455 
       
   456 		if( ch == '\r' ||ch == '\n' || ch == '\0' || !IsTokenChar( ch ) )
       
   457 			{
       
   458 			return EFalse;
       
   459 			}
       
   460 		}
       
   461 	return ETrue;
       
   462 	}
       
   463 
       
   464 // -----------------------------------------------------------------------------
       
   465 // SdpUtil::IsTokenChar
       
   466 // Checks if the character is a valid token character
       
   467 // -----------------------------------------------------------------------------
       
   468 //
       
   469 TBool SdpUtil::IsTokenChar( 
       
   470     TChar aChar )
       
   471 	{
       
   472     return ( ( aChar == '!')||
       
   473 	         ( aChar >= '#' && aChar <= '\'' ) ||
       
   474 	         ( aChar == '*' || aChar == '+' ) ||
       
   475 	         ( aChar == '-' || aChar == '.' ) ||
       
   476 	         ( aChar.IsDigit() ) ||
       
   477 	         ( aChar >= 'a' && aChar <= 'z' ) ||
       
   478 	         ( aChar >= 'A' && aChar <= 'Z' ) ||
       
   479 	         ( aChar >= '^' && aChar <= '~' ) );	
       
   480 	}
       
   481 
       
   482 // ---------------------------------------------------------------------------
       
   483 // SdpUtil::EncodeBufferL
       
   484 // Encodes headername and a value to the stream
       
   485 // ---------------------------------------------------------------------------
       
   486 //
       
   487 void SdpUtil::EncodeBufferL(
       
   488     const TDesC8& aValue, 
       
   489     TInt aIndex,
       
   490     RWriteStream& aStream )
       
   491 	{
       
   492 	if( aValue.Length() != 0 )
       
   493 		{
       
   494         RStringPool pool = SdpCodecStringPool::StringPoolL();
       
   495 		RStringF headername = pool.StringF( aIndex, 
       
   496                                         SdpCodecStringPool::StringTableL() );
       
   497 		aStream.WriteL( headername.DesC() );
       
   498 		aStream.WriteL( aValue );
       
   499 		aStream.WriteL( KCRLFStr );
       
   500 		}
       
   501 	}
       
   502 
       
   503 // ---------------------------------------------------------------------------
       
   504 // SdpUtil::SetDefaultNetTypeAndAddrType
       
   505 // Sets network type and address type to their "default" values
       
   506 // ---------------------------------------------------------------------------
       
   507 //
       
   508 void SdpUtil::SetDefaultNetTypeAndAddrType( 
       
   509     RStringPool aPool, 
       
   510     const TInetAddr& aAddress,
       
   511     RStringF& aNetType, 
       
   512     RStringF& aAddressType )
       
   513     {
       
   514      // Sets network type to IN
       
   515     aNetType.Close();
       
   516     aNetType = aPool.StringF( SdpCodecStringConstants::ENetType,
       
   517                               SdpCodecStringConstants::Table ).Copy();
       
   518     // Address type       
       
   519     aAddressType.Close();
       
   520 
       
   521     TBuf16 <KMaxAddressLength> output;
       
   522     aAddress.Output(output);
       
   523 
       
   524 
       
   525     //addresstype for IPv4    
       
   526 	if((aAddress.Address() &&  !aAddress.IsV4Mapped()) ||
       
   527        (!aAddress.Address() && aAddress.IsWildAddr() && 
       
   528         output.Match(KWildAddr) == 0))
       
   529         {
       
   530         aAddressType = aPool.StringF( SdpCodecStringConstants::EAddressTypeIP4,
       
   531                                       SdpCodecStringConstants::Table ).Copy();
       
   532         }
       
   533     else
       
   534         {
       
   535 		//addresstype for IPv4-Mapped IPv6 && IPv6
       
   536         aAddressType = aPool.StringF( SdpCodecStringConstants::EAddressType,
       
   537                                       SdpCodecStringConstants::Table ).Copy();
       
   538         }
       
   539     }
       
   540 
       
   541 // ---------------------------------------------------------------------------
       
   542 // SdpUtil::SkipSpacesUntilNextLineBreak
       
   543 // Skips spaces until next line break, if the line break can be found.
       
   544 // Examples: "   \r\n" -> "\r\n", "abc def\r\n" -> "abc def\r\n"
       
   545 // ---------------------------------------------------------------------------
       
   546 //       
       
   547 TBool SdpUtil::SkipSpacesUntilNextLineBreak( TLex8& aLexer )
       
   548     {
       
   549     TBool found = EFalse;
       
   550     if ( aLexer.Peek() == KSPChar )
       
   551         {
       
   552         TInt spaceCount = 0;
       
   553         while ( aLexer.Peek() == KSPChar )
       
   554             {
       
   555             spaceCount++;
       
   556             aLexer.Get();
       
   557             }
       
   558         if ( aLexer.Peek() != KCRChar && aLexer.Peek() != KLFChar )
       
   559             {
       
   560             for ( TInt i=0; i < spaceCount; i++ )
       
   561                 {
       
   562                 aLexer.UnGet();
       
   563                 }
       
   564             }
       
   565         else
       
   566             {
       
   567             found = ETrue;
       
   568             }
       
   569         }
       
   570     return found;
       
   571     }
       
   572 
       
   573 // ---------------------------------------------------------------------------
       
   574 // SdpUtil::ChopElementsFromLineL
       
   575 // Chops all the elements that are divided by delimiter from the string
       
   576 // ---------------------------------------------------------------------------
       
   577 //
       
   578 void SdpUtil::ChopElementsFromLineL( 
       
   579     RArray<TPtrC8>& aArray, 
       
   580     TLex8& aLexer,
       
   581     TChar aDelimiter,
       
   582     TInt aErrCode )
       
   583     {
       
   584     // Chop the elements to the array from lexer
       
   585     TBool eofcFound = EFalse;
       
   586     while (!eofcFound)
       
   587         {
       
   588         aLexer.Mark();        
       
   589         // Parse single token, leave other special characters
       
   590         // to token except aDelimiter | '\r' | '\n' | '\0'
       
   591         while ( aLexer.Peek() != aDelimiter && 
       
   592                 aLexer.Peek() != KCRChar &&
       
   593                 aLexer.Peek() != KLFChar && 
       
   594                 aLexer.Peek() != KEofChar )
       
   595             {
       
   596             aLexer.Inc();
       
   597             }
       
   598 		
       
   599         if ( aLexer.MarkedToken().Length() > 0 )
       
   600             {            
       
   601             aArray.AppendL( aLexer.MarkedToken() );
       
   602             }
       
   603 
       
   604         if ( aDelimiter == KSPChar &&
       
   605              aLexer.Peek() == aDelimiter )
       
   606             {
       
   607             SkipSpacesUntilNextLineBreak( aLexer );
       
   608             }
       
   609 
       
   610         // Check if its end-of-line
       
   611         if ( aLexer.Peek() == KCRChar )
       
   612             {
       
   613             aLexer.Inc();
       
   614             }
       
   615 
       
   616         if ( aLexer.Peek() == KLFChar )
       
   617             {
       
   618             aLexer.Inc();
       
   619             if ( aLexer.Peek() != KEofChar )
       
   620                 {
       
   621                 User::Leave( aErrCode );
       
   622                 }
       
   623             eofcFound = ETrue;
       
   624             }
       
   625         else if ( aLexer.Peek() == KEofChar )
       
   626             {
       
   627             // EoF character not tolerated at the middle of the string
       
   628             User::Leave( aErrCode );
       
   629             }
       
   630         else
       
   631             {
       
   632             aLexer.Inc();
       
   633             }
       
   634         }
       
   635     }