windowing/windowserver/nga/SERVER/INIFILE.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/INIFILE.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,550 @@
+// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32std.h>
+#include "server.h"
+#include "inifile.h"
+
+// uncomment so that if the wsini.ini file is not found on drive Wserv loaded from or drive Z: (if different)
+// it will be searched for on drive C: (if different from Wserv's drive)
+//#define LOAD_INI_FILE_FROM_DRIVE_Z_OR_C
+
+
+GLREF_D CDebugLogBase *wsDebugLog;
+
+_LIT(KDefaultSectionName,"DEFAULT");
+_LIT(KCommentMarker,"//");
+_LIT(KScreenSectionName,"SCREEN");
+const TUint16 KNewSection('[');
+const TUint16 KSpaceChar(' ');
+const TUint16 KNewSection2(']');
+const TInt KDefaultSectionNumber(0);
+const TInt KDefaultScreenId(-1);
+
+
+CIniFile::CIniFile()
+	{}
+
+CIniFile::~CIniFile()
+	{
+	FreeData();
+	}
+
+CIniSection * CIniFile::FindSection(TInt aScreen)
+	{
+	for (TInt sect = 0; sect < iSectionArray.Count(); ++sect)
+		{
+		if (iSectionArray[sect]->Screen() == aScreen)
+			{
+			return iSectionArray[sect];
+			}
+		}
+	return NULL;
+	}
+
+CIniSection * CIniFile::FindSection(const TDesC& aName)
+	{
+	for (TInt sect = 0; sect < iSectionArray.Count(); ++sect)
+		{
+		if (iSectionArray[sect]->Screen() == KDefaultScreenId && !iSectionArray[sect]->Name().CompareF(aName))
+			{
+			return iSectionArray[sect];
+			}
+		}
+	return NULL;
+	}
+
+/* Processes a .ini file entry section name.
+
+ @return the corresponding index.
+ @param aLine Input line of text from the .ini file, stripped of comments & excess whitespace.
+ @leave KErrNoMemory
+ */
+CIniSection * CIniFile::AddOrFindIniSectionL(TPtr& aSectionName)
+	{
+	aSectionName.Trim();
+
+	// DEFAULT section
+	if (aSectionName.CompareF(KDefaultSectionName) == 0)
+		{ 
+		return iSectionArray[KDefaultSectionNumber];
+		}
+
+	// SCREENx section
+	if (0 == aSectionName.FindF(KScreenSectionName))
+		{
+		TLex lex(aSectionName.Mid(KScreenSectionName().Length()));
+		TInt screenNum;
+		lex.SkipSpace();
+		if (lex.Val(screenNum) == KErrNone)
+			{
+			return AddOrFindScreenSectionL(screenNum);
+			}
+		}
+		
+	// other section
+	return AddOrFindNamedSectionL(aSectionName);
+	}
+
+CIniSection * CIniFile::CreateSectionL(TInt aScreen)
+	{
+	CIniSection* newSection = new (ELeave) CIniSection(aScreen);
+	CleanupStack::PushL( newSection ) ;
+	newSection->ConstructL() ;
+	User::LeaveIfError(iSectionArray.Append(newSection));
+	CleanupStack::Pop( newSection ) ;
+	if (aScreen + 1 > iScreenCount)
+		iScreenCount = aScreen + 1;
+	return newSection;
+	}
+
+CIniSection * CIniFile::CreateSectionL(const TDesC& aName)
+	{
+	CIniSection* newSection = new (ELeave) CIniSection(KDefaultScreenId);
+	CleanupStack::PushL( newSection ) ;
+	newSection->ConstructL(aName) ;
+	User::LeaveIfError(iSectionArray.Append(newSection));
+	CleanupStack::Pop( newSection ) ;
+	return newSection;
+	}
+
+
+void CIniFile::doConstructL(RFile &aFile)
+	{
+	TFileText textFile;
+	textFile.Set(aFile);
+	const TInt KMaxIniLine=256;
+	TBuf<KMaxIniLine> readLine;
+	TBool first=ETrue;
+
+	// always have a [DEFAULT] section
+	CIniSection * currentSection = CreateSectionL(KDefaultSectionName);
+
+	FOREVER
+		{
+		TInt err=textFile.Read(readLine);
+		if (err==KErrEof)
+			break;
+		User::LeaveIfError(err);
+
+		if (readLine.Length()>0)
+			{
+			if (first && (readLine[0]==0xFFFE || readLine[0]==0xFEFF))
+				readLine.Delete(0,1);
+			
+			// Comment marker "//" indicates the rest of the line should be discarded
+			TInt commentStart = readLine.Find(KCommentMarker);
+			if (commentStart != KErrNotFound)
+				{
+				readLine.Delete(commentStart, readLine.Length());
+				}
+
+			// compact unnecessary whitespace
+			readLine.TrimAll();
+
+			// anything left in buffer?
+			if (readLine.Length() > 0)
+				{
+				// section name requires "[" and "]"
+				if (readLine[0] == KNewSection && readLine.LocateReverse(KNewSection2) == readLine.Length() - 1)
+					{
+					TPtr nameText = readLine.MidTPtr(1, readLine.Length() - 2); // strip [ and ]
+					currentSection = AddOrFindIniSectionL(nameText);
+					}
+				else
+					{
+					if (currentSection)
+						{
+						currentSection->AddVariableL(readLine);
+						}
+					}
+				}
+			first=EFalse;
+			}
+		}
+
+	if (iScreenCount == 0)
+		{
+		iScreenCount = 1;
+		}
+	}
+
+CIniFile* CIniFile::NewL()
+    {
+    CIniFile* self = new(ELeave) CIniFile();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+void CIniFile::FreeData() 
+	{
+	iSectionArray.ResetAndDestroy() ;
+	iScreenCount = 0;
+	}
+
+void errFreeData(TAny *aIniFile)
+	{
+	((CIniFile *)aIniFile)->FreeData();
+	}
+
+HBufC* IniFileSearchPathLC()
+	{
+	_LIT(KPath,"\\SYSTEM\\DATA\\");
+	_LIT(KPathSep,";");
+	const TInt KLengthPerPath = 2 + KPath().Length();
+	// work out which drive Wserv loaded from
+	RProcess self;
+	TFileName myPath = self.FileName();
+	TParsePtrC myDrive(myPath);
+	TDriveUnit myDriveUnit(myDrive.Drive());
+	// need extra buffer space for search paths for drives Z: or C: ?
+#if defined(LOAD_INI_FILE_FROM_DRIVE_Z_OR_C)
+	TInt numPaths = 2;
+	if (myDriveUnit != EDriveZ && myDriveUnit != EDriveC)
+		{
+		numPaths += 1;
+		}
+#else
+	TInt numPaths = 1;
+	if (myDriveUnit != EDriveZ)
+		{
+		numPaths += 1;
+		}
+#endif
+	HBufC* searchPath = HBufC::NewLC(numPaths * KLengthPerPath + (numPaths - 1) * KPathSep().Length());
+	TPtr pPath(searchPath->Des());
+	pPath.Append(myDrive.Drive());
+	pPath.Append(KPath);
+	if (myDriveUnit != EDriveZ)
+		{
+		pPath.Append(KPathSep);
+		pPath.Append(TDriveUnit(EDriveZ).Name());
+		pPath.Append(KPath);
+		}
+#if defined(LOAD_INI_FILE_FROM_DRIVE_Z_OR_C)
+	if (myDriveUnit != EDriveC)
+		{
+		pPath.Append(KPathSep);
+		pPath.Append(TDriveUnit(EDriveC).Name());
+		pPath.Append(KPath);
+		}
+#endif
+	return searchPath;
+	}
+
+void CIniFile::ConstructL()
+	{
+	TAutoClose<RFs> fs;
+	User::LeaveIfError(fs.iObj.Connect());
+	fs.iObj.SetNotifyUser(EFalse);
+	fs.PushL();
+	HBufC* searchPath = IniFileSearchPathLC();
+	_LIT(KFileName,"WSINI.INI");
+	TFindFile findinifile(fs.iObj);
+	TInt err=findinifile.FindByPath(KFileName,searchPath);
+	User::LeaveIfError(err);
+	CleanupStack::PopAndDestroy(searchPath);
+ 	TAutoClose<RFile> file;
+	User::LeaveIfError(file.iObj.Open(fs.iObj,findinifile.File(),EFileStreamText|EFileRead));
+	file.PushL();
+	CleanupStack::PushL(TCleanupItem(errFreeData,this));
+	doConstructL(file.iObj);
+	CleanupStack::Pop(); // TCleanupItem
+	file.Pop();
+	fs.Pop();
+	}
+
+/* If the Section for the screen exists find the data, otherwise create a new data structure.
+
+ @param aScreen Screen number
+ @return index to section
+ @leave KErrNoMemory
+ */
+CIniSection * CIniFile::AddOrFindScreenSectionL(TInt aScreen)
+	{
+	CIniSection * section = FindSection(aScreen);
+	if (!section)
+		section = CreateSectionL(aScreen);
+	return section;
+	}
+
+/* If the Section exists find the data, otherwise create a new data structure.
+
+ @param aName section name
+ @return index to section
+ @leave KErrNoMemory
+ */
+CIniSection * CIniFile::AddOrFindNamedSectionL(const TDesC& aName)
+	{
+	CIniSection * section = FindSection(aName);
+	if (!section)
+		section = CreateSectionL(aName);
+	return section;
+	}
+
+TBool CIniFile::FindVar(const TDesC &aVarName, TPtrC &aResult)
+	{
+	return iSectionArray[KDefaultSectionNumber]->FindVar(aVarName, aResult);
+	}
+
+
+TBool CIniFile::FindVar(const TDesC &aVarName, TInt &aResult)
+	{
+	return iSectionArray[KDefaultSectionNumber]->FindVar(aVarName, aResult);
+	}
+
+TBool CIniFile::FindVar(const TDesC &aVarName)
+//
+// Used to simply detect the presence of the specified variable name
+//
+	{
+	TPtrC ptr(NULL,0);
+	return FindVar(aVarName, ptr);
+	}
+
+// FindVar in [SCREENx] sections
+TBool CIniFile::FindVar( TInt aScreen, const TDesC &aVarName)
+	{
+	TPtrC ptr(NULL,0);
+	return FindVar(aScreen, aVarName, ptr);
+	}
+
+TBool CIniFile::FindVar( TInt aScreen, const TDesC& aVarName, TPtrC &aResult )
+	{
+	CIniSection * section = FindSection(aScreen);
+	TBool found = EFalse;
+	if (section)
+		found = section->FindVar(aVarName, aResult);
+	if (!found)
+		found = FindVar(aVarName, aResult);
+	return found;
+	}
+
+TBool CIniFile::FindVar(TInt aScreen, const TDesC &aVarName, TInt &aResult)
+	{
+	CIniSection * section = FindSection(aScreen);
+	TBool found = EFalse;
+	if (section)
+		found = section->FindVar(aVarName, aResult);
+	if (!found)
+		found = FindVar(aVarName, aResult);
+	return found;
+	}
+
+// FindVar in named sections
+TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC &aVarName)
+	{
+	TPtrC ptr(NULL,0);
+	return FindVar(aSectionName, aVarName, ptr);
+	}
+
+TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC& aVarName, TPtrC &aResult )
+	{
+	CIniSection * section = FindSection(aSectionName);
+	TBool found = EFalse;
+	if (section)
+		found = section->FindVar(aVarName, aResult);
+	if (!found)
+		found = FindVar(aVarName, aResult);
+	return found;
+	}
+
+TBool CIniFile::FindVar(const TDesC& aSectionName, const TDesC &aVarName, TInt &aResult)
+	{
+	CIniSection * section = FindSection(aSectionName);
+	TBool found = EFalse;
+	if (section)
+		found = section->FindVar(aVarName, aResult);
+	if (!found)
+		found = FindVar(aVarName, aResult);
+	return found;
+	}
+
+TInt CIniFile::NumberOfScreens() const 
+	{
+  	return iScreenCount;
+	}
+
+
+// CIniSection.
+// ini file structure is now in sections like this
+//
+// [DEFAULT]
+// varname value
+// varname2 value2
+// [SCREEN0]
+// screenvar value
+// etc
+//
+// CIniSection represents a section - i.e. section name and content pairs.  
+// Content pairs are as ini file was previously (so use same code)
+// [default] section name is optional to support backwards compatibility
+// if no sutable value is found in a [screenN] section the [default] section will be searched.
+
+
+CIniSection::CIniSection(TInt aScreen) : iScreen(aScreen)
+	{}
+
+void CIniSection::ConstructL()
+	{
+	iPtrArray = new (ELeave) CArrayPtrFlat<TDesC>(8) ;
+	}
+
+void CIniSection::ConstructL(const TDesC& aName)
+	{
+	iName.CreateL(aName);
+	ConstructL();
+	}
+
+CIniSection::~CIniSection()
+	{
+	iName.Close();
+	iPtrArray->ResetAndDestroy() ;
+	delete iPtrArray ;
+	}
+
+inline TInt CIniSection::Screen() const
+	{ return iScreen; }
+
+inline const TDesC& CIniSection::Name() const
+	{ return iName; }
+
+TBool CIniSection::FindVar( const TDesC& aVarName, TPtrC &aResult )
+	{
+	if (iPtrArray)
+		{
+		TInt index(KErrNotFound);
+		
+		if (FindVarName(aVarName, index))
+			{
+			TLex lex((*iPtrArray)[index]->Mid(aVarName.Length()));
+			lex.SkipSpace();
+			aResult.Set(lex.Remainder());
+
+			if (wsDebugLog)
+				{
+				wsDebugLog->IniFileSettingRead(iScreen, aVarName, ETrue, aResult);
+				}
+			return(ETrue);
+			}
+		}
+
+	if (wsDebugLog)
+		{
+		wsDebugLog->IniFileSettingRead(iScreen, aVarName, EFalse, KNullDesC);
+		}
+	return(EFalse);
+	}
+
+/*
+ create a TPtrC with just the first word (variable name) in the given string
+ */
+TPtrC CIniSection::VarName(const TDesC& aVarString)
+	{
+	TInt varLength = aVarString.Locate(KSpaceChar);
+	if (varLength == KErrNotFound)
+		{
+		varLength = aVarString.Length();
+		}
+	return aVarString.Left(varLength);
+	}
+
+
+TBool CIniSection::FindVar(const TDesC &aVarName, TInt &aResult)
+	{
+	TPtrC ptr(NULL,0);
+	// do text Find
+	if (FindVar(aVarName, ptr))
+		{
+		TLex lex(ptr);
+		_LIT(HexFormatCheck,"0x");
+		TPtrC hexPtr(HexFormatCheck);
+		if(ptr.Left(2) != hexPtr)
+			{
+			if (lex.Val(aResult) == KErrNone)
+				{
+				return ETrue;
+				}
+			}
+		else
+			{
+			lex.SkipAndMark(2); //To skip 0x in hex code
+			if (lex.Val((TUint32&)aResult, EHex) == KErrNone)
+				{
+				return ETrue;
+				}
+			}
+		}
+
+	return EFalse;
+	}
+
+
+/*
+ Find variable name in sorted array, using binary search
+ @param aVarName variable name to search for, must have any space and variable value stripped.
+ @param aIndex output index of matching or preceeding item
+ @return
+ */
+TBool CIniSection::FindVarName(const TDesC& aVarName, TInt& aIndex)
+	{
+	// Binary Search
+	// left is lowest index to include, right is highest index + 1;
+	TInt left = 0;
+	TInt right = iPtrArray->Count();
+
+	while (right > left)
+		{
+		TInt middle = (left + right)>>1;
+		// compare to start of variable string
+		TPtrC cmpString = VarName(*(*iPtrArray)[middle]);
+		TInt cmp = aVarName.CompareF(cmpString);
+
+		if (cmp == 0)
+			{
+			aIndex = middle;
+			return ETrue;
+			}
+		else if (cmp > 0)
+			{
+			left = middle + 1;
+			}
+		else
+			{
+			right = middle;
+			}
+		}
+
+	aIndex = right;
+	return EFalse;
+	}
+
+void CIniSection::AddVariableL(const TDesC& aNewVariable)
+	{
+	// use variable name only for search
+	TPtrC varName = VarName(aNewVariable);
+	TInt index(0);
+	
+	// ignore duplicate definitions
+	if (0 == FindVarName(varName, index))
+		{ // insert in sorted array
+		HBufC* hbuf = aNewVariable.AllocLC() ;
+		iPtrArray->InsertL(index, hbuf);
+		CleanupStack::Pop(hbuf);
+		}
+	}
+