imgtools/imglib/filesystem/source/dirregion.cpp
changeset 590 360bd6b35136
parent 0 044383f39525
--- a/imgtools/imglib/filesystem/source/dirregion.cpp	Wed Jun 16 16:51:40 2010 +0300
+++ b/imgtools/imglib/filesystem/source/dirregion.cpp	Wed Jun 23 16:56:47 2010 +0800
@@ -1,690 +1,505 @@
-/*
-* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "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: 
-* Class receives tree structured directory and file information. And 
-* prepares the cluster versus content MAP by traversing through the same. 
-* Later all the prepared clusters are written into image file.
-* @internalComponent
-* @released
-*
-*/
-
-
-#include "dirregion.h"
-
-/**
-Constructor:
-1.Get the instance of class CCluster
-2.Intializes the Cluster pointer
-3.Intialize the flags and other variables
-
-@internalComponent
-@released
-
-@param aNodeList - Root node placed in this list
-@param aFileSystemPtr - CFileSystem class pointer
-*/
-CDirRegion::CDirRegion(EntryList aNodeList,
-					   CFileSystem * aFileSystemPtr):
-					   iCurrentDirEntry(false),
-					   iParentDirEntry(false),
-					   iFirstCluster(true),
-   					   iNodeList(aNodeList)
-{
-	iClusterSize = aFileSystemPtr->GetClusterSize();
-	iRootDirSizeInBytes = (aFileSystemPtr->GetRootDirSectors () * 
-						   aFileSystemPtr->GetBytesPerSector());
-	int totalClusters = aFileSystemPtr->GetTotalCluster();
-	iClusterPtr = CCluster::Instance(iClusterSize,totalClusters);
-	if(iClusterPtr == NULL)
-	{
-		throw ErrorHandler(CLUSTERERROR,"Instance creation error", __FILE__, __LINE__);
-	}
-	iClusterSize = iClusterPtr->GetClusterSize();
-}
-
-/**
-Destructor: 
-1. Clean the Node List 
-2. Clean the instance of Cluster object 
-3. Clean the Cluster MAP.
-4. Invokes the DestroyShortEntryList to clear the contents of static GShortEntryList.
-
-@internalComponent
-@released
-*/
-CDirRegion::~CDirRegion()
-{
-	if(iNodeList.size() > 0)
-	{
-		//Delete the root node
-		delete iNodeList.front();
-	}
-	if(iClusterPtr != NULL)
-	{
-		delete iClusterPtr;
-		iClusterPtr = NULL;
-	}
-	iClusterMap.clear();
-	ClongName::DestroyShortEntryList();
-}
-
-/**
-Function to return Clusters per entry map(input for FAT table generator function) 
-container
-
-@internalComponent
-@released
-
-@return - returns clusters per entry map container
-*/
-TClustersPerEntryMap* CDirRegion::GetClustersPerEntryMap() const
-{
-	return iClusterPtr->GetClustersPerEntryMap();
-}
-
-/**
-Function responsible to write all the clusters available in iClusterMap
-into file. 
-
-@internalComponent
-@released
-
-@param aOutPutStream - output file stream to write clusters in it
-*/
-void CDirRegion::WriteClustersIntoFile(OfStream& aOutPutStream)
-{
-	StringMap::iterator mapBeginIter = iClusterMap.begin();
-	StringMap::iterator mapEndIter= iClusterMap.end();
-	//MAPs are sorted associative containers, so no need to sort
-	String tempString;
-	while(mapBeginIter != mapEndIter)
-	{
-		tempString = (*mapBeginIter++).second;
-		aOutPutStream.write(tempString.c_str(),tempString.length());
-	}
-	aOutPutStream.flush();
-	if(aOutPutStream.bad())
-	{
-		throw ErrorHandler(FILEWRITEERROR, __FILE__, __LINE__);
-	}
-}
-
-
-/**
-Function takes the full entry name and formats it as per FAT spec requirement
-Requirement:
-1. All the names should be of 11 characters length.
-2. Name occupies 8 characters and the extension occupies 3 characters.
-3. If the name length is less than 8 characters, padd remaining characters with '0x20' 
-4. If the extension length is less than 3 characters, padd remaining characters with '0x20' 
-5. If the Name or extension exceeds from its actual length then it is treated as long name.
-
-@internalComponent
-@released
-
-@param aString - the String needs to be formatted
-@param aAttrValue - the entry attribute
-*/
-void CDirRegion::FormatName(String& aString, char aAttrValue)
-{
-	if(!aString.empty())
-	{
-		if((*aString.begin()) != KDot)
-		{
-			//Get the file extension start index
-			int extensionStartIndex = aString.find_last_of (KDot);
-			if(aAttrValue != EAttrDirectory && extensionStartIndex != -1)
-			{
-				//Erase the dot, because it is not required to be written in the FAT image
-				aString.erase(extensionStartIndex,1);
-				//Apply Space padding for the Name
-				aString.insert (extensionStartIndex,(ENameLength - extensionStartIndex), KSpace);
-				int totalStringLength = aString.length();
-				//Apply Space padding for the  Extension
-				if(totalStringLength < ENameLengthWithExtension)
-				{
-					aString.insert(totalStringLength,(ENameLengthWithExtension - totalStringLength), KSpace);
-					return;
-				}
-			}
-			else
-			{
-				int nameEndIndex = aString.length();
-				//Apply Space padding for the directory Name
-				aString.insert(nameEndIndex,(ENameLengthWithExtension - nameEndIndex),KSpace);
-				return;
-			}
-		}
-		else
-		{	//Apply Space padding for either '.' or ".."
-			aString.append((ENameLengthWithExtension - aString.length()),KSpace);
-			return;
-		}
-	}
-	else
-	{
-		throw ErrorHandler(EMPTYFILENAME, __FILE__, __LINE__);
-	}
-}
-
-/**
-Function responsible to classify the entry name as long name or regular name.
-
-@internalComponent
-@released
-
-@param aEntry - the directory entry
-@return - returns true if it is long name else false.
-*/
-bool CDirRegion::IsLongEntry(CDirectory* aEntry) const
-{
-	String entryName = aEntry->GetEntryName();
-	unsigned int receivedNameLength = entryName.length();
-	unsigned int firstDotLocation = entryName.find_first_of(KDot);
-	unsigned int lastDotLocation = entryName.find_last_of(KDot);
-
-	if(firstDotLocation == lastDotLocation)
-	{
-		if(aEntry->GetEntryAttribute() == EAttrDirectory)
-		{
-			// If the directory name length is more than 8 characters, then it is a long name
-			if(receivedNameLength > ENameLength)
-			{
-				return true;
-			}
-		}
-		else
-		{
-			int extensionIndex = lastDotLocation;
-			unsigned int fileExtensionLength = receivedNameLength - extensionIndex - 1;
-			/*Either the full name length is greater than 11 or the extension 
-			 *length is greater than 3, then it is considered as long name.
-			 */
-			if((receivedNameLength > ENameLengthWithExtension) 
-			   || (fileExtensionLength > EExtensionLength))
-			{
-				return true;
-			}
-		}
-		return false;
-	}
-	else
-	{
-		//If the name contains multiple dots, then it is a long name.
-		return true;	
-	}
-}
-
-/**
-Function responsible to 
-1. Invoke long name class
-2. Invoke the methods to create long and short entries
-3. Receive the string filled with long entries
-
-@internalComponent
-@released
-
-@param aEntry - the entry
-@param aDirString - long name entry appended to this string
-*/
-
-void CDirRegion::CreateLongEntries(CDirectory* aEntry,String& aDirString)
-{
-	ClongName aLongNameObject(iClusterPtr,aEntry);
-	String tempString = aLongNameObject.CreateLongEntries();
-	if(tempString.length() == 0)
-	{
-		tempString.erase();
-		throw ErrorHandler(EMPTYFILENAME, __FILE__, __LINE__);
-	}
-	else
-	{
-		aDirString.append(tempString.c_str(),tempString.length());
-		tempString.erase();
-		WriteEntryToString(aLongNameObject.CreateShortEntry(aEntry),aDirString);
-	}
-}
-
-/**
-Function takes a single entry and writes its attributes into tempString.
-Later this string is appended with the string received in the argument
-
-@internalComponent
-@released
-
-@param aEntry - the entry which attributes are needs to be written into aString
-@param aString - entry attributes appended into this string
-*/
-void CDirRegion::WriteEntryToString(CDirectory* aEntry,String& aString)
-{
-	String tempString;
-	String entryName = aEntry->GetEntryName();
-	tempString.append(ToUpper(entryName));
-	//appends the attributes only once
-	tempString.append(KWriteOnce, aEntry->GetEntryAttribute());
-	tempString.append(KWriteOnce, aEntry->GetNtReservedByte());
-	tempString.append(KWriteOnce, aEntry->GetCreationTimeMsecs());
-	unsigned short int createdTime = aEntry->GetCreatedTime();
-	tempString.append(ToString(createdTime));
-	unsigned short int creationDate = aEntry->GetCreationDate();
-	tempString.append(ToString(creationDate));
-	unsigned short int lastAccessDate = aEntry->GetLastAccessDate();
-	tempString.append(ToString(lastAccessDate));
-	unsigned short int clusterNumberHi = aEntry->GetClusterNumberHi();
-	tempString.append(ToString(clusterNumberHi));
-	unsigned short int lastWriteTime = aEntry->GetLastWriteTime();
-	tempString.append(ToString(lastWriteTime));
-	unsigned short int lastWriteDate = aEntry->GetLastWriteDate();
-	tempString.append(ToString(lastWriteDate));
-	unsigned short int clusterNumberLow = aEntry->GetClusterNumberLow();
-	tempString.append(ToString(clusterNumberLow));
-	unsigned int fileSize = aEntry->GetFileSize();
-	tempString.append(ToString(fileSize));
-
-	aString.append(tempString.c_str(),KDirectoryEntrySize);
-	tempString.erase();
-}
-
- 
-
-/**
-Function responsible to 
-1. Read the file content and write into string.
-2. Invoke the function to push data clusters into cluster Map
-
-@internalComponent
-@released
-
-@param aEntry - the directory entry node
-*/
-void CDirRegion::WriteFileDataInToCluster(CDirectory* aEntry)
-{
-	iInputStream.open(aEntry->GetFilePath().c_str(),Ios::binary);
-	if(iInputStream.fail() == true )
-	{
-		throw ErrorHandler(FILEOPENERROR,(char*)aEntry->GetFilePath().c_str(),__FILE__,__LINE__);
-	}
-	else
-	{
-		iInputStream.seekg (0,Ios::end);
-		Long64 fileSize = iInputStream.tellg(); 
-		iInputStream.seekg(0,Ios::beg);
-		char* dataBuffer = (char*)malloc((unsigned int)fileSize);
-		if(dataBuffer == 0)
-		{
-			throw ErrorHandler(MEMORYALLOCATIONERROR, __FILE__, __LINE__);
-		}
-		//Read the whole file in one short
-		iInputStream.read (dataBuffer,fileSize);
-		
-		Long64 bytesRead = (unsigned int)iInputStream.tellg();
-		if((iInputStream.bad()) || (bytesRead != fileSize))
-		{
-			throw ErrorHandler(FILEREADERROR,(char*)aEntry->GetFilePath().c_str(), __FILE__, __LINE__);
-		}
-		String clusterData(dataBuffer,(unsigned int)bytesRead);
-		PushStringIntoClusterMap(iClusterPtr->GetCurrentClusterNumber(),clusterData,iClusterSize,aEntry->GetEntryAttribute());
-	}
-	iInputStream.close();
-}
-
-
-/**
-Function invokes 
-1. CheckEntry function, to identify whether the received entry list is proper or not.
-2. Invokes CreateDirEntry, to create directory and data portion of FAT image.
-
-@internalComponent
-@released
-  
-*/
-void CDirRegion::Execute()
-{
-	CheckEntry(iNodeList);
-	CreateDirEntry(iNodeList.front(),KParentDirClusterNumber);
-}
-
-/**
-Function is to initialize the Parent directory entry with parent cluster number
-and appends all the attributes into the string (aString).
-
-@internalComponent
-@released
-
-@param aParDirClusterNumber - parent directory cluster number
-@param aString - parent directory entry attributes appended to this string
-*/
-void CDirRegion::CreateAndWriteParentDirEntry(unsigned int aParDirClusterNumber,String& aString)
-{
-	const char* parentDirName = ".."; //Indicates parent directory entry name
-	CDirectory* parentDirectory = new CDirectory((char*)parentDirName);
-
-	parentDirectory->SetEntryAttribute(EAttrDirectory);
-	parentDirectory->SetClusterNumberLow((unsigned short) (aParDirClusterNumber & KHighWordMask));
-	parentDirectory->SetClusterNumberHi((unsigned short) (aParDirClusterNumber >> KBitShift16));
-
-	String tempString(parentDirectory->GetEntryName());
-	FormatName(tempString,EAttrDirectory);
-	parentDirectory->SetEntryName(tempString);
-	tempString.erase();
-	
-	WriteEntryToString(parentDirectory,aString);
-	iParentDirEntry = true;
-	delete parentDirectory;
-	parentDirectory = NULL;
-}
-
-/**
-Function responsible to 
-1. Initialize the Current directory entry attribute
-2. Write the entry attributes into received string
-
-@internalComponent
-@released
-
-@param aCurDirClusterNumber - Current directory Cluster number
-@param aString - the entry attributes should be appended to this string
-*/
-void CDirRegion::CreateAndWriteCurrentDirEntry(unsigned int aCurClusterNumber,String& aString)
-{
-	const char* currentDirName = "."; //Indicates Current Directory entry name
-	iCurEntryClusterNumber = aCurClusterNumber;
-	CDirectory* currentDirectory = new CDirectory((char*)currentDirName);
-
-	currentDirectory->SetEntryAttribute(EAttrDirectory);
-	currentDirectory->SetClusterNumberLow((unsigned short) (iCurEntryClusterNumber & KHighWordMask));
-	currentDirectory->SetClusterNumberHi((unsigned short) (iCurEntryClusterNumber >> KBitShift16));
-
-	String tempString(currentDirectory->GetEntryName());
-	FormatName(tempString,EAttrDirectory);
-	currentDirectory->SetEntryName(tempString);
-	tempString.erase();
-
-	WriteEntryToString(currentDirectory,aString);
-	iCurrentDirEntry = true;
-	delete currentDirectory;
-	currentDirectory = NULL;
-}
-
-/**
-Function responsible to push the directory entry clusters into cluster MAP only if the
-directory entry string size is greater than the cluster size.
-
-@internalComponent
-@released
-
-@param aNumber - is the Cluster Key used to insert the cluster into cluster map
-@param aString - is the directory entry string
-@param aClustersRequired - No of clusters required to hold this string
-*/
-
-void CDirRegion::PushDirectoryEntryString(unsigned int aNumber,String& aString,int aClustersRequired)
-{
-	int clusterCount = 0;
-	int clusterKey = aNumber;
-	iClusterPtr->CreateMap(aNumber,clusterKey);
-	iClusterMap[clusterKey] =	aString.substr(clusterCount*iClusterSize,iClusterSize);
-	++clusterCount;
-	String clusterSizeString;
-	for(; clusterCount < aClustersRequired; ++clusterCount)
-	{
-		clusterKey = iClusterPtr->GetCurrentClusterNumber();
-		clusterSizeString = aString.substr(clusterCount*iClusterSize,iClusterSize);
-		clusterSizeString.append((iClusterSize - clusterSizeString.length()),0);
-		iClusterMap[clusterKey] = clusterSizeString;
-		iClusterPtr->CreateMap(aNumber,clusterKey);
-		iClusterPtr->UpdateNextAvailableClusterNumber();
-	}
-}
-
-/**Function responsible to 
-1. Convert the string into equal size clusters of cluster size
-2. Insert the clusters into Cluster MAP
-
-@internalComponent
-@released
-
-@param aNumber - cluster number, used to map the cluster
-@param aString - reference of input string
-@param aClusterSize - used to split the string
-@param aAttribute - current entry attribute
-*/
-void CDirRegion::PushStringIntoClusterMap(unsigned int aNumber, String& aString, unsigned long int aClusterSize,char aAttribute)
-{
-	int receivedStringLength = aString.length();
-	/* Precaution, once the map is initialized with specific cluster number don't over write
-	 * it once again. Look for the cluster number within the existing MAP and then proceed with 
-	 * filling in the cluster.
-	 */
-	StringMap::iterator iter= iClusterMap.find(aNumber);
-	if(iter == iClusterMap.end())
-	{
-		/* The length of the cluster content (aString) can be more or less than the cluster size, 
-		 * hence, calculate the total number of clusters required.
-		 */
-		int clustersRequired = receivedStringLength / aClusterSize;
-		if((receivedStringLength % aClusterSize) > 0)
-		{
-			++clustersRequired;
-		}
-		if((clustersRequired > 1) && (aAttribute == EAttrDirectory))
-		{
-			PushDirectoryEntryString(aNumber,aString,clustersRequired);
-			return;
-		}
-		int updatedClusterNumber = aNumber;
-		String clusterSizeString;
-		for(short int clusterCount = 0; clusterCount < clustersRequired; ++clusterCount)
-		{
-			/* In case of the contents occupying more than one cluster, break the contents into
-			 * multiple parts, each one measuring as that of the cluster size.
-			 */
-			clusterSizeString = aString.substr(clusterCount * aClusterSize,aClusterSize);
-			iClusterPtr->CreateMap(aNumber,updatedClusterNumber);
-			if(clusterSizeString.length() < aClusterSize)
-			{
-				/* Copied string size is less than cluster size, fill the remaining space
-				 * with zero
-				 */
-				clusterSizeString.append((aClusterSize - clusterSizeString.length()),0);
-			}
-			// Insert the String into ClusterMap	
-			iClusterMap[updatedClusterNumber] = clusterSizeString;
-		
-			iClusterPtr->UpdateNextAvailableClusterNumber();
-			updatedClusterNumber = iClusterPtr->GetCurrentClusterNumber ();
-		}
-		/* In the above loop, cluster number is incremented to point to the next entry.
-		 * However, before writing a directory or a volume id entry, it is always ensured 
-		 * to get the next cluster number. Hence in this case, it is required to decrement
-		 * the cluster number, so that the pointer points to the end of the cluster occupied.
-		 */
-		if(aAttribute == EAttrDirectory || aAttribute == EAttrVolumeId)
-		{
-			iClusterPtr->DecrementCurrentClusterNumber ();
-		}
-	}
-}
-
-/**
-Function is responsible to take in the tree structured directory 
-information and to initialize the starting cluster in the Cluster Map.
-
-@internalComponent
-@released
-
-@param aNodeList - the list which holds root entry
-*/
-void CDirRegion::CheckEntry(EntryList aNodeList)
-{
-	if(aNodeList.size() > 0)
-	{
-		if(iRootDirSizeInBytes > 0)
-		{
-			//FAT16 Root entries are written into Cluster 1
-			iClusterKey = KFat16RootEntryNumber;
-		}
-		else
-		{
-			//FAT32 Root entries are written into Cluster 2			
-			iClusterPtr->UpdateNextAvailableClusterNumber();
-			iClusterKey = KFat32RootEntryNumber; 
-		}
-		if(aNodeList.front()->GetEntryList()->size() <= 0)
-		{
-			throw ErrorHandler(NOENTRIESFOUND, __FILE__, __LINE__);
-		}
-	}
-	else
-	{
-		throw ErrorHandler(ROOTNOTFOUND, __FILE__, __LINE__);
-	}
-}
-
-/**
-Function receives Tree structured folder information and does the following:
-1. Generates Directory Entry portion of FAT image recursively.
-2. If it finds the entry as file then writes its contents.
-3. If the entry is long name then longfilename class invoked to create long entries.
-
-@internalComponent
-@released
-
-@param aEntry  - Subdirectory pointer of root directory
-@param aParentDirClusterNumber - parent directory cluster number
-*/
-void CDirRegion::CreateDirEntry(CDirectory* aEntry,unsigned int aParentDirClusterNumber)
-{
-	unsigned int currentDirClusterNumber = 0;
-	int rootClusterSize = 0;
-	if(iFirstCluster == true)
-	{
-			iCurrentDirEntry = true;
-			iParentDirEntry = true;
-			/**Root directory and Normal directory has one difference.
-			FAT16 : Root cluster occupies 32 sectors
-			FAT32 : Root cluster occupies only one cluster
-			*/
-			rootClusterSize = (iRootDirSizeInBytes > 0)?iRootDirSizeInBytes:iClusterSize; 
-	}
-	else
-	{
-		currentDirClusterNumber = Get32BitClusterNumber(aEntry->GetClusterNumberHi(),
-														aEntry->GetClusterNumberLow());
-	}
-	
-	//printIterator used while printing the entries
-	EntryList::iterator printIterator = aEntry->GetEntryList()->begin(); 
-	//traverseIterator used during recursive call
-	EntryList::iterator traverseIterator = printIterator;
-	
-	unsigned int dirEntryCount = aEntry->GetEntryList()->size();
-
-	String dirString;
-	String nameString;
-	CDirectory* tempDirEntry = (*printIterator);
-	//Writes all the Directory entries available in one Directory entry
-	while(dirEntryCount > 0)
-	{
-		tempDirEntry = (*printIterator);
-		
-		tempDirEntry->SetClusterNumberHi(iClusterPtr->GetHighWordClusterNumber());
-		tempDirEntry->SetClusterNumberLow(iClusterPtr->GetLowWordClusterNumber());
-
-		/* Every directory should have current and parent directory entries in its
-		 * respective cluster. Hence Create the current and parent directory entries 
-		 * only if it is not created already.
-		 */
-		if(!iCurrentDirEntry && !iParentDirEntry)
-		{
-			CreateAndWriteCurrentDirEntry(currentDirClusterNumber,dirString);
-			iClusterKey = currentDirClusterNumber;
-			CreateAndWriteParentDirEntry(aParentDirClusterNumber,dirString);
-		}
-		MessageHandler::ReportMessage(INFORMATION,
-									  ENTRYCREATEMSG,
-									  (char*)tempDirEntry->GetEntryName().c_str());
-		if(!IsLongEntry(tempDirEntry))
-		{
-			nameString.assign(tempDirEntry->GetEntryName());
-			FormatName(nameString,tempDirEntry->GetEntryAttribute());
-			tempDirEntry->SetEntryName(nameString);
-			nameString.erase();
-			WriteEntryToString(tempDirEntry,dirString);
-		}
-		else
-		{
-			CreateLongEntries(tempDirEntry,dirString);
-		}
-		if(tempDirEntry->IsFile())
-		{
-			WriteFileDataInToCluster(tempDirEntry);
-		}
-		else
-		{
-			iClusterPtr->UpdateNextAvailableClusterNumber ();
-		}
-		++printIterator;
-		--dirEntryCount;
-	}
-
-	iCurrentDirEntry = false;
-	iParentDirEntry = false;
-	aParentDirClusterNumber = currentDirClusterNumber;
-	if(iFirstCluster == true)
-	{
-		PushStringIntoClusterMap(iClusterKey,dirString,rootClusterSize,aEntry->GetEntryAttribute());
-		iFirstCluster = false;
-	}
-	else
-	{
-		PushStringIntoClusterMap(iClusterKey,dirString,iClusterSize,aEntry->GetEntryAttribute());
-	}
-
-	dirEntryCount = aEntry->GetEntryList()->size();
-
-	//Recursive algorithm to print all entries
-	while(dirEntryCount > 0)
-	{
-		if(aEntry->GetEntryList()->size() > 0)
-		{		
-			CreateDirEntry((*traverseIterator),aParentDirClusterNumber);
-		}
-		--dirEntryCount;
-		//if no entries found don't go deep
-		if(dirEntryCount > 0)
-		{
-			aEntry = (*++traverseIterator);
-		}
-	}
-}
-
-/**
-Function responsible to convert two 16 bit words into single 32 bit integer
-
-@internalComponent
-@released
-
-@param aHighWord - 16 bit high word
-@param aLowWord - 16 bit low word
-@return returns the 32 bit integer
-*/
-unsigned int CDirRegion::Get32BitClusterNumber(unsigned int aHighWord, unsigned int aLowWord)
-{
-	unsigned int clusterNumber = aHighWord;
-	clusterNumber <<= KBitShift16;
-	clusterNumber |= aLowWord;
-	return clusterNumber;
-}
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+* Class receives tree structured directory and file information. And 
+* prepares the cluster versus content MAP by traversing through the same. 
+* Later all the prepared clusters are written into image file.
+* @internalComponent
+* @released
+*
+*/
+
+
+#include "dirregion.h"
+#include "directory.h"
+/**
+Constructor:
+1.Get the instance of class CCluster
+2.Intializes the Cluster pointer
+3.Intialize the flags and other variables
+
+@internalComponent
+@released
+
+@param aNodeList - Root node placed in this list
+@param aFileSystemPtr - CFileSystem class pointer
+*/
+CDirRegion::CDirRegion(EntryList aNodeList,
+					   CFileSystem * aFileSystemPtr):
+					   iCurrentDirEntry(false),
+					   iParentDirEntry(false),
+					   iFirstCluster(true),
+   					   iNodeList(aNodeList)
+{
+	iClusterSize = aFileSystemPtr->GetClusterSize();
+	iRootDirSizeInBytes = (aFileSystemPtr->GetRootDirSectors () * 
+						   aFileSystemPtr->GetBytesPerSector());
+	int totalClusters = aFileSystemPtr->GetTotalCluster();
+	iClusterPtr = CCluster::Instance(iClusterSize,totalClusters);
+	if(iClusterPtr == NULL)
+	{
+		throw ErrorHandler(CLUSTERERROR,"Instance creation error", __FILE__, __LINE__);
+	}
+	iClusterSize = iClusterPtr->GetClusterSize();
+}
+
+/**
+Destructor: 
+1. Clean the Node List 
+2. Clean the instance of Cluster object 
+3. Clean the Cluster MAP.
+4. Invokes the DestroyShortEntryList to clear the contents of static GShortEntryList.
+
+@internalComponent
+@released
+*/
+CDirRegion::~CDirRegion()
+{
+	if(iNodeList.size() > 0)
+	{
+		//Delete the root node
+		delete iNodeList.front();
+	}
+	if(iClusterPtr != NULL)
+	{
+		delete iClusterPtr;
+		iClusterPtr = NULL;
+	}
+	iClusterMap.clear();
+	ClongName::DestroyShortEntryList();
+}
+
+/**
+Function to return Clusters per entry map(input for FAT table generator function) 
+container
+
+@internalComponent
+@released
+
+@return - returns clusters per entry map container
+*/
+TClustersPerEntryMap* CDirRegion::GetClustersPerEntryMap() const
+{
+	return iClusterPtr->GetClustersPerEntryMap();
+}
+
+/**
+Function responsible to write all the clusters available in iClusterMap
+into file. 
+
+@internalComponent
+@released
+
+@param aOutPutStream - output file stream to write clusters in it
+*/
+void CDirRegion::WriteClustersIntoFile(OfStream& aOutPutStream)
+{
+	StringMap::iterator mapBeginIter = iClusterMap.begin();
+	StringMap::iterator mapEndIter= iClusterMap.end();
+	//MAPs are sorted associative containers, so no need to sort
+	string tempString;
+	while(mapBeginIter != mapEndIter)
+	{
+		tempString = (*mapBeginIter++).second;
+		aOutPutStream.write(tempString.c_str(),tempString.length());
+	}
+	aOutPutStream.flush();
+	if(aOutPutStream.bad())
+	{
+		throw ErrorHandler(FILEWRITEERROR, __FILE__, __LINE__);
+	}
+}
+
+/**
+Function responsible to 
+1. Read the file content and write into string.
+2. Invoke the function to push data clusters into cluster Map
+
+@internalComponent
+@released
+
+@param aEntry - the directory entry node
+*/
+void CDirRegion::WriteFileDataInToCluster(CDirectory* aEntry)
+{
+	iInputStream.open(aEntry->GetFilePath().c_str(),ios_base::binary);
+	if(iInputStream.fail() == true )
+	{
+		throw ErrorHandler(FILEOPENERROR,(char*)aEntry->GetFilePath().c_str(),__FILE__,__LINE__);
+	}
+	else
+	{
+		iInputStream.seekg (0,ios_base::end);
+		Long64 fileSize = iInputStream.tellg(); 
+		iInputStream.seekg(0,ios_base::beg);
+		char* dataBuffer = (char*)malloc((unsigned int)fileSize);
+		if(dataBuffer == 0)
+		{
+			throw ErrorHandler(MEMORYALLOCATIONERROR, __FILE__, __LINE__);
+		}
+		//Read the whole file in one short
+		iInputStream.read (dataBuffer,fileSize);
+		
+		Long64 bytesRead = (unsigned int)iInputStream.tellg();
+		if((iInputStream.bad()) || (bytesRead != fileSize))
+		{
+			throw ErrorHandler(FILEREADERROR,(char*)aEntry->GetFilePath().c_str(), __FILE__, __LINE__);
+		}
+		string clusterData(dataBuffer,(unsigned int)bytesRead);
+		PushStringIntoClusterMap(iClusterPtr->GetCurrentClusterNumber(),clusterData,iClusterSize,aEntry->GetEntryAttribute());
+	}
+	iInputStream.close();
+}
+
+
+/**
+Function invokes 
+1. CheckEntry function, to identify whether the received entry list is proper or not.
+2. Invokes CreateDirEntry, to create directory and data portion of FAT image.
+
+@internalComponent
+@released
+  
+*/
+void CDirRegion::Execute()
+{
+	CheckEntry(iNodeList);
+	CreateDirEntry(iNodeList.front(),KParentDirClusterNumber);
+}
+
+/**
+Function is to initialize the Parent directory entry with parent cluster number
+and appends all the attributes into the string (aString).
+
+@internalComponent
+@released
+
+@param aParDirClusterNumber - parent directory cluster number
+@param aString - parent directory entry attributes appended to this string
+*/
+void CDirRegion::CreateAndWriteParentDirEntry(unsigned int aParDirClusterNumber,string& aString)
+{
+	CDirectory* parentDirectory = new CDirectory("..",NULL);
+
+	parentDirectory->SetEntryAttribute(EAttrDirectory);
+	parentDirectory->SetClusterNumberLow((unsigned short) (aParDirClusterNumber & KHighWordMask));
+	parentDirectory->SetClusterNumberHi((unsigned short) (aParDirClusterNumber >> KBitShift16));
+
+	TShortDirEntry entry ;
+	parentDirectory->GetShortEntry(entry);
+	aString.append((const char*)(&entry),sizeof(entry));
+	iParentDirEntry = true;
+	delete parentDirectory;
+	parentDirectory = NULL;
+}
+
+/**
+Function responsible to 
+1. Initialize the Current directory entry attribute
+2. Write the entry attributes into received string
+
+@internalComponent
+@released
+
+@param aCurDirClusterNumber - Current directory Cluster number
+@param aString - the entry attributes should be appended to this string
+*/
+void CDirRegion::CreateAndWriteCurrentDirEntry(unsigned int aCurClusterNumber,string& aString)
+{
+	iCurEntryClusterNumber = aCurClusterNumber;
+	CDirectory* currentDirectory = new CDirectory(".",NULL);
+
+	currentDirectory->SetEntryAttribute(EAttrDirectory);
+	currentDirectory->SetClusterNumberLow((unsigned short) (iCurEntryClusterNumber & KHighWordMask));
+	currentDirectory->SetClusterNumberHi((unsigned short) (iCurEntryClusterNumber >> KBitShift16));
+
+	TShortDirEntry entry ;
+    currentDirectory->GetShortEntry(entry);
+    aString.append((const char*)(&entry),sizeof(entry));
+	iCurrentDirEntry = true;
+	delete currentDirectory;
+	currentDirectory = NULL;
+}
+
+/**
+Function responsible to push the directory entry clusters into cluster MAP only if the
+directory entry string size is greater than the cluster size.
+
+@internalComponent
+@released
+
+@param aNumber - is the Cluster Key used to insert the cluster into cluster map
+@param aString - is the directory entry string
+@param aClustersRequired - No of clusters required to hold this string
+*/
+
+void CDirRegion::PushDirectoryEntryString(unsigned int aNumber,string& aString,int aClustersRequired)
+{
+	int clusterCount = 0;
+	int clusterKey = aNumber;
+	iClusterPtr->CreateMap(aNumber,clusterKey);
+	iClusterMap[clusterKey] =	aString.substr(clusterCount*iClusterSize,iClusterSize);
+	++clusterCount;
+	string clusterSizeString;
+	for(; clusterCount < aClustersRequired; ++clusterCount)
+	{
+		clusterKey = iClusterPtr->GetCurrentClusterNumber();
+		clusterSizeString = aString.substr(clusterCount*iClusterSize,iClusterSize);
+		clusterSizeString.append((iClusterSize - clusterSizeString.length()),0);
+		iClusterMap[clusterKey] = clusterSizeString;
+		iClusterPtr->CreateMap(aNumber,clusterKey);
+		iClusterPtr->UpdateNextAvailableClusterNumber();
+	}
+}
+
+/**Function responsible to 
+1. Convert the string into equal size clusters of cluster size
+2. Insert the clusters into Cluster MAP
+
+@internalComponent
+@released
+
+@param aNumber - cluster number, used to map the cluster
+@param aString - reference of input string
+@param aClusterSize - used to split the string
+@param aAttribute - current entry attribute
+*/
+void CDirRegion::PushStringIntoClusterMap(unsigned int aNumber, string& aString, unsigned long int aClusterSize,char aAttribute)
+{
+	int receivedStringLength = aString.length();
+	/* Precaution, once the map is initialized with specific cluster number don't over write
+	 * it once again. Look for the cluster number within the existing MAP and then proceed with 
+	 * filling in the cluster.
+	 */
+	StringMap::iterator iter= iClusterMap.find(aNumber);
+	if(iter == iClusterMap.end())
+	{
+		/* The length of the cluster content (aString) can be more or less than the cluster size, 
+		 * hence, calculate the total number of clusters required.
+		 */
+		int clustersRequired = receivedStringLength / aClusterSize;
+		if((receivedStringLength % aClusterSize) > 0)
+		{
+			++clustersRequired;
+		}
+		if((clustersRequired > 1) && (aAttribute == EAttrDirectory))
+		{
+			PushDirectoryEntryString(aNumber,aString,clustersRequired);
+			return;
+		}
+		int updatedClusterNumber = aNumber;
+		string clusterSizeString;
+		for(short int clusterCount = 0; clusterCount < clustersRequired; ++clusterCount)
+		{
+			/* In case of the contents occupying more than one cluster, break the contents into
+			 * multiple parts, each one measuring as that of the cluster size.
+			 */
+			clusterSizeString = aString.substr(clusterCount * aClusterSize,aClusterSize);
+			iClusterPtr->CreateMap(aNumber,updatedClusterNumber);
+			if(clusterSizeString.length() < aClusterSize)
+			{
+				/* Copied string size is less than cluster size, fill the remaining space
+				 * with zero
+				 */
+				clusterSizeString.append((aClusterSize - clusterSizeString.length()),0);
+			}
+			// Insert the string into ClusterMap	
+			iClusterMap[updatedClusterNumber] = clusterSizeString;
+		
+			iClusterPtr->UpdateNextAvailableClusterNumber();
+			updatedClusterNumber = iClusterPtr->GetCurrentClusterNumber ();
+		}
+		/* In the above loop, cluster number is incremented to point to the next entry.
+		 * However, before writing a directory or a volume id entry, it is always ensured 
+		 * to get the next cluster number. Hence in this case, it is required to decrement
+		 * the cluster number, so that the pointer points to the end of the cluster occupied.
+		 */
+		if(aAttribute == EAttrDirectory || aAttribute == EAttrVolumeId)
+		{
+			iClusterPtr->DecrementCurrentClusterNumber ();
+		}
+	}
+}
+
+/**
+Function is responsible to take in the tree structured directory 
+information and to initialize the starting cluster in the Cluster Map.
+
+@internalComponent
+@released
+
+@param aNodeList - the list which holds root entry
+*/
+void CDirRegion::CheckEntry(EntryList aNodeList)
+{
+	if(aNodeList.size() > 0)
+	{
+		if(iRootDirSizeInBytes > 0)
+		{
+			//FAT16 Root entries are written into Cluster 1
+			iClusterKey = KFat16RootEntryNumber;
+		}
+		else
+		{
+			//FAT32 Root entries are written into Cluster 2			
+			iClusterPtr->UpdateNextAvailableClusterNumber();
+			iClusterKey = KFat32RootEntryNumber; 
+		}
+		if(aNodeList.front()->GetEntryList()->size() <= 0)
+		{
+			throw ErrorHandler(NOENTRIESFOUND, __FILE__, __LINE__);
+		}
+	}
+	else
+	{
+		throw ErrorHandler(ROOTNOTFOUND, __FILE__, __LINE__);
+	}
+}
+
+/**
+Function receives Tree structured folder information and does the following:
+1. Generates Directory Entry portion of FAT image recursively.
+2. If it finds the entry as file then writes its contents.
+3. If the entry is long name then longfilename class invoked to create long entries.
+
+@internalComponent
+@released
+
+@param aEntry  - Subdirectory pointer of root directory
+@param aParentDirClusterNumber - parent directory cluster number
+*/
+void CDirRegion::CreateDirEntry(CDirectory* aEntry,unsigned int aParentDirClusterNumber)
+{
+	unsigned int currentDirClusterNumber = 0;
+	int rootClusterSize = 0;
+	if(iFirstCluster == true)
+	{
+			iCurrentDirEntry = true;
+			iParentDirEntry = true;
+			/**Root directory and Normal directory has one difference.
+			FAT16 : Root cluster occupies 32 sectors
+			FAT32 : Root cluster occupies only one cluster
+			*/
+			rootClusterSize = (iRootDirSizeInBytes > 0)?iRootDirSizeInBytes:iClusterSize; 
+	}
+	else
+	{
+		currentDirClusterNumber = Get32BitClusterNumber(aEntry->GetClusterNumberHi(),
+														aEntry->GetClusterNumberLow());
+	}
+	
+	//printIterator used while printing the entries
+	EntryList::iterator printIterator = aEntry->GetEntryList()->begin(); 
+	//traverseIterator used during recursive call
+	EntryList::iterator traverseIterator = printIterator;
+	
+	unsigned int dirEntryCount = aEntry->GetEntryList()->size();
+
+	string dirString;
+	string nameString;
+	CDirectory* tempDirEntry = (*printIterator);
+	list<TLongDirEntry> longNames ; 
+	//Writes all the Directory entries available in one Directory entry
+	while(dirEntryCount > 0)
+	{
+		tempDirEntry = (*printIterator);
+		
+		tempDirEntry->SetClusterNumberHi(iClusterPtr->GetHighWordClusterNumber());
+		tempDirEntry->SetClusterNumberLow(iClusterPtr->GetLowWordClusterNumber());
+
+		/* Every directory should have current and parent directory entries in its
+		 * respective cluster. Hence Create the current and parent directory entries 
+		 * only if it is not created already.
+		 */
+		if(!iCurrentDirEntry && !iParentDirEntry)
+		{
+			CreateAndWriteCurrentDirEntry(currentDirClusterNumber,dirString);
+			iClusterKey = currentDirClusterNumber;
+			CreateAndWriteParentDirEntry(aParentDirClusterNumber,dirString);
+		}
+		MessageHandler::ReportMessage(INFORMATION,
+									  ENTRYCREATEMSG,
+									  (char*)tempDirEntry->GetEntryName().c_str()); 
+									  
+		if(tempDirEntry->GetLongEntries(longNames)){ 
+			list<TLongDirEntry>::const_iterator i = longNames.begin();
+			while(i != longNames.end()) {
+				dirString.append((char*)(&(*i)),sizeof(TLongDirEntry)); 
+				i++ ;
+			} 
+		}
+		TShortDirEntry shortEntry ;
+		tempDirEntry->GetShortEntry(shortEntry);	 
+		dirString.append((char*)(&shortEntry),sizeof(TShortDirEntry));		 
+		if(tempDirEntry->IsFile())
+		{
+			WriteFileDataInToCluster(tempDirEntry);
+		}
+		else
+		{
+			iClusterPtr->UpdateNextAvailableClusterNumber ();
+			//tempDirEntry->SetEntryAttribute(tempDirEntry->GetEntryAttribute() | EAttrDirectory);
+		}
+		++printIterator;
+		--dirEntryCount;
+	}
+
+	iCurrentDirEntry = false;
+	iParentDirEntry = false;
+	aParentDirClusterNumber = currentDirClusterNumber;
+	if(iFirstCluster == true)
+	{
+		PushStringIntoClusterMap(iClusterKey,dirString,rootClusterSize,aEntry->GetEntryAttribute());
+		iFirstCluster = false;
+	}
+	else
+	{
+		PushStringIntoClusterMap(iClusterKey,dirString,iClusterSize,aEntry->GetEntryAttribute());
+	}
+
+	dirEntryCount = aEntry->GetEntryList()->size();
+
+	//Recursive algorithm to print all entries
+	while(dirEntryCount > 0)
+	{
+		if(aEntry->GetEntryList()->size() > 0)
+		{		
+			CreateDirEntry((*traverseIterator),aParentDirClusterNumber);
+		}
+		--dirEntryCount;
+		//if no entries found don't go deep
+		if(dirEntryCount > 0)
+		{
+			aEntry = (*++traverseIterator);
+		}
+	}
+}
+
+/**
+Function responsible to convert two 16 bit words into single 32 bit integer
+
+@internalComponent
+@released
+
+@param aHighWord - 16 bit high word
+@param aLowWord - 16 bit low word
+@return returns the 32 bit integer
+*/
+unsigned int CDirRegion::Get32BitClusterNumber(unsigned int aHighWord, unsigned int aLowWord)
+{
+	unsigned int clusterNumber = aHighWord;
+	clusterNumber <<= KBitShift16;
+	clusterNumber |= aLowWord;
+	return clusterNumber;
+}