imgtools/imglib/filesystem/source/longname.cpp
changeset 0 044383f39525
child 590 360bd6b35136
equal deleted inserted replaced
-1:000000000000 0:044383f39525
       
     1 /*
       
     2 * Copyright (c) 2006-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 the License "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 * Receives the long file name and prepares short and long directory 
       
    16 * entries.
       
    17 * @internalComponent
       
    18 * @released
       
    19 *
       
    20 */
       
    21 
       
    22 
       
    23 #include "longname.h"
       
    24 
       
    25 
       
    26 /** 
       
    27 Constructor: Responsible to create 
       
    28 1. Short entry
       
    29 2. Sub components of long entry name as per microsoft FAT spec.
       
    30 
       
    31 @internalComponent
       
    32 @released
       
    33 
       
    34 @param aClusterPtr - Cluster instance address
       
    35 @param aEntry - CDirectory class pointer
       
    36 */
       
    37 
       
    38 ClongName::ClongName(CCluster* aClusterPtr,
       
    39 					 CDirectory* aEntry):
       
    40 					 iClusterPtr(aClusterPtr),
       
    41 					 iTildeNumberPosition(ETildeNumberPosition),
       
    42 					 iSubNameProperEnd(false),
       
    43 					 iFirstNullName(false)
       
    44 {
       
    45 	iLongName = aEntry->GetEntryName();
       
    46 	iLongEntryAttribute = aEntry->GetEntryAttribute();
       
    47 	iClusterNumber = aClusterPtr->GetCurrentClusterNumber();
       
    48 	iLongNameLength = iLongName.length();
       
    49 	if(iLongNameLength == 0)
       
    50 	{
       
    51 		throw ErrorHandler(EMPTYFILENAME, __FILE__, __LINE__);
       
    52 	}
       
    53 	FormatLongFileName(iLongName);
       
    54 	iShortName = GetShortEntryName();
       
    55 	GShortEntryList.push_back(iShortName);
       
    56 }
       
    57 
       
    58 
       
    59 /**
       
    60 Static function to clear the strings stored in static Global Stringlist
       
    61 
       
    62 @internalComponent
       
    63 @released
       
    64 */
       
    65 void ClongName::DestroyShortEntryList()
       
    66 {
       
    67 	GShortEntryList.clear();
       
    68 }
       
    69 
       
    70 /**
       
    71 Destructor: To clear the contents from the STL containers in any exception case.
       
    72 In normal case the containers are cleared once its usage is finished
       
    73 
       
    74 @internalComponent
       
    75 @released
       
    76 */
       
    77 
       
    78 ClongName::~ClongName()
       
    79 {
       
    80 	iSubNamesList.clear();
       
    81 	while(iLongEntryStack.size() > 0)
       
    82 	{
       
    83 		delete iLongEntryStack.top();
       
    84 		iLongEntryStack.pop();
       
    85 	}
       
    86 	/* Cluster instance should be deleted only by dirregion, So just assign 
       
    87 	 * NULL value to the pointer
       
    88 	 */
       
    89 	iClusterPtr = NULL;
       
    90 }
       
    91 
       
    92 /**
       
    93 Function takes a long entry and writes all of the attributes into iLongNameEntryString.
       
    94 To write the sub name's in a formatted WriteSubName() function invoked
       
    95 
       
    96 @internalComponent
       
    97 @released
       
    98 
       
    99 @param aLongEntry - the long entry
       
   100 */
       
   101 void ClongName::WriteLongEntry(CLongEntry* aLongEntry,String& longEntryString)
       
   102 {
       
   103 	longEntryString.append(KWriteOnce, aLongEntry->GetDirOrder());
       
   104 	WriteSubName(aLongEntry->GetSubName1(),(ESubName1Length*2),longEntryString);
       
   105 	longEntryString.append(KWriteOnce, aLongEntry->GetAttribute());
       
   106 	longEntryString.append(KWriteOnce, aLongEntry->GetDirType());
       
   107 	longEntryString.append(KWriteOnce, aLongEntry->GetCheckSum());
       
   108 	WriteSubName(aLongEntry->GetSubName2(),(ESubName2Length*2),longEntryString);
       
   109 	unsigned short int lowClusterNumber = aLongEntry->GetClusterNumberLow();
       
   110 	longEntryString.append(ToString(lowClusterNumber));
       
   111 	WriteSubName(aLongEntry->GetSubName3(),(ESubName3Length*2),longEntryString);
       
   112 }
       
   113 
       
   114 /**
       
   115 Function responsible to 
       
   116 1. Write the sub name of the long entry, every character splitted by '.'(00)
       
   117 2. If the name is not multiple of 13 this function applies NULL character padding and 
       
   118    padding with 'FF'.
       
   119 
       
   120 @internalComponent
       
   121 @released
       
   122 
       
   123 @param aName - Sub name of a long entry
       
   124 @param aSubNameLength - No of characters to be filled
       
   125 @param alongEntryString - formatted sub name appended to this string
       
   126 */
       
   127 void ClongName::WriteSubName(String& aSubName,unsigned short aSubNameLength,String& alongEntryString)
       
   128 {
       
   129 	unsigned int subNameCurrLength = aSubName.length();
       
   130 	if(subNameCurrLength == 0)
       
   131 	{
       
   132 		iFirstNullName = true;
       
   133 	}
       
   134 	else
       
   135 	{
       
   136 		iFirstNullName = false;
       
   137 	}
       
   138 	unsigned int beginIndex = 1;
       
   139 	if(subNameCurrLength > 0)
       
   140 	{
       
   141 		//Insert zero between every character, as per FAT spec requirement
       
   142 		while(subNameCurrLength > 0)
       
   143 		{
       
   144 			aSubName.insert(beginIndex,1,0); //Insert zero once
       
   145 			beginIndex += 2; //Jump 2 characters
       
   146 			--subNameCurrLength;
       
   147 		}
       
   148 		subNameCurrLength = aSubName.length();
       
   149 		if(subNameCurrLength == aSubNameLength)
       
   150 		{
       
   151 			iSubNameProperEnd = true;
       
   152 		}
       
   153 		//Apply padding with two zero's to mention Long Name end.
       
   154 		if(subNameCurrLength < aSubNameLength)
       
   155 		{
       
   156 			aSubName.insert(subNameCurrLength, KPaddingCharCnt, 0); 
       
   157 		}
       
   158 	}
       
   159 	subNameCurrLength = aSubName.length();
       
   160 	if((iSubNameProperEnd == true) && (iFirstNullName == true))
       
   161 	{
       
   162 		aSubName.insert(subNameCurrLength, KPaddingCharCnt, 0);
       
   163 		iSubNameProperEnd = false;
       
   164 		iFirstNullName = false;
       
   165 	}
       
   166 	subNameCurrLength = aSubName.length();
       
   167 	//Insert FF for all unfilled characters.
       
   168 	if(subNameCurrLength < aSubNameLength)
       
   169 	{
       
   170 			aSubName.insert(subNameCurrLength,(aSubNameLength - subNameCurrLength),
       
   171 							KLongNamePaddingChar);
       
   172 	}
       
   173 	alongEntryString.append(aSubName.c_str(),aSubName.length());
       
   174 }
       
   175 
       
   176 /**
       
   177 Function responsible to push the string into iNameList container and to erase the input
       
   178 strings data
       
   179 
       
   180 @internalComponent
       
   181 @released
       
   182 
       
   183 @param aFirstName - first sub name
       
   184 @param aSecondName - Second sub name
       
   185 @param aThirdName - third sub name
       
   186 */
       
   187 void ClongName::PushAndErase(String& aFirstName,String& aSecondName,String& aThirdName)
       
   188 {
       
   189 	iSubNamesList.push_back(aFirstName);
       
   190 	aFirstName.erase();
       
   191 	iSubNamesList.push_back(aSecondName);
       
   192 	aSecondName.erase();
       
   193 	iSubNamesList.push_back(aThirdName);
       
   194 	aThirdName.erase();
       
   195 }
       
   196 
       
   197 /**
       
   198 Function responsible split single sub name from the long name
       
   199 
       
   200 @internalComponent
       
   201 @released
       
   202 
       
   203 @param aLongName - The long name need to be splitted
       
   204 @param aStartIndex - Sub name starting index
       
   205 @param aStringLength - total string length
       
   206 @param aSubNameLength - Length of the Sub Name of required length
       
   207 @param aSubName - splitted Sub Name assigned using this string
       
   208 */
       
   209 void ClongName::GetSubName(String& aLongName,
       
   210 						   int& aStartIndex,
       
   211 						   int& aStringLength,
       
   212 						   int aSubNameLength,
       
   213 						   String& aSubName)
       
   214 {
       
   215 	if((aStartIndex + aSubNameLength) <= aStringLength)
       
   216 	{
       
   217 		aSubName = aLongName.substr(aStartIndex,aSubNameLength);
       
   218 		aStartIndex += aSubNameLength;
       
   219 		return;
       
   220 	}
       
   221 	aSubName = aLongName.substr(aStartIndex);
       
   222 	aStartIndex += aSubName.length();
       
   223 }
       
   224 
       
   225 /** 
       
   226 Function to split the long file name into smaller sub names,such as it should be 
       
   227 written into long directory entries. All splitted names are pushed into the 
       
   228 iNameList container.
       
   229 
       
   230 @internalComponent
       
   231 @released
       
   232 */
       
   233 void ClongName::FormatLongFileName(String& aLongName)
       
   234 {
       
   235 	int stringLength = aLongName.length();
       
   236 	int startIndex = 0;
       
   237 	String iSubName1;
       
   238 	String iSubName2;
       
   239 	String iSubName3;
       
   240 
       
   241 	while(startIndex < stringLength)
       
   242 	{
       
   243 		GetSubName(aLongName,startIndex,stringLength,ESubName1Length,iSubName1);
       
   244 		GetSubName(aLongName,startIndex,stringLength,ESubName2Length,iSubName2);
       
   245 		GetSubName(aLongName,startIndex,stringLength,ESubName3Length,iSubName3);
       
   246 		PushAndErase(iSubName1,iSubName2,iSubName3);
       
   247 	}
       
   248 }
       
   249 
       
   250 /**
       
   251 Function responsible to create new short name if the currently generated short name 
       
   252 already exists. 
       
   253 
       
   254 eg. Input:UNITTE~1TXT returns:UNITTE~2TXT
       
   255 
       
   256 @internalComponent
       
   257 @released
       
   258 
       
   259 @return - returns the short name
       
   260 */
       
   261 void ClongName::CheckAndUpdateShortName(String& aShortName)
       
   262 {
       
   263 	char trailingChar;
       
   264 	StringList::iterator beginIter = GShortEntryList.begin();
       
   265 	StringList::iterator endIter = GShortEntryList.end();
       
   266 	String tempString;
       
   267 	while(beginIter != endIter)
       
   268 	{
       
   269 		tempString = (*beginIter);
       
   270 		if(strcmp(tempString.c_str(),aShortName.c_str()) == 0)
       
   271 		{
       
   272 			trailingChar = aShortName.at(iTildeNumberPosition);
       
   273 			aShortName[iTildeNumberPosition] = ++trailingChar; //Increment the character value by 1
       
   274 			continue;
       
   275 		}
       
   276 		++beginIter;
       
   277 	}
       
   278 }
       
   279 
       
   280 /**
       
   281 Function responsible to take the long file name as input and to prepare the short name.
       
   282 e.g. Long File Name.pl to LONGFI~1PL
       
   283 
       
   284 @internalComponent
       
   285 @released
       
   286 
       
   287 @return - returns the short name
       
   288 */
       
   289 
       
   290 String ClongName::GetShortEntryName()
       
   291 {
       
   292 	String shortName;
       
   293 	unsigned int extensionIndex = iLongName.find_last_of(KDot);
       
   294 
       
   295 	unsigned int dotIndex = extensionIndex;
       
   296 	//Erase all the dots from the string, but keep the extension index 
       
   297 	while(dotIndex != String::npos)
       
   298 	{
       
   299 		iLongName.erase(dotIndex,1); //Erase the dot
       
   300 		dotIndex = iLongName.find_first_of(KDot);
       
   301 		if(dotIndex != String::npos)
       
   302 		{
       
   303 			//Decrement only if more than one dot exists
       
   304 			--extensionIndex;
       
   305 		}
       
   306 	}
       
   307 
       
   308 	if((iLongEntryAttribute & EAttrDirectory)== 0) 
       
   309 	{
       
   310 		if(extensionIndex <= EShortNameInitialLength)
       
   311 		{
       
   312 			//if the full name length is less than 6 characters, assign the whole name
       
   313 			shortName.assign(iLongName.c_str(),extensionIndex);
       
   314 		}
       
   315 		else
       
   316 		{
       
   317 			shortName.assign(iLongName.c_str(),EShortNameInitialLength);
       
   318 		}
       
   319 		//+1 is added to get '~' symbol position
       
   320 		iTildeNumberPosition = shortName.length() + 1;
       
   321 	}
       
   322 	else
       
   323 	{
       
   324 		shortName.assign(iLongName.c_str(),EShortNameInitialLength);
       
   325 	}
       
   326 	shortName += KTilde;
       
   327 	shortName += KTildeNumber;
       
   328 	shortName.assign(ToUpper(shortName));
       
   329 	if(extensionIndex <  iLongName.length()) //to identify whether the name has any extension.
       
   330 	{
       
   331 		if(shortName.length() < ENameLength)
       
   332 		{
       
   333 			shortName.append((ENameLength - shortName.length()),KSpace);
       
   334 		}
       
   335 		String shortNameString = iLongName.substr(extensionIndex,EExtensionLength);
       
   336 		shortName.append(ToUpper(shortNameString));
       
   337 		CheckAndUpdateShortName(shortName);
       
   338 		return shortName;
       
   339 	}
       
   340 	//extension padding
       
   341 	shortName.append(EExtensionLength,KSpace);
       
   342 	CheckAndUpdateShortName(shortName);
       
   343 	return shortName;
       
   344 }
       
   345 
       
   346 /**
       
   347 Function takes the short entry name as input and calculates checksum as per the 
       
   348 Microsoft FAT spec.
       
   349 
       
   350 @internalComponent
       
   351 @released
       
   352 
       
   353 @return - returns checkSum
       
   354 */
       
   355 
       
   356 unsigned char ClongName::CalculateCheckSum()
       
   357 {
       
   358 	char* tempShortNamePtr = (char*)iShortName.c_str();
       
   359 	unsigned short int nameLength = 0;
       
   360 	unsigned char chckSum = '\0';
       
   361 	for(nameLength = ENameLengthWithExtension; nameLength != 0; nameLength--)
       
   362 	{
       
   363 		chckSum = ((chckSum & 1) ? 0x80 : NULL) + (chckSum >>1) + *tempShortNamePtr++;
       
   364 	}
       
   365 	return chckSum;
       
   366 }
       
   367 
       
   368 /**
       
   369 Function responsible to initialize short entry attributes.
       
   370 Short entry is also an sub entry along with Long entries
       
   371 
       
   372 @internalComponent
       
   373 @released
       
   374 
       
   375 @param aEntry - directory entry which has long file name
       
   376 @return shortEntry - returns the initialized short Directory entry
       
   377 */
       
   378 CDirectory* ClongName::CreateShortEntry(CDirectory* aEntry)
       
   379 {
       
   380 	CDirectory* shortEntry = new CDirectory((char*)iShortName.c_str());
       
   381 	shortEntry->SetEntryAttribute(aEntry->GetEntryAttribute()); 
       
   382 	if(aEntry->IsFile())
       
   383 	{	 
       
   384 		shortEntry->SetFilePath((char*)aEntry->GetFilePath().c_str());
       
   385 	}
       
   386 	shortEntry->SetFileSize(aEntry->GetFileSize());
       
   387 	/** Initialize the cluster number variables by splitting high and low words of
       
   388 	current cluster number
       
   389 	*/
       
   390 	shortEntry->SetClusterNumberHi((unsigned short)(iClusterNumber >> KBitShift16));
       
   391 	shortEntry->SetClusterNumberLow((unsigned short)(iClusterNumber & KHighWordMask));
       
   392 	return shortEntry;
       
   393 }
       
   394 
       
   395 /**
       
   396 Function responsible
       
   397 1. To erase the string from the iNameList container.
       
   398 2. To pop out the element
       
   399 
       
   400 @internalComponent
       
   401 @released
       
   402 */
       
   403 void ClongName::PopAndErase()
       
   404 {
       
   405 	iSubNamesList.front().erase();
       
   406 	iSubNamesList.pop_front();
       
   407 }
       
   408 
       
   409 /** 
       
   410 Function responsible to 
       
   411 1. Pop all the name's 3 by 3 from iNameList container
       
   412 2. Construct long name directory entries
       
   413 3. Push the long entries into iLongEntryStack 
       
   414 4. finally create Long name sub entries as string and append it to longEntryString.
       
   415 
       
   416 @internalComponent
       
   417 @released
       
   418 
       
   419 @return - returns the formatted long name string
       
   420 */
       
   421 String ClongName::CreateLongEntries()
       
   422 {
       
   423 	String longEntryString;
       
   424 	CLongEntry* longEntryObject;
       
   425 	unsigned char chckSum = CalculateCheckSum();
       
   426 	unsigned char dirOrderNumber = 0x00;
       
   427 	while(iSubNamesList.size() > 0)
       
   428 	{
       
   429 		longEntryObject = new CLongEntry(chckSum);
       
   430 		longEntryObject->SetSubName1(iSubNamesList.front());
       
   431 		PopAndErase();
       
   432 		longEntryObject->SetSubName2(iSubNamesList.front());
       
   433 		PopAndErase();
       
   434 		longEntryObject->SetSubName3(iSubNamesList.front());
       
   435 		PopAndErase();
       
   436 		longEntryObject->SetDirOrder(++dirOrderNumber);
       
   437 	
       
   438 		iLongEntryStack.push(longEntryObject);
       
   439 	}
       
   440 
       
   441 	bool lastLongEntry = true;
       
   442 	while(iLongEntryStack.size() > 0)
       
   443 	{
       
   444 		if(lastLongEntry == true)
       
   445 		{
       
   446 			longEntryObject = iLongEntryStack.top();
       
   447 			/* As per Microsoft FAT spec, Last sub entry of Long name Directory Order attribute
       
   448 			 * should be logically OR'ed with value '0x40'
       
   449 			 */
       
   450 			longEntryObject->SetDirOrder(longEntryObject->GetDirOrder() | ELastLongEntry);
       
   451 			lastLongEntry = false;
       
   452 		}
       
   453 		WriteLongEntry(iLongEntryStack.top(),longEntryString);
       
   454 		delete iLongEntryStack.top();
       
   455 		iLongEntryStack.pop();
       
   456 	}
       
   457 	return longEntryString;
       
   458 }