Add LzmaCustomDecompressLib based on the LZMA SDK 4.65 which was

placed in the public domain on 2009-02-03. The LZMA SDK
4.65 was released at the http://www.7-zip.org/sdk.html
website.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8227 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
jljusten 2009-05-01 00:28:19 +00:00
parent 33d487d463
commit 306bf4e22a
22 changed files with 3986 additions and 0 deletions

View File

@ -0,0 +1,30 @@
/*++
Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
LzmaDecompress.h
Abstract:
Lzma Custom decompress algorithm Guid definitions
--*/
#ifndef __LZMA_DECOMPRESS_GUID_H__
#define __LZMA_DECOMPRESS_GUID_H__
#define LZMA_CUSTOM_DECOMPRESS_GUID \
{ 0xEE4E5898, 0x3914, 0x4259, { 0x9D, 0x6E, 0xDC, 0x7B, 0xD7, 0x94, 0x03, 0xCF } }
extern GUID gLzmaCustomDecompressGuid;
#endif

View File

@ -51,6 +51,9 @@
## Include/Guid/CustomDecompress.h
gTianoCustomDecompressGuid = { 0xA31280AD, 0x481E, 0x41B6, { 0x95, 0xE8, 0x12, 0x7F, 0x4C, 0x98, 0x47, 0x79 }}
## Include/Guid/LzmaDecompress.h
gLzmaCustomDecompressGuid = { 0xEE4E5898, 0x3914, 0x4259, { 0x9D, 0x6E, 0xDC, 0x7B, 0xD7, 0x94, 0x03, 0xCF }}
## Guid specify the default BMP logo file.
## Include/Guid/Logo.h
gEfiDefaultBmpLogoGuid = { 0x7BB28B99, 0x61BB, 0x11D5, { 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D }}

View File

@ -201,6 +201,8 @@
[Components.common]
IntelFrameworkModulePkg/Library/BaseUefiTianoCustomDecompressLib/BaseUefiTianoCustomDecompressLib.inf
IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Pei/LzmaCustomDecompressLib.inf
IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Dxe/LzmaCustomDecompressLib.inf
IntelFrameworkModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
IntelFrameworkModulePkg/Library/PciIncompatibleDeviceSupportLib/PciIncompatibleDeviceSupportLib.inf
IntelFrameworkModulePkg/Library/PeiS3Lib/PeiS3Lib.inf

View File

@ -0,0 +1,55 @@
#/** @file
# LZMA GUIDed Section Extraction Protocol Library
#
# Uefi Decompression library instance
# Copyright (c) 2006, 2009, Intel Corporation.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LzmaDxeDecompressLib
FILE_GUID = 35194660-7421-44ad-9636-e44885f092d1
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = BASE
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
CONSTRUCTOR = LzmaDecompressLibConstructor
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
LzmaDxeMemory.c
../LzmaDecompress.c
../Sdk/C/LzFind.c
../Sdk/C/LzmaDec.c
../GuidedSectionExtraction.c
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[Guids]
gLzmaCustomDecompressGuid
[LibraryClasses]
BaseLib
DebugLib
BaseMemoryLib
MemoryAllocationLib
ExtractGuidedSectionLib

View File

@ -0,0 +1,47 @@
/** @file
LZMA Memory Allocation for DXE
Copyright (c) 2006 - 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include "Sdk/C/Types.h"
STATIC
VOID *
SzAlloc(
void *p,
size_t size
)
{
void *np;
p = p;
np = AllocatePool(size);
return np;
}
STATIC
VOID
SzFree(
void *p,
void *address
)
{
p = p;
if (address != NULL) {
FreePool(address);
}
}
ISzAlloc g_Alloc = { SzAlloc, SzFree };

View File

@ -0,0 +1,177 @@
/** @file
LZMA Decompress GUIDed Section Extraction Library
Copyright (c) 2006 - 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/ExtractGuidedSectionLib.h>
#include <Pi/PiFirmwareFile.h>
#include <Guid/LzmaDecompress.h>
#include "LzmaDecompress.h"
STATIC
RETURN_STATUS
EFIAPI
LzmaGuidedSectionGetCompressedLocation (
IN CONST VOID *InputSection,
OUT VOID **LmzaCompressedData,
OUT UINT32 *LmzaCompressedDataSize OPTIONAL
)
{
if (!CompareGuid (
&gLzmaCustomDecompressGuid,
&(((EFI_GUID_DEFINED_SECTION *) InputSection)->SectionDefinitionGuid))) {
return RETURN_INVALID_PARAMETER;
}
//
// Retrieve the size and attribute of the input section data.
//
*LmzaCompressedData =
(VOID*) (
(UINT8 *) InputSection +
((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset
);
if (LmzaCompressedDataSize != NULL) {
*LmzaCompressedDataSize =
(UINT32)(
(
(*(UINT32 *) (((EFI_COMMON_SECTION_HEADER *) InputSection)->Size)) &
0x00ffffff
) -
((EFI_GUID_DEFINED_SECTION *) InputSection)->DataOffset
);
}
return RETURN_SUCCESS;
}
/**
The implementation of 'GetInfo' for Guided Section
Extraction of LZMA compression.
@param InputSection Buffer containing the input GUIDed section to be processed.
@param OutputBufferSize The size of OutputBuffer.
@param ScratchBufferSize The size of ScratchBuffer.
@param SectionAttribute The attribute of the input guided section.
@retval RETURN_SUCCESS The size of destination buffer and the size of scratch buffer are successull retrieved.
@retval RETURN_INVALID_PARAMETER The source data is corrupted, or
The GUID in InputSection does not match this instance guid.
**/
RETURN_STATUS
EFIAPI
LzmaGuidedSectionGetInfo (
IN CONST VOID *InputSection,
OUT UINT32 *OutputBufferSize,
OUT UINT32 *ScratchBufferSize,
OUT UINT16 *SectionAttribute
)
{
RETURN_STATUS Status;
VOID *LzmaInput;
UINT32 LzmaInputSize;
Status = LzmaGuidedSectionGetCompressedLocation(
InputSection,
&LzmaInput,
&LzmaInputSize
);
if (RETURN_ERROR (Status)) {
return Status;
}
*SectionAttribute = ((EFI_GUID_DEFINED_SECTION *) InputSection)->Attributes;
return LzmaUefiDecompressGetInfo (
LzmaInput,
LzmaInputSize,
OutputBufferSize,
ScratchBufferSize
);
}
/**
The implementation of Guided Section Extraction
for LZMA compression.
@param InputSection Buffer containing the input GUIDed section to be processed.
@param OutputBuffer OutputBuffer to point to the start of the section's contents.
if guided data is not prcessed. Otherwise,
OutputBuffer to contain the output data, which is allocated by the caller.
@param ScratchBuffer A pointer to a caller-allocated buffer for function internal use.
@param AuthenticationStatus A pointer to a caller-allocated UINT32 that indicates the
authentication status of the output buffer.
@retval RETURN_SUCCESS Decompression is successfull
@retval RETURN_INVALID_PARAMETER The source data is corrupted, or
The GUID in InputSection does not match this instance guid.
**/
RETURN_STATUS
EFIAPI
LzmaGuidedSectionExtraction (
IN CONST VOID *InputSection,
OUT VOID **OutputBuffer,
IN VOID *ScratchBuffer, OPTIONAL
OUT UINT32 *AuthenticationStatus
)
{
RETURN_STATUS Status;
VOID *LzmaInput;
Status = LzmaGuidedSectionGetCompressedLocation(
InputSection,
&LzmaInput,
NULL
);
if (RETURN_ERROR (Status)) {
return Status;
}
//
// Authentication is set to Zero, which may be ignored.
//
*AuthenticationStatus = 0;
return LzmaUefiDecompress (
LzmaInput,
*OutputBuffer,
ScratchBuffer
);
}
/**
Register LzmaDecompress handler.
@retval RETURN_SUCCESS Register successfully.
@retval RETURN_OUT_OF_RESOURCES No enough memory to store this handler.
**/
EFI_STATUS
EFIAPI
LzmaDecompressLibConstructor (
)
{
return ExtractGuidedSectionRegisterHandlers (
&gLzmaCustomDecompressGuid,
LzmaGuidedSectionGetInfo,
LzmaGuidedSectionExtraction
);
}

