windowing/windowserver/nonnga/SERVER/INIFILE.CPP
author Faisal Memon <faisal.memon@nokia.com>
Thu, 06 May 2010 11:31:11 +0100
branchNewGraphicsArchitecture
changeset 47 48b924ae7197
parent 0 5d03bc08d59c
permissions -rw-r--r--
Applied patch 1, to provide a syborg specific minigui oby file. Need to compare this with the "stripped" version currently in the tree. This supplied version applies for Nokia builds, but need to repeat the test for SF builds to see if pruning is needed, or if the file needs to be device-specific.

// 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);
		}
	}