reszip/src/rcmp.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 09:14:18 +0200
changeset 0 f58d6ec98e88
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* Copyright (c) 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:
*
*/
// RCMP.CPP
//
//

#include <e32svr.h>
#include <e32cons.h>
#include <s32file.h>
#include <s32mem.h>


#include "rescomp.h"
#include "resdict.h"
#include "resentry.h"

const TInt KConsWidth = 20;
const TInt KConsHeight = 15;

// TOOL version string (will be printed on command line so please keep upto date)
_LIT(KReszipVersionString, "reszip version 2.0.0");

LOCAL_D CConsoleBase* console;
LOCAL_D RFs TheFs;
LOCAL_D CTrapCleanup* TheTrapCleanup;

LOCAL_D CArrayFixFlat<TFileName>* iFileList;

TBuf<256> Arg;


_LIT(KUncompressedExt,".orig");

LOCAL_C void setupCleanup()
//
// Initialise the cleanup stack.
//
    {
	TheTrapCleanup=CTrapCleanup::New();
	}

void AddToFileListL(const TDesC& aName);


void AddFileListL(const TDesC& aName)
	{
	RDebug::Print(_L("Adding files from "));
	RDebug::Print(aName);
	
	RFileReadStream stream;
	User::LeaveIfError( stream.Open(TheFs, aName, EFileRead) );
	CleanupClosePushL(stream);

	TBuf<512> buf;
	TInt ch = 0;
	TInt err = KErrNone;
	while(err == KErrNone)
		{
		TRAP(err, ch = stream.ReadUint8L());
		if (err == KErrNone)
			{
			if (ch != 13 && ch != 10)
				{
				buf.Append(ch);
				}
			else
				{
				AddToFileListL(buf);
				buf.Zero();
				}
			}
		}

	CleanupStack::PopAndDestroy();	// stream
	}

void AddToFileListL(const TDesC& aName)
	{
	if (aName.Length() == 0)
		{
		return;
		}
	RDebug::Print(aName);

	if (aName[0] == '@')
		{
		AddFileListL(aName.Right(aName.Length()-1));
		return;
		}

	TParse parse;
	if (parse.Set(aName, NULL, NULL) != KErrNone)
		{
		return;
		}
	TFileName name(parse.NameAndExt());
	TPtrC driveAndPath(parse.DriveAndPath());

	CDir* fileList = NULL; 
	CDir* dirList = NULL; 


	// Report any missing files (not fatal, as we don't want to stop the list)
	TEntry entry;
	if((!parse.IsWild()) && TheFs.Entry(aName,entry) != KErrNone)
		console->Printf(_L("Error: Cannot find %S\n"), &aName);
			

	TInt err = TheFs.GetDir(aName, KEntryAttNormal,ESortByName,fileList,dirList);	
	if (err != KErrNone)
		{
		delete fileList;
		delete dirList;
		return;
		}

	TInt count = fileList->Count();

	_LIT(KString,"%S\n"); 

	TInt appendErr = KErrNone;
	for (TInt i=0;i<count;i++) 
		{
		TFileName fullName(driveAndPath);
		fullName.Append((*fileList)[i].iName);
		TRAPD(appendErr, iFileList->AppendL(fullName) );
		if(appendErr!=KErrNone)
			break;
		}

	delete fileList;
	delete dirList;
	User::LeaveIfError(appendErr);
	}