View File

@ -0,0 +1,4 @@
LzmaCustomDecompressLib is based on the LZMA SDK 4.65.
LZMA SDK 4.65 was placed in the public domain on
2009-02-03. It was released on the
http://www.7-zip.org/sdk.html website.

View File

@ -0,0 +1,144 @@
/** @file
LZMA Decompress routines for edk2
Portions based on LZMA SDK 4.65:
LzmaUtil.c -- Test application for LZMA compression
2008-11-23 : Igor Pavlov : Public domain
Copyright (c) 2006 - 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/UefiDecompressLib.h>
#include <Library/ExtractGuidedSectionLib.h>
#include <Guid/LzmaDecompress.h>
#include "Sdk/C/Types.h"
#include "Sdk/C/7zVersion.h"
#include "Sdk/C/LzmaDec.h"
extern ISzAlloc g_Alloc;
#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8)
STATIC
UINT64
GetDecodedSizeOfBuf(
UINT8 *encodedData
)
{
UINT64 DecodedSize;
INTN Index;
/* Parse header */
DecodedSize = 0;
for (Index = LZMA_PROPS_SIZE + 7; Index >= LZMA_PROPS_SIZE; Index--)
DecodedSize = LShiftU64(DecodedSize, 8) + encodedData[Index];
return DecodedSize;
}
//
// LZMA functions and data as defined in local LzmaDecompress.h
//
STATIC CONST VOID *mSourceLastUsedWithGetInfo;
STATIC UINT32 mSizeOfLastSource;
STATIC UINT32 mDecompressedSizeForLastSource;
/**
The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
@param Source The source buffer containing the compressed data.
@param SourceSize The size of source buffer
@param DestinationSize The size of destination buffer.
@param ScratchSize The size of scratch buffer.
@retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
@retval RETURN_INVALID_PARAMETER - The source data is corrupted
**/
RETURN_STATUS
EFIAPI
LzmaUefiDecompressGetInfo (
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
OUT UINT32 *ScratchSize
)
{
UInt64 DecodedSize;
ASSERT(SourceSize >= LZMA_HEADER_SIZE);
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
mSourceLastUsedWithGetInfo = Source;
mSizeOfLastSource = SourceSize;
mDecompressedSizeForLastSource = (UInt32)DecodedSize;
*DestinationSize = mDecompressedSizeForLastSource;
*ScratchSize = 0x10;
return RETURN_SUCCESS;
}
/**
The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
@param Source - The source buffer containing the compressed data.
@param Destination - The destination buffer to store the decompressed data
@param Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
@retval RETURN_SUCCESS - Decompression is successfull
@retval RETURN_INVALID_PARAMETER - The source data is corrupted
**/
RETURN_STATUS
EFIAPI
LzmaUefiDecompress (
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
)
{
SRes lzmaResult;
ELzmaStatus status;
SizeT decodedBufSize;
SizeT encodedDataSize;
if (Source != mSourceLastUsedWithGetInfo) {
return RETURN_INVALID_PARAMETER;
}
decodedBufSize = (SizeT)mDecompressedSizeForLastSource;
encodedDataSize = (SizeT)(mSizeOfLastSource - LZMA_HEADER_SIZE);
lzmaResult = LzmaDecode(
Destination,
&decodedBufSize,
(Byte*)((UINT8*)Source + LZMA_HEADER_SIZE),
&encodedDataSize,
Source,
LZMA_PROPS_SIZE,
LZMA_FINISH_END,
&status,
&g_Alloc
);
if (lzmaResult == SZ_OK) {
return RETURN_SUCCESS;
} else {
return RETURN_INVALID_PARAMETER;
}
}

View File

@ -0,0 +1,57 @@
/** @file
LZMA Decompress Library header file
Copyright (c) 2006 - 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __LZMADECOMPRESS_H__
#define __LZMADECOMPRESS_H__
/**
The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo().
@param Source The source buffer containing the compressed data.
@param SourceSize The size of source buffer
@param DestinationSize The size of destination buffer.
@param ScratchSize The size of scratch buffer.
@retval RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved.
@retval RETURN_INVALID_PARAMETER - The source data is corrupted
**/
RETURN_STATUS
EFIAPI
LzmaUefiDecompressGetInfo (
IN CONST VOID *Source,
IN UINT32 SourceSize,
OUT UINT32 *DestinationSize,
OUT UINT32 *ScratchSize
);
/**
The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress().
@param Source - The source buffer containing the compressed data.
@param Destination - The destination buffer to store the decompressed data
@param Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data.
@retval RETURN_SUCCESS - Decompression is successfull
@retval RETURN_INVALID_PARAMETER - The source data is corrupted
**/
RETURN_STATUS
EFIAPI
LzmaUefiDecompress (
IN CONST VOID *Source,
IN OUT VOID *Destination,
IN OUT VOID *Scratch
);
#endif // __LZMADECOMPRESS_H__

View File

@ -0,0 +1,55 @@
#/** @file
# LZMA GUIDed Section Extraction Protocol Library
#
# Uefi Decompression library instance
# Copyright (c) 2006, 2009, Intel Corporation.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = LzmaPeiDecompressLib
FILE_GUID = 6725ae86-6ed1-43bd-aeec-0517c0749d70
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = BASE
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
CONSTRUCTOR = LzmaDecompressLibConstructor
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
LzmaPeiMemory.c
../LzmaDecompress.c
../Sdk/C/LzFind.c
../Sdk/C/LzmaDec.c
../GuidedSectionExtraction.c
[Packages]
MdePkg/MdePkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[Guids]
gLzmaCustomDecompressGuid
[LibraryClasses]
BaseLib
DebugLib
BaseMemoryLib
MemoryAllocationLib
ExtractGuidedSectionLib

View File

