omads/omadsextensions/dsutils/nsmlfolderutils/src/nsmlxmlparser.cpp
changeset 1 95fdac6ccb5c
equal deleted inserted replaced
0:dab8a81a92de 1:95fdac6ccb5c
       
     1 /*
       
     2 * Copyright (c) 2004 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Sources
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // 1.2 Changes: nsmlxmlparser module added
       
    20 
       
    21 // ------------------------------------------------------------------------------------------------
       
    22 // Includes
       
    23 // ------------------------------------------------------------------------------------------------
       
    24 #include <s32buf.h>
       
    25 #include <s32file.h>
       
    26 #include <nsmlfolderparser.h>
       
    27 #include "nsmlparserconstants.h"
       
    28 
       
    29 
       
    30 // ------------------------------------------------------------------------------------------------
       
    31 // 
       
    32 // CNSmlXmlParser methods
       
    33 // 
       
    34 // ------------------------------------------------------------------------------------------------
       
    35 
       
    36 // ------------------------------------------------------------------------------------------------
       
    37 // Constructor
       
    38 // ------------------------------------------------------------------------------------------------
       
    39 EXPORT_C CNSmlXmlParser::CNSmlXmlParser()
       
    40 	{
       
    41 	}
       
    42 
       
    43 
       
    44 // ------------------------------------------------------------------------------------------------
       
    45 // Destructor.
       
    46 // ------------------------------------------------------------------------------------------------
       
    47 EXPORT_C CNSmlXmlParser::~CNSmlXmlParser()
       
    48 	{
       
    49 	if( iBuffer ) delete iBuffer;
       
    50 	if ( iCompleteBuffer ) delete iCompleteBuffer;
       
    51 	}
       
    52 
       
    53 
       
    54 // ------------------------------------------------------------------------------------------------
       
    55 // Parses the given string for cdata areas and entitys. If a cdata area is 
       
    56 // found, the data in it is skipped over. The entities outside cdata are converted 
       
    57 // into characters they represent (but only if cdata is found).
       
    58 // Note: This method is intended for processing the CDATA used right after <Data>. 
       
    59 // I.e. this method removes the cdata-elements used for wrapping the whole xml data 
       
    60 // and processes the string so that the inner cdatas used in the xml become valid.
       
    61 // THIS METHOD SHOULD BE CALLED RIGHT IN THE BEGINNING OF PARSING IF <Data>-BLOCK 
       
    62 // IS WRAPPED WITHIN CDATA.
       
    63 // ------------------------------------------------------------------------------------------------
       
    64 void CNSmlXmlParser::PreProcessL( HBufC8* aXml ) const
       
    65 	{
       
    66 	// take a modifiable pointer
       
    67 	TPtr8 xml = aXml->Des();
       
    68 
       
    69 	// the string used for searching and moving in the string
       
    70 	TPtrC8 searchString(*aXml);
       
    71 
       
    72 	// the current position in the original string
       
    73 	TInt searchStartPos = 0;
       
    74 
       
    75 	// find the first cdata start
       
    76 	TInt cdataStartPos = searchString.Find(KCDataStart);
       
    77 	
       
    78 	// If CDATA is not found from beginning then data is not inside CDATA and then
       
    79 	// preprocessing is not needed
       
    80 	if ( cdataStartPos != 0 )
       
    81 	    {
       
    82 	    return;
       
    83 	    }
       
    84 
       
    85 	TInt cdataEndPos = KErrNotFound;
       
    86 
       
    87 	// while cdata is found
       
    88 	while ( cdataStartPos != KErrNotFound )
       
    89 		{
       
    90 		cdataStartPos += searchStartPos;
       
    91 
       
    92 		// find an end of cdata before entities are converted
       
    93 		cdataEndPos = searchString.Find(KCDataEnd);
       
    94 
       
    95 		// convert entities between search start and cdata start
       
    96 		TInt entityChange = EntitiesToCharactersL(aXml, searchStartPos, cdataStartPos);
       
    97 		xml.Set(aXml->Des());
       
    98 		cdataStartPos += entityChange;
       
    99 
       
   100 		if ( cdataEndPos != KErrNotFound )
       
   101 			{
       
   102 			cdataEndPos += entityChange;
       
   103 			cdataEndPos += searchStartPos;
       
   104 
       
   105 			// if the end is before start -> error
       
   106 			if (cdataEndPos < cdataStartPos)
       
   107 				User::Leave( EInvalidCDataStructure );
       
   108 				
       
   109 			// remove cdata end
       
   110 			xml.Delete(cdataEndPos, KCDataEnd().Length());
       
   111 			// remove cdata start
       
   112 			xml.Delete(cdataStartPos, KCDataStart().Length());
       
   113 
       
   114 			searchStartPos = cdataEndPos - KCDataStart().Length();
       
   115 			searchString.Set( xml.Right(xml.Length() - searchStartPos) );
       
   116 			}
       
   117 		else 
       
   118 			{
       
   119 			// the end of cdata was not found or cdata end was before start -> error
       
   120 			User::Leave( EInvalidCDataStructure );
       
   121 			}
       
   122 
       
   123 		// find a new cdata start that is after the found end
       
   124 		cdataStartPos = searchString.Find(KCDataStart);
       
   125 
       
   126 		}
       
   127 
       
   128 	}
       
   129 
       
   130 
       
   131 // ------------------------------------------------------------------------------------------------
       
   132 // Return the TNSmlBoolean-value's string-representation.
       
   133 // ------------------------------------------------------------------------------------------------
       
   134 TPtrC8 CNSmlXmlParser::BooleanToString( const TNSmlBoolean aValue ) const
       
   135 	{
       
   136 	TPtrC8 str;
       
   137 	switch(aValue)
       
   138 		{
       
   139 		case EBooleanTrue:
       
   140 			{
       
   141 			str.Set(KStringTrue);
       
   142 			break;
       
   143 			}
       
   144 		case EBooleanFalse:
       
   145 			{
       
   146 			str.Set(KStringFalse);
       
   147 			break;
       
   148 			}
       
   149 		default:
       
   150 			{
       
   151 			str.Set(KStringEmpty);
       
   152 			}
       
   153 		}
       
   154 
       
   155 	return str;
       
   156 	}
       
   157 
       
   158 
       
   159 // ------------------------------------------------------------------------------------------------
       
   160 // Returns the TTime-value's string-representation.
       
   161 // ------------------------------------------------------------------------------------------------
       
   162 TBuf8<KDateTimeLength> CNSmlXmlParser::DateTimeToStringL( const TTime& aValue ) const
       
   163 	{
       
   164 	TBuf<KDateTimeLength> str;
       
   165 	
       
   166 	// aValue is not changed but Z character is added to the end of string.
       
   167 	// Messaging uses UTC times and that is reason why time is not changed.
       
   168 	aValue.FormatL( str, _L("%F%Y%M%DT%H%T%SZ") );
       
   169 
       
   170 	// from 16-bit to 8-bit
       
   171 	TBuf8<KDateTimeLength> dt;
       
   172 	dt.Copy(str);
       
   173 
       
   174 	return dt;
       
   175 	}
       
   176 
       
   177 
       
   178 // ------------------------------------------------------------------------------------------------
       
   179 // Returns the integer value's string-representation.
       
   180 // ------------------------------------------------------------------------------------------------
       
   181 TBuf8<KIntegerMaxLength> CNSmlXmlParser::IntegerToString( const TInt aValue ) const
       
   182 	{
       
   183 	TBuf8<KIntegerMaxLength> str;
       
   184 	str.AppendNum(aValue);
       
   185 	return str;
       
   186 	}
       
   187 
       
   188 
       
   189 // ------------------------------------------------------------------------------------------------
       
   190 // Returns the boolean representation of the string or leaves if error (EInvalidBooleanValue).
       
   191 // ------------------------------------------------------------------------------------------------
       
   192 TNSmlBoolean CNSmlXmlParser::StringToBooleanL( const TPtrC8& aValue ) const
       
   193 	{
       
   194 	if( aValue == KStringTrue )
       
   195 		return EBooleanTrue;
       
   196 	else if( aValue == KStringFalse || aValue == KStringEmpty )
       
   197 		return EBooleanFalse;
       
   198 	else
       
   199 		User::Leave(EInvalidBooleanValue);
       
   200 
       
   201 	return EBooleanMissing;
       
   202 	}
       
   203 
       
   204 	
       
   205 // ------------------------------------------------------------------------------------------------
       
   206 // Returns the integer representation of the string or leaves if error (EInvalidIntegerValue).
       
   207 // ------------------------------------------------------------------------------------------------
       
   208 TInt CNSmlXmlParser::StringToIntegerL( const TPtrC8& aValue ) const
       
   209 	{
       
   210 	if (aValue.Length() <= 0)
       
   211 		return 0;
       
   212 
       
   213 	// convert the data to an integer
       
   214 	TLex8 lex(aValue);
       
   215 	TUint uValue = 0;
       
   216 	TBool isNegative = EFalse;
       
   217 
       
   218 	TChar c = lex.Peek();
       
   219 
       
   220 	// check for a minus or plus sign
       
   221 	if ( c == '-' )
       
   222 		{
       
   223 		isNegative = ETrue;
       
   224 		lex.Inc();
       
   225 		}
       
   226 	else if ( c == '+' )
       
   227 		{
       
   228 		lex.Inc();
       
   229 		}
       
   230 
       
   231 	TRadix radix = EDecimal;
       
   232 	c = lex.Peek();
       
   233 
       
   234 	if (c == '0') // octal or hex
       
   235 		{
       
   236 		lex.Get();
       
   237 		c = lex.Get();
       
   238 		if ( c == 'x' || c == 'X' )
       
   239 			{
       
   240 			radix = EHex;
       
   241 			}
       
   242 		else
       
   243 			{
       
   244 			radix = EOctal;
       
   245 			lex.UnGet(); // back up
       
   246 			}
       
   247 		}
       
   248 
       
   249 	TInt err = lex.Val(uValue, radix);
       
   250 	if ( err != KErrNone )
       
   251 		User::Leave(EInvalidIntegerValue);
       
   252 
       
   253 	TInt value = uValue;
       
   254 
       
   255 	return isNegative ? value*(-1) : value;
       
   256 	}
       
   257 
       
   258 
       
   259 // ------------------------------------------------------------------------------------------------
       
   260 // Returns the TTime representation of the string or leaves if error (EInvalidDatetimeValue).
       
   261 // UTC times are not supported, i.e. datetimes that have Z-ending are treated as 
       
   262 // local times.
       
   263 // ------------------------------------------------------------------------------------------------
       
   264 TTime CNSmlXmlParser::StringToTTimeL( TPtrC8& aValue ) const
       
   265 	{
       
   266 	// check that there is data
       
   267 	if (aValue.Length() <= 0)
       
   268 		User::Leave( EInvalidDatetimeValue );
       
   269 
       
   270 	// format the data into a TTime
       
   271 
       
   272 	if (aValue[aValue.Length()-1] == 'Z')
       
   273 		{
       
   274 		// The datetime is in UTC, which is not supported
       
   275 		// no correction done, treat as local time
       
   276 		aValue.Set( aValue.Left( aValue.Length()-1 ) );
       
   277 		}
       
   278 
       
   279 	TDateTime datetime(0,(TMonth)0,0,0,0,0,0);
       
   280 
       
   281 	// read datetime and check errors
       
   282 
       
   283 	TInt error = KErrNone;
       
   284 
       
   285 	// read year
       
   286 	TPtrC8 str = aValue.Left(4);
       
   287 	TLex8 lex(str);
       
   288 	TInt value;
       
   289 	error = lex.Val(value);
       
   290 	CheckDatetimeErrorL( error );
       
   291 	error  = datetime.SetYear(value);
       
   292 	CheckDatetimeErrorL( error );
       
   293 
       
   294 	// read month
       
   295 	str.Set(aValue.Mid(4, 2));
       
   296 	lex.Assign(str);
       
   297 	error = lex.Val(value);
       
   298 	CheckDatetimeErrorL( error );
       
   299 	--value;
       
   300 	error = datetime.SetMonth((TMonth)value);
       
   301 	CheckDatetimeErrorL( error );
       
   302 
       
   303 	// read day
       
   304 	str.Set(aValue.Mid(6, 2));
       
   305 	lex.Assign(str);
       
   306 	error = lex.Val(value);
       
   307 	CheckDatetimeErrorL( error );
       
   308 	--value;
       
   309 	error = datetime.SetDay(value);
       
   310 	CheckDatetimeErrorL( error );
       
   311 
       
   312 	// Skip character 'T' and read hour
       
   313 	str.Set(aValue.Mid(9, 2));
       
   314 	lex.Assign(str);
       
   315 	error = lex.Val(value);
       
   316 	CheckDatetimeErrorL( error );
       
   317 	error = datetime.SetHour(value);
       
   318 	CheckDatetimeErrorL( error );
       
   319 
       
   320 	// minutes
       
   321 	str.Set(aValue.Mid(11, 2));
       
   322 	lex.Assign(str);
       
   323 	error = lex.Val(value);
       
   324 	CheckDatetimeErrorL( error );
       
   325 	error = datetime.SetMinute(value);
       
   326 	CheckDatetimeErrorL( error );
       
   327 
       
   328 	// seconds
       
   329 	str.Set(aValue.Mid(13, 2));
       
   330 	lex.Assign(str);
       
   331 	error = lex.Val(value);
       
   332 	CheckDatetimeErrorL( error );
       
   333 	error = datetime.SetSecond(value);
       
   334 	CheckDatetimeErrorL( error );
       
   335 
       
   336 	return TTime(datetime);
       
   337 	}
       
   338 
       
   339 
       
   340 // ------------------------------------------------------------------------------------------------
       
   341 // Adds start element, the value and end element to aPtr.
       
   342 // ------------------------------------------------------------------------------------------------
       
   343 void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName, const TDesC8& aValue ) const
       
   344 	{
       
   345 	// start element
       
   346 	aPtr.Append(KElementStart);
       
   347 	aPtr.Append(aElementName);
       
   348 	aPtr.Append(KElementEnd);
       
   349 
       
   350 	// value
       
   351 	aPtr.Append(aValue);
       
   352 
       
   353 	// end element
       
   354 	aPtr.Append(KElementStart);
       
   355 	aPtr.Append(KCharacterSlash);
       
   356 	aPtr.Append(aElementName);
       
   357 	aPtr.Append(KElementEnd);
       
   358 	}
       
   359 
       
   360 
       
   361 // ------------------------------------------------------------------------------------------------
       
   362 // Forms an element using the given element name and appends it to the given string.
       
   363 // ------------------------------------------------------------------------------------------------
       
   364 void CNSmlXmlParser::AppendElement( TPtr8& aPtr, const TDesC8& aElementName ) const
       
   365 	{
       
   366 	aPtr.Append(KElementStart);
       
   367 	aPtr.Append(aElementName);
       
   368 	aPtr.Append(KElementEnd);
       
   369 	}
       
   370 
       
   371 
       
   372 // ------------------------------------------------------------------------------------------------
       
   373 // Forms an end element using the given element name and appends it to the given string.
       
   374 // ------------------------------------------------------------------------------------------------
       
   375 void CNSmlXmlParser::AppendEndElement( TPtr8& aPtr, const TDesC8& aElementName ) const
       
   376 	{
       
   377 	aPtr.Append(KElementStart);
       
   378 	aPtr.Append(KCharacterSlash);
       
   379 	aPtr.Append(aElementName);
       
   380 	aPtr.Append(KElementEnd);
       
   381 	}
       
   382 
       
   383 
       
   384 // ------------------------------------------------------------------------------------------------
       
   385 // Returns the total length of start and end tag.
       
   386 // ------------------------------------------------------------------------------------------------
       
   387 TInt CNSmlXmlParser::SizeOfElements( const TDesC8& aElementName ) const
       
   388 	{
       
   389 	TInt size = 0;
       
   390 
       
   391 	// start element plus end element ( 1 = length of '/' char )
       
   392 	size += 2*aElementName.Length() + 1;
       
   393 	size += 2*KElementStartEndWidth; // '<' and '>'
       
   394 
       
   395 	return size;
       
   396 	}
       
   397 
       
   398 
       
   399 // ------------------------------------------------------------------------------------------------
       
   400 // Returns the length of the given boolean element and it's data if it was a string.
       
   401 // ------------------------------------------------------------------------------------------------
       
   402 TInt CNSmlXmlParser::SizeOfBoolean( const TNSmlBoolean aValue, const TDesC8& aElementName ) const
       
   403 	{
       
   404 	TInt size = 0;
       
   405 	size += SizeOfElements( aElementName );
       
   406 	switch ( aValue )
       
   407 		{
       
   408 		case EBooleanTrue:
       
   409 			return size+4; // "true"
       
   410 		case EBooleanFalse:
       
   411 			return size+5; // "false"
       
   412 		default:
       
   413 			return 0;
       
   414 		}
       
   415 	}
       
   416 
       
   417 
       
   418 // ------------------------------------------------------------------------------------------------
       
   419 // Returns the length of the given datetime element and it's data if it was a string.
       
   420 // ------------------------------------------------------------------------------------------------
       
   421 TInt CNSmlXmlParser::SizeOfDatetime( const TDesC8& aElementName ) const
       
   422 	{
       
   423 	TInt size = SizeOfElements( aElementName ) + KDateTimeLength;
       
   424 	return size;
       
   425 	}
       
   426 
       
   427 
       
   428 // ------------------------------------------------------------------------------------------------
       
   429 // Returns the maximum length of the given integer element and it's data if it was a string.
       
   430 // ------------------------------------------------------------------------------------------------
       
   431 TInt CNSmlXmlParser::SizeOfInteger( const TDesC8& aElementName ) const
       
   432 	{
       
   433 	TInt size = SizeOfElements( aElementName ) + KIntegerMaxLength;
       
   434 	return size;
       
   435 	}
       
   436 
       
   437 
       
   438 // ------------------------------------------------------------------------------------------------
       
   439 // Returns the length of the given string element and it's data if it was a string.
       
   440 // ------------------------------------------------------------------------------------------------
       
   441 TInt CNSmlXmlParser::SizeOfString( const HBufC8* aValue, const TDesC8& aElementName ) const
       
   442 	{
       
   443 	TInt size = SizeOfElements( aElementName ) + aValue->Length();
       
   444 	return size;
       
   445 	}
       
   446 
       
   447 
       
   448 // ------------------------------------------------------------------------------------------------
       
   449 // Finds entities and replaces them with the characters they represent. Returns 
       
   450 // an integer indicating the size change in aXml.
       
   451 // ------------------------------------------------------------------------------------------------
       
   452 TInt CNSmlXmlParser::EntitiesToCharactersL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
       
   453 	{
       
   454 	TInt change = 0;
       
   455 	TInt changeSum = 0;
       
   456 
       
   457 	change = ReplaceL(aXml, KEntityLT, KLessThan, aStartPos, aEndPos);
       
   458 	changeSum += change;
       
   459 	aEndPos += change;
       
   460 
       
   461 	change = ReplaceL(aXml, KEntityGT, KGreaterThan, aStartPos, aEndPos);
       
   462 	changeSum += change;
       
   463 	aEndPos += change;
       
   464 
       
   465 	change = ReplaceL(aXml, KEntityAMP, KAmpersand, aStartPos, aEndPos);
       
   466 	changeSum += change;
       
   467 	aEndPos += change;
       
   468 
       
   469 	change = ReplaceL(aXml, KEntityAPOS, KApostrophe, aStartPos, aEndPos);
       
   470 	changeSum += change;
       
   471 	aEndPos += change;
       
   472 
       
   473 	change = ReplaceL(aXml, KEntityQUOT, KQuotation, aStartPos, aEndPos);
       
   474 	changeSum += change;
       
   475 
       
   476 	return changeSum;
       
   477 	}
       
   478 
       
   479 
       
   480 // ------------------------------------------------------------------------------------------------
       
   481 // Finds special characters and replaces them with corresponding entities. Returns 
       
   482 // an integer indicating the size change in aXml.
       
   483 // ------------------------------------------------------------------------------------------------
       
   484 TInt CNSmlXmlParser::CharactersToEntitiesL( HBufC8*& aXml, TInt aStartPos, TInt aEndPos ) const
       
   485 	{
       
   486 	TInt change = 0;
       
   487 	TInt changeSum = 0;
       
   488 
       
   489 	// Note: this replace has to be the first one, since it changes 
       
   490 	// &-characters to &amp;s and all the other replaces generate 
       
   491 	// &-characters as they are entities.
       
   492 	change = ReplaceL(aXml, KAmpersand, KEntityAMP, aStartPos, aEndPos);
       
   493 	changeSum += change;
       
   494 	aEndPos += change;
       
   495 
       
   496 	change = ReplaceL(aXml, KLessThan, KEntityLT, aStartPos, aEndPos);
       
   497 	changeSum += change;
       
   498 	aEndPos += change;
       
   499 
       
   500 	change = ReplaceL(aXml, KGreaterThan, KEntityGT, aStartPos, aEndPos);
       
   501 	changeSum += change;
       
   502 	aEndPos += change;
       
   503 
       
   504 	change = ReplaceL(aXml, KApostrophe, KEntityAPOS, aStartPos, aEndPos);
       
   505 	changeSum += change;
       
   506 	aEndPos += change;
       
   507 
       
   508 	change = ReplaceL(aXml, KQuotation, KEntityQUOT, aStartPos, aEndPos);
       
   509 	changeSum += change;
       
   510 
       
   511 	return changeSum;
       
   512 	}
       
   513 
       
   514 
       
   515 // ------------------------------------------------------------------------------------------------
       
   516 // Returns ETrue if all the characters in the given text are whitespace 
       
   517 // characters, else EFalse.
       
   518 // ------------------------------------------------------------------------------------------------
       
   519 TBool CNSmlXmlParser::IsWhitespace( const TDesC8& aText ) const
       
   520 	{
       
   521 	// loop the string character by character
       
   522 	TText c;
       
   523 	for ( TInt i=0; i < aText.Length(); ++i )
       
   524 		{
       
   525 		c = aText[i];
       
   526 		switch( c )
       
   527 			{
       
   528 			case KWhitespaceEmpty:
       
   529 				break;
       
   530 			case KWhitespaceLineFeed:
       
   531 				break;
       
   532 			case KWhitespaceNewLine:
       
   533 				break;
       
   534 			case KWhitespaceTabular:
       
   535 				break;
       
   536 			case KWhitespaceLineFeedNewLine:
       
   537 				break;
       
   538 			default:
       
   539 				return EFalse;
       
   540 			}
       
   541 		}
       
   542 
       
   543 	return ETrue;
       
   544 	}
       
   545 
       
   546 
       
   547 // ------------------------------------------------------------------------------------------------
       
   548 // Leaves with EInvalidXmlError if the given string is not whitespace.
       
   549 // ------------------------------------------------------------------------------------------------
       
   550 void CNSmlXmlParser::LeaveIfNotWhiteSpaceL( const TDesC8& aText ) const
       
   551 	{
       
   552 	if ( !IsWhitespace( aText ) )
       
   553 		{
       
   554 		User::Leave( EInvalidXmlError );
       
   555 		}
       
   556 	}
       
   557 
       
   558 
       
   559 // ------------------------------------------------------------------------------------------------
       
   560 // Maps the given value to TNSmlParserGeneratorError.
       
   561 // ------------------------------------------------------------------------------------------------
       
   562 TNSmlParserGeneratorError CNSmlXmlParser::CheckError( const TInt error ) const
       
   563 	{
       
   564 	if ( error == KErrNoMemory )
       
   565 		{
       
   566 		return EOutOfMemory;
       
   567 		}
       
   568 	else if ( error < KErrNone )
       
   569 		{
       
   570 		// some system wide error, should not occur
       
   571 		return EUnknownError;
       
   572 		}
       
   573 	else if ( error != EErrorNone )
       
   574 		{
       
   575 		return (TNSmlParserGeneratorError)error;
       
   576 		}
       
   577 
       
   578 	return EErrorNone;
       
   579 	}
       
   580 
       
   581 
       
   582 // ------------------------------------------------------------------------------------------------
       
   583 // Parses the given xml and calls NextDataL and NextElementL methods when finds 
       
   584 // data or element. 
       
   585 // ------------------------------------------------------------------------------------------------
       
   586 void CNSmlXmlParser::ParseL( TPtrC8& aXml )
       
   587 	{
       
   588 
       
   589 	ResetBufferL(iBuffer);
       
   590 	ResetBufferL(iCompleteBuffer);
       
   591 
       
   592 	// boolean indicating if reading element name (true) or insides of 
       
   593 	// an element (false)
       
   594 	TBool readingElementName = EFalse;
       
   595 	TText c;
       
   596 
       
   597 	for( TInt i=0; i < aXml.Length(); ++i )
       
   598 		{
       
   599 		c = aXml[i];
       
   600 		switch(c)
       
   601 			{
       
   602 			case KElementStart:
       
   603 				// if currently reading element, error
       
   604 				if( readingElementName )
       
   605 					{
       
   606 					User::Leave(EInvalidXmlError);
       
   607 					}
       
   608 
       
   609 				if( aXml.Length()-i >= KCDataStart().Length() &&
       
   610 					!aXml.Mid(i, KCDataStart().Length()).Compare(KCDataStart()) )
       
   611 					{ // cdata
       
   612 					aXml.Set( aXml.Right( aXml.Length() - i ) );
       
   613 					TInt endPos = aXml.Find(KCDataEnd);
       
   614 
       
   615 					TPtrC8 cdata = _L8("");
       
   616 					if ( endPos == KErrNotFound )
       
   617 						{
       
   618 						User::Leave(EInvalidCDataStructure);
       
   619 						}
       
   620 
       
   621 					cdata.Set( aXml.Mid( KCDataStart().Length(), endPos - KCDataStart().Length() ) );
       
   622 					aXml.Set( aXml.Right( aXml.Length() - endPos - KCDataEnd().Length() ) );
       
   623 
       
   624 					i = -1;
       
   625 
       
   626 					// add current buffer to complete buffer
       
   627 					EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   628 					AddToCompleteL(*iBuffer);
       
   629 					ResetBufferL(iBuffer);
       
   630 					AddToCompleteL(cdata);
       
   631 					}
       
   632 #ifndef __NO_XML_COMMENTS_
       
   633 				else if( aXml.Length()-i >= KCommentStart().Length() &&
       
   634 					!aXml.Mid(i, KCommentStart().Length()).Compare(KCommentStart()) )
       
   635 					{ // comment
       
   636 					aXml.Set( aXml.Right( aXml.Length() - i ) );
       
   637 					TInt endPos = aXml.Find(KCommentEnd);
       
   638 
       
   639 					if ( endPos != KErrNotFound )
       
   640 						{
       
   641 						aXml.Set( aXml.Right( aXml.Length() - endPos - KCommentEnd().Length() ) );
       
   642 						}
       
   643 					else
       
   644 						{
       
   645 						User::Leave(EInvalidXmlError);
       
   646 						}
       
   647 
       
   648 					i = -1;
       
   649 					}
       
   650 #endif
       
   651 				else 
       
   652 					{
       
   653 					// send the buffer
       
   654 					EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   655 					AddToCompleteL(*iBuffer);
       
   656 					NextDataL(*iCompleteBuffer);
       
   657 					ResetBufferL(iBuffer);
       
   658 					ResetBufferL(iCompleteBuffer);
       
   659 					readingElementName = ETrue;
       
   660 					}
       
   661 
       
   662 				break;
       
   663 			case KElementEnd:
       
   664 				// stop reading element name
       
   665 				if( !readingElementName )
       
   666 					{
       
   667 					User::Leave(EInvalidXmlError);
       
   668 					}
       
   669 				else 
       
   670 					{
       
   671 					NextElementL(*iBuffer);
       
   672 					ResetBufferL(iBuffer);
       
   673 					readingElementName = EFalse;
       
   674 					}
       
   675 				break;
       
   676 			default:
       
   677 				// add char to buffer
       
   678 				AddToBufferL(c, iBuffer);
       
   679 				break;
       
   680 			}
       
   681 		}
       
   682 
       
   683 	EntitiesToCharactersL( iBuffer, 0, iBuffer->Length() );
       
   684 	AddToCompleteL(*iBuffer);
       
   685 	NextDataL(*iCompleteBuffer);
       
   686 	}
       
   687 
       
   688 
       
   689 // ------------------------------------------------------------------------------------------------
       
   690 // Adds the given string to iCompleteBuffer
       
   691 // ------------------------------------------------------------------------------------------------
       
   692 void CNSmlXmlParser::AddToCompleteL( const TPtrC8 aStr )
       
   693 	{
       
   694 	if(!iCompleteBuffer)
       
   695 		{
       
   696 		iCompleteBuffer = HBufC8::NewL(aStr.Length());
       
   697 		}
       
   698 
       
   699 	TPtr8 ptr = iCompleteBuffer->Des();
       
   700 	if( ptr.MaxLength() < iCompleteBuffer->Length()+aStr.Length() )
       
   701 		{
       
   702 		iCompleteBuffer = iCompleteBuffer->ReAllocL(iCompleteBuffer->Length()+aStr.Length());
       
   703 		ptr.Set(iCompleteBuffer->Des());
       
   704 		}
       
   705 
       
   706 	ptr.Append(aStr);
       
   707 	}
       
   708 
       
   709 
       
   710 // ------------------------------------------------------------------------------------------------
       
   711 // Deletes the given buffer and initializes it again to length 10
       
   712 // ------------------------------------------------------------------------------------------------
       
   713 void CNSmlXmlParser::ResetBufferL( HBufC8*& aBuf ) const
       
   714 	{
       
   715 	if( aBuf )
       
   716 		{
       
   717 		delete aBuf;
       
   718 		aBuf = NULL;
       
   719 		}
       
   720 
       
   721 	aBuf = HBufC8::NewL(10);
       
   722 	}
       
   723 
       
   724 
       
   725 // ------------------------------------------------------------------------------------------------
       
   726 // Adds the given char to given buffer
       
   727 // ------------------------------------------------------------------------------------------------
       
   728 void CNSmlXmlParser::AddToBufferL( const TText c, HBufC8*& aBuf ) const
       
   729 	{
       
   730 	TPtr8 ptr = aBuf->Des();
       
   731 	if( ptr.MaxLength() == aBuf->Length()+1 )
       
   732 		{
       
   733 		aBuf = aBuf->ReAllocL(aBuf->Length()+10);
       
   734 		ptr.Set(aBuf->Des());
       
   735 		}
       
   736 
       
   737 	TChar str = c;
       
   738 	ptr.Append(str);
       
   739 	}
       
   740 
       
   741 
       
   742 
       
   743 // ------------------------------------------------------------------------------------------------
       
   744 // Replaces all occurances of aTarget in aText with aItem. Returns an integer indicating 
       
   745 // the size change in aText. aStartPos and aEndPos indicate the start and end positions 
       
   746 // of aText to be parsed (if whole string should be parsed, use 0 and aText.Length()).
       
   747 // ------------------------------------------------------------------------------------------------
       
   748 TInt CNSmlXmlParser::ReplaceL( HBufC8*& aText, const TDesC8& aTarget, const TDesC8& aItem, TInt aStartPos, TInt aEndPos ) const
       
   749 	{
       
   750 	TInt change = 0;
       
   751 	TInt searchPos = aStartPos;
       
   752 	TPtrC8 text = aText->Mid(aStartPos, aEndPos-aStartPos);
       
   753 	TInt pos = text.Find(aTarget);
       
   754 
       
   755 	while ( pos != KErrNotFound )
       
   756 		{
       
   757 		pos += searchPos;
       
   758 
       
   759 		TInt currentChange = aItem.Length() - aTarget.Length();
       
   760 		change += currentChange;
       
   761 		aEndPos += currentChange;
       
   762 		searchPos = pos;
       
   763 
       
   764 		if ( currentChange > 0 )
       
   765 			{
       
   766 			searchPos += currentChange;
       
   767 
       
   768 			// check that aText is large enough
       
   769 			if ( aText->Des().MaxLength() < aText->Length()+currentChange )
       
   770 				{
       
   771 				aText = aText->ReAllocL(aText->Length()+currentChange);
       
   772 				}
       
   773 			}
       
   774 
       
   775 		// the actual replace
       
   776 		aText->Des().Replace(pos, aTarget.Length(), aItem);
       
   777 
       
   778 		text.Set( aText->Mid(searchPos, aEndPos-searchPos) );
       
   779 		pos = text.Find(aTarget);
       
   780 		}
       
   781 
       
   782 	return change;
       
   783 	}
       
   784 
       
   785 
       
   786 // ------------------------------------------------------------------------------------------------
       
   787 // 
       
   788 // ------------------------------------------------------------------------------------------------
       
   789 void CNSmlXmlParser::CheckDatetimeErrorL( const TInt error ) const
       
   790 	{
       
   791 	if ( error != KErrNone )
       
   792 		{
       
   793 		User::Leave( EInvalidDatetimeValue );
       
   794 		}
       
   795 	}
       
   796 
       
   797 //End of File
       
   798