void ProcessAllFilesL()
	{
	TInt totalSize = 0;
	TInt totalCompressed = 0;

	if (Arg.Length() == 0)
		{
		// Write help information
		console->Printf(_L("ResZip ROM Resource Compressor (%S)\n------------------------------\n"), &KReszipVersionString);
		console->Printf(_L("Syntax: ResZip [full path to resource files]\n"));
		console->Printf(_L("        ResZip [@full path to text file containing resource filenames]\n"));
		console->Printf(_L("e.g: ResZip r:\\epoc32\\release\\wins\\udeb\\z\\system\\data\\*.rsc\n"));
		console->Printf(_L("     ResZip @r:\\files.txt\n"));
		console->Printf(_L("         where r:\\files.txt contains list of filenames (wildcards allowed)\n"));
		console->Printf(_L("Full Path may include wildcards for compressing all resources in a directory\n"));
		console->Printf(_L("May be used to compress non-ROM resources, with lower run-time performance\n"));
		return;
		}

	iFileList = new(ELeave)CArrayFixFlat<TFileName>(32);

	AddToFileListL(Arg);

	TInt filecount = iFileList->Count();

	if (filecount == 0)
		{
		console->Printf(_L("No files to process\n"));
		}
	else
		{
		TBuf<80> buf;
		buf.Format(_L("Processing %d files\n"), filecount);
		console->Printf(buf);
		console->Printf(_L("Name\t\t\t Resource\tOrig\tUncompressed\tNew\t%%\tDictSize\n"));
		console->Printf(_L("====\t\t\t ========\t====\t============\t===\t==\t========\n"));
		}

	TTime startTime;
	startTime.UniversalTime();

	for (TInt ii=0; ii<filecount; ii++)
		{

		CResComp* compressor = new(ELeave)CResComp(console);
		CleanupStack::PushL(compressor);

		TFileName fullName(iFileList->At(ii));
		compressor->LoadFileL(TheFs, fullName);
		compressor->CompressL();

		if (!compressor->IsValid())
			{
			console->Printf(_L("\r"));
			console->Printf(compressor->iConOutput);
			console->Printf(_L("Not compressed\n"));
			}
		else
			{
			compressor->DisplayStats();
			totalSize += compressor->OriginalFileSize();
			totalCompressed += compressor->CompressedSize();
			TFileName newName(fullName);
			newName.Append(KUncompressedExt);
			TheFs.Delete(newName);
			User::LeaveIfError(TheFs.Rename(fullName, newName));
			TRAPD(err, compressor->WriteFileL(TheFs,fullName));
			if(err != KErrNone)
				{
				TheFs.Delete(fullName);
				TheFs.Rename(newName, fullName);
				User::Leave(err);
				}
			}

		CleanupStack::PopAndDestroy(compressor);	
		}

	console->Printf(_L("------------------------------\n"));
	console->Printf(_L("Total File Size: %d bytes\n"), totalSize);
	console->Printf(_L("Total Compressed Size: %d bytes\n"), totalCompressed);

	if (totalSize > 0)
		{
		TInt compression = ((totalCompressed) * 100) / totalSize;
		console->Printf(_L("Total Compression = %d %%\n"), compression);
		}

	TTime endTime;
	endTime.UniversalTime();

	TTimeIntervalSeconds seconds;
	endTime.SecondsFrom(startTime, seconds);

	TInt secs = seconds.Int();
	
	TInt mins = secs / 60;
	TInt hour = mins / 60;

	secs -= (mins * 60);
	mins -= (hour * 60);

	TBuf<80> time;
	time.Format(_L("Total time: %02d:%02d:%02d"), hour, mins, secs);
	console->Printf(time);

	delete iFileList;
	}


void DoConsoleL()
	{
	console=Console::NewL(_L("EPOC32 - reszip"),
		TSize(KConsWidth,KConsHeight));
	CleanupStack::PushL(console);
	//
	User::CommandLine(Arg);
	//
	User::LeaveIfError( TheFs.Connect() );
	//
	TRAPD(r,ProcessAllFilesL());

	if (r!=KErrNone)
		console->Printf(_L("failed with code %d\n"), r);
	CleanupStack::PopAndDestroy(); // console
	TheFs.Close();
	}

GLDEF_C TInt E32Main()
	{
	setupCleanup();
	TRAPD(err,DoConsoleL());
	delete TheTrapCleanup;
	return KErrNone;
	}