@ -0,0 +1,54 @@
/** @file
LZMA Memory Allocation for PEI
AllocatePool does not work for large blocks during PEI, so we must
use AllocatePages.
Copyright (c) 2006 - 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include "Sdk/C/Types.h"
STATIC
VOID *
SzAlloc(
void *p,
size_t size
)
{
void *np;
p = p;
if (size > EFI_PAGE_SIZE) {
np = AllocatePages(EFI_SIZE_TO_PAGES(size));
} else {
np = AllocatePool(size);
}
return np;
}
STATIC
VOID
SzFree(
void *p,
void *address
)
{
p = p;
if (address != NULL) {
FreePool(address);
}
}
ISzAlloc g_Alloc = { SzAlloc, SzFree };

View File

@ -0,0 +1,7 @@
#define MY_VER_MAJOR 4
#define MY_VER_MINOR 65
#define MY_VER_BUILD 0
#define MY_VERSION "4.65"
#define MY_DATE "2009-02-03"
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE

View File

@ -0,0 +1,69 @@
/* CpuArch.h
2008-08-05
Igor Pavlov
Public domain */
#ifndef __CPUARCH_H
#define __CPUARCH_H
/*
LITTLE_ENDIAN_UNALIGN means:
1) CPU is LITTLE_ENDIAN
2) it's allowed to make unaligned memory accesses
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
about these properties of platform.
*/
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
#define LITTLE_ENDIAN_UNALIGN
#endif
#ifdef LITTLE_ENDIAN_UNALIGN
#define GetUi16(p) (*(const UInt16 *)(p))
#define GetUi32(p) (*(const UInt32 *)(p))
#define GetUi64(p) (*(const UInt64 *)(p))
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
#else
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
#define GetUi32(p) ( \
((const Byte *)(p))[0] | \
((UInt32)((const Byte *)(p))[1] << 8) | \
((UInt32)((const Byte *)(p))[2] << 16) | \
((UInt32)((const Byte *)(p))[3] << 24))
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
#define SetUi32(p, d) { UInt32 _x_ = (d); \
((Byte *)(p))[0] = (Byte)_x_; \
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#endif
#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64)
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
#else
#define GetBe32(p) ( \
((UInt32)((const Byte *)(p))[0] << 24) | \
((UInt32)((const Byte *)(p))[1] << 16) | \
((UInt32)((const Byte *)(p))[2] << 8) | \
((const Byte *)(p))[3] )
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
#endif
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
#endif

View File

@ -0,0 +1,770 @@
/** @file
LzFind.c
Based on LZMA SDK 4.65:
LzFind.c -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain
Copyright (c) 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef EFIAPI
#include <string.h>
#endif // !EFIAPI
#include "LzFind.h"
#include "LzHash.h"
#define kEmptyHashValue 0
#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
#define kNormalizeMask (~(kNormalizeStepMin - 1))
#define kMaxHistorySize ((UInt32)3 << 30)
#define kStartMaxLen 3
static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
{
if (!p->directInput)
{
alloc->Free(alloc, p->bufferBase);
p->bufferBase = 0;
}
}
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
{
UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
if (p->directInput)
{
p->blockSize = blockSize;
return 1;
}
if (p->bufferBase == 0 || p->blockSize != blockSize)
{
LzInWindow_Free(p, alloc);
p->blockSize = blockSize;
p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
}
return (p->bufferBase != 0);
}
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
{
p->posLimit -= subValue;
p->pos -= subValue;
p->streamPos -= subValue;
}
static void MatchFinder_ReadBlock(CMatchFinder *p)
{
if (p->streamEndWasReached || p->result != SZ_OK)
return;
for (;;)
{
Byte *dest = p->buffer + (p->streamPos - p->pos);
size_t size = (p->bufferBase + p->blockSize - dest);
if (size == 0)
return;
p->result = p->stream->Read(p->stream, dest, &size);
if (p->result != SZ_OK)
return;
if (size == 0)
{
p->streamEndWasReached = 1;
return;
}
p->streamPos += (UInt32)size;
if (p->streamPos - p->pos > p->keepSizeAfter)
return;
}
}
void MatchFinder_MoveBlock(CMatchFinder *p)
{
memmove(p->bufferBase,
p->buffer - p->keepSizeBefore,
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
p->buffer = p->bufferBase + p->keepSizeBefore;
}
int MatchFinder_NeedMove(CMatchFinder *p)
{
/* if (p->streamEndWasReached) return 0; */
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
}
void MatchFinder_ReadIfRequired(CMatchFinder *p)
{
if (p->streamEndWasReached)
return;
if (p->keepSizeAfter >= p->streamPos - p->pos)
MatchFinder_ReadBlock(p);
}
static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
{
if (MatchFinder_NeedMove(p))
MatchFinder_MoveBlock(p);
MatchFinder_ReadBlock(p);
}
static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
{
p->cutValue = 32;
p->btMode = 1;
p->numHashBytes = 4;
/* p->skipModeBits = 0; */
p->directInput = 0;
p->bigHash = 0;
}
#define kCrcPoly 0xEDB88320
void MatchFinder_Construct(CMatchFinder *p)
{
UInt32 i;
p->bufferBase = 0;
p->directInput = 0;
p->hash = 0;
MatchFinder_SetDefaultSettings(p);
for (i = 0; i < 256; i++)
{
UInt32 r = i;
int j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
p->crc[i] = r;
}
}
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
{
alloc->Free(alloc, p->hash);
p->hash = 0;
}
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
{
MatchFinder_FreeThisClassMemory(p, alloc);
LzInWindow_Free(p, alloc);
}
static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
{
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
if (sizeInBytes / sizeof(CLzRef) != num)
return 0;
return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
}
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc)
{
UInt32 sizeReserv;
if (historySize > kMaxHistorySize)
{
MatchFinder_Free(p, alloc);
return 0;
}
sizeReserv = historySize >> 1;
if (historySize > ((UInt32)2 << 30))
sizeReserv = historySize >> 2;
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
if (LzInWindow_Create(p, sizeReserv, alloc))
{
UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
UInt32 hs;
p->matchMaxLen = matchMaxLen;
{
p->fixedHashSize = 0;
if (p->numHashBytes == 2)
hs = (1 << 16) - 1;
else
{
hs = historySize - 1;
hs |= (hs >> 1);
hs |= (hs >> 2);
hs |= (hs >> 4);
hs |= (hs >> 8);
hs >>= 1;
/* hs >>= p->skipModeBits; */
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
if (hs > (1 << 24))
{
if (p->numHashBytes == 3)
hs = (1 << 24) - 1;
else
hs >>= 1;
}
}
p->hashMask = hs;
hs++;
if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
hs += p->fixedHashSize;
}
{
UInt32 prevSize = p->hashSizeSum + p->numSons;
UInt32 newSize;
p->historySize = historySize;
p->hashSizeSum = hs;
p->cyclicBufferSize = newCyclicBufferSize;
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
newSize = p->hashSizeSum + p->numSons;
if (p->hash != 0 && prevSize == newSize)
return 1;
MatchFinder_FreeThisClassMemory(p, alloc);
p->hash = AllocRefs(newSize, alloc);
if (p->hash != 0)
{
p->son = p->hash + p->hashSizeSum;
return 1;
}
}
}
MatchFinder_Free(p, alloc);
return 0;
}
static void MatchFinder_SetLimits(CMatchFinder *p)
{
UInt32 limit = kMaxValForNormalize - p->pos;
UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
if (limit2 < limit)
limit = limit2;
limit2 = p->streamPos - p->pos;
if (limit2 <= p->keepSizeAfter)
{
if (limit2 > 0)
limit2 = 1;
}
else
limit2 -= p->keepSizeAfter;
if (limit2 < limit)
limit = limit2;
{
UInt32 lenLimit = p->streamPos - p->pos;
if (lenLimit > p->matchMaxLen)
lenLimit = p->matchMaxLen;
p->lenLimit = lenLimit;
}
p->posLimit = p->pos + limit;
}
void MatchFinder_Init(CMatchFinder *p)
{
UInt32 i;
for (i = 0; i < p->hashSizeSum; i++)
p->hash[i] = kEmptyHashValue;
p->cyclicBufferPos = 0;
p->buffer = p->bufferBase;
p->pos = p->streamPos = p->cyclicBufferSize;
p->result = SZ_OK;
p->streamEndWasReached = 0;
MatchFinder_ReadBlock(p);
MatchFinder_SetLimits(p);
}
static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
{
return (p->pos - p->historySize - 1) & kNormalizeMask;
}
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
{
UInt32 i;
for (i = 0; i < numItems; i++)
{
UInt32 value = items[i];
if (value <= subValue)
value = kEmptyHashValue;
else
value -= subValue;
items[i] = value;
}
}
static void MatchFinder_Normalize(CMatchFinder *p)
{
UInt32 subValue = MatchFinder_GetSubValue(p);
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
MatchFinder_ReduceOffsets(p, subValue);
}
static void MatchFinder_CheckLimits(CMatchFinder *p)
{
if (p->pos == kMaxValForNormalize)
MatchFinder_Normalize(p);
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
MatchFinder_CheckAndMoveAndRead(p);
if (p->cyclicBufferPos == p->cyclicBufferSize)
p->cyclicBufferPos = 0;
MatchFinder_SetLimits(p);
}
static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
son[_cyclicBufferPos] = curMatch;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
return distances;
{
const Byte *pb = cur - delta;
curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
{
UInt32 len = 0;
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
*distances++ = delta - 1;
if (len == lenLimit)
return distances;
}
}
}
}
}
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
return distances;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
if (maxLen < len)
{
*distances++ = maxLen = len;
*distances++ = delta - 1;
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
return distances;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
}
}
}
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
UInt32 len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
{
*ptr0 = *ptr1 = kEmptyHashValue;
return;
}
{
CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
UInt32 len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
while (++len != lenLimit)
if (pb[len] != cur[len])
break;
{
if (len == lenLimit)
{
*ptr1 = pair[0];
*ptr0 = pair[1];
return;
}
}
}
if (pb[len] < cur[len])
{
*ptr1 = curMatch;
ptr1 = pair + 1;
curMatch = *ptr1;
len1 = len;
}
else
{
*ptr0 = curMatch;
ptr0 = pair;
curMatch = *ptr0;
len0 = len;
}
}
}
}
#define MOVE_POS \
++p->cyclicBufferPos; \
p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
#define MOVE_POS_RET MOVE_POS return offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \
offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
distances + offset, maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 1)
}
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = 0;
GET_MATCHES_FOOTER(offset, 2)
}
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, delta2, maxLen, offset;
GET_MATCHES_HEADER(3)
HASH3_CALC;
delta2 = p->pos - p->hash[hash2Value];
curMatch = p->hash[kFix3HashSize + hashValue];
p->hash[hash2Value] =
p->hash[kFix3HashSize + hashValue] = p->pos;
maxLen = 2;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[0] = maxLen;
distances[1] = delta2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
GET_MATCHES_FOOTER(offset, maxLen)
}
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
GET_MATCHES_HEADER(4)
HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value];
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = delta2 - 1;
offset = 2;
}
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
{
maxLen = 3;
distances[offset + 1] = delta3 - 1;
offset += 2;
delta2 = delta3;
}
if (offset != 0)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
if (maxLen < 3)
maxLen = 3;
GET_MATCHES_FOOTER(offset, maxLen)
}
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
GET_MATCHES_HEADER(4)
HASH4_CALC;
delta2 = p->pos - p->hash[ hash2Value];
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
maxLen = 1;
offset = 0;
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
{
distances[0] = maxLen = 2;
distances[1] = delta2 - 1;
offset = 2;
}
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
{
maxLen = 3;
distances[offset + 1] = delta3 - 1;
offset += 2;
delta2 = delta3;
}
if (offset != 0)
{
for (; maxLen != lenLimit; maxLen++)
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
break;
distances[offset - 2] = maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS_RET;
}
}
if (maxLen < 3)
maxLen = 3;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
UInt32 offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances));
MOVE_POS_RET
}
static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value;
SKIP_HEADER(3)
HASH3_CALC;
curMatch = p->hash[kFix3HashSize + hashValue];
p->hash[hash2Value] =
p->hash[kFix3HashSize + hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value, hash3Value;
SKIP_HEADER(4)
HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] = p->pos;
p->hash[kFix4HashSize + hashValue] = p->pos;
SKIP_FOOTER
}
while (--num != 0);
}
static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
UInt32 hash2Value, hash3Value;
SKIP_HEADER(4)
HASH4_CALC;
curMatch = p->hash[kFix4HashSize + hashValue];
p->hash[ hash2Value] =
p->hash[kFix3HashSize + hash3Value] =
p->hash[kFix4HashSize + hashValue] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
{
do
{
SKIP_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hashValue];
p->hash[hashValue] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
MOVE_POS
}
while (--num != 0);
}
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
{
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
if (!p->btMode)
{
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
}
else if (p->numHashBytes == 2)
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
}
else if (p->numHashBytes == 3)
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
}
else
{
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
}
}

