windowing/windowserver/nga/SERVER/INIFILE.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1996-2009 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 //
       
    15 
       
    16 #include <e32std.h>
       
    17 #include "server.h"
       
    18 #include "inifile.h"
       
    19 
       
    20 // uncomment so that if the wsini.ini file is not found on drive Wserv loaded from or drive Z: (if different)
       
    21 // it will be searched for on drive C: (if different from Wserv's drive)
       
    22 //#define LOAD_INI_FILE_FROM_DRIVE_Z_OR_C
       
    23 
       
    24 
       
    25 GLREF_D CDebugLogBase *wsDebugLog;
       
    26 
       
    27 _LIT(KDefaultSectionName,"DEFAULT");
       
    28 _LIT(KCommentMarker,"//");
       
    29 _LIT(KScreenSectionName,"SCREEN");
       
    30 const TUint16 KNewSection('[');
       
    31 const TUint16 KSpaceChar(' ');
       
    32 const TUint16 KNewSection2(']');
       
    33 const TInt KDefaultSectionNumber(0);
       
    34 const TInt KDefaultScreenId(-1);
       
    35 
       
    36 
       
    37 CIniFile::CIniFile()
       
    38 	{}
       
    39 
       
    40 CIniFile::~CIniFile()
       
    41 	{
       
    42 	FreeData();
       
    43 	}
       
    44 
       
    45 CIniSection * CIniFile::FindSection(TInt aScreen)
       
    46 	{
       
    47 	for (TInt sect = 0; sect < iSectionArray.Count(); ++sect)
       
    48 		{
       
    49 		if (iSectionArray[sect]->Screen() == aScreen)
       
    50 			{
       
    51 			return iSectionArray[sect];
       
    52 			}
       
    53 		}
       
    54 	return NULL;
       
    55 	}
       
    56 
       
    57 CIniSection * CIniFile::FindSection(const TDesC& aName)
       
    58 	{
       
    59 	for (TInt sect = 0; sect < iSectionArray.Count(); ++sect)
       
    60 		{
       
    61 		if (iSectionArray[sect]->Screen() == KDefaultScreenId && !iSectionArray[sect]->Name().CompareF(aName))
       
    62 			{
       
    63 			return iSectionArray[sect];
       
    64 			}
       
    65 		}
       
    66 	return NULL;
       
    67 	}
       
    68 
       
    69 /* Processes a .ini file entry section name.
       
    70 
       
    71  @return the corresponding index.
       
    72  @param aLine Input line of text from the .ini file, stripped of comments & excess whitespace.
       
    73  @leave KErrNoMemory
       
    74  */
       
    75 CIniSection * CIniFile::AddOrFindIniSectionL(TPtr& aSectionName)
       
    76 	{
       
    77 	aSectionName.Trim();
       
    78 
       
    79 	// DEFAULT section
       
    80 	if (aSectionName.CompareF(KDefaultSectionName) == 0)
       
    81 		{ 
       
    82 		return iSectionArray[KDefaultSectionNumber];
       
    83 		}
       
    84 
       
    85 	// SCREENx section
       
    86 	if (0 == aSectionName.FindF(KScreenSectionName))
       
    87 		{
       
    88 		TLex lex(aSectionName.Mid(KScreenSectionName().Length()));
       
    89 		TInt screenNum;
       
    90 		lex.SkipSpace();
       
    91 		if (lex.Val(screenNum) == KErrNone)
       
    92 			{
       
    93 			return AddOrFindScreenSectionL(screenNum);
       
    94 			}
       
    95 		}
       
    96 		
       
    97 	// other section
       
    98 	return AddOrFindNamedSectionL(aSectionName);
       
    99 	}
       
   100 
       
   101 CIniSection * CIniFile::CreateSectionL(TInt aScreen)
       
   102 	{
       
   103 	CIniSection* newSection = new (ELeave) CIniSection(aScreen);
       
   104 	CleanupStack::PushL( newSection ) ;
       
   105 	newSection->ConstructL() ;
       
   106 	User::LeaveIfError(iSectionArray.Append(newSection));
       
   107 	CleanupStack::Pop( newSection ) ;
       
   108 	if (aScreen + 1 > iScreenCount)
       
   109 		iScreenCount = aScreen + 1;
       
   110 	return newSection;
       
   111 	}
       
   112 
       
   113 CIniSection * CIniFile::CreateSectionL(const TDesC& aName)
       
   114 	{
       
   115 	CIniSection* newSection = new (ELeave) CIniSection(KDefaultScreenId);
       
   116 	CleanupStack::PushL( newSection ) ;
       
   117 	newSection->ConstructL(aName) ;
       
   118 	User::LeaveIfError(iSectionArray.Append(newSection));
       
   119 	CleanupStack::Pop( newSection ) ;
       
   120 	return newSection;
       
   121 	}
       
   122 
       
   123 
       
   124 void CIniFile::doConstructL(RFile &aFile)
       
   125 	{
       
   126 	TFileText textFile;
       
   127 	textFile.Set(aFile);
       
   128 	const TInt KMaxIniLine=256;
       
   129 	TBuf<KMaxIniLine> readLine;
       
   130 	TBool first=ETrue;
       
   131 
       
   132 	// always have a [DEFAULT] section
       
   133 	CIniSection * currentSection = CreateSectionL(KDefaultSectionName);
       
   134 
       
   135 	FOREVER
       
   136 		{
       
   137 		TInt err=textFile.Read(readLine);
       
   138 		if (err==KErrEof)
       
   139 			break;
       
   140 		User::LeaveIfError(err);
       
   141 
       
   142 		if (readLine.Length()>0)
       
   143 			{
       
   144 			if (first && (readLine[0]==0xFFFE || readLine[0]==0xFEFF))
       
   145 				readLine.Delete(0,1);
       
   146 			
       
   147 			// Comment marker "//" indicates the rest of the line should be discarded
       
   148 			TInt commentStart = readLine.Find(KCommentMarker);
       
   149 			if (commentStart != KErrNotFound)
       
   150 				{
       
   151 				readLine.Delete(commentStart, readLine.Length());
       
   152 				}
       
   153 
       
   154 			// compact unnecessary whitespace
       
   155 			readLine.TrimAll();
       
   156 
       
   157 			// anything left in buffer?
       
   158 			if (readLine.Length() > 0)
       
   159 				{
       
   160 				// section name requires "[" and "]"
       
   161 				if (readLine[0] == KNewSection && readLine.LocateReverse(KNewSection2) == readLine.Length() - 1)
       
   162 					{
       
   163 					TPtr nameText = readLine.MidTPtr(1, readLine.Length() - 2); // strip [ and ]
       
   164 					currentSection = AddOrFindIniSectionL(nameText);
       
   165 					}
       
   166 				else
       
   167 					{
       
   168 					if (currentSection)
       
   169 						{
       
   170 						currentSection->AddVariableL(readLine);
       
   171 						}
       
   172 					}
       
   173 				}
       
   174 			first=EFalse;
       
   175 			}
       
   176 		}
       
   177 
       
   178 	if (iScreenCount == 0)
       
   179 		{
       
   180 		iScreenCount = 1;
       
   181 		}
       
   182 	}
       
   183 
       
   184 CIniFile* CIniFile::NewL()
       
   185     {
       
   186     CIniFile* self = new(ELeave) CIniFile();
       
   187     CleanupStack::PushL(self);
       
   188     self->ConstructL();
       
   189     CleanupStack::Pop(self);
       
   190     return self;
       
   191     }
       
   192 
       
   193 void CIniFile::FreeData() 
       
   194 	{
       
   195 	iSectionArray.ResetAndDestroy() ;
       
   196 	iScreenCount = 0;
       
   197 	}
       
   198 
       
   199 void errFreeData(TAny *aIniFile)
       
   200 	{
       
   201 	((CIniFile *)aIniFile)->FreeData();
       
   202 	}
       
   203 
       
   204 HBufC* IniFileSearchPathLC()
       
   205 	{
       
   206 	_LIT(KPath,"\\SYSTEM\\DATA\\");
       
   207 	_LIT(KPathSep,";");
       
   208 	const TInt KLengthPerPath = 2 + KPath().Length();
       
   209 	// work out which drive Wserv loaded from
       
   210 	RProcess self;
       
   211 	TFileName myPath = self.FileName();
       
   212 	TParsePtrC myDrive(myPath);
       
   213 	TDriveUnit myDriveUnit(myDrive.Drive());
       
   214 	// need extra buffer space for search paths for drives Z: or C: ?
       
   215 #if defined(LOAD_INI_FILE_FROM_DRIVE_Z_OR_C)
       
   216 	TInt numPaths = 2;
       
   217 	if (myDriveUnit != EDriveZ && myDriveUnit != EDriveC)
       
   218 		{
       
   219 		numPaths += 1;
       
   220 		}
       
   221 #else
       
   222 	TInt numPaths = 1;
       
   223 	if (myDriveUnit != EDriveZ)
       
   224 		{
       
   225 		numPaths += 1;
       
   226 		}
       
   227 #endif
       
   228 	HBufC* searchPath = HBufC::NewLC(numPaths * KLengthPerPath + (numPaths - 1) * KPathSep().Length());
       
   229 	TPtr pPath(searchPath->Des());
       
   230 	pPath.Append(myDrive.Drive());
       
   231 	pPath.Append(KPath);
       
   232 	if (myDriveUnit != EDriveZ)
       
   233 		{
       
   234 		pPath.Append(KPathSep);
       
   235 		pPath.Append(TDriveUnit(EDriveZ).Name());
       
   236 		pPath.Append(KPath);
       
   237 		}
       
   238 #if defined(LOAD_INI_FILE_FROM_DRIVE_Z_OR_C)
       
   239 	if (myDriveUnit != EDriveC)
       
   240 		{
       
   241 		pPath.Append(KPathSep);
       
   242 		pPath.Append(TDriveUnit(EDriveC).Name());
       
   243 		pPath.Append(KPath);
       
   244 		}
       
   245 #endif
       
   246 	return searchPath;
       
   247 	}
       
   248 
       
   249 void CIniFile::ConstructL()
       
   250 	{
       
   251 	TAutoClose<RFs> fs;
       
   252 	User::LeaveIfError(fs.iObj.Connect());
       
   253 	fs.iObj.SetNotifyUser(EFalse);
       
   254 	fs.PushL();
       
   255 	HBufC* searchPath = IniFileSearchPathLC();
       
   256 	_LIT(KFileName,"WSINI.INI");
       
   257 	TFindFile findinifile(fs.iObj);
       
   258 	TInt err=findinifile.FindByPath(KFileName,searchPath);
       
   259 	User::LeaveIfError(err);
       
   260 	CleanupStack::PopAndDestroy(searchPath);
       
   261  	TAutoClose<RFile> file;
       
   262 	User::LeaveIfError(file.iObj.Open(fs.iObj,findinifile.File(),EFileStreamText|EFileRead));
       
   263 	file.PushL();
       
   264 	CleanupStack::PushL(TCleanupItem(errFreeData,this));
       
   265 	doConstructL(file.iObj);
       
   266 	CleanupStack::Pop(); // TCleanupItem
       
   267 	file.Pop();
       
   268 	fs.Pop();
       
   269 	}
       
   270 
       
   271 /* If the Section for the screen exists find the data, otherwise create a new data structure.
       
   272 
       
   273  @param aScreen Screen number
       
   274  @return index to section
       
   275  @leave KErrNoMemory
       
   276  */
       
   277 CIniSection * CIniFile::AddOrFindScreenSectionL(TInt aScreen)
       
   278 	{
       
   279 	CIniSection * section = FindSection(aScreen);
       
   280 	if (!section)
       
   281 		section = CreateSectionL(aScreen);
       
   282 	return section;
       
   283 	}
       
   284 
       
   285 /* If the Section exists find the data, otherwise create a new data structure.
       
   286 
       
   287  @param aName section name
       
   288  @return index to section
       
   289  @leave KErrNoMemory
       
   290  */
       
   291 CIniSection * CIniFile::AddOrFindNamedSectionL(const TDesC& aName)
       
   292 	{
       
   293 	CIniSection * section = FindSection(aName);
       
   294 	if (!section)
       
   295 		section = CreateSectionL(aName);
       
   296 	return section;
       
   297 	}
       
   298 
       
   299 TBool CIniFile::FindVar(const TDesC &aVarName, TPtrC &aResult)
       
   300 	{
       
   301 	return iSectionArray[KDefaultSectionNumber]->FindVar(aVarName, aResult);
       
   302 	}
       
   303 
       
   304 
       
   305 TBool CIniFile::FindVar(const TDesC &aVarName, TInt &aResult)
       
   306 	{
       
   307 	return iSectionArray[KDefaultSectionNumber]->FindVar(aVarName, aResult);
       
   308 	}
       
   309 
       
   310 TBool CIniFile::FindVar(const TDesC &aVarName)
       
   311 //
       
   312 // Used to simply detect the presence of the specified variable name
       
   313 //
       
   314 	{
       
   315 	TPtrC ptr(NULL,0);
       
   316 	return FindVar(aVarName, ptr);
       
   317 	}
       
   318 
       
   319 // FindVar in [SCREENx] sections
       
   320 TBool CIniFile::FindVar( TInt aScreen, const TDesC &aVarName)
       
   321 	{
       
   322 	TPtrC ptr(NULL,0);
       
   323 	return FindVar(aScreen, aVarName, ptr);
       
   324 	}
       
   325 
       
   326 TBool CIniFile::FindVar( TInt aScreen, const TDesC& aVarName, TPtrC &aResult )
       
   327 	{
       
   328 	CIniSection * section = FindSection(aScreen);
       
   329 	TBool found = EFalse;
       
   330 	if (section)
       
   331 		found = section->FindVar(aVarName, aResult);
       
   332 	if (!found)
       
   333 		found = FindVar(aVarName, aResult);
       
   334 	return found;
       
   335 	}
       
   336 
       
   337 TBool CIniFile::FindVar(TInt aScreen, const TDesC &aVarName, TInt &aResult)
       
   338 	{
       
   339 	CIniSection * section = FindSection(aScreen);
       
   340 	TBool found = EFalse;
       
   341 	if (section)
       
   342 		found = section->FindVar(aVarName, aResult);
       
   343 	if (!found)
       
   344 		found = FindVar(aVarName, aResult);
       
   345 	return found;
       
   346 	}
       
   347 
       
   348 // FindVar in named sections
       
   349 TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC &aVarName)
       
   350 	{
       
   351 	TPtrC ptr(NULL,0);
       
   352 	return FindVar(aSectionName, aVarName, ptr);
       
   353 	}
       
   354 
       
   355 TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC& aVarName, TPtrC &aResult )
       
   356 	{
       
   357 	CIniSection * section = FindSection(aSectionName);
       
   358 	TBool found = EFalse;
       
   359 	if (section)
       
   360 		found = section->FindVar(aVarName, aResult);
       
   361 	if (!found)
       
   362 		found = FindVar(aVarName, aResult);
       
   363 	return found;
       
   364 	}
       
   365 
       
   366 TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC &aVarName, TInt &aResult)
       
   367 	{
       
   368 	CIniSection * section = FindSection(aSectionName);
       
   369 	TBool found = EFalse;
       
   370 	if (section)
       
   371 		found = section->FindVar(aVarName, aResult);
       
   372 	if (!found)
       
   373 		found = FindVar(aVarName, aResult);
       
   374 	return found;
       
   375 	}
       
   376 
       
   377 TInt CIniFile::NumberOfScreens() const 
       
   378 	{
       
   379   	return iScreenCount;
       
   380 	}
       
   381 
       
   382 
       
   383 // CIniSection.
       
   384 // ini file structure is now in sections like this
       
   385 //
       
   386 // [DEFAULT]
       
   387 // varname value
       
   388 // varname2 value2
       
   389 // [SCREEN0]
       
   390 // screenvar value
       
   391 // etc
       
   392 //
       
   393 // CIniSection represents a section - i.e. section name and content pairs.  
       
   394 // Content pairs are as ini file was previously (so use same code)
       
   395 // [default] section name is optional to support backwards compatibility
       
   396 // if no sutable value is found in a [screenN] section the [default] section will be searched.
       
   397 
       
   398 
       
   399 CIniSection::CIniSection(TInt aScreen) : iScreen(aScreen)
       
   400 	{}
       
   401 
       
   402 void CIniSection::ConstructL()
       
   403 	{
       
   404 	iPtrArray = new (ELeave) CArrayPtrFlat<TDesC>(8) ;
       
   405 	}
       
   406 
       
   407 void CIniSection::ConstructL(const TDesC& aName)
       
   408 	{
       
   409 	iName.CreateL(aName);
       
   410 	ConstructL();
       
   411 	}
       
   412 
       
   413 CIniSection::~CIniSection()
       
   414 	{
       
   415 	iName.Close();
       
   416 	iPtrArray->ResetAndDestroy() ;
       
   417 	delete iPtrArray ;
       
   418 	}
       
   419 
       
   420 inline TInt CIniSection::Screen() const
       
   421 	{ return iScreen; }
       
   422 
       
   423 inline const TDesC& CIniSection::Name() const
       
   424 	{ return iName; }
       
   425 
       
   426 TBool CIniSection::FindVar( const TDesC& aVarName, TPtrC &aResult )
       
   427 	{
       
   428 	if (iPtrArray)
       
   429 		{
       
   430 		TInt index(KErrNotFound);
       
   431 		
       
   432 		if (FindVarName(aVarName, index))
       
   433 			{
       
   434 			TLex lex((*iPtrArray)[index]->Mid(aVarName.Length()));
       
   435 			lex.SkipSpace();
       
   436 			aResult.Set(lex.Remainder());
       
   437 
       
   438 			if (wsDebugLog)
       
   439 				{
       
   440 				wsDebugLog->IniFileSettingRead(iScreen, aVarName, ETrue, aResult);
       
   441 				}
       
   442 			return(ETrue);
       
   443 			}
       
   444 		}
       
   445 
       
   446 	if (wsDebugLog)
       
   447 		{
       
   448 		wsDebugLog->IniFileSettingRead(iScreen, aVarName, EFalse, KNullDesC);
       
   449 		}
       
   450 	return(EFalse);
       
   451 	}
       
   452 
       
   453 /*
       
   454  create a TPtrC with just the first word (variable name) in the given string
       
   455  */
       
   456 TPtrC CIniSection::VarName(const TDesC& aVarString)
       
   457 	{
       
   458 	TInt varLength = aVarString.Locate(KSpaceChar);
       
   459 	if (varLength == KErrNotFound)
       
   460 		{
       
   461 		varLength = aVarString.Length();
       
   462 		}
       
   463 	return aVarString.Left(varLength);
       
   464 	}
       
   465 
       
   466 
       
   467 TBool CIniSection::FindVar(const TDesC &aVarName, TInt &aResult)
       
   468 	{
       
   469 	TPtrC ptr(NULL,0);
       
   470 	// do text Find
       
   471 	if (FindVar(aVarName, ptr))
       
   472 		{
       
   473 		TLex lex(ptr);
       
   474 		_LIT(HexFormatCheck,"0x");
       
   475 		TPtrC hexPtr(HexFormatCheck);
       
   476 		if(ptr.Left(2) != hexPtr)
       
   477 			{
       
   478 			if (lex.Val(aResult) == KErrNone)
       
   479 				{
       
   480 				return ETrue;
       
   481 				}
       
   482 			}
       
   483 		else
       
   484 			{
       
   485 			lex.SkipAndMark(2); //To skip 0x in hex code
       
   486 			if (lex.Val((TUint32&)aResult, EHex) == KErrNone)
       
   487 				{
       
   488 				return ETrue;
       
   489 				}
       
   490 			}
       
   491 		}
       
   492 
       
   493 	return EFalse;
       
   494 	}
       
   495 
       
   496 
       
   497 /*
       
   498  Find variable name in sorted array, using binary search
       
   499  @param aVarName variable name to search for, must have any space and variable value stripped.
       
   500  @param aIndex output index of matching or preceeding item
       
   501  @return
       
   502  */
       
   503 TBool CIniSection::FindVarName(const TDesC& aVarName, TInt& aIndex)
       
   504 	{
       
   505 	// Binary Search
       
   506 	// left is lowest index to include, right is highest index + 1;
       
   507 	TInt left = 0;
       
   508 	TInt right = iPtrArray->Count();
       
   509 
       
   510 	while (right > left)
       
   511 		{
       
   512 		TInt middle = (left + right)>>1;
       
   513 		// compare to start of variable string
       
   514 		TPtrC cmpString = VarName(*(*iPtrArray)[middle]);
       
   515 		TInt cmp = aVarName.CompareF(cmpString);
       
   516 
       
   517 		if (cmp == 0)
       
   518 			{
       
   519 			aIndex = middle;
       
   520 			return ETrue;
       
   521 			}
       
   522 		else if (cmp > 0)
       
   523 			{
       
   524 			left = middle + 1;
       
   525 			}
       
   526 		else
       
   527 			{
       
   528 			right = middle;
       
   529 			}
       
   530 		}
       
   531 
       
   532 	aIndex = right;
       
   533 	return EFalse;
       
   534 	}
       
   535 
       
   536 void CIniSection::AddVariableL(const TDesC& aNewVariable)
       
   537 	{
       
   538 	// use variable name only for search
       
   539 	TPtrC varName = VarName(aNewVariable);
       
   540 	TInt index(0);
       
   541 	
       
   542 	// ignore duplicate definitions
       
   543 	if (0 == FindVarName(varName, index))
       
   544 		{ // insert in sorted array
       
   545 		HBufC* hbuf = aNewVariable.AllocLC() ;
       
   546 		iPtrArray->InsertL(index, hbuf);
       
   547 		CleanupStack::Pop(hbuf);
       
   548 		}
       
   549 	}
       
   550