reszip/src/rescomp.cpp
changeset 0 f58d6ec98e88
child 16 7c80ebddf816
equal deleted inserted replaced
-1:000000000000 0:f58d6ec98e88
       
     1 /*
       
     2 * Copyright (c) 1997-1999 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 "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 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "rescomp.h"
       
    21 #include <e32cons.h>
       
    22 #include <s32file.h>
       
    23 #include <s32mem.h>
       
    24 
       
    25 #include <barsc.h>
       
    26 
       
    27 #include "resdict.h"
       
    28 #include "resentry.h"
       
    29 
       
    30 //#define __DEBUG_WRITE_UNCOMPRESSED_BAFL_RESOURCE
       
    31 
       
    32 // TBit Writer
       
    33 
       
    34 TBitWriter::TBitWriter(RWriteStream& aStream)
       
    35 :iStream(aStream)
       
    36 	{
       
    37 	iValue = 0;
       
    38 	iBitsWritten = 0;
       
    39 	}
       
    40 
       
    41 void TBitWriter::WriteL(TInt aValue, TInt aBits)
       
    42 	{
       
    43 	// 1<< aBits is the max Value;
       
    44 
       
    45 	__ASSERT_DEBUG((1<<aBits) > aValue, User::Panic(_L("TBitWriter"),KErrOverflow));
       
    46 	if (aBits + iBitsWritten < 8)
       
    47 		{
       
    48 		// Not enough data to write a byte
       
    49 		iValue += (aValue << iBitsWritten);
       
    50 		iBitsWritten += aBits;
       
    51 		}
       
    52 	else
       
    53 		{
       
    54 		TInt bitsLeft = 8-iBitsWritten;
       
    55 		TInt mask = (1<<bitsLeft)-1;
       
    56 		TInt maskValue = (aValue & mask) << iBitsWritten;
       
    57 
       
    58 		iValue += maskValue;
       
    59 		iStream.WriteUint8L(iValue);
       
    60 //		RDebug::Print(_L("Writing: %b [0x%x]"), iValue, iValue);
       
    61 		
       
    62 		TInt newValue = aValue >> bitsLeft;
       
    63 		TInt bits = aBits - bitsLeft;
       
    64 		while (bits > 7)
       
    65 			{
       
    66 			iStream.WriteUint8L(newValue & 0xff);
       
    67 			bits -= 8;
       
    68 			newValue = (newValue >> 8);
       
    69 			}
       
    70 		iValue = newValue;
       
    71 		iBitsWritten=bits;
       
    72 		}
       
    73 	}
       
    74 
       
    75 void TBitWriter::FlushL()
       
    76 	{
       
    77 	if (iBitsWritten > 0)
       
    78 		{
       
    79 		iStream.WriteUint8L(iValue);
       
    80 		iValue = 0;
       
    81 		iBitsWritten=0;
       
    82 		}
       
    83 	}
       
    84 
       
    85 
       
    86 
       
    87 
       
    88 CResComp::CResComp(CConsoleBase* aConsole)
       
    89 :iConsole(aConsole)
       
    90 	{
       
    91 	}
       
    92 
       
    93 CResComp::~CResComp()
       
    94 	{
       
    95 	if (iResArray)
       
    96 		{
       
    97 		iResArray->ResetAndDestroy();
       
    98 		}
       
    99 	delete iResArray;
       
   100 	delete iResData;
       
   101 	delete iDict;
       
   102 	}
       
   103 
       
   104 
       
   105 void CResComp::LoadBAFLCompressedFileL(RFs& aFs, const TDesC& aName)
       
   106 	{
       
   107 
       
   108 	RResourceFile res;
       
   109 	res.OpenL(aFs, aName);
       
   110 	CleanupClosePushL(res);
       
   111 
       
   112 	// Count resources
       
   113 	TInt count = 0;
       
   114 
       
   115 // This code around ConfirmSigniture had to be added because some S60 resources don't seem to have signature and panic.
       
   116 // See	DEF019933 - RResourceFile::ConfirmSignatureL() needs to be more robust  
       
   117 
       
   118 	HBufC8* const resource=res.AllocReadLC(1);
       
   119 	if(resource->Length()==8) // 8 =Sizeof SSigRecord
       
   120 		{
       
   121 		res.ConfirmSignatureL(0);
       
   122 		}
       
   123 	CleanupStack::PopAndDestroy(resource);
       
   124 
       
   125 	TInt offset = res.Offset();
       
   126 	while (res.OwnsResourceId(count+offset+1))
       
   127 		{
       
   128 		count++;
       
   129 		};
       
   130 
       
   131 	const TInt KBufferGranularity = 1000;
       
   132 	CBufFlat* buffer = CBufFlat::NewL(KBufferGranularity);
       
   133 	CleanupStack::PushL(buffer);
       
   134 
       
   135 	CBufFlat* indexbuffer = CBufFlat::NewL(KBufferGranularity);
       
   136 	CleanupStack::PushL(indexbuffer);
       
   137 
       
   138 	RBufWriteStream stream;
       
   139 	stream.Open(*buffer);
       
   140 	CleanupClosePushL(stream);
       
   141 
       
   142 	RBufWriteStream indexstream;
       
   143 	indexstream.Open(*indexbuffer);
       
   144 	CleanupClosePushL(indexstream);
       
   145 
       
   146 	TInt total = 0;
       
   147 
       
   148 	for (TInt ii=0; ii<count; ii++)
       
   149 		{
       
   150 		indexstream.WriteUint16L(total+4);
       
   151 		HBufC8* data = res.AllocReadLC(ii+offset+1);
       
   152 		TInt len = data->Length();
       
   153 		total += len;
       
   154 		stream.WriteL(*data, len);
       
   155 		CleanupStack::PopAndDestroy();
       
   156 		}
       
   157 	indexstream.WriteUint16L(total+4);
       
   158 
       
   159 
       
   160 	indexstream.CommitL();
       
   161 	CleanupStack::PopAndDestroy();	// close indexstream
       
   162 
       
   163 	stream.CommitL();
       
   164 	CleanupStack::PopAndDestroy();	// close stream
       
   165 
       
   166 	CBufFlat* outputBuffer = CBufFlat::NewL(KBufferGranularity);
       
   167 	CleanupStack::PushL(outputBuffer);
       
   168 
       
   169 	RBufWriteStream outStream;
       
   170 	outStream.Open(*outputBuffer);
       
   171 	CleanupClosePushL(outStream);
       
   172 
       
   173 	
       
   174 	outStream.WriteUint16L(total + 4);	// 4 byte header
       
   175 	outStream.WriteUint16L(((count+1)*2)+1);
       
   176 
       
   177 	TPtr8 ptr = buffer->Ptr(0);
       
   178 	outStream.WriteL(ptr.Ptr(), ptr.Length());
       
   179 	TPtr8 indexptr = indexbuffer->Ptr(0);
       
   180 	outStream.WriteL(indexptr.Ptr(), indexptr.Length());
       
   181 	outStream.CommitL();
       
   182 	CleanupStack::PopAndDestroy();// outStream
       
   183 
       
   184 
       
   185 /* DEBUG - OUTPUT UNCOMPRESSED REPRESENTATION TO A FILE - FOR VERIFICATION */
       
   186 #ifdef __DEBUG_WRITE_UNCOMPRESSED_BAFL_RESOURCE
       
   187 	{
       
   188 	TFileName newName(aName);
       
   189 	newName.Append(_L(".ER5u"));
       
   190 
       
   191 	RFileWriteStream outStream;
       
   192 	User::LeaveIfError(outStream.Replace(aFs, newName, EFileWrite));
       
   193 	CleanupClosePushL(outStream);
       
   194 
       
   195 	
       
   196 	outStream.WriteUint16L(total + 4);	// 4 byte header
       
   197 	outStream.WriteUint16L(((count+1)*2)+1);
       
   198 
       
   199 	TPtr8 ptr = buffer->Ptr(0);
       
   200 	outStream.WriteL(ptr.Ptr(), ptr.Length());
       
   201 	TPtr8 indexptr = indexbuffer->Ptr(0);
       
   202 	outStream.WriteL(indexptr.Ptr(), indexptr.Length());
       
   203 	outStream.CommitL();
       
   204 	CleanupStack::PopAndDestroy(); // outStream
       
   205 	}
       
   206 #endif /* END __DEBUG_WRITE_UNCOMPRESSED_BAFL_RESOURCE */
       
   207 
       
   208 	iDict = new(ELeave)CDictArray();
       
   209 
       
   210 	iFileLength = outputBuffer->Size();
       
   211 
       
   212 	iResData = (TUint8*)User::AllocL(iFileLength);
       
   213 
       
   214 	Mem::Copy(iResData, const_cast<TUint8*>(outputBuffer->Ptr(0).Ptr()), iFileLength );
       
   215 
       
   216 	CleanupStack::PopAndDestroy(outputBuffer);
       
   217 
       
   218 	CleanupStack::PopAndDestroy(indexbuffer);
       
   219 	CleanupStack::PopAndDestroy(buffer);
       
   220 
       
   221 	CleanupStack::PopAndDestroy(); // res
       
   222 
       
   223 	// Need to keep original size in order to compare with new compression for IsValid()
       
   224 	TEntry entry;
       
   225 	if(	aFs.Entry(aName, entry) ==KErrNone)
       
   226 		{
       
   227 		iOriginalCompressedSize = entry.iSize;
       
   228 		}
       
   229 
       
   230 	}
       
   231 
       
   232 TBool CResComp::FileIsBAFLCompressedL(RFs& aFs, const TDesC& aFileName)
       
   233 	{
       
   234 	const TUid KBAFLCompressedFileUid = {0x101f4a6b};	// rcomp unicode compressed
       
   235 
       
   236 	TEntry entry;
       
   237 	User::LeaveIfError(aFs.Entry(aFileName,entry));
       
   238 	
       
   239 	return  entry.IsUidPresent(KBAFLCompressedFileUid);
       
   240 	}
       
   241 
       
   242 void CResComp::LoadFileL(RFs& aFs, const TDesC& aFileName)
       
   243 	{
       
   244 	ASSERT(iDict==NULL);
       
   245 
       
   246 	TParsePtrC parse(aFileName);
       
   247 	iConOutput.Format(parse.NameAndExt());
       
   248 	iConOutput.Append(_L("\t"));
       
   249 	if (parse.NameAndExt().Length() < 16)
       
   250 		{
       
   251 		iConOutput.Append(_L("\t"));
       
   252 		}
       
   253 
       
   254 	if(FileIsBAFLCompressedL(aFs, aFileName))
       
   255 		{
       
   256 		LoadBAFLCompressedFileL(aFs, aFileName);
       
   257 		}
       
   258 	else
       
   259 		{
       
   260 		LoadUnCompressedFileL(aFs, aFileName);
       
   261 		}
       
   262 	
       
   263 	}
       
   264 
       
   265 void CResComp::LoadUnCompressedFileL(RFs& aFs, const TDesC& aFileName)
       
   266 	{
       
   267 
       
   268 	iDict = new(ELeave)CDictArray();
       
   269 
       
   270 	TEntry entry;
       
   271 	User::LeaveIfError( aFs.Entry(aFileName, entry) );
       
   272 	iFileLength = entry.iSize;
       
   273 
       
   274 	iResData = (TUint8*)User::AllocL(entry.iSize + 2); // +2 for file size
       
   275 
       
   276 	RFileReadStream stream;
       
   277 	User::LeaveIfError( stream.Open(aFs, aFileName, EFileRead) );
       
   278 	CleanupClosePushL(stream);
       
   279 	stream.ReadL(iResData, entry.iSize);
       
   280 	CleanupStack::PopAndDestroy();	 // stream
       
   281 	}
       
   282 
       
   283 
       
   284 void CResComp::CompressL()
       
   285 	{
       
   286 	if (iFileLength == 0)
       
   287 		{
       
   288 		iCompressedSize = iFileLength;
       
   289 		return;
       
   290 		}
       
   291 
       
   292 	TUint16* resData16 = (TUint16*)iResData;
       
   293 	TInt indexOffset = resData16[0];
       
   294 	TInt indexLength = resData16[1];
       
   295 
       
   296 	if (indexOffset == 4)
       
   297 		{
       
   298 		// File is already compressed
       
   299 		iCompressedSize = iFileLength;
       
   300 		return;
       
   301 		}
       
   302 
       
   303 	if (indexOffset > iFileLength)
       
   304 		{
       
   305 		iCompressedSize = iFileLength;
       
   306 		return;
       
   307 		}
       
   308 
       
   309 	iResources = (indexLength / 2) - 1;
       
   310 
       
   311 //	iConsole->Printf(_L("Resources: %d\n"), iResources);
       
   312 
       
   313 //	iConOutput.AppendFormat(_L("%d\t\t"), iResources);
       
   314 
       
   315 
       
   316 	iResIndex = (TUint16*)(iResData + indexOffset);
       
   317 
       
   318 
       
   319 	iResArray = new(ELeave)CArrayPtrFlat<CResEntry>(10);
       
   320 
       
   321 	iResIndex[iResources] = (TUint16)(iFileLength-((iResources+1) * 2)); // end of file - index
       
   322 
       
   323 	// Build dictionary
       
   324 
       
   325 //	iConsole->Printf(_L("Building Dictionary\n"));
       
   326 
       
   327 	for (TInt ii=0; ii<iResources; ii++)
       
   328 		{
       
   329 		TBuf<80> lineOut(_L("\r"));
       
   330 		lineOut.Append(iConOutput);
       
   331 		lineOut.AppendFormat(_L("%3d / %3d"), ii+1, iResources);
       
   332 		iConsole->Printf(lineOut);
       
   333 //		iConsole->Printf(_L("\r%d / %d"), ii+1, iResources);
       
   334 		CResEntry* rEntry = new(ELeave)CResEntry(iDict);
       
   335 		CleanupStack::PushL(rEntry);
       
   336 
       
   337 		TInt resSize = iResIndex[ii+1] - iResIndex[ii];
       
   338 		if (resSize > iLargestResourceSize)
       
   339 			iLargestResourceSize = resSize;
       
   340 
       
   341 		rEntry->AddPlainDataL(iResData+iResIndex[ii], iResIndex[ii+1] - iResIndex[ii]);
       
   342 		iResArray->AppendL(rEntry);
       
   343 		CleanupStack::Pop();	//rEntry
       
   344 
       
   345 
       
   346 		rEntry->MatchSelfL(ii, this);
       
   347 		}
       
   348 
       
   349 	// Compress using dictionary
       
   350 
       
   351 
       
   352 //	iConsole->Printf(_L("\nCompressing\n"));
       
   353 
       
   354 	CDictArray* backupDict = iDict->DuplicateL();
       
   355 	CleanupStack::PushL(backupDict);
       
   356 
       
   357 	AttemptCompressionL(32);
       
   358 	iDict = backupDict->DuplicateL();
       
   359 	AttemptCompressionL(64);
       
   360 	iDict = backupDict->DuplicateL();
       
   361 	AttemptCompressionL(128);
       
   362 	iDict = backupDict->DuplicateL();
       
   363 	AttemptCompressionL(256);
       
   364 	iDict = backupDict->DuplicateL();
       
   365 	AttemptCompressionL(512);
       
   366 	iDict = backupDict->DuplicateL();
       
   367 
       
   368 
       
   369 	CompressResourcesL(iBestCompression);
       
   370 
       
   371 
       
   372 	CleanupStack::PopAndDestroy();	// backupDict
       
   373 	}
       
   374 
       
   375 TInt CResComp::AttemptCompressionL(TInt aDictEntries)
       
   376 	{
       
   377 	TInt size = CompressResourcesL(aDictEntries);
       
   378 //	RDebug::Print(_L("Entries: %d  Size:%d"), aDictEntries, size);
       
   379 
       
   380 	TBool valid = IsValid();
       
   381 	if (!valid)
       
   382 		{
       
   383 		RDebug::Print(_L("Compression Not Valid"));
       
   384 		}
       
   385 
       
   386 	if ((size < iBestSize || iBestSize == 0) && valid)
       
   387 		{
       
   388 		iBestCompression = aDictEntries;
       
   389 		iBestSize = size;
       
   390 		}
       
   391 	delete iDict;
       
   392     iDict = NULL;
       
   393 	return size;
       
   394 	}
       
   395 
       
   396 
       
   397 TInt CResComp::CompressResourcesL(TInt aDictEntries)
       
   398 	{
       
   399 	iMaxEntries = aDictEntries;
       
   400 	iBitsForDict = 0;
       
   401 	while ( (1<<iBitsForDict) < aDictEntries)
       
   402 		{
       
   403 		iBitsForDict++;
       
   404 		}
       
   405 	iDict->iDictionaryBits = iBitsForDict;
       
   406 //	RDebug::Print(_L("Entries: %d  Bits: %d"), aDictEntries, iBitsForDict);
       
   407 	iResArray->ResetAndDestroy();
       
   408 	// Reset dictionary count
       
   409 
       
   410 	TInt dCount = iDict->Count();
       
   411 	for (TInt ll=0; ll<dCount; ll++)
       
   412 		{
       
   413 		iDict->At(ll).iUses = 0;
       
   414 		}
       
   415 
       
   416 	for (TInt kk=0; kk<iResources; kk++)
       
   417 		{
       
   418 		CResEntry* rEntry = new(ELeave)CResEntry(iDict);
       
   419 		CleanupStack::PushL(rEntry);
       
   420 		rEntry->AddPlainDataL(iResData+iResIndex[kk], iResIndex[kk+1] - iResIndex[kk]);
       
   421 		rEntry->MatchDictL();
       
   422 		iResArray->AppendL(rEntry);
       
   423 		CleanupStack::Pop();	// rEntry
       
   424 	}
       
   425 
       
   426 
       
   427 	// Optimize Dictionary
       
   428 
       
   429 	OptimizeDict();
       
   430 
       
   431 	// Compress using optimized dictionary
       
   432 
       
   433 	dCount = iDict->Count();
       
   434 	for (TInt x=0; x<dCount; x++)
       
   435 		{
       
   436 		iDict->At(x).iUses = 0;
       
   437 		}
       
   438 
       
   439 	iResArray->ResetAndDestroy();
       
   440 	for (TInt xx=0; xx<iResources; xx++)
       
   441 		{
       
   442 		CResEntry* rEntry = new(ELeave)CResEntry(iDict);
       
   443 		CleanupStack::PushL(rEntry);
       
   444 		rEntry->AddPlainDataL(iResData+iResIndex[xx], iResIndex[xx+1] - iResIndex[xx]);
       
   445 		rEntry->MatchDictL();
       
   446 		iResArray->AppendL(rEntry);
       
   447 		CleanupStack::Pop();	// rEntry
       
   448 		}
       
   449 
       
   450 
       
   451 	// Make sure that there is no more than 256 data bytes in each resource component
       
   452 	CheckForLongDataStringsL();
       
   453 	
       
   454 	TInt size = ResourceSize();
       
   455 
       
   456 	TInt count = iResArray->Count();
       
   457 
       
   458 	size += 4;			// res header
       
   459 	size += 7;			// dict header
       
   460 	size += (count + 1) * 2;	// res index
       
   461 
       
   462 	TInt dSize = iDict->DictionarySize();
       
   463 
       
   464 	iCompressedSize = size+dSize;
       
   465 	return size+dSize;
       
   466 	}
       
   467 
       
   468 TInt CResComp::ResourceSize()
       
   469 	{
       
   470 	TInt resSize = 0;
       
   471 	if (!iResArray)
       
   472 		return -1;
       
   473 	TInt count = iResArray->Count();
       
   474 	for (TInt jj=0; jj<count; jj++)
       
   475 		{
       
   476 		resSize += ((iResArray->At(jj))->Size(iBitsForDict));
       
   477 		}
       
   478 	resSize = (resSize + 7) / 8;
       
   479 	return resSize;
       
   480 	}
       
   481 
       
   482 
       
   483 
       
   484 
       
   485 TBool CResComp::IsValid()
       
   486 	{
       
   487 	TInt resSize = ResourceSize();
       
   488 	TInt dSize = iDict->DictionarySizeWithoutIndex();
       
   489 
       
   490 	RDebug::Print(_L("Ressize = %D, dsize=%D, compressedsize=%D , fileSize=%D\n"), resSize, dSize, CompressedSize(), OriginalFileSize());
       
   491 
       
   492 	if (resSize < 8192 && dSize < 8192 && (CompressedSize() < OriginalFileSize()) && resSize > 0)
       
   493 		{
       
   494 		return ETrue;
       
   495 		}
       
   496 	return EFalse;
       
   497 	}
       
   498 
       
   499 
       
   500 
       
   501 
       
   502 
       
   503 
       
   504 
       
   505 
       
   506 void CResComp::WriteFileL(RFs& aFs, const TDesC& aName)
       
   507 	{
       
   508 	CBufFlat* buffer = CBufFlat::NewL(1024);
       
   509 	CleanupStack::PushL(buffer);
       
   510 
       
   511 	RBufWriteStream bStream;
       
   512 	bStream.Open(*buffer);
       
   513 	CleanupClosePushL(bStream);
       
   514 
       
   515 
       
   516 	RFileWriteStream fStream;
       
   517 	User::LeaveIfError(fStream.Replace(aFs, aName, EFileWrite));
       
   518 
       
   519 	WriteHeaderL(fStream);
       
   520 	WriteDictionaryL(fStream);
       
   521 	WriteResourceL(fStream);
       
   522 
       
   523 	fStream.Close();
       
   524 
       
   525 	CleanupStack::PopAndDestroy(2);	// bStream, buffer
       
   526 	}
       
   527 
       
   528 
       
   529 
       
   530 void CResComp::OptimizeDict()
       
   531 	{
       
   532 	// Find referenced dicts
       
   533 	TInt entries = iDict->Count();
       
   534 
       
   535 	for (TInt ii=0; ii<entries-1; ii++)
       
   536 		{		
       
   537 		TBuf8<KMaxDictEntry> dc;
       
   538 		dc.Copy(iDict->At(ii).iData);
       
   539 
       
   540 		FindEmbeddedDict(dc, ii+1);
       
   541 		}
       
   542 
       
   543 	// Sort dictionary in order of use
       
   544 
       
   545 	CDictArray* newDict = new(ELeave)CDictArray();
       
   546 	CleanupStack::PushL(newDict);
       
   547 
       
   548 	for (TInt jj=0; jj<entries; jj++)
       
   549 		{
       
   550 		newDict->OrderedInsertL(iDict->At(jj));
       
   551 		}
       
   552 
       
   553 	TInt newDictEntries = newDict->Count();
       
   554 	if (newDictEntries > iMaxEntries)
       
   555 		newDictEntries = iMaxEntries;
       
   556 
       
   557 	iDict->Reset();
       
   558 
       
   559 	for (TInt kk=0; kk<newDictEntries; kk++)
       
   560 		{
       
   561 		iDict->SizedInsertL(newDict->At(kk));
       
   562 		}
       
   563 
       
   564 	CleanupStack::PopAndDestroy();	// newDict
       
   565 
       
   566 	for (TInt zz=0; zz<newDictEntries; zz++)
       
   567 		{
       
   568 		iDict->At(zz).CreateEmbeddedDict(zz, iDict);
       
   569 		}
       
   570 	}
       
   571 
       
   572 
       
   573 void CResComp::FindEmbeddedDict(TDesC8& aMatch, TInt aStart)
       
   574 	{
       
   575 	TInt entries = iDict->Count();
       
   576 	for (TInt ii=aStart; ii<entries; ii++)
       
   577 		{
       
   578 		TInt found = aMatch.Find(iDict->At(ii).iData);
       
   579 		if (found != KErrNotFound)
       
   580 			{
       
   581 			// Found embedded dict
       
   582 			iDict->At(ii).iRef++;
       
   583 			if (found > 1)
       
   584 				{
       
   585 				TPtrC8 left = aMatch.Left(found);
       
   586 				FindEmbeddedDict(left, ii);
       
   587 				}
       
   588 			TInt right = aMatch.Length() - iDict->At(ii).iData.Length() - found;
       
   589 			if (right > 1)
       
   590 				{
       
   591 				TPtrC8 rt = aMatch.Right(right);
       
   592 				FindEmbeddedDict(rt, ii);
       
   593 				}
       
   594 			break;
       
   595 			}
       
   596 		}
       
   597 	}
       
   598 
       
   599 
       
   600 TPtrC8 CResComp::Resource(TInt aRes)
       
   601 	{
       
   602 	return TPtrC8(iResData+iResIndex[aRes], iResIndex[aRes+1] - iResIndex[aRes]);
       
   603 	}
       
   604 
       
   605 
       
   606 TInt CResComp::FindInResources(TDesC8& aBuf, TInt aMax)
       
   607 	{
       
   608 	TInt result = KErrNotFound;
       
   609 	for (TInt ii=0; ii<aMax; ii++)
       
   610 		{
       
   611 		TPtrC8 res = Resource(ii);
       
   612 		TInt found = res.Find(aBuf);
       
   613 		if (found != KErrNotFound)
       
   614 			return ii;
       
   615 		}
       
   616 	return result;
       
   617 	}
       
   618 
       
   619 
       
   620 
       
   621 
       
   622 void CResComp::WriteHeaderL(RWriteStream& aStream)
       
   623 	{
       
   624 	// Write resource header
       
   625 
       
   626 	aStream.WriteInt16L(4);	// position of dictionary data
       
   627 	aStream.WriteInt16L(iResources);
       
   628 	}
       
   629 
       
   630 
       
   631 void CResComp::WriteDictionaryL(RWriteStream& aStream)
       
   632 	{
       
   633 	WriteDictionaryHeaderL(aStream);
       
   634 	WriteDictionaryIndexL(aStream);
       
   635 	WriteDictionaryDataL(aStream);
       
   636 	}
       
   637 
       
   638 void CResComp::WriteDictionaryHeaderL(RWriteStream& aStream)
       
   639 	{
       
   640 /*	Dictionary header format
       
   641 
       
   642 	Offset	Length(bytes)	Data
       
   643 	0		1				Version number
       
   644 	1		1				Number of dictionary items
       
   645 	2		2				File offset of resource index
       
   646 	4		2				Size of largest resource
       
   647 
       
   648 //	2		2				File offset of dictionary
       
   649 //	6		2				File offset of resource data
       
   650 */
       
   651 	aStream.WriteUint8L(1);	// used to define different compression methods
       
   652 	TInt dictSize = iDict->Count();
       
   653 	TInt diff = (1 << iBitsForDict) - dictSize;
       
   654 	aStream.WriteUint8L(diff);
       
   655 	TInt headerSize = 4 + 7;
       
   656 	TInt resourceIndex = headerSize + iDict->DictionarySize();
       
   657 //	TInt resourceData = resourceIndex + (iResources	* 2);
       
   658 	aStream.WriteUint16L(resourceIndex);
       
   659 	aStream.WriteUint16L(iLargestResourceSize);
       
   660 //	RDebug::Print(_L("ResourceIndex:%d bytes"), resourceIndex);
       
   661 	aStream.WriteUint8L(iBitsForDict);
       
   662 	}
       
   663 
       
   664 void CResComp::WriteDictionaryIndexL(RWriteStream& aStream)
       
   665 	{
       
   666 	// Write bitIndex of each dictionary element
       
   667 	// (as offset from start of dictionaryData)
       
   668 	TInt dSize = iDict->Count();
       
   669 	TInt offset = 0;
       
   670 	aStream.WriteUint16L(0);
       
   671 	for (TInt ii=0; ii<dSize; ii++)
       
   672 		{
       
   673 		offset += iDict->BitSize(ii);
       
   674 		aStream.WriteUint16L(offset);
       
   675 		}
       
   676 	}
       
   677 
       
   678 void CResComp::WriteDictionaryDataL(RWriteStream& aStream)
       
   679 	{
       
   680 	TBitWriter bitWrite(aStream);
       
   681 	TInt dSize = iDict->Count();
       
   682 	for (TInt ii=0; ii<dSize; ii++)
       
   683 		{
       
   684 		iDict->WriteBitStreamL(ii, bitWrite);
       
   685 		}
       
   686 	bitWrite.FlushL();
       
   687 	}
       
   688 
       
   689 
       
   690 
       
   691 void CResComp::WriteResourceL(RWriteStream& aStream)
       
   692 	{
       
   693 	WriteResourceIndexL(aStream);
       
   694 	WriteResourceDataL(aStream);
       
   695 	}
       
   696 
       
   697 void CResComp::WriteResourceIndexL(RWriteStream& aStream)
       
   698 	{
       
   699 	// Write bitIndex of each resource element
       
   700 	// (as offset from start of resource Index)
       
   701 	TInt offset = 0;
       
   702 	aStream.WriteUint16L(0);
       
   703 	for (TInt ii=0; ii<iResources; ii++)
       
   704 		{
       
   705 		offset += ((iResArray->At(ii))->Size(iBitsForDict));
       
   706 		aStream.WriteUint16L(offset);
       
   707 		}
       
   708 	}
       
   709 
       
   710 void CResComp::WriteResourceDataL(RWriteStream& aStream)
       
   711 	{
       
   712 //	RDebug::Print(_L("Writing Resource Data"));
       
   713 	TBitWriter bitWrite(aStream);
       
   714 	for (TInt ii=0; ii<iResources; ii++)
       
   715 		{
       
   716 //		RDebug::Print(_L("Writing Resource %d"), ii);
       
   717 		(iResArray->At(ii))->WriteBitStreamL(bitWrite,iBitsForDict);
       
   718 		}
       
   719 	bitWrite.FlushL();
       
   720 	}
       
   721 
       
   722 
       
   723 
       
   724 TInt CResComp::OriginalFileSize()
       
   725 	{
       
   726 	if(iOriginalCompressedSize)
       
   727 		return iOriginalCompressedSize;
       
   728 	else
       
   729 		return iFileLength;
       
   730 	}
       
   731 
       
   732 TInt CResComp::CompressedSize()
       
   733 	{
       
   734 	return iCompressedSize;
       
   735 	}
       
   736 
       
   737 void CResComp::DisplayStats()
       
   738 	{
       
   739 	TInt size = 0;
       
   740 	TInt rsize = 0;
       
   741 	TInt count = iResArray->Count();
       
   742 
       
   743 	for (TInt jj=0; jj<count; jj++)
       
   744 		{
       
   745 		rsize += ((iResArray->At(jj))->Size(iBitsForDict));// + 7) / 8;
       
   746 		}
       
   747 
       
   748 	rsize = (rsize + 7) / 8;
       
   749 
       
   750 	size += 4;			// res header
       
   751 	size += 7;			// dict header
       
   752 	size += (count + 1) * 2;	// res index
       
   753 
       
   754 	size += rsize;
       
   755 	TInt dSize = iDict->DictionarySize();
       
   756 
       
   757 //	iConsole->Printf(_L("Original Size: %d bytes\n"), iFileLength);
       
   758 //	iConsole->Printf(_L("Compressed Resource Size: %d bytes\n"), size);
       
   759 //	iConsole->Printf(_L("Compressed Dictionary Size: %d bytes\n"), dSize);
       
   760 //	iConsole->Printf(_L("Compressed Size: %d bytes\n"), size+dSize);
       
   761 //	iConsole->Printf(_L("Dictionary Size: %d \n"), iDict->Count());
       
   762 
       
   763 	TInt compression = ((size + dSize) * 100) / iFileLength;
       
   764 //	iConsole->Printf(_L("Compression = %d %%\n"), compression);
       
   765 
       
   766 
       
   767 	iConsole->Printf(_L("\t%d\t%d\t%d\t%d %%\t%d\n"), iFileLength, size+dSize, compression,iOriginalCompressedSize, 1<<iBitsForDict);
       
   768 
       
   769 	TInt bitsForDictIndex = 0;
       
   770 	while ( (1<<bitsForDictIndex) < dSize)
       
   771 		{
       
   772 		bitsForDictIndex++;
       
   773 		}
       
   774 	TInt bitsSaved = iDict->Count() * (16 - bitsForDictIndex);
       
   775 	bitsSaved = (bitsSaved + 7) / 8;
       
   776 //	RDebug::Print(_L("Possible saving for dictionary: %d"), bitsSaved);
       
   777 
       
   778 	TInt bitsForResIndex = 0;
       
   779 	while ( (1<<bitsForResIndex) < rsize)
       
   780 		{
       
   781 		bitsForResIndex++;
       
   782 		}
       
   783 	TInt rbitsSaved = count * (16 - bitsForResIndex);
       
   784 	rbitsSaved = (rbitsSaved + 7) / 8;
       
   785 //	RDebug::Print(_L("Possible saving for res: %d"), rbitsSaved);
       
   786 
       
   787 //	RDebug::Print(_L("Total Compressed Size: %d  Possible: %d"), size+dSize, (size+dSize) - (bitsSaved+rbitsSaved));
       
   788 	}
       
   789 
       
   790 
       
   791 
       
   792 // Check that none of the data lengths exceed 256 bytes.
       
   793 
       
   794 void CResComp::CheckForLongDataStringsL()
       
   795 	{
       
   796 	RDebug::Print(_L("CheckingForLongDataStrings"));
       
   797 	for (TInt ii=0; ii<iResources; ii++)
       
   798 		{
       
   799 		RDebug::Print(_L("Checking Resource %d"), ii);
       
   800 		(iResArray->At(ii))->CheckForLongDataStringsL();
       
   801 		}
       
   802 	}