View File

@ -0,0 +1,107 @@
/* LzFind.h -- Match finder for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __LZFIND_H
#define __LZFIND_H
#include "Types.h"
typedef UInt32 CLzRef;
typedef struct _CMatchFinder
{
Byte *buffer;
UInt32 pos;
UInt32 posLimit;
UInt32 streamPos;
UInt32 lenLimit;
UInt32 cyclicBufferPos;
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
UInt32 matchMaxLen;
CLzRef *hash;
CLzRef *son;
UInt32 hashMask;
UInt32 cutValue;
Byte *bufferBase;
ISeqInStream *stream;
int streamEndWasReached;
UInt32 blockSize;
UInt32 keepSizeBefore;
UInt32 keepSizeAfter;
UInt32 numHashBytes;
int directInput;
int btMode;
/* int skipModeBits; */
int bigHash;
UInt32 historySize;
UInt32 fixedHashSize;
UInt32 hashSizeSum;
UInt32 numSons;
SRes result;
UInt32 crc[256];
} CMatchFinder;
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
int MatchFinder_NeedMove(CMatchFinder *p);
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
void MatchFinder_MoveBlock(CMatchFinder *p);
void MatchFinder_ReadIfRequired(CMatchFinder *p);
void MatchFinder_Construct(CMatchFinder *p);
/* Conditions:
historySize <= 3 GB
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
*/
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
ISzAlloc *alloc);
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
UInt32 *distances, UInt32 maxLen);
/*
Conditions:
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
*/
typedef void (*Mf_Init_Func)(void *object);
typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
typedef void (*Mf_Skip_Func)(void *object, UInt32);
typedef struct _IMatchFinder
{
Mf_Init_Func Init;
Mf_GetIndexByte_Func GetIndexByte;
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
Mf_GetMatches_Func GetMatches;
Mf_Skip_Func Skip;
} IMatchFinder;
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
void MatchFinder_Init(CMatchFinder *p);
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
#endif

View File

