telephonyserverplugins/simtsy/testconfigfileparser/src/testconfigfile.cpp
branchRCL_3
changeset 20 07a122eea281
parent 19 630d2f34d719
child 21 4814c5a49428
equal deleted inserted replaced
19:630d2f34d719 20:07a122eea281
     1 /*
       
     2 * Copyright (c) 2009 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: 
       
    15 *
       
    16 */
       
    17 #include "testconfigfileparser.h"
       
    18 #include <f32file.h>
       
    19 
       
    20 
       
    21 
       
    22 #ifndef EKA2
       
    23 GLDEF_C TInt E32Dll(TDllReason/* aReason*/)	
       
    24 //
       
    25 // DLL entry point
       
    26 //
       
    27 	{
       
    28 	return (KErrNone);
       
    29 	}
       
    30 #endif
       
    31 
       
    32 
       
    33 EXPORT_C CTestConfig* CTestConfig::NewLC(RFs& aFs, const TDesC& aComponent, const TDesC& aScript)
       
    34 	{
       
    35 	CTestConfig* self = NewLC(aFs, aComponent);
       
    36 	self->ReadScriptL(aScript);
       
    37 	return self;
       
    38 	}
       
    39 
       
    40 EXPORT_C CTestConfig* CTestConfig::NewLC(RFs& aFs, const TDesC& aComponent)
       
    41 	{
       
    42 	CTestConfig* self = new (ELeave) CTestConfig(aFs);
       
    43 	CleanupStack::PushL(self);
       
    44 	self->ConstructL(aComponent);
       
    45 	return self;
       
    46 	}
       
    47 
       
    48 void CTestConfig::ConstructL(const TDesC& aComponent)
       
    49 	{
       
    50 	iComponent = aComponent.AllocL();
       
    51 	}
       
    52 
       
    53 CTestConfig::CTestConfig(RFs& aFs)
       
    54 : iFs(aFs)
       
    55 	{
       
    56 	}
       
    57 
       
    58 EXPORT_C CTestConfig::~CTestConfig()
       
    59 	{
       
    60 	iSections.ResetAndDestroy();
       
    61 	iSections.Close();
       
    62 	delete iComponent;
       
    63 	}
       
    64 
       
    65 EXPORT_C const CTestConfigSection* CTestConfig::Section(const TDesC8& aSectionName) const
       
    66 	{
       
    67 	const CTestConfigSection* section = NULL;
       
    68 	const TInt count = iSections.Count();
       
    69 		
       
    70 	for (TInt i = 0; i < count; i++) //order important
       
    71 		{
       
    72 		if (iSections[i]->SectionName().CompareF(aSectionName) == 0)
       
    73 			{
       
    74 			section = iSections[i];
       
    75 			break;
       
    76 			}
       
    77 		}
       
    78 
       
    79 	return section;
       
    80 	}
       
    81 
       
    82 EXPORT_C CTestConfigSection* CTestConfig::Section(const TDesC8& aSectionName)
       
    83 	{
       
    84 	CTestConfigSection* section = NULL;
       
    85 	const TInt count = iSections.Count();
       
    86 		
       
    87 	for (TInt i = 0; i < count; i++) //order important
       
    88 		{
       
    89 		if (iSections[i]->SectionName().CompareF(aSectionName) == 0)
       
    90 			{
       
    91 			section = iSections[i];
       
    92 			break;
       
    93 			}
       
    94 		}
       
    95 
       
    96 	return section;
       
    97 	}
       
    98 
       
    99 EXPORT_C const TDesC8& CTestConfig::ItemValue(const TDesC8& aSection, const TDesC8& aItem, const TDesC8& aDefault) const
       
   100 	{
       
   101 	const CTestConfigSection* section = Section(aSection);
       
   102 
       
   103 	if (section != NULL)
       
   104 		return section->ItemValue(aItem, aDefault);
       
   105 
       
   106 	return aDefault;
       
   107 	}
       
   108 
       
   109 EXPORT_C TInt CTestConfig::ItemValue(const TDesC8& aSection, const TDesC8& aItem, const TInt aDefault) const
       
   110 	{
       
   111 	TInt output = aDefault;
       
   112 	const CTestConfigSection* section = Section(aSection);
       
   113 
       
   114 	if (section != NULL)
       
   115 		{
       
   116 		output = section->ItemValue(aItem, aDefault);
       
   117 		}
       
   118 
       
   119 	return output;
       
   120 	}
       
   121 
       
   122 
       
   123 
       
   124 
       
   125 HBufC8* CTestConfig::ReadFileL(const TDesC& aFile) const
       
   126 	{
       
   127 	//Returns a HBufC8 with the contents of aFile
       
   128 	RFile file;
       
   129 	const TInt err = file.Open(iFs, aFile, EFileShareAny | EFileRead);
       
   130 
       
   131 	if (err != KErrNone)
       
   132 		{
       
   133 		TParse fileOut;
       
   134 		User::LeaveIfError(ResolveFile(iFs, *iComponent, aFile, fileOut));
       
   135 		User::LeaveIfError(file.Open(iFs, fileOut.FullName(), EFileShareAny | EFileRead));
       
   136 		}
       
   137 
       
   138 	CleanupClosePushL(file);
       
   139 
       
   140 	TInt size = 0;
       
   141 	User::LeaveIfError(file.Size(size));
       
   142 
       
   143 	HBufC8* contents = HBufC8::NewLC(size + 4);
       
   144 	TPtr8 contentsPtr(contents->Des());
       
   145 	User::LeaveIfError(file.Read(0, contentsPtr));
       
   146 
       
   147 	CleanupStack::Pop(contents);
       
   148 	CleanupStack::PopAndDestroy(&file);
       
   149 	return contents;
       
   150 	}
       
   151 
       
   152 EXPORT_C TInt CTestConfig::ResolveFile(RFs& aFs, const TDesC& aComponent, const TDesC& aFileName, TParse& aParseOut)
       
   153 	{
       
   154 	TFileName* savedPath = new TFileName;
       
   155 	TFileName* fileName = new TFileName;
       
   156 	if ((savedPath == NULL) || (fileName == NULL))
       
   157 		{
       
   158 		delete savedPath;
       
   159 		delete fileName;
       
   160 		return KErrNoMemory;
       
   161 		}
       
   162 
       
   163 	fileName->Append(KScriptPathSep);
       
   164 //	fileName->Append(KSmsTestFileInputBase);
       
   165 //	fileName->Append(KScriptPathSep);
       
   166 	fileName->Append(aComponent);
       
   167 	fileName->Append(KScriptPathSep);
       
   168 	fileName->Append(aFileName);
       
   169 	
       
   170 	// file finder will look in the session drive first, then Y->A,Z
       
   171 	// so set session drive to Y (save old and restore it afterwards)
       
   172 	aFs.SessionPath(*savedPath);
       
   173 	_LIT(KTopDrive,"Y:\\");
       
   174 	aFs.SetSessionPath(KTopDrive);
       
   175     TFindFile file_finder(aFs);
       
   176     TInt err = file_finder.FindByDir(*fileName,KNullDesC);
       
   177 	if(err==KErrNone)
       
   178 		aParseOut.Set(file_finder.File(),NULL,NULL);
       
   179 	aFs.SetSessionPath(*savedPath);
       
   180 	delete savedPath;
       
   181 	delete fileName;
       
   182 	return(err);
       
   183 	}
       
   184 
       
   185 EXPORT_C void CTestConfig::ReadScriptL(const TDesC& aScript)
       
   186 	{
       
   187 	iSections.ResetAndDestroy();
       
   188 
       
   189 	CTestConfigSection* section = NULL;
       
   190 	CTestConfigItem* currentItem = NULL;
       
   191 	TInt currentItemStart = 0;
       
   192 	CTestConfigSection* sectionDefaults = NULL;
       
   193 
       
   194 	HBufC8* scriptContents = ReadFileL(aScript);
       
   195 	CleanupStack::PushL(scriptContents);
       
   196 
       
   197 	TLex8 input(*scriptContents);
       
   198 
       
   199 	while (!input.Eos())
       
   200 		{
       
   201 		input.SkipSpaceAndMark();
       
   202 		input.SkipCharacters();
       
   203 
       
   204 		if ( input.TokenLength() == 0)    // if valid potential token
       
   205 			{
       
   206 			//end of the script file found
       
   207 			break;
       
   208 			}
       
   209 
       
   210 		const TPtrC8 token(input.MarkedToken());
       
   211 
       
   212 		if (token.CompareF(_L8("endscript")) == 0)
       
   213 			{
       
   214 			//end of the script file found
       
   215 			break;
       
   216 			}
       
   217 		else if (IsNewSection(*scriptContents, input))
       
   218 			{
       
   219 			ParseAndSetItemValueL(*scriptContents, input, currentItemStart, currentItem);
       
   220 
       
   221 			TInt mid = 1;
       
   222 			TInt len = token.Length() - 2;
       
   223 
       
   224 			const TPtrC8 sectionName(token.Mid(mid, len));
       
   225 
       
   226 			if (sectionDefaults != NULL)
       
   227 				section = CTestConfigSection::NewLC(sectionName, *sectionDefaults);
       
   228 			else
       
   229 				section = CTestConfigSection::NewLC(sectionName);
       
   230 
       
   231 			if (sectionDefaults == NULL && IsDefaultSection(section->SectionName()))
       
   232 				sectionDefaults = section;
       
   233 
       
   234 			User::LeaveIfError(iSections.Append(section));
       
   235 			CleanupStack::Pop(section);
       
   236 			}
       
   237 		else if (section != NULL)
       
   238 			{
       
   239 			TInt valueOffset;
       
   240 			TPtrC8 newItem;
       
   241 
       
   242 			if (IsNewComment(*scriptContents, input))
       
   243 				{
       
   244 				ParseAndSetItemValueL(*scriptContents, input, currentItemStart, currentItem);
       
   245 				__ASSERT_DEBUG(currentItem == NULL, User::Invariant());
       
   246 				SkipToNextLine(input);
       
   247 				}
       
   248 			else if (IsNewItem(*scriptContents, input, newItem, valueOffset))
       
   249 				{
       
   250 				ParseAndSetItemValueL(*scriptContents, input, currentItemStart, currentItem);
       
   251 				currentItemStart = input.MarkedOffset() + valueOffset;
       
   252 				currentItem = &section->AddItemL(newItem, KNullDesC8);
       
   253 				}
       
   254 			}
       
   255 		}
       
   256 
       
   257 	ParseAndSetItemValueL(*scriptContents, input, currentItemStart, currentItem);
       
   258 	CleanupStack::PopAndDestroy(scriptContents);
       
   259 	}
       
   260 
       
   261 TBool CTestConfig::IsNewSection(const TDesC8& aSource, const TLex8& aInput) const
       
   262 /**
       
   263  * Checks whether the current marked token in aInput starts with a '[' and ends with a ']',
       
   264  * and checks that this token is at the start of a line.
       
   265  *
       
   266  * @returns Whether this is a new section in the script file
       
   267  */
       
   268 	{
       
   269 	const TPtrC8 token(aInput.MarkedToken());
       
   270 	const TInt offset(aInput.MarkedOffset());
       
   271 
       
   272 	TBool ret = token.Length() > 2 && token.Find(KScriptSectionStart) == 0;
       
   273 	ret = ret && token.Find(KScriptSectionEnd) != KErrNotFound;
       
   274 
       
   275 	if (ret && offset > 0)
       
   276 		{
       
   277 		const TPtrC8 lastChar(aSource.Mid(offset-1, 1));
       
   278 		ret = ret && (lastChar == KScriptLF || lastChar == KScriptCR);
       
   279 		}
       
   280 
       
   281 	return ret;
       
   282 	}
       
   283 
       
   284 void CTestConfig::SkipToNextLine(TLex8& aInput) const
       
   285 	{
       
   286 	const TChar cr('\n');
       
   287 
       
   288 	while (!aInput.Eos() && aInput.Peek() != cr)
       
   289 		{
       
   290 		aInput.Inc();
       
   291 		}
       
   292 	}
       
   293 
       
   294 TBool CTestConfig::IsNewItem(const TDesC8& aSource, const TLex8& aLex, TPtrC8& aItem, TInt& aStartOfVal) const
       
   295 	{
       
   296 	TBool ret(EFalse);
       
   297 
       
   298 	if (IsAtStartOfNewLine(aSource, aLex, ETrue))
       
   299 		{
       
   300 		const TPtrC8 itemEnd(KScriptItemEnd);
       
   301 		const TInt itemEndLen(itemEnd.Length());
       
   302 
       
   303 		TPtrC8 token(aLex.MarkedToken());
       
   304 
       
   305 		//First check to see if this token contains '='
       
   306 		const TInt find = token.Find(itemEnd);
       
   307 		if (find > 0)
       
   308 			{
       
   309 			aStartOfVal = find + itemEndLen;
       
   310 			aItem.Set(token.Left(find));
       
   311 			ret = ETrue;
       
   312 			}
       
   313 		else
       
   314 			{
       
   315 			aItem.Set(token);
       
   316 			aStartOfVal = token.Length();
       
   317 
       
   318 			const TPtrC8 remain(aLex.Remainder());
       
   319 			TLex8 lex(remain);
       
   320 			//Check that the next token starts with and '='
       
   321 			lex.SkipSpaceAndMark();
       
   322 			lex.SkipCharacters();
       
   323 			token.Set(lex.MarkedToken());
       
   324 
       
   325 			if (token.Find(itemEnd) == 0)
       
   326 				{
       
   327 				aStartOfVal += lex.MarkedOffset() + itemEndLen;
       
   328 				ret = ETrue;
       
   329 				}
       
   330 			}
       
   331 		}
       
   332 
       
   333 	return ret;
       
   334 	}
       
   335 
       
   336 TBool CTestConfig::IsNewComment(const TDesC8& aSource, const TLex8& aLex) const
       
   337 	{
       
   338 	TBool ret(EFalse);
       
   339 
       
   340 	const TPtrC8 token(aLex.MarkedToken());
       
   341 	const TPtrC8 commentStart(KScriptCommentStart);
       
   342 	const TInt commentStartLen(commentStart.Length());
       
   343 	const TInt tokenLen(token.Length());
       
   344 
       
   345 	if (commentStartLen <= tokenLen && token.Left(commentStartLen).Compare(commentStart) == 0)
       
   346 		{
       
   347 		ret = IsAtStartOfNewLine(aSource, aLex, ETrue);
       
   348 		}
       
   349 
       
   350 	return ret;
       
   351 	}
       
   352 
       
   353 TBool CTestConfig::IsAtStartOfNewLine(const TDesC8& aSource, const TLex8& aLex, TBool aIgnoreSpaces) const
       
   354 	{
       
   355 	TInt offset(aLex.MarkedOffset());
       
   356 	__ASSERT_ALWAYS(offset != 0, User::Invariant());
       
   357 
       
   358 	TChar ch = NULL;
       
   359 
       
   360 	if (aIgnoreSpaces)
       
   361 		{
       
   362 		while (offset--)
       
   363 			{
       
   364 			ch = aSource[offset];
       
   365 			if (ch == KScriptLFChar || ch == KScriptCRChar || !ch.IsSpace())
       
   366 				break;
       
   367 			}
       
   368 		}
       
   369 	else
       
   370 		ch = aSource[offset-1];
       
   371 
       
   372 	TBool ret(EFalse);
       
   373 
       
   374 	if (offset <= 0)
       
   375 		ret = ETrue;
       
   376 	else
       
   377 		ret = (ch == KScriptLFChar || ch == KScriptCRChar);
       
   378 
       
   379 	return ret;
       
   380 	}
       
   381 
       
   382 TBool CTestConfig::IsDefaultSection(const TDesC8& aSectionName) const
       
   383 	{
       
   384 	TBool retVal = (aSectionName.CompareF(KScriptDefaults) == 0);
       
   385 	retVal = retVal || (aSectionName.CompareF(KScriptDefault1) == 0);
       
   386 	return retVal;
       
   387 	}
       
   388 
       
   389 TPtrC8 CTestConfig::ParseValue(const TDesC8& aText, const TLex8& aInput, TInt aCurrentItemStart) const
       
   390 	{
       
   391 	const TInt mid = aCurrentItemStart;
       
   392 	const TInt len = aInput.MarkedOffset() - mid;
       
   393 	TPtrC8 ret(KNullDesC8);
       
   394 
       
   395 	if (len > 0)
       
   396 		ret.Set(aText.Mid(mid, len));
       
   397 
       
   398 	return ret;
       
   399 	}
       
   400 
       
   401 void CTestConfig::ParseAndSetItemValueL(const TDesC8& aText, const TLex8& aInput, TInt aCurrentItemStart, CTestConfigItem*& arCurrentItem)
       
   402 	{
       
   403 	if (arCurrentItem)
       
   404 		{
       
   405 		delete arCurrentItem->iValue;
       
   406 		arCurrentItem->iValue = NULL;
       
   407 
       
   408 		TPtrC8 val(ParseValue(aText, aInput, aCurrentItemStart));
       
   409 		arCurrentItem->iValue = ReplaceLC(KScriptCRLF, KScriptLF, val);
       
   410 		arCurrentItem->iValue->Des().Trim();
       
   411 		CleanupStack::Pop(arCurrentItem->iValue);
       
   412 
       
   413 		if (arCurrentItem->Item().CompareF(KScriptDefaults) == 0)
       
   414 			{
       
   415 			TName filename;
       
   416 			filename.Copy(arCurrentItem->Value());
       
   417 			CopyInDefaultsL(arCurrentItem->iParent, filename);
       
   418 			}
       
   419 		}
       
   420 
       
   421 	arCurrentItem = NULL;
       
   422 	}
       
   423 
       
   424 void CTestConfig::CopyInDefaultsL(CTestConfigSection& aSection, const TDesC& aDefaultFile)
       
   425 	{
       
   426 	CTestConfig* file = CTestConfig::NewLC(iFs, aDefaultFile);
       
   427 
       
   428 	TInt count = file->Sections().Count();
       
   429 
       
   430 	if (count > 0)
       
   431 		{
       
   432 		const CTestConfigSection& def = (*file)[0];
       
   433 		aSection.SetDefaultsL(def);
       
   434 		}
       
   435 
       
   436 	CleanupStack::PopAndDestroy(file);
       
   437 	}
       
   438 
       
   439 EXPORT_C TInt CTestConfig::CountElements(const TDesC8& aInput, TChar aDelimiter)
       
   440 	{
       
   441 	TInt pos = aInput.Length();
       
   442 	TInt count = 1;
       
   443 
       
   444 	while (pos--)
       
   445 		{
       
   446 		if (TChar(aInput[pos]) == aDelimiter)
       
   447 			count++;
       
   448 		}
       
   449 
       
   450 	return count;
       
   451 	}
       
   452 
       
   453 EXPORT_C TInt CTestConfig::GetElement(const TDesC8& aInput, TChar aDelimiter, TInt aIndex, TInt& aOutput)
       
   454 	{
       
   455 	aOutput = 0;
       
   456 	TPtrC8 string;
       
   457 	TInt err = GetElement(aInput, aDelimiter, aIndex, string, ETrue);
       
   458 
       
   459 	if (err == KErrNone)
       
   460 		{
       
   461 		TLex8 number(string);
       
   462 		err = number.Val(aOutput);
       
   463 		}
       
   464 
       
   465 	return err;
       
   466 	}
       
   467 
       
   468 EXPORT_C TInt CTestConfig::GetElement(const TDesC8& aInput, TChar aDelimiter, TInt aIndex, TPtrC8& aOutput, TBool aTrimOutput)
       
   469 	{
       
   470 	TLex8 input(aInput);
       
   471 	TInt err = KErrNone;
       
   472 	TPtrC8 ptr;
       
   473 
       
   474 	for (TInt i = 0; i <= aIndex && err == KErrNone; i++)
       
   475 		{
       
   476 		err = GetNextElement(input, aDelimiter, ptr);
       
   477 		}
       
   478 
       
   479 	if (err == KErrNone)
       
   480 		{
       
   481 		if (aTrimOutput)
       
   482 			aOutput.Set(Trim(ptr));
       
   483 		else
       
   484 			aOutput.Set(ptr);
       
   485 		}
       
   486 	else 
       
   487 		{
       
   488 		const TInt count = CountElements(aInput, aDelimiter);
       
   489 		const TInt len = aInput.Length();
       
   490 
       
   491 		if (len != 0 && count - 1 == aIndex && TChar(aInput[len-1]) == aDelimiter)
       
   492 			{
       
   493 			aOutput.Set(KNullDesC8);
       
   494 			err = KErrNone;
       
   495 			}
       
   496 		}
       
   497 
       
   498 	return err;
       
   499 	}
       
   500 
       
   501 EXPORT_C TPtrC8 CTestConfig::Trim(const TDesC8& aInput)
       
   502 	{
       
   503 	const TPtrC8 ptr(TrimLeft(aInput));
       
   504 	return TrimRight(ptr);
       
   505 	}
       
   506 
       
   507 EXPORT_C TPtrC8 CTestConfig::TrimRight(const TDesC8& aInput)
       
   508 	{
       
   509 	const TText8* first = aInput.Ptr();					// pointer to first char
       
   510 	const TText8* last = first + aInput.Length() - 1;		// pointer to last char
       
   511 	while (last >= first && TChar(*last).IsSpace()) last--;	// trim the right
       
   512 	return TPtrC8(first, last + 1 - first);				// return the result
       
   513 	}
       
   514 
       
   515 EXPORT_C TPtrC8 CTestConfig::TrimLeft(const TDesC8& aInput)
       
   516 	{
       
   517 	const TText8* first = aInput.Ptr();					// pointer to first char
       
   518 	const TText8* last = first + aInput.Length() - 1;		// pointer to last char
       
   519 	while (first < last && TChar(*first).IsSpace()) first++;	// trim the left
       
   520 	return TPtrC8(first, last + 1 - first);				// return the result
       
   521 	}
       
   522 
       
   523 
       
   524 TInt CTestConfig::GetNextElement(TLex8& aInput, TChar aDelimiter, TPtrC8& aOutput)
       
   525 	{
       
   526 	if (aInput.Eos())
       
   527 		return KErrNotFound;
       
   528 
       
   529 	//Get to the start of the descriptor
       
   530 	while (!aInput.Eos() && aInput.Peek() != aDelimiter)
       
   531 		aInput.Inc();
       
   532 
       
   533 	aOutput.Set(aInput.MarkedToken());
       
   534 	if (!aInput.Eos())
       
   535 		aInput.SkipAndMark(1);
       
   536 
       
   537 	return KErrNone;
       
   538 	}
       
   539 
       
   540 /*EXPORT_C void CTestConfig::ReplaceL(const TDesC8& aOld, const TDesC8& aNew, HBufC*& rString)
       
   541 	{
       
   542 	HBufC* repl = ReplaceLC(aOld, aNew, *rString);
       
   543 	CleanupStack::Pop(repl);
       
   544 	rString = repl;
       
   545 	}*/
       
   546 
       
   547 EXPORT_C HBufC8* CTestConfig::ReplaceLC(const TDesC8& aOld, const TDesC8& aNew, const TDesC8& aOldString)
       
   548 	{
       
   549 	HBufC8* rString = aOldString.AllocLC();
       
   550 	TInt oldLen = aOld.Length();
       
   551 	TInt newLen = aNew.Length();
       
   552 
       
   553 	if (!oldLen)
       
   554 		return rString;
       
   555 
       
   556 	for (TInt pos = 0; pos < rString->Length(); pos += newLen)
       
   557 		{
       
   558 		TPtrC8 ptrC = rString->Mid(pos);
       
   559 		TInt find = ptrC.Find(aOld);
       
   560 
       
   561 		if (find == KErrNotFound)
       
   562 			return rString;
       
   563 	
       
   564 		pos += find;
       
   565 
       
   566 		if (newLen > oldLen)
       
   567 			{
       
   568 			rString = rString->ReAllocL(rString->Length() + newLen - oldLen);
       
   569 			CleanupStack::Pop();
       
   570 			CleanupStack::PushL(rString);
       
   571 			}
       
   572 
       
   573 		TPtr8 ptr(rString->Des());
       
   574 		ptr.Replace(pos, oldLen, aNew);
       
   575 		}
       
   576 
       
   577 	return rString;
       
   578 	}
       
   579 
       
   580 
       
   581 EXPORT_C void CTestConfig::WriteFileL(const TDesC& aFileName)
       
   582 	{
       
   583 	RFile file;
       
   584 	User::LeaveIfError(file.Replace(iFs, aFileName, EFileShareAny | EFileWrite));
       
   585 	CleanupClosePushL(file);
       
   586 
       
   587 	const TInt count = iSections.Count();
       
   588 	
       
   589 	for (TInt i=0; i < count; i++)
       
   590 		iSections[i]->WriteL(file);
       
   591 
       
   592 	User::LeaveIfError(file.Flush());
       
   593 	CleanupStack::PopAndDestroy();  //file
       
   594 	}
       
   595 
       
   596 EXPORT_C TBool CTestConfig::operator==(const CTestConfig& aFile) const
       
   597 	{
       
   598 	TInt count = iSections.Count();
       
   599 	if (count != aFile.Sections().Count())
       
   600 		return EFalse;
       
   601 
       
   602 	TBool retVal = ETrue;
       
   603 
       
   604 	while (count-- && retVal)
       
   605 		{
       
   606 		retVal = retVal && (*iSections[count] == aFile[count]);
       
   607 		}
       
   608 
       
   609 	return retVal;
       
   610 	}