mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-16 12:11:47 -06:00
365 lines
8.6 KiB
C++
Executable File
365 lines
8.6 KiB
C++
Executable File
// Pat.h
|
|
|
|
// #pragma once
|
|
|
|
// #ifndef __PATRICIA__H
|
|
// #define __PATRICIA__H
|
|
|
|
#include "../../../../Common/AlignedBuffer.h"
|
|
#include "../../../../Common/MyCom.h"
|
|
#include "../LZInWindow.h"
|
|
|
|
namespace PAT_NAMESPACE {
|
|
|
|
struct CNode;
|
|
|
|
typedef CNode *CNodePointer;
|
|
|
|
#pragma pack(push, PragmaPatrTree)
|
|
#pragma pack(push, 1)
|
|
|
|
// #define __AUTO_REMOVE
|
|
|
|
// #define __USE_3_BYTES
|
|
|
|
// #define __NODE_4_BITS
|
|
// #define __NODE_3_BITS
|
|
// #define __NODE_2_BITS
|
|
// #define __NODE_2_BITS_PADDING
|
|
|
|
// #define __HASH_3
|
|
|
|
|
|
#ifdef __USE_3_BYTES
|
|
struct CIndex
|
|
{
|
|
BYTE Data[3];
|
|
operator =(UINT32 aValue)
|
|
{
|
|
Data[0] = aValue & 0xFF;
|
|
Data[1] = (aValue >> 8) & 0xFF;
|
|
Data[2] = (aValue >> 16) & 0xFF;
|
|
}
|
|
operator UINT32() const { return (*((const UINT32 *)Data)) & 0xFFFFFF; }
|
|
};
|
|
#else
|
|
typedef UINT32 CIndex;
|
|
#endif
|
|
|
|
|
|
#pragma pack(pop)
|
|
#pragma pack(pop, PragmaPatrTree)
|
|
|
|
#ifdef __NODE_4_BITS
|
|
typedef UINT32 CIndex2;
|
|
typedef UINT32 CSameBitsType;
|
|
#else
|
|
#ifdef __NODE_3_BITS
|
|
typedef UINT32 CIndex2;
|
|
typedef UINT32 CSameBitsType;
|
|
#else
|
|
|
|
#ifdef __USE_3_BYTES
|
|
typedef BYTE CSameBitsType;
|
|
#else
|
|
typedef UINT32 CIndex;
|
|
typedef UINT32 CSameBitsType;
|
|
#endif
|
|
|
|
typedef CIndex CIndex2;
|
|
#endif
|
|
#endif
|
|
|
|
const UINT32 kNumBitsInIndex = sizeof(CIndex) * 8;
|
|
const UINT32 kMatchStartValue = UINT32(1) << (kNumBitsInIndex - 1);
|
|
|
|
typedef CIndex CMatchPointer;
|
|
|
|
const UINT32 kDescendantEmptyValue = kMatchStartValue - 1;
|
|
|
|
#pragma pack(push, PragmaPatrTree2)
|
|
#pragma pack(push, 1)
|
|
|
|
union CDescendant
|
|
{
|
|
CIndex NodePointer;
|
|
CMatchPointer MatchPointer;
|
|
bool IsEmpty() const { return NodePointer == kDescendantEmptyValue; }
|
|
bool IsNode() const { return NodePointer < kDescendantEmptyValue; }
|
|
bool IsMatch() const { return NodePointer > kDescendantEmptyValue; }
|
|
void MakeEmpty() { NodePointer = kDescendantEmptyValue; }
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
#pragma pack(pop, PragmaPatrTree2)
|
|
|
|
#pragma pack( push, PragmaBackNode)
|
|
#pragma pack( push, 1)
|
|
|
|
#undef MY_BYTE_SIZE
|
|
|
|
#ifdef __NODE_4_BITS
|
|
#define MY_BYTE_SIZE 8
|
|
const UINT32 kNumSubBits = 4;
|
|
#else
|
|
#ifdef __NODE_3_BITS
|
|
#define MY_BYTE_SIZE 9
|
|
const UINT32 kNumSubBits = 3;
|
|
#else
|
|
#define MY_BYTE_SIZE 8
|
|
#ifdef __NODE_2_BITS
|
|
const UINT32 kNumSubBits = 2;
|
|
#else
|
|
const UINT32 kNumSubBits = 1;
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
const UINT32 kNumSubNodes = 1 << kNumSubBits;
|
|
const UINT32 kSubNodesMask = kNumSubNodes - 1;
|
|
|
|
struct CNode
|
|
{
|
|
CIndex2 LastMatch;
|
|
CSameBitsType NumSameBits;
|
|
union
|
|
{
|
|
CDescendant Descendants[kNumSubNodes];
|
|
UINT32 NextFreeNode;
|
|
};
|
|
#ifdef __NODE_2_BITS
|
|
#ifdef __NODE_2_BITS_PADDING
|
|
UINT32 Padding[2];
|
|
#endif
|
|
#endif
|
|
};
|
|
|
|
#pragma pack(pop)
|
|
#pragma pack(pop, PragmaBackNode)
|
|
|
|
#undef kIDNumBitsByte
|
|
#undef kIDNumBitsString
|
|
|
|
#ifdef __NODE_4_BITS
|
|
#define kIDNumBitsByte 0x30
|
|
#define kIDNumBitsString TEXT("4")
|
|
#else
|
|
#ifdef __NODE_3_BITS
|
|
#define kIDNumBitsByte 0x20
|
|
#define kIDNumBitsString TEXT("3")
|
|
#else
|
|
#ifdef __NODE_2_BITS
|
|
#define kIDNumBitsByte 0x10
|
|
#define kIDNumBitsString TEXT("2")
|
|
#else
|
|
#define kIDNumBitsByte 0x00
|
|
#define kIDNumBitsString TEXT("1")
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#undef kIDManualRemoveByte
|
|
#undef kIDManualRemoveString
|
|
|
|
#ifdef __AUTO_REMOVE
|
|
#define kIDManualRemoveByte 0x00
|
|
#define kIDManualRemoveString TEXT("")
|
|
#else
|
|
#define kIDManualRemoveByte 0x08
|
|
#define kIDManualRemoveString TEXT("R")
|
|
#endif
|
|
|
|
#undef kIDHash3Byte
|
|
#undef kIDHash3String
|
|
|
|
#ifdef __HASH_3
|
|
#define kIDHash3Byte 0x04
|
|
#define kIDHash3String TEXT("H")
|
|
#else
|
|
#define kIDHash3Byte 0x00
|
|
#define kIDHash3String TEXT("")
|
|
#endif
|
|
|
|
#undef kIDUse3BytesByte
|
|
#undef kIDUse3BytesString
|
|
|
|
#ifdef __USE_3_BYTES
|
|
#define kIDUse3BytesByte 0x02
|
|
#define kIDUse3BytesString TEXT("T")
|
|
#else
|
|
#define kIDUse3BytesByte 0x00
|
|
#define kIDUse3BytesString TEXT("")
|
|
#endif
|
|
|
|
#undef kIDPaddingByte
|
|
#undef kIDPaddingString
|
|
|
|
#ifdef __NODE_2_BITS_PADDING
|
|
#define kIDPaddingByte 0x01
|
|
#define kIDPaddingString TEXT("P")
|
|
#else
|
|
#define kIDPaddingByte 0x00
|
|
#define kIDPaddingString TEXT("")
|
|
#endif
|
|
|
|
|
|
// #undef kIDString
|
|
// #define kIDString TEXT("Compress.MatchFinderPat") kIDNumBitsString kIDManualRemoveString kIDUse3BytesString kIDPaddingString kIDHash3String
|
|
|
|
// {23170F69-40C1-278C-01XX-0000000000}
|
|
|
|
DEFINE_GUID(PAT_CLSID,
|
|
0x23170F69, 0x40C1, 0x278C, 0x01,
|
|
kIDNumBitsByte |
|
|
kIDManualRemoveByte | kIDHash3Byte | kIDUse3BytesByte | kIDPaddingByte,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00);
|
|
|
|
// III(PAT_NAMESPACE)
|
|
|
|
class CPatricia:
|
|
public IMatchFinder,
|
|
public IMatchFinderSetCallback,
|
|
public CMyUnknownImp,
|
|
CLZInWindow
|
|
{
|
|
MY_UNKNOWN_IMP1(IMatchFinderSetCallback)
|
|
|
|
STDMETHOD(Init)(ISequentialInStream *aStream);
|
|
STDMETHOD_(void, ReleaseStream)();
|
|
STDMETHOD(MovePos)();
|
|
STDMETHOD_(BYTE, GetIndexByte)(UINT32 anIndex);
|
|
STDMETHOD_(UINT32, GetMatchLen)(UINT32 aIndex, UINT32 aBack, UINT32 aLimit);
|
|
STDMETHOD_(UINT32, GetNumAvailableBytes)();
|
|
STDMETHOD(Create)(UINT32 aSizeHistory,
|
|
UINT32 aKeepAddBufferBefore, UINT32 aMatchMaxLen,
|
|
UINT32 aKeepAddBufferAfter);
|
|
STDMETHOD_(UINT32, GetLongestMatch)(UINT32 *aDistances);
|
|
STDMETHOD_(void, DummyLongestMatch)();
|
|
STDMETHOD_(const BYTE *, GetPointerToCurrentPos)();
|
|
|
|
void FreeMemory();
|
|
public:
|
|
CPatricia();
|
|
~CPatricia();
|
|
|
|
UINT32 _sizeHistory;
|
|
UINT32 _matchMaxLen;
|
|
|
|
CDescendant *m_HashDescendants;
|
|
#ifdef __HASH_3
|
|
CDescendant *m_Hash2Descendants;
|
|
#endif
|
|
|
|
CNode *m_Nodes;
|
|
|
|
UINT32 m_FreeNode;
|
|
UINT32 m_FreeNodeMax;
|
|
|
|
#ifdef __AUTO_REMOVE
|
|
UINT32 m_NumUsedNodes;
|
|
UINT32 m_NumNodes;
|
|
#else
|
|
bool m_SpecialRemoveMode;
|
|
#endif
|
|
|
|
bool m_SpecialMode;
|
|
UINT32 m_NumNotChangedCycles;
|
|
UINT32 *m_TmpBacks;
|
|
|
|
CAlignedBuffer m_AlignBuffer;
|
|
|
|
CMyComPtr<IMatchFinderCallback> m_Callback;
|
|
|
|
virtual void BeforeMoveBlock();
|
|
virtual void AfterMoveBlock();
|
|
|
|
// IMatchFinderSetCallback
|
|
STDMETHOD(SetCallback)(IMatchFinderCallback *aCallback);
|
|
|
|
void ChangeLastMatch(UINT32 aHashValue);
|
|
|
|
#ifdef __AUTO_REMOVE
|
|
void TestRemoveDescendant(CDescendant &aDescendant, UINT32 aLimitPos);
|
|
void TestRemoveNodes();
|
|
void RemoveNode(UINT32 anIndex);
|
|
void TestRemoveAndNormalizeDescendant(CDescendant &aDescendant,
|
|
UINT32 aLimitPos, UINT32 aSubValue);
|
|
void TestRemoveNodesAndNormalize();
|
|
#else
|
|
void NormalizeDescendant(CDescendant &aDescendant, UINT32 aSubValue);
|
|
void Normalize();
|
|
void RemoveMatch();
|
|
#endif
|
|
private:
|
|
void AddInternalNode(CNodePointer aNode, CIndex *aNodePointerPointer,
|
|
BYTE aByte, BYTE aByteXOR, UINT32 aNumSameBits, UINT32 aPos)
|
|
{
|
|
while((aByteXOR & kSubNodesMask) == 0)
|
|
{
|
|
aByteXOR >>= kNumSubBits;
|
|
aByte >>= kNumSubBits;
|
|
aNumSameBits -= kNumSubBits;
|
|
}
|
|
// Insert New Node
|
|
CNodePointer aNewNode = &m_Nodes[m_FreeNode];
|
|
UINT32 aNodeIndex = *aNodePointerPointer;
|
|
*aNodePointerPointer = m_FreeNode;
|
|
m_FreeNode = aNewNode->NextFreeNode;
|
|
#ifdef __AUTO_REMOVE
|
|
m_NumUsedNodes++;
|
|
#endif
|
|
if (m_FreeNode > m_FreeNodeMax)
|
|
{
|
|
m_FreeNodeMax = m_FreeNode;
|
|
m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
|
|
}
|
|
|
|
UINT32 aBitsNew = aByte & kSubNodesMask;
|
|
UINT32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
|
|
for (UINT32 i = 0; i < kNumSubNodes; i++)
|
|
aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
|
|
aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
|
|
aNewNode->Descendants[aBitsOld].NodePointer = aNodeIndex;
|
|
aNewNode->NumSameBits = CSameBitsType(aNode->NumSameBits - aNumSameBits);
|
|
aNewNode->LastMatch = aPos;
|
|
|
|
aNode->NumSameBits = CSameBitsType(aNumSameBits - kNumSubBits);
|
|
}
|
|
|
|
void AddLeafNode(CNodePointer aNode, BYTE aByte, BYTE aByteXOR,
|
|
UINT32 aNumSameBits, UINT32 aPos, UINT32 aDescendantIndex)
|
|
{
|
|
for(;(aByteXOR & kSubNodesMask) == 0; aNumSameBits += kNumSubBits)
|
|
{
|
|
aByte >>= kNumSubBits;
|
|
aByteXOR >>= kNumSubBits;
|
|
}
|
|
UINT32 aNewNodeIndex = m_FreeNode;
|
|
CNodePointer aNewNode = &m_Nodes[m_FreeNode];
|
|
m_FreeNode = aNewNode->NextFreeNode;
|
|
#ifdef __AUTO_REMOVE
|
|
m_NumUsedNodes++;
|
|
#endif
|
|
if (m_FreeNode > m_FreeNodeMax)
|
|
{
|
|
m_FreeNodeMax = m_FreeNode;
|
|
m_Nodes[m_FreeNode].NextFreeNode = m_FreeNode + 1;
|
|
}
|
|
|
|
UINT32 aBitsNew = (aByte & kSubNodesMask);
|
|
UINT32 aBitsOld = (aByte ^ aByteXOR) & kSubNodesMask;
|
|
for (UINT32 i = 0; i < kNumSubNodes; i++)
|
|
aNewNode->Descendants[i].NodePointer = kDescendantEmptyValue;
|
|
aNewNode->Descendants[aBitsNew].MatchPointer = aPos + kMatchStartValue;
|
|
aNewNode->Descendants[aBitsOld].MatchPointer =
|
|
aNode->Descendants[aDescendantIndex].MatchPointer;
|
|
aNewNode->NumSameBits = CSameBitsType(aNumSameBits);
|
|
aNewNode->LastMatch = aPos;
|
|
aNode->Descendants[aDescendantIndex].NodePointer = aNewNodeIndex;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
// #endif
|