@ -0,0 +1,54 @@
/* LzHash.h -- HASH functions for LZ algorithms
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __LZHASH_H
#define __LZHASH_H
#define kHash2Size (1 << 10)
#define kHash3Size (1 << 16)
#define kHash4Size (1 << 20)
#define kFix3HashSize (kHash2Size)
#define kFix4HashSize (kHash2Size + kHash3Size)
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
#define HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
#define HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
#define HASH5_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
hash4Value &= (kHash4Size - 1); }
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
#define MT_HASH2_CALC \
hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
#define MT_HASH3_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
#define MT_HASH4_CALC { \
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
hash2Value = temp & (kHash2Size - 1); \
hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
/* LzmaDec.h -- LZMA Decoder
2008-10-04 : Igor Pavlov : Public domain */
#ifndef __LZMADEC_H
#define __LZMADEC_H
#include "Types.h"
/* #define _LZMA_PROB32 */
/* _LZMA_PROB32 can increase the speed on some CPUs,
but memory usage for CLzmaDec::probs will be doubled in that case */
#ifdef _LZMA_PROB32
#define CLzmaProb UInt32
#else
#define CLzmaProb UInt16
#endif
/* ---------- LZMA Properties ---------- */
#define LZMA_PROPS_SIZE 5
typedef struct _CLzmaProps
{
unsigned lc, lp, pb;
UInt32 dicSize;
} CLzmaProps;
/* LzmaProps_Decode - decodes properties
Returns:
SZ_OK
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
/* ---------- LZMA Decoder state ---------- */
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
#define LZMA_REQUIRED_INPUT_MAX 20
typedef struct
{
CLzmaProps prop;
CLzmaProb *probs;
Byte *dic;
const Byte *buf;
UInt32 range, code;
SizeT dicPos;
SizeT dicBufSize;
UInt32 processedPos;
UInt32 checkDicSize;
unsigned state;
UInt32 reps[4];
unsigned remainLen;
int needFlush;
int needInitState;
UInt32 numProbs;
unsigned tempBufSize;
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
} CLzmaDec;
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
void LzmaDec_Init(CLzmaDec *p);
/* There are two types of LZMA streams:
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
typedef enum
{
LZMA_FINISH_ANY, /* finish at any point */
LZMA_FINISH_END /* block must be finished at the end */
} ELzmaFinishMode;
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
You must use LZMA_FINISH_END, when you know that current output buffer
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
and output value of destLen will be less than output buffer size limit.
You can check status result also.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
typedef enum
{
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
} ELzmaStatus;
/* ELzmaStatus is used only as output value for function call */
/* ---------- Interfaces ---------- */
/* There are 3 levels of interfaces:
1) Dictionary Interface
2) Buffer Interface
3) One Call Interface
You can select any of these interfaces, but don't mix functions from different
groups for same object. */
/* There are two variants to allocate state for Dictionary Interface:
1) LzmaDec_Allocate / LzmaDec_Free
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
You can use variant 2, if you set dictionary buffer manually.
For Buffer Interface you must always use variant 1.
LzmaDec_Allocate* can return:
SZ_OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
*/
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
/* ---------- Dictionary Interface ---------- */
/* You can use it, if you want to eliminate the overhead for data copying from
dictionary to some other external buffer.
You must work with CLzmaDec variables directly in this interface.
STEPS:
LzmaDec_Constr()
LzmaDec_Allocate()
for (each new stream)
{
LzmaDec_Init()
while (it needs more decompression)
{
LzmaDec_DecodeToDic()
use data from CLzmaDec::dic and update CLzmaDec::dicPos
}
}
LzmaDec_Free()
*/
/* LzmaDec_DecodeToDic
The decoding to internal dictionary buffer (CLzmaDec::dic).
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
finishMode:
It has meaning only if the decoding reaches output limit (dicLimit).
LZMA_FINISH_ANY - Decode just dicLimit bytes.
LZMA_FINISH_END - Stream must be finished after dicLimit.
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_NEEDS_MORE_INPUT
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
*/
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- Buffer Interface ---------- */
/* It's zlib-like interface.
See LzmaDec_DecodeToDic description for information about STEPS and return results,
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
to work with CLzmaDec variables manually.
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
*/
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
/* ---------- One Call Interface ---------- */
/* LzmaDecode
finishMode:
It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
Returns:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
*/
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
#endif

View File

@ -0,0 +1,231 @@
/** @file
Types.h
Based on LZMA SDK 4.65:
Types.h -- Basic types
2008-11-23 : Igor Pavlov : Public domain
Copyright (c) 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
#ifdef EFIAPI
#include "UefiLzma.h"
#else
#include <stddef.h>
#ifdef _WIN32
#include <windows.h>
#endif
#endif
#define SZ_OK 0
#define SZ_ERROR_DATA 1
#define SZ_ERROR_MEM 2
#define SZ_ERROR_CRC 3
#define SZ_ERROR_UNSUPPORTED 4
#define SZ_ERROR_PARAM 5
#define SZ_ERROR_INPUT_EOF 6
#define SZ_ERROR_OUTPUT_EOF 7
#define SZ_ERROR_READ 8
#define SZ_ERROR_WRITE 9
#define SZ_ERROR_PROGRESS 10
#define SZ_ERROR_FAIL 11
#define SZ_ERROR_THREAD 12
#define SZ_ERROR_ARCHIVE 16
#define SZ_ERROR_NO_ARCHIVE 17
typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif
typedef unsigned char Byte;
typedef short Int16;
typedef unsigned short UInt16;
#ifdef _LZMA_UINT32_IS_ULONG
typedef long Int32;
typedef unsigned long UInt32;
#else
typedef int Int32;
typedef unsigned int UInt32;
#endif
#ifdef _SZ_NO_INT_64
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
NOTES: Some code will work incorrectly in that case! */
typedef long Int64;
typedef unsigned long UInt64;
#else
#if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
#else
typedef long long int Int64;
typedef unsigned long long int UInt64;
#endif
#endif
#ifdef _LZMA_NO_SYSTEM_SIZE_T
typedef UInt32 SizeT;
#else
typedef size_t SizeT;
#endif
typedef int Bool;
#define True 1
#define False 0
#ifdef _MSC_VER
#if _MSC_VER >= 1300
#define MY_NO_INLINE __declspec(noinline)
#else
#define MY_NO_INLINE
#endif
#define MY_CDECL __cdecl
#define MY_STD_CALL __stdcall
#define MY_FAST_CALL MY_NO_INLINE __fastcall
#else
#define MY_CDECL
#define MY_STD_CALL
#define MY_FAST_CALL
#endif
/* The following interfaces use first parameter as pointer to structure */
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) < input(*size)) is allowed */
} ISeqInStream;
/* it can return SZ_ERROR_INPUT_EOF */
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
typedef struct
{
size_t (*Write)(void *p, const void *buf, size_t size);
/* Returns: result - the number of actually written bytes.
(result < size) means error */
} ISeqOutStream;
typedef enum
{
SZ_SEEK_SET = 0,
SZ_SEEK_CUR = 1,
SZ_SEEK_END = 2
} ESzSeek;
typedef struct
{
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ISeekInStream;
typedef struct
{
SRes (*Look)(void *p, void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */
SRes (*Skip)(void *p, size_t offset);
/* offset must be <= output(*size) of Look */
SRes (*Read)(void *p, void *buf, size_t *size);
/* reads directly (without buffer). It's same as ISeqInStream::Read */
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
} ILookInStream;
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
/* reads via ILookInStream::Read */
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
#define LookToRead_BUF_SIZE (1 << 14)
typedef struct
{
ILookInStream s;
ISeekInStream *realStream;
size_t pos;
size_t size;
Byte buf[LookToRead_BUF_SIZE];
} CLookToRead;
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
void LookToRead_Init(CLookToRead *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToLook;
void SecToLook_CreateVTable(CSecToLook *p);
typedef struct
{
ISeqInStream s;
ILookInStream *realStream;
} CSecToRead;
void SecToRead_CreateVTable(CSecToRead *p);
typedef struct
{
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
/* Returns: result. (result != SZ_OK) means break.
Value (UInt64)(Int64)-1 for size means unknown value. */
} ICompressProgress;
typedef struct
{
void *(*Alloc)(void *p, size_t size);
void (*Free)(void *p, void *address); /* address can be 0 */
} ISzAlloc;
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
#define IAlloc_Free(p, a) (p)->Free((p), a)
#endif

View File

@ -0,0 +1,236 @@
HISTORY of the LZMA SDK
-----------------------
4.65 2009-02-03
-------------------------
- Some minor fixes
4.63 2008-12-31
-------------------------
- Some minor fixes
4.61 beta 2008-11-23
-------------------------
- The bug in ANSI-C LZMA Decoder was fixed:
If encoded stream was corrupted, decoder could access memory
outside of allocated range.
- Some changes in ANSI-C 7z Decoder interfaces.
- LZMA SDK is placed in the public domain.
4.60 beta 2008-08-19
-------------------------
- Some minor fixes.
4.59 beta 2008-08-13
-------------------------
- The bug was fixed:
LZMA Encoder in fast compression mode could access memory outside of
allocated range in some rare cases.
4.58 beta 2008-05-05
-------------------------
- ANSI-C LZMA Decoder was rewritten for speed optimizations.
- ANSI-C LZMA Encoder was included to LZMA SDK.
- C++ LZMA code now is just wrapper over ANSI-C code.
4.57 2007-12-12
-------------------------
- Speed optimizations in Ñ++ LZMA Decoder.
- Small changes for more compatibility with some C/C++ compilers.
4.49 beta 2007-07-05
-------------------------
- .7z ANSI-C Decoder:
- now it supports BCJ and BCJ2 filters
- now it supports files larger than 4 GB.
- now it supports "Last Write Time" field for files.
- C++ code for .7z archives compressing/decompressing from 7-zip
was included to LZMA SDK.
4.43 2006-06-04
-------------------------
- Small changes for more compatibility with some C/C++ compilers.
4.42 2006-05-15
-------------------------
- Small changes in .h files in ANSI-C version.
4.39 beta 2006-04-14
-------------------------
- The bug in versions 4.33b:4.38b was fixed:
C++ version of LZMA encoder could not correctly compress
files larger than 2 GB with HC4 match finder (-mfhc4).
4.37 beta 2005-04-06
-------------------------
- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined.
4.35 beta 2005-03-02
-------------------------
- The bug was fixed in C++ version of LZMA Decoder:
If encoded stream was corrupted, decoder could access memory
outside of allocated range.
4.34 beta 2006-02-27
-------------------------
- Compressing speed and memory requirements for compressing were increased
- LZMA now can use only these match finders: HC4, BT2, BT3, BT4
4.32 2005-12-09
-------------------------
- Java version of LZMA SDK was included
4.30 2005-11-20
-------------------------
- Compression ratio was improved in -a2 mode
- Speed optimizations for compressing in -a2 mode
- -fb switch now supports values up to 273
- The bug in 7z_C (7zIn.c) was fixed:
It used Alloc/Free functions from different memory pools.
So if program used two memory pools, it worked incorrectly.
- 7z_C: .7z format supporting was improved
- LZMA# SDK (C#.NET version) was included
4.27 (Updated) 2005-09-21
-------------------------
- Some GUIDs/interfaces in C++ were changed.
IStream.h:
ISequentialInStream::Read now works as old ReadPart
ISequentialOutStream::Write now works as old WritePart
4.27 2005-08-07
-------------------------
- The bug in LzmaDecodeSize.c was fixed:
if _LZMA_IN_CB and _LZMA_OUT_READ were defined,
decompressing worked incorrectly.
4.26 2005-08-05
-------------------------
- Fixes in 7z_C code and LzmaTest.c:
previous versions could work incorrectly,
if malloc(0) returns 0
4.23 2005-06-29
-------------------------
- Small fixes in C++ code
4.22 2005-06-10
-------------------------
- Small fixes
4.21 2005-06-08
-------------------------
- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed
- New additional version of ANSI-C LZMA Decoder with zlib-like interface:
- LzmaStateDecode.h
- LzmaStateDecode.c
- LzmaStateTest.c
- ANSI-C LZMA Decoder now can decompress files larger than 4 GB
4.17 2005-04-18
-------------------------
- New example for RAM->RAM compressing/decompressing:
LZMA + BCJ (filter for x86 code):
- LzmaRam.h
- LzmaRam.cpp
- LzmaRamDecode.h
- LzmaRamDecode.c
- -f86 switch for lzma.exe
4.16 2005-03-29
-------------------------
- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder):
If _LZMA_OUT_READ was defined, and if encoded stream was corrupted,
decoder could access memory outside of allocated range.
- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster).
Old version of LZMA Decoder now is in file LzmaDecodeSize.c.
LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c
- Small speed optimization in LZMA C++ code
- filter for SPARC's code was added
- Simplified version of .7z ANSI-C Decoder was included
4.06 2004-09-05
-------------------------
- The bug in v4.05 was fixed:
LZMA-Encoder didn't release output stream in some cases.
4.05 2004-08-25
-------------------------
- Source code of filters for x86, IA-64, ARM, ARM-Thumb
and PowerPC code was included to SDK
- Some internal minor changes
4.04 2004-07-28
-------------------------
- More compatibility with some C++ compilers
4.03 2004-06-18
-------------------------
- "Benchmark" command was added. It measures compressing
and decompressing speed and shows rating values.
Also it checks hardware errors.
4.02 2004-06-10
-------------------------
- C++ LZMA Encoder/Decoder code now is more portable
and it can be compiled by GCC on Linux.
4.01 2004-02-15
-------------------------
- Some detection of data corruption was enabled.
LzmaDecode.c / RangeDecoderReadByte
.....
{
rd->ExtraBytes = 1;
return 0xFF;
}
4.00 2004-02-13
-------------------------
- Original version of LZMA SDK
HISTORY of the LZMA
-------------------
2001-2008: Improvements to LZMA compressing/decompressing code,
keeping compatibility with original LZMA format
1996-2001: Development of LZMA compression format
Some milestones:
2001-08-30: LZMA compression was added to 7-Zip
1999-01-02: First version of 7-Zip was released
End of document

View File

@ -0,0 +1,594 @@
LZMA SDK 4.65
-------------
LZMA SDK provides the documentation, samples, header files, libraries,
and tools you need to develop applications that use LZMA compression.
LZMA is default and general compression method of 7z format
in 7-Zip compression program (www.7-zip.org). LZMA provides high
compression ratio and very fast decompression.
LZMA is an improved version of famous LZ77 compression algorithm.
It was improved in way of maximum increasing of compression ratio,
keeping high decompression speed and low memory requirements for
decompressing.
LICENSE
-------
LZMA SDK is written and placed in the public domain by Igor Pavlov.
LZMA SDK Contents
-----------------
LZMA SDK includes:
- ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
- Compiled file->file LZMA compressing/decompressing program for Windows system
UNIX/Linux version
------------------
To compile C++ version of file->file LZMA encoding, go to directory
C++/7zip/Compress/LZMA_Alone
and call make to recompile it:
make -f makefile.gcc clean all
In some UNIX/Linux versions you must compile LZMA with static libraries.
To compile with static libraries, you can use
LIB = -lm -static
Files
---------------------
lzma.txt - LZMA SDK description (this file)
7zFormat.txt - 7z Format description
7zC.txt - 7z ANSI-C Decoder description
methods.txt - Compression method IDs for .7z
lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
history.txt - history of the LZMA SDK
Source code structure
---------------------
C/ - C files
7zCrc*.* - CRC code
Alloc.* - Memory allocation functions
Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
LzFind.* - Match finder for LZ (LZMA) encoders
LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
LzHash.h - Additional file for LZ match finder
LzmaDec.* - LZMA decoding
LzmaEnc.* - LZMA encoding
LzmaLib.* - LZMA Library for DLL calling
Types.h - Basic types for another .c files
Threads.* - The code for multithreading.
LzmaLib - LZMA Library (.DLL for Windows)
LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
Archive - files related to archiving
7z - 7z ANSI-C Decoder
CPP/ -- CPP files
Common - common files for C++ projects
Windows - common files for Windows related code
7zip - files related to 7-Zip Project
Common - common files for 7-Zip
Compress - files related to compression/decompression
Copy - Copy coder
RangeCoder - Range Coder (special code of compression/decompression)
LZMA - LZMA compression/decompression on C++
LZMA_Alone - file->file LZMA compression/decompression
Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
Archive - files related to archiving
Common - common files for archive handling
7z - 7z C++ Encoder/Decoder
Bundles - Modules that are bundles of other modules
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
UI - User Interface files
Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
Common - Common UI files
Console - Code for console archiver
CS/ - C# files
7zip
Common - some common files for 7-Zip
Compress - files related to compression/decompression
LZ - files related to LZ (Lempel-Ziv) compression algorithm
LZMA - LZMA compression/decompression
LzmaAlone - file->file LZMA compression/decompression
RangeCoder - Range Coder (special code of compression/decompression)
Java/ - Java files
SevenZip
Compression - files related to compression/decompression
LZ - files related to LZ (Lempel-Ziv) compression algorithm
LZMA - LZMA compression/decompression
RangeCoder - Range Coder (special code of compression/decompression)
C/C++ source code of LZMA SDK is part of 7-Zip project.
7-Zip source code can be downloaded from 7-Zip's SourceForge page:
http://sourceforge.net/projects/sevenzip/
LZMA features
-------------
- Variable dictionary size (up to 1 GB)
- Estimated compressing speed: about 2 MB/s on 2 GHz CPU
- Estimated decompressing speed:
- 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
- 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
- Small memory requirements for decompressing (16 KB + DictionarySize)
- Small code size for decompressing: 5-8 KB
LZMA decoder uses only integer operations and can be
implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
Some critical operations that affect the speed of LZMA decompression:
1) 32*16 bit integer multiply
2) Misspredicted branches (penalty mostly depends from pipeline length)
3) 32-bit shift and arithmetic operations
The speed of LZMA decompressing mostly depends from CPU speed.
Memory speed has no big meaning. But if your CPU has small data cache,
overall weight of memory speed will slightly increase.
How To Use
----------
Using LZMA encoder/decoder executable
--------------------------------------
Usage: LZMA <e|d> inputFile outputFile [<switches>...]
e: encode file
d: decode file
b: Benchmark. There are two tests: compressing and decompressing
with LZMA method. Benchmark shows rating in MIPS (million
instructions per second). Rating value is calculated from
measured speed and it is normalized with Intel's Core 2 results.
Also Benchmark checks possible hardware errors (RAM
errors in most cases). Benchmark uses these settings:
(-a1, -d21, -fb32, -mfbt4). You can change only -d parameter.
Also you can change the number of iterations. Example for 30 iterations:
LZMA b 30
Default number of iterations is 10.
<Switches>
-a{N}: set compression mode 0 = fast, 1 = normal
default: 1 (normal)
d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB)
The maximum value for dictionary size is 1 GB = 2^30 bytes.
Dictionary size is calculated as DictionarySize = 2^N bytes.
For decompressing file compressed by LZMA method with dictionary
size D = 2^N you need about D bytes of memory (RAM).
-fb{N}: set number of fast bytes - [5, 273], default: 128
Usually big number gives a little bit better compression ratio
and slower compression process.
-lc{N}: set number of literal context bits - [0, 8], default: 3
Sometimes lc=4 gives gain for big files.
-lp{N}: set number of literal pos bits - [0, 4], default: 0
lp switch is intended for periodical data when period is
equal 2^N. For example, for 32-bit (4 bytes)
periodical data you can use lp=2. Often it's better to set lc0,
if you change lp switch.
-pb{N}: set number of pos bits - [0, 4], default: 2
pb switch is intended for periodical data
when period is equal 2^N.
-mf{MF_ID}: set Match Finder. Default: bt4.
Algorithms from hc* group doesn't provide good compression
ratio, but they often works pretty fast in combination with
fast mode (-a0).
Memory requirements depend from dictionary size
(parameter "d" in table below).
MF_ID Memory Description
bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing.
bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing.
bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing.
hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing.
-eos: write End Of Stream marker. By default LZMA doesn't write
eos marker, since LZMA decoder knows uncompressed size
stored in .lzma file header.
-si: Read data from stdin (it will write End Of Stream marker).
-so: Write data to stdout
Examples:
1) LZMA e file.bin file.lzma -d16 -lc0
compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)
and 0 literal context bits. -lc0 allows to reduce memory requirements
for decompression.
2) LZMA e file.bin file.lzma -lc0 -lp2
compresses file.bin to file.lzma with settings suitable
for 32-bit periodical data (for example, ARM or MIPS code).
3) LZMA d file.lzma file.bin
decompresses file.lzma to file.bin.
Compression ratio hints
-----------------------
Recommendations
---------------
To increase the compression ratio for LZMA compressing it's desirable
to have aligned data (if it's possible) and also it's desirable to locate
data in such order, where code is grouped in one place and data is
grouped in other place (it's better than such mixing: code, data, code,
data, ...).
Filters
-------
You can increase the compression ratio for some data types, using
special filters before compressing. For example, it's possible to
increase the compression ratio on 5-10% for code for those CPU ISAs:
x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
You can find C source code of such filters in C/Bra*.* files
You can check the compression ratio gain of these filters with such
7-Zip commands (example for ARM code):
No filter:
7z a a1.7z a.bin -m0=lzma
With filter for little-endian ARM code:
7z a a2.7z a.bin -m0=arm -m1=lzma
It works in such manner:
Compressing = Filter_encoding + LZMA_encoding
Decompressing = LZMA_decoding + Filter_decoding
Compressing and decompressing speed of such filters is very high,
so it will not increase decompressing time too much.
Moreover, it reduces decompression time for LZMA_decoding,
since compression ratio with filtering is higher.
These filters convert CALL (calling procedure) instructions
from relative offsets to absolute addresses, so such data becomes more
compressible.
For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
LZMA compressed file format
---------------------------
Offset Size Description
0 1 Special LZMA properties (lc,lp, pb in encoded form)
1 4 Dictionary size (little endian)
5 8 Uncompressed size (little endian). -1 means unknown size
13 Compressed data
ANSI-C LZMA Decoder
~~~~~~~~~~~~~~~~~~~
Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
If you want to use old interfaces you can download previous version of LZMA SDK
from sourceforge.net site.
To use ANSI-C LZMA Decoder you need the following files:
1) LzmaDec.h + LzmaDec.c + Types.h
LzmaUtil/LzmaUtil.c is example application that uses these files.
Memory requirements for LZMA decoding
-------------------------------------
Stack usage of LZMA decoding function for local variables is not
larger than 200-400 bytes.
LZMA Decoder uses dictionary buffer and internal state structure.
Internal state structure consumes
state_size = (4 + (1.5 << (lc + lp))) KB
by default (lc=3, lp=0), state_size = 16 KB.
How To decompress data
----------------------
LZMA Decoder (ANSI-C version) now supports 2 interfaces:
1) Single-call Decompressing
2) Multi-call State Decompressing (zlib-like interface)
You must use external allocator:
Example:
void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
void SzFree(void *p, void *address) { p = p; free(address); }
ISzAlloc alloc = { SzAlloc, SzFree };
You can use p = p; operator to disable compiler warnings.
Single-call Decompressing
-------------------------
When to use: RAM->RAM decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Compile defines: no defines
Memory Requirements:
- Input buffer: compressed size
- Output buffer: uncompressed size
- LZMA Internal Structures: state_size (16 KB for default settings)
Interface:
int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
ELzmaStatus *status, ISzAlloc *alloc);
In:
dest - output data
destLen - output data size
src - input data
srcLen - input data size
propData - LZMA properties (5 bytes)
propSize - size of propData buffer (5 bytes)
finishMode - It has meaning only if the decoding reaches output limit (*destLen).
LZMA_FINISH_ANY - Decode just destLen bytes.
LZMA_FINISH_END - Stream must be finished after (*destLen).
You can use LZMA_FINISH_END, when you know that
current output buffer covers last bytes of stream.
alloc - Memory allocator.
Out:
destLen - processed output size
srcLen - processed input size
Output:
SZ_OK
status:
LZMA_STATUS_FINISHED_WITH_MARK
LZMA_STATUS_NOT_FINISHED
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
SZ_ERROR_DATA - Data error
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_UNSUPPORTED - Unsupported properties
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
and output value of destLen will be less than output buffer size limit.
You can use multiple checks to test data integrity after full decompression:
1) Check Result and "status" variable.
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
You must use correct finish mode in that case. */
Multi-call State Decompressing (zlib-like interface)
----------------------------------------------------
When to use: file->file decompressing
Compile files: LzmaDec.h + LzmaDec.c + Types.h
Memory Requirements:
- Buffer for input stream: any size (for example, 16 KB)
- Buffer for output stream: any size (for example, 16 KB)
- LZMA Internal Structures: state_size (16 KB for default settings)
- LZMA dictionary (dictionary size is encoded in LZMA properties header)
1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
unsigned char header[LZMA_PROPS_SIZE + 8];
ReadFile(inFile, header, sizeof(header)
2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
CLzmaDec state;
LzmaDec_Constr(&state);
res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
if (res != SZ_OK)
return res;
3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
LzmaDec_Init(&state);
for (;;)
{
...
int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
...
}
4) Free all allocated structures
LzmaDec_Free(&state, &g_Alloc);
For full code example, look at C/LzmaUtil/LzmaUtil.c code.
How To compress data
--------------------
Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
Memory Requirements:
- (dictSize * 11.5 + 6 MB) + state_size
Lzma Encoder can use two memory allocators:
1) alloc - for small arrays.
2) allocBig - for big arrays.
For example, you can use Large RAM Pages (2 MB) in allocBig allocator for
better compression speed. Note that Windows has bad implementation for
Large RAM Pages.
It's OK to use same allocator for alloc and allocBig.
Single-call Compression with callbacks
--------------------------------------
Check C/LzmaUtil/LzmaUtil.c as example,
When to use: file->file decompressing
1) you must implement callback structures for interfaces:
ISeqInStream
ISeqOutStream
ICompressProgress
ISzAlloc
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
CFileSeqInStream inStream;
CFileSeqOutStream outStream;
inStream.funcTable.Read = MyRead;
inStream.file = inFile;
outStream.funcTable.Write = MyWrite;
outStream.file = outFile;
2) Create CLzmaEncHandle object;
CLzmaEncHandle enc;
enc = LzmaEnc_Create(&g_Alloc);
if (enc == 0)
return SZ_ERROR_MEM;
3) initialize CLzmaEncProps properties;
LzmaEncProps_Init(&props);
Then you can change some properties in that structure.
4) Send LZMA properties to LZMA Encoder
res = LzmaEnc_SetProps(enc, &props);
5) Write encoded properties to header
Byte header[LZMA_PROPS_SIZE + 8];
size_t headerSize = LZMA_PROPS_SIZE;
UInt64 fileSize;
int i;
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
fileSize = MyGetFileLength(inFile);
for (i = 0; i < 8; i++)
header[headerSize++] = (Byte)(fileSize >> (8 * i));
MyWriteFileAndCheck(outFile, header, headerSize)
6) Call encoding function:
res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
NULL, &g_Alloc, &g_Alloc);
7) Destroy LZMA Encoder Object
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
If callback function return some error code, LzmaEnc_Encode also returns that code.
Single-call RAM->RAM Compression
--------------------------------
Single-call RAM->RAM Compression is similar to Compression with callbacks,
but you provide pointers to buffers instead of pointers to stream callbacks:
HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
Return code:
SZ_OK - OK
SZ_ERROR_MEM - Memory allocation error
SZ_ERROR_PARAM - Incorrect paramater
SZ_ERROR_OUTPUT_EOF - output buffer overflow
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
LZMA Defines
------------
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for
some structures will be doubled in that case.
_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit.
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
C++ LZMA Encoder/Decoder
~~~~~~~~~~~~~~~~~~~~~~~~
C++ LZMA code use COM-like interfaces. So if you want to use it,
you can study basics of COM/OLE.
C++ LZMA code is just wrapper over ANSI-C code.
C++ Notes
~~~~~~~~~~~~~~~~~~~~~~~~
If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
you must check that you correctly work with "new" operator.
7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
operator new(size_t size)
{
void *p = ::malloc(size);
if (p == 0)
throw CNewException();
return p;
}
If you use MSCV that throws exception for "new" operator, you can compile without
"NewHandler.cpp". So standard exception will be used. Actually some code of
7-Zip catches any exception in internal code and converts it to HRESULT code.
So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
---
http://www.7-zip.org
http://www.7-zip.org/sdk.html
http://www.7-zip.org/support.html

View File

@ -0,0 +1,41 @@
/** @file
LZMA UEFI Library header file
Allows LZMA code to build under UEFI (edk2) build environment
Copyright (c) 2009, Intel Corporation<BR>
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#ifndef __UEFILZMA_H__
#define __UEFILZMA_H__
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#ifdef _WIN32
#undef _WIN32
#endif
#if !defined(_WIN64) || defined(__GNUC__)
typedef unsigned int size_t;
#endif
#ifdef _WIN64
#undef _WIN64
#endif
typedef int ptrdiff_t;
#define memcpy CopyMem
#define memmove CopyMem
#endif // __UEFILZMA_H__