reszip/src/resentry.cpp
changeset 0 f58d6ec98e88
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/reszip/src/resentry.cpp	Thu Dec 17 09:14:18 2009 +0200
@@ -0,0 +1,502 @@
+/*
+* Copyright (c) 1997-1999 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+#include "resentry.h"
+#include "resdict.h"
+#include "rescomp.h"
+
+//TResComponent
+
+TInt TResComponent::Size(TInt aDictionaryBits)
+	{
+	if (iType == EResTypePlain)
+		{
+		if (iLength == 0)
+			return 0;
+		TInt bits = iLength * 8;
+		bits++;			// data flag
+		if (iLength == 1)
+			bits ++;	// first bit zero if 1 byte of data
+		else 
+			{
+			bits++;		// first bit 1 if >1 byte of data
+			if (iLength == 2)
+				{
+				bits ++;	// second bit zero if 2 bytes of data
+				}
+			else
+				{
+				bits ++;		// second bit 1 if >2 bytes of data
+				if (iLength < 11)
+					{
+					// write 4 bits of data + 1 zero bit flag
+					bits += 4;
+					}
+				else
+					{
+					// write 8 bits of data + 1 '1' bit flag
+					bits += 9;
+					}
+				}
+			}
+
+//		console->Printf(_L("Type Plain: %d\n"), bits);
+		return bits;
+		}
+	if (iType == EResTypeToken)
+		{
+		return 1+aDictionaryBits;
+//		console->Printf(_L("Type Token: %d\n"), iToken);
+//		return 8;		// dictionary entries are stored in 6 bits
+		}
+	return 0;
+	}
+
+
+void TResComponent::WriteBitStreamL(TBitWriter& aWriter, TInt aDictionaryBits)
+	{
+	if (iType == EResTypePlain)
+		{
+		if (iLength == 0)
+			return;
+// Debugging code
+/*
+		RDebug::Print(_L("Data Length: %d"), iLength);
+		TBuf<100> b;
+		for (TInt xx=0; xx<iLength; xx++)
+			{
+			b.AppendFormat(_L("%02x "), iData[xx]);
+			}
+		RDebug::Print(b);
+*/
+//
+		// Write 'data' flag
+		aWriter.WriteL(1, 1);
+		if (iLength == 1)
+			{
+			aWriter.WriteL(0, 1); // first bit zero if 1 byte of data
+			}
+		else 
+			{
+			aWriter.WriteL(1, 1);		// first bit 1 if >1 byte of data
+			if (iLength == 2)
+				{
+				aWriter.WriteL(0, 1); // second bit zero if 2 bytes of data
+				}
+			else
+				{
+				aWriter.WriteL(1, 1); // second bit 1 if >2 bytes of data
+				if (iLength < 11)
+					{
+					aWriter.WriteL(0, 1);
+					aWriter.WriteL(iLength-3, 3);
+					// write 4 bits of data + 1 zero bit flag
+					}
+				else
+					{
+					aWriter.WriteL(1, 1);
+					aWriter.WriteL(iLength, 8);
+					// write 8 bits of data + 1 '1' bit flag
+					if (iLength > 255)
+						{
+						User::Panic(_L("Entry too long"),0);
+						}
+					}
+				}
+			}
+		// Now write data to output
+		for (TInt ii=0; ii<iLength; ii++)
+			{
+			aWriter.WriteL(iData[ii], 8);
+			}
+		}
+	if (iType == EResTypeToken)
+		{
+		// Write 'token' flag
+		aWriter.WriteL(0, 1);
+
+		// Write token
+		aWriter.WriteL(iToken, aDictionaryBits);
+//		RDebug::Print(_L("Token [%d] "), iToken);
+		}
+	}
+
+
+
+// CResEntry
+CResEntry::CResEntry(CDictArray* aDict)
+:iDict(aDict)
+	{
+	iComponent = new(ELeave)CArrayFixFlat<TResComponent>(4);
+	}
+
+CResEntry::~CResEntry()
+	{
+	delete iComponent;
+	}
+
+
+void CResEntry::AddPlainDataL(TUint8* aData, TInt aLength)
+	{
+	TResComponent comp;
+	comp.iType = EResTypePlain;
+	comp.iData = aData;
+	comp.iLength = aLength;
+	iComponent->AppendL(comp);
+	}
+
+void CResEntry::InsertTokenL(TInt aPosition, TInt aToken)
+	{
+	TResComponent comp;
+	comp.iType = EResTypeToken;
+	comp.iToken = aToken;
+	comp.iLength=0;
+	iComponent->InsertL(aPosition,comp);
+	(*iDict)[aToken].iUses++;
+	}
+
+void CResEntry::SplitPlainDataWithZeroSpacedL(TInt aComponent, TInt aZeroSpacedStart, TInt aLength)
+	{
+	TResComponent comp = (*iComponent)[aComponent];
+
+	TResComponent newComp1;
+	newComp1.iType = EResTypePlain;
+	newComp1.iData = comp.iData;
+	newComp1.iLength = aZeroSpacedStart;
+
+	TResComponent newComp2;
+	newComp2.iType = EResTypePlain;
+	newComp2.iData = comp.iData + aZeroSpacedStart + aLength;
+	newComp2.iLength = comp.iLength-(aZeroSpacedStart+aLength);
+
+	TResComponent newComp3;
+	newComp3.iType = EResTypeZeroSpaced;
+	newComp3.iData = comp.iData + aZeroSpacedStart;
+	newComp3.iLength = aLength;
+
+
+	iComponent->Delete(aComponent);
+	TInt componentPos = aComponent;
+    if (newComp1.iLength != 0)
+		{
+		iComponent->InsertL(componentPos, newComp1);
+		componentPos++;
+		}
+
+	iComponent->InsertL(componentPos, newComp3);
+	componentPos++;
+
+	if (newComp2.iLength != 0)
+		{
+		iComponent->InsertL(componentPos, newComp2);
+		}
+	}
+
+
+void CResEntry::SplitPlainDataWithTokenL(TInt aComponent, TInt aToken, TInt aPosition)
+	{
+	TResComponent comp = (*iComponent)[aComponent];
+	TDesC8& dEntry = (*iDict)[aToken].Data();
+	TInt dictLength = dEntry.Length();
+
+	TResComponent newComp1;
+	newComp1.iType = EResTypePlain;
+	newComp1.iData = comp.iData;
+	newComp1.iLength = aPosition;
+
+	TResComponent newComp2;
+	newComp2.iType = EResTypePlain;
+	newComp2.iData = comp.iData + aPosition + dictLength;
+	newComp2.iLength = comp.iLength - dictLength - aPosition;
+
+	iComponent->Delete(aComponent);
+	TInt componentPos = aComponent;
+    if (newComp1.iLength != 0)
+		{
+		iComponent->InsertL(componentPos, newComp1);
+		componentPos++;
+		}
+	InsertTokenL(componentPos, aToken);
+	componentPos++;
+
+	if (newComp2.iLength != 0)
+		{
+		iComponent->InsertL(componentPos, newComp2);
+		}
+
+	}
+
+
+TInt CResEntry::Size(TInt aDictionaryBits)
+	{
+	TInt size = 0;
+	TInt count = iComponent->Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		size += iComponent->At(ii).Size(aDictionaryBits);
+		}
+	return size;
+	}
+
+void CResEntry::WriteBitStreamL(TBitWriter& aWriter, TInt aDictionaryBits)
+	{
+	TInt count = iComponent->Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		iComponent->At(ii).WriteBitStreamL(aWriter, aDictionaryBits);
+		}
+	}
+
+
+
+TBool CResEntry::DoMatchDictL(TResComponent& aComp, TInt aOffset, TInt aDictIndex)
+	{
+	TInt dCount = iDict->Count();
+	TInt cSize = aComp.iLength;
+	for (TInt ii=0; ii<dCount; ii++)
+		{
+		if (ii != aDictIndex)
+			{
+			TDesC8& dEntry = (*iDict)[ii].Data();
+			if (dEntry.Length() <= cSize)
+				{
+				TPtrC8 data(aComp.iData, cSize);
+				TInt pos = data.Find(dEntry);
+				if (pos != KErrNotFound)
+					{
+//					console->Printf(_L("Found %d Offset: %d\n"),ii, pos);
+					SplitPlainDataWithTokenL(aOffset, ii, pos);
+					return ETrue;
+				}
+			}
+			}
+		}
+	return EFalse;
+	}
+
+
+void CResEntry::MatchDictL(TInt aDictIndex)
+	{
+	// Match plain text components against dictionary
+	TInt count = iComponent->Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		TResComponent comp = (*iComponent)[ii];
+		if (comp.iType == EResTypePlain)
+			{
+			if (DoMatchDictL(comp, ii, aDictIndex))
+				{
+				count = iComponent->Count();
+				ii--;
+				}
+			}
+		}
+	}
+
+
+/*
+void CResEntry::MatchZeroSpacedL()
+	{
+	// Find zero spaced data
+	TInt count = iComponent->Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		TResComponent comp = (*iComponent)[ii];
+		if (comp.iType == EResTypePlain)
+			{
+			if (DoMatchZeroSpacedL(comp, ii))
+				{
+				count = iComponent->Count();
+				ii--;
+				}
+			}
+		}
+	}
+
+
+TBool CResEntry::DoMatchZeroSpacedL(TResComponent& aComp, TInt aOffset)
+	{
+	// Analyse data and see if there is a string of zero spaced data
+	// Data, followed by zero
+	TInt length = aComp.iLength;
+	TInt pos = 0;
+	TInt dataSize = 0;
+	for (TInt ii=0; ii<length-1; ii++)
+		{
+		if (aComp.iData[ii+1] == 0)
+			{
+			// Found zero spaced data
+			if (dataSize == 0)
+				{
+				// Start of zero spaced data
+				pos = ii;
+				dataSize = 2;
+				}
+			else
+				{
+				dataSize += 2;
+				}
+			ii++;
+			}
+		else
+			{
+			// End of zero spaced data
+			if (dataSize > 2)
+				{
+				SplitPlainDataWithZeroSpacedL(aOffset, pos, dataSize);
+				return ETrue;
+				}
+			dataSize = 0;
+			}
+		}
+	return EFalse;
+	}
+*/
+
+
+void CResEntry::MatchSelfL(TInt aRes,CResComp* aResComp)
+	{
+	// Find duplicates within resource
+	TInt count = iComponent->Count();
+	for (TInt ii=0; ii<count; ii++)
+		{
+		TResComponent comp = (*iComponent)[ii];
+		if (comp.iType == EResTypePlain)
+			{
+			if (DoMatchSelfL(comp, ii, aRes, aResComp))
+				{
+				count = iComponent->Count();
+				ii--;
+				}
+			}
+		}
+	}
+
+
+
+
+/*
+TBool CResEntry::MatchPreviousComponent(TInt aCompIndex, TDesC8& aMatch)
+	{
+	TInt size = aMatch.Size();
+	for (TInt ii=0; ii<aCompIndex; ii++)
+		{
+		TResComponent comp = (*iComponent)[ii];
+		if (comp.iType == EResTypePlain)
+			{
+			console->Printf(_L("Matching: %d (Length: %d)\n"), aCompIndex, size);
+			if (comp.iLength <= size)
+				{
+				 TPtrC8 buf(comp.iData, comp.iLength);
+				 TInt found = buf.Find(aMatch);
+				 if (found != KErrNotFound)
+					 {
+					 console->Printf(_L("Found\n"));
+					 return ii;
+					 }
+				}
+			}
+		}
+
+	return KErrNotFound;
+	}
+*/
+
+TBool CResEntry::DoMatchSelfL(TResComponent& aComp, TInt aOffset, TInt aRes, CResComp* aResComp)
+	{
+	TInt cSize = aComp.iLength;
+	TInt matchSize = cSize/2;
+	if (matchSize > KMaxDictEntry)
+		matchSize = KMaxDictEntry;
+
+	while (matchSize > 1)
+		{
+		TInt pos=matchSize;
+		TInt positions = (cSize-(matchSize*2))+1;
+		while (positions)
+			{
+			TPtr8 match(aComp.iData + pos, matchSize,matchSize);
+			TPtr8 left(aComp.iData, pos, pos);
+			TInt found = left.Find(match);
+			if (found != KErrNotFound)
+				{
+				TInt token = iDict->AddEntryL(match);
+				// Remove both matches and replace with token
+				SplitPlainDataWithTokenL(aOffset, token, pos);
+				SplitPlainDataWithTokenL(aOffset, token, found);
+				return ETrue;
+				}
+			else
+				{
+				// Find in all other resources
+				TInt find = aResComp->FindInResources(match, aRes);
+				if (find != KErrNotFound)
+					{
+					TInt token = iDict->AddEntryL(match);
+					SplitPlainDataWithTokenL(aOffset, token, pos);
+					return ETrue;
+					}
+
+				}
+			positions--;
+			pos++;
+			}
+		matchSize--;
+		}
+	return EFalse;
+	}
+
+
+	TResType iType;
+	TUint8* iData;
+	TInt iLength;
+	TInt iToken;
+
+
+void CResEntry::CheckForLongDataStringsL()
+	{
+	TInt components = iComponent->Count();
+	for (TInt ii=0; ii<components; ii++)
+		{
+		TResComponent comp = (*iComponent)[ii];
+		if (comp.iLength > 255)
+			{
+			TInt length = comp.iLength;
+			RDebug::Print(_L("Component Too Long!"));
+			TResComponent comp1;
+			comp1.iType = comp.iType;
+			comp1.iData = comp.iData;
+			comp1.iLength = 255;
+			comp1.iToken = comp.iToken;
+
+			TResComponent comp2;
+			comp2.iType = comp.iType;
+			comp2.iData = comp.iData + 255;
+			comp2.iLength = length - 255;
+			comp2.iToken = comp.iToken;
+
+			iComponent->Delete(ii);
+			iComponent->InsertL(ii, comp1);
+			iComponent->InsertL(ii+1, comp2);
+
+			components = iComponent->Count();
+			}
+		}
+	}
+