mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
9.04 beta
This commit is contained in:
committed by
Kornel Lesiński
parent
8874e4fbc9
commit
829409452d
10
C/7zBuf.h
10
C/7zBuf.h
@@ -1,11 +1,15 @@
|
|||||||
/* 7zBuf.h -- Byte Buffer
|
/* 7zBuf.h -- Byte Buffer
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_BUF_H
|
#ifndef __7Z_BUF_H
|
||||||
#define __7Z_BUF_H
|
#define __7Z_BUF_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte *data;
|
Byte *data;
|
||||||
@@ -28,4 +32,8 @@ void DynBuf_SeekToBeg(CDynBuf *p);
|
|||||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
||||||
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
C/7zCrc.h
12
C/7zCrc.h
@@ -1,7 +1,5 @@
|
|||||||
/* 7zCrc.h -- CRC32 calculation
|
/* 7zCrc.h -- CRC32 calculation
|
||||||
2008-03-13
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __7Z_CRC_H
|
#ifndef __7Z_CRC_H
|
||||||
#define __7Z_CRC_H
|
#define __7Z_CRC_H
|
||||||
@@ -10,6 +8,10 @@ Public domain */
|
|||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
extern UInt32 g_CrcTable[];
|
extern UInt32 g_CrcTable[];
|
||||||
|
|
||||||
void MY_FAST_CALL CrcGenerateTable(void);
|
void MY_FAST_CALL CrcGenerateTable(void);
|
||||||
@@ -21,4 +23,8 @@ void MY_FAST_CALL CrcGenerateTable(void);
|
|||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
C/7zFile.h
10
C/7zFile.h
@@ -1,5 +1,5 @@
|
|||||||
/* 7zFile.h -- File IO
|
/* 7zFile.h -- File IO
|
||||||
2008-11-22 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_FILE_H
|
#ifndef __7Z_FILE_H
|
||||||
#define __7Z_FILE_H
|
#define __7Z_FILE_H
|
||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* ---------- File ---------- */
|
/* ---------- File ---------- */
|
||||||
|
|
||||||
@@ -71,4 +75,8 @@ typedef struct
|
|||||||
|
|
||||||
void FileOutStream_CreateVTable(CFileOutStream *p);
|
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#define MY_VER_MAJOR 4
|
#define MY_VER_MAJOR 9
|
||||||
#define MY_VER_MINOR 65
|
#define MY_VER_MINOR 04
|
||||||
#define MY_VER_BUILD 0
|
#define MY_VER_BUILD 0
|
||||||
#define MY_VERSION "4.65"
|
#define MY_VERSION "9.04 beta"
|
||||||
#define MY_DATE "2009-02-03"
|
#define MY_DATE "2009-05-30"
|
||||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
||||||
|
|||||||
12
C/Aes.h
12
C/Aes.h
@@ -1,13 +1,15 @@
|
|||||||
/* Aes.h -- AES encryption / decryption
|
/* Aes.h -- AES encryption / decryption
|
||||||
2008-08-05
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __AES_H
|
#ifndef __AES_H
|
||||||
#define __AES_H
|
#define __AES_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define AES_BLOCK_SIZE 16
|
#define AES_BLOCK_SIZE 16
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -45,4 +47,8 @@ void AesCbc_Init(CAesCbc *p, const Byte *iv); /* iv size is AES_BLOCK_SIZE */
|
|||||||
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size);
|
SizeT AesCbc_Encode(CAesCbc *p, Byte *data, SizeT size);
|
||||||
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size);
|
SizeT AesCbc_Decode(CAesCbc *p, Byte *data, SizeT size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
C/Alloc.h
12
C/Alloc.h
@@ -1,13 +1,15 @@
|
|||||||
/* Alloc.h -- Memory allocation functions
|
/* Alloc.h -- Memory allocation functions
|
||||||
2008-03-13
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __COMMON_ALLOC_H
|
#ifndef __COMMON_ALLOC_H
|
||||||
#define __COMMON_ALLOC_H
|
#define __COMMON_ALLOC_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
void *MyAlloc(size_t size);
|
void *MyAlloc(size_t size);
|
||||||
void MyFree(void *address);
|
void MyFree(void *address);
|
||||||
|
|
||||||
@@ -29,4 +31,8 @@ void BigFree(void *address);
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -132,6 +132,14 @@ SOURCE=..\..\Bra86.c
|
|||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\..\Lzma2Dec.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\LzmaDec.c
|
SOURCE=..\..\LzmaDec.c
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|||||||
@@ -1,15 +1,23 @@
|
|||||||
/* 7zAlloc.h -- Allocation functions
|
/* 7zAlloc.h -- Allocation functions
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_ALLOC_H
|
#ifndef __7Z_ALLOC_H
|
||||||
#define __7Z_ALLOC_H
|
#define __7Z_ALLOC_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
void *SzAlloc(void *p, size_t size);
|
void *SzAlloc(void *p, size_t size);
|
||||||
void SzFree(void *p, void *address);
|
void SzFree(void *p, void *address);
|
||||||
|
|
||||||
void *SzAllocTemp(void *p, size_t size);
|
void *SzAllocTemp(void *p, size_t size);
|
||||||
void SzFreeTemp(void *p, void *address);
|
void SzFreeTemp(void *p, void *address);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,14 +1,17 @@
|
|||||||
/* 7zDecode.c -- Decoding from 7z folder
|
/* 7zDecode.c -- Decoding from 7z folder
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "../../Bcj2.h"
|
#include "../../Bcj2.h"
|
||||||
#include "../../Bra.h"
|
#include "../../Bra.h"
|
||||||
#include "../../LzmaDec.h"
|
#include "../../LzmaDec.h"
|
||||||
|
#include "../../Lzma2Dec.h"
|
||||||
|
|
||||||
#include "7zDecode.h"
|
#include "7zDecode.h"
|
||||||
|
|
||||||
#define k_Copy 0
|
#define k_Copy 0
|
||||||
|
#define k_LZMA2 0x21
|
||||||
#define k_LZMA 0x30101
|
#define k_LZMA 0x30101
|
||||||
#define k_BCJ 0x03030103
|
#define k_BCJ 0x03030103
|
||||||
#define k_BCJ2 0x0303011B
|
#define k_BCJ2 0x0303011B
|
||||||
@@ -61,6 +64,55 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||||
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
|
{
|
||||||
|
CLzma2Dec state;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
Lzma2Dec_Construct(&state);
|
||||||
|
if (coder->Props.size != 1)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
|
||||||
|
state.decoder.dic = outBuffer;
|
||||||
|
state.decoder.dicBufSize = outSize;
|
||||||
|
Lzma2Dec_Init(&state);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Byte *inBuf = NULL;
|
||||||
|
size_t lookahead = (1 << 18);
|
||||||
|
if (lookahead > inSize)
|
||||||
|
lookahead = (size_t)inSize;
|
||||||
|
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
{
|
||||||
|
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||||
|
ELzmaStatus status;
|
||||||
|
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||||
|
lookahead -= inProcessed;
|
||||||
|
inSize -= inProcessed;
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||||
|
{
|
||||||
|
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||||
|
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||||
|
res = SZ_ERROR_DATA;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
res = inStream->Skip((void *)inStream, inProcessed);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||||
{
|
{
|
||||||
while (inSize > 0)
|
while (inSize > 0)
|
||||||
@@ -80,7 +132,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
|
|||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA && (m) != k_LZMA2)
|
||||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
||||||
@@ -152,7 +204,7 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
|
|||||||
{
|
{
|
||||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA || coder->MethodID == k_LZMA2)
|
||||||
{
|
{
|
||||||
UInt32 si = 0;
|
UInt32 si = 0;
|
||||||
UInt64 offset;
|
UInt64 offset;
|
||||||
@@ -196,10 +248,14 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
|
|||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||||
}
|
}
|
||||||
else
|
else if (coder->MethodID == k_LZMA)
|
||||||
{
|
{
|
||||||
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (coder->MethodID == k_BCJ)
|
else if (coder->MethodID == k_BCJ)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
/* 7zDecode.h -- Decoding from 7z folder
|
/* 7zDecode.h -- Decoding from 7z folder
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_DECODE_H
|
#ifndef __7Z_DECODE_H
|
||||||
#define __7Z_DECODE_H
|
#define __7Z_DECODE_H
|
||||||
|
|
||||||
#include "7zItem.h"
|
#include "7zItem.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||||
ILookInStream *stream, UInt64 startPos,
|
ILookInStream *stream, UInt64 startPos,
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* 7zExtract.h -- Extracting from 7z archive
|
/* 7zExtract.h -- Extracting from 7z archive
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_EXTRACT_H
|
#ifndef __7Z_EXTRACT_H
|
||||||
#define __7Z_EXTRACT_H
|
#define __7Z_EXTRACT_H
|
||||||
|
|
||||||
#include "7zIn.h"
|
#include "7zIn.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzExtract extracts file from archive
|
SzExtract extracts file from archive
|
||||||
|
|
||||||
@@ -38,4 +42,8 @@ SRes SzAr_Extract(
|
|||||||
ISzAlloc *allocMain,
|
ISzAlloc *allocMain,
|
||||||
ISzAlloc *allocTemp);
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* 7zHeader.h -- 7z Headers
|
/* 7zHeader.h -- 7z Headers
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_HEADER_H
|
#ifndef __7Z_HEADER_H
|
||||||
#define __7Z_HEADER_H
|
#define __7Z_HEADER_H
|
||||||
|
|
||||||
#include "../../Types.h"
|
#include "../../Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define k7zSignatureSize 6
|
#define k7zSignatureSize 6
|
||||||
extern Byte k7zSignature[k7zSignatureSize];
|
extern Byte k7zSignature[k7zSignatureSize];
|
||||||
|
|
||||||
@@ -54,4 +58,8 @@ enum EIdEnum
|
|||||||
k7zIdDummy
|
k7zIdDummy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* 7zIn.h -- 7z Input functions
|
/* 7zIn.h -- 7z Input
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_IN_H
|
#ifndef __7Z_IN_H
|
||||||
#define __7Z_IN_H
|
#define __7Z_IN_H
|
||||||
@@ -7,6 +7,10 @@
|
|||||||
#include "7zHeader.h"
|
#include "7zHeader.h"
|
||||||
#include "7zItem.h"
|
#include "7zItem.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CSzAr db;
|
CSzAr db;
|
||||||
@@ -38,4 +42,8 @@ SZ_ERROR_FAIL
|
|||||||
|
|
||||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
/* 7zItem.h -- 7z Items
|
/* 7zItem.h -- 7z Items
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_ITEM_H
|
#ifndef __7Z_ITEM_H
|
||||||
#define __7Z_ITEM_H
|
#define __7Z_ITEM_H
|
||||||
|
|
||||||
#include "../../7zBuf.h"
|
#include "../../7zBuf.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 NumInStreams;
|
UInt32 NumInStreams;
|
||||||
@@ -81,4 +85,8 @@ typedef struct
|
|||||||
void SzAr_Init(CSzAr *p);
|
void SzAr_Init(CSzAr *p);
|
||||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* 7zMain.c - Test application for 7z Decoder
|
/* 7zMain.c - Test application for 7z Decoder
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-04-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -13,6 +13,37 @@
|
|||||||
#include "7zExtract.h"
|
#include "7zExtract.h"
|
||||||
#include "7zIn.h"
|
#include "7zIn.h"
|
||||||
|
|
||||||
|
#ifndef USE_WINDOWS_FILE
|
||||||
|
/* for mkdir */
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <direct.h>
|
||||||
|
#else
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define CHAR_PATH_SEPARATOR '\\'
|
||||||
|
#else
|
||||||
|
#define CHAR_PATH_SEPARATOR '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static WRes MyCreateDir(const char *name)
|
||||||
|
{
|
||||||
|
#ifdef USE_WINDOWS_FILE
|
||||||
|
return CreateDirectoryA(name, NULL) ? 0 : GetLastError();
|
||||||
|
#else
|
||||||
|
#ifdef _WIN32
|
||||||
|
return _mkdir(name)
|
||||||
|
#else
|
||||||
|
return mkdir(name, 0777)
|
||||||
|
#endif
|
||||||
|
== 0 ? 0 : errno;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ConvertNumberToString(UInt64 value, char *s)
|
static void ConvertNumberToString(UInt64 value, char *s)
|
||||||
{
|
{
|
||||||
char temp[32];
|
char temp[32];
|
||||||
@@ -33,7 +64,7 @@ static void ConvertNumberToString(UInt64 value, char *s)
|
|||||||
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
#define PERIOD_100 (PERIOD_4 * 25 - 1)
|
||||||
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
#define PERIOD_400 (PERIOD_100 * 4 + 1)
|
||||||
|
|
||||||
static void ConvertFileTimeToString(CNtfsFileTime *ft, char *s)
|
static void ConvertFileTimeToString(const CNtfsFileTime *ft, char *s)
|
||||||
{
|
{
|
||||||
unsigned year, mon, day, hour, min, sec;
|
unsigned year, mon, day, hour, min, sec;
|
||||||
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
|
UInt64 v64 = ft->Low | ((UInt64)ft->High << 32);
|
||||||
@@ -97,16 +128,19 @@ int MY_CDECL main(int numargs, char *args[])
|
|||||||
SRes res;
|
SRes res;
|
||||||
ISzAlloc allocImp;
|
ISzAlloc allocImp;
|
||||||
ISzAlloc allocTempImp;
|
ISzAlloc allocTempImp;
|
||||||
|
char *temp = NULL;
|
||||||
|
size_t tempSize = 0;
|
||||||
|
|
||||||
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n");
|
printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");
|
||||||
if (numargs == 1)
|
if (numargs == 1)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"\nUsage: 7zDec <command> <archive_name>\n\n"
|
"Usage: 7zDec <command> <archive_name>\n\n"
|
||||||
"<Commands>\n"
|
"<Commands>\n"
|
||||||
" e: Extract files from archive\n"
|
" e: Extract files from archive (without using directory names)\n"
|
||||||
" l: List contents of archive\n"
|
" l: List contents of archive\n"
|
||||||
" t: Test integrity of archive\n");
|
" t: Test integrity of archive\n"
|
||||||
|
" x: eXtract files with full paths\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (numargs < 3)
|
if (numargs < 3)
|
||||||
@@ -141,17 +175,18 @@ int MY_CDECL main(int numargs, char *args[])
|
|||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
{
|
{
|
||||||
char *command = args[1];
|
char *command = args[1];
|
||||||
int listCommand = 0, testCommand = 0, extractCommand = 0;
|
int listCommand = 0, testCommand = 0, extractCommand = 0, fullPaths = 0;
|
||||||
if (strcmp(command, "l") == 0) listCommand = 1;
|
if (strcmp(command, "l") == 0) listCommand = 1;
|
||||||
else if (strcmp(command, "t") == 0) testCommand = 1;
|
else if (strcmp(command, "t") == 0) testCommand = 1;
|
||||||
else if (strcmp(command, "e") == 0) extractCommand = 1;
|
else if (strcmp(command, "e") == 0) extractCommand = 1;
|
||||||
|
else if (strcmp(command, "x") == 0) { extractCommand = 1; fullPaths = 1; }
|
||||||
|
|
||||||
if (listCommand)
|
if (listCommand)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < db.db.NumFiles; i++)
|
for (i = 0; i < db.db.NumFiles; i++)
|
||||||
{
|
{
|
||||||
CSzFileItem *f = db.db.Files + i;
|
const CSzFileItem *f = db.db.Files + i;
|
||||||
char s[32], t[32];
|
char s[32], t[32];
|
||||||
ConvertNumberToString(f->Size, s);
|
ConvertNumberToString(f->Size, s);
|
||||||
if (f->MTimeDefined)
|
if (f->MTimeDefined)
|
||||||
@@ -159,7 +194,10 @@ int MY_CDECL main(int numargs, char *args[])
|
|||||||
else
|
else
|
||||||
strcpy(t, " ");
|
strcpy(t, " ");
|
||||||
|
|
||||||
printf("%s %10s %s\n", t, s, f->Name);
|
printf("%s %10s %s", t, s, f->Name);
|
||||||
|
if (f->IsDir)
|
||||||
|
printf("/");
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (testCommand || extractCommand)
|
else if (testCommand || extractCommand)
|
||||||
@@ -174,44 +212,67 @@ int MY_CDECL main(int numargs, char *args[])
|
|||||||
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
|
||||||
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
size_t outBufferSize = 0; /* it can have any value before first call (if outBuffer = 0) */
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
for (i = 0; i < db.db.NumFiles; i++)
|
for (i = 0; i < db.db.NumFiles; i++)
|
||||||
{
|
{
|
||||||
size_t offset;
|
size_t offset;
|
||||||
size_t outSizeProcessed;
|
size_t outSizeProcessed;
|
||||||
CSzFileItem *f = db.db.Files + i;
|
const CSzFileItem *f = db.db.Files + i;
|
||||||
if (f->IsDir)
|
if (f->IsDir && !fullPaths)
|
||||||
printf("Directory ");
|
continue;
|
||||||
else
|
|
||||||
printf(testCommand ?
|
printf(testCommand ?
|
||||||
"Testing ":
|
"Testing ":
|
||||||
"Extracting");
|
"Extracting");
|
||||||
printf(" %s", f->Name);
|
printf(" %s", f->Name);
|
||||||
if (f->IsDir)
|
if (f->IsDir)
|
||||||
|
printf("/");
|
||||||
|
else
|
||||||
{
|
{
|
||||||
printf("\n");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
res = SzAr_Extract(&db, &lookStream.s, i,
|
res = SzAr_Extract(&db, &lookStream.s, i,
|
||||||
&blockIndex, &outBuffer, &outBufferSize,
|
&blockIndex, &outBuffer, &outBufferSize,
|
||||||
&offset, &outSizeProcessed,
|
&offset, &outSizeProcessed,
|
||||||
&allocImp, &allocTempImp);
|
&allocImp, &allocTempImp);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (!testCommand)
|
if (!testCommand)
|
||||||
{
|
{
|
||||||
CSzFile outFile;
|
CSzFile outFile;
|
||||||
size_t processedSize;
|
size_t processedSize;
|
||||||
char *fileName = f->Name;
|
size_t j, nameLen = strlen(f->Name);
|
||||||
size_t nameLen = strlen(f->Name);
|
const char *destPath;
|
||||||
for (; nameLen > 0; nameLen--)
|
if (nameLen + 1 > tempSize)
|
||||||
if (f->Name[nameLen - 1] == '/')
|
|
||||||
{
|
{
|
||||||
fileName = f->Name + nameLen;
|
SzFree(NULL, temp);
|
||||||
|
tempSize = nameLen + 1;
|
||||||
|
temp = (char *)SzAlloc(NULL, tempSize);
|
||||||
|
if (temp == 0)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_MEM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
destPath = temp;
|
||||||
|
strcpy(temp, f->Name);
|
||||||
|
for (j = 0; j < nameLen; j++)
|
||||||
|
if (temp[j] == '/')
|
||||||
|
{
|
||||||
|
if (fullPaths)
|
||||||
|
{
|
||||||
|
temp[j] = 0;
|
||||||
|
MyCreateDir(temp);
|
||||||
|
temp[j] = CHAR_PATH_SEPARATOR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
destPath = temp + j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (OutFile_Open(&outFile, fileName))
|
if (f->IsDir)
|
||||||
|
{
|
||||||
|
MyCreateDir(destPath);
|
||||||
|
printf("\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (OutFile_Open(&outFile, destPath))
|
||||||
{
|
{
|
||||||
PrintError("can not open output file");
|
PrintError("can not open output file");
|
||||||
res = SZ_ERROR_FAIL;
|
res = SZ_ERROR_FAIL;
|
||||||
@@ -243,6 +304,7 @@ int MY_CDECL main(int numargs, char *args[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SzArEx_Free(&db, &allocImp);
|
SzArEx_Free(&db, &allocImp);
|
||||||
|
SzFree(NULL, temp);
|
||||||
|
|
||||||
File_Close(&archiveStream.file);
|
File_Close(&archiveStream.file);
|
||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ C_OBJS = \
|
|||||||
$O\7zBuf2.obj \
|
$O\7zBuf2.obj \
|
||||||
$O\7zCrc.obj \
|
$O\7zCrc.obj \
|
||||||
$O\LzmaDec.obj \
|
$O\LzmaDec.obj \
|
||||||
|
$O\Lzma2Dec.obj \
|
||||||
$O\Bra86.obj \
|
$O\Bra86.obj \
|
||||||
$O\Bcj2.obj \
|
$O\Bcj2.obj \
|
||||||
$O\7zFile.obj \
|
$O\7zFile.obj \
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ LIB =
|
|||||||
RM = rm -f
|
RM = rm -f
|
||||||
CFLAGS = -c -O2 -Wall
|
CFLAGS = -c -O2 -Wall
|
||||||
|
|
||||||
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
|
OBJS = 7zAlloc.o 7zBuf.o 7zBuf2.o 7zCrc.o 7zDecode.o 7zExtract.o 7zHeader.o 7zIn.o 7zItem.o 7zMain.o LzmaDec.o Lzma2Dec.o Bra86.o Bcj2.o 7zFile.o 7zStream.o
|
||||||
|
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
|
|
||||||
@@ -44,6 +44,9 @@ $(PROG): $(OBJS)
|
|||||||
LzmaDec.o: ../../LzmaDec.c
|
LzmaDec.o: ../../LzmaDec.c
|
||||||
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
$(CXX) $(CFLAGS) ../../LzmaDec.c
|
||||||
|
|
||||||
|
Lzma2Dec.o: ../../Lzma2Dec.c
|
||||||
|
$(CXX) $(CFLAGS) ../../Lzma2Dec.c
|
||||||
|
|
||||||
Bra86.o: ../../Bra86.c
|
Bra86.o: ../../Bra86.c
|
||||||
$(CXX) $(CFLAGS) ../../Bra86.c
|
$(CXX) $(CFLAGS) ../../Bra86.c
|
||||||
|
|
||||||
|
|||||||
10
C/Bcj2.h
10
C/Bcj2.h
@@ -1,11 +1,15 @@
|
|||||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __BCJ2_H
|
#ifndef __BCJ2_H
|
||||||
#define __BCJ2_H
|
#define __BCJ2_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
Conditions:
|
||||||
outSize <= FullOutputSize,
|
outSize <= FullOutputSize,
|
||||||
@@ -27,4 +31,8 @@ int Bcj2_Decode(
|
|||||||
const Byte *buf3, SizeT size3,
|
const Byte *buf3, SizeT size3,
|
||||||
Byte *outBuf, SizeT outSize);
|
Byte *outBuf, SizeT outSize);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
10
C/Bra.h
10
C/Bra.h
@@ -1,11 +1,15 @@
|
|||||||
/* Bra.h -- Branch converters for executables
|
/* Bra.h -- Branch converters for executables
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __BRA_H
|
#ifndef __BRA_H
|
||||||
#define __BRA_H
|
#define __BRA_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
These functions convert relative addresses to absolute addresses
|
These functions convert relative addresses to absolute addresses
|
||||||
in CALL instructions to increase the compression ratio.
|
in CALL instructions to increase the compression ratio.
|
||||||
@@ -57,4 +61,8 @@ SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
|||||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
16
C/BwtSort.h
16
C/BwtSort.h
@@ -1,13 +1,15 @@
|
|||||||
/* BwtSort.h -- BWT block sorting
|
/* BwtSort.h -- BWT block sorting
|
||||||
2008-03-26
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __BWTSORT_H
|
#ifndef __BWT_SORT_H
|
||||||
#define __BWTSORT_H
|
#define __BWT_SORT_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
|
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize can be > 1M */
|
||||||
/* #define BLOCK_SORT_EXTERNAL_FLAGS */
|
/* #define BLOCK_SORT_EXTERNAL_FLAGS */
|
||||||
|
|
||||||
@@ -21,4 +23,8 @@ Public domain */
|
|||||||
|
|
||||||
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
|
UInt32 BlockSort(UInt32 *indices, const Byte *data, UInt32 blockSize);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
C/CpuArch.h
21
C/CpuArch.h
@@ -1,10 +1,12 @@
|
|||||||
/* CpuArch.h
|
/* CpuArch.h
|
||||||
2008-08-05
|
2009-03-22 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __CPUARCH_H
|
#ifndef __CPU_ARCH_H
|
||||||
#define __CPUARCH_H
|
#define __CPU_ARCH_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LITTLE_ENDIAN_UNALIGN means:
|
LITTLE_ENDIAN_UNALIGN means:
|
||||||
@@ -23,6 +25,7 @@ about these properties of platform.
|
|||||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||||
|
#define SetUi16(p, d) *(UInt16 *)(p) = (d);
|
||||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -37,6 +40,10 @@ about these properties of platform.
|
|||||||
|
|
||||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||||
|
|
||||||
|
#define SetUi16(p, d) { UInt32 _x_ = (d); \
|
||||||
|
((Byte *)(p))[0] = (Byte)_x_; \
|
||||||
|
((Byte *)(p))[1] = (Byte)(_x_ >> 8); }
|
||||||
|
|
||||||
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||||
((Byte *)(p))[0] = (Byte)_x_; \
|
((Byte *)(p))[0] = (Byte)_x_; \
|
||||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||||
@@ -66,4 +73,8 @@ about these properties of platform.
|
|||||||
|
|
||||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
62
C/Delta.c
Executable file
62
C/Delta.c
Executable file
@@ -0,0 +1,62 @@
|
|||||||
|
/* Delta.c -- Delta converter
|
||||||
|
2009-05-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Delta.h"
|
||||||
|
|
||||||
|
void Delta_Init(Byte *state)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
||||||
|
state[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
dest[i] = src[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
Byte buf[DELTA_STATE_SIZE];
|
||||||
|
unsigned j = 0;
|
||||||
|
MyMemCpy(buf, state, delta);
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < size;)
|
||||||
|
{
|
||||||
|
for (j = 0; j < delta && i < size; i++, j++)
|
||||||
|
{
|
||||||
|
Byte b = data[i];
|
||||||
|
data[i] = (Byte)(b - buf[j]);
|
||||||
|
buf[j] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == delta)
|
||||||
|
j = 0;
|
||||||
|
MyMemCpy(state, buf + j, delta - j);
|
||||||
|
MyMemCpy(state + delta - j, buf, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||||
|
{
|
||||||
|
Byte buf[DELTA_STATE_SIZE];
|
||||||
|
unsigned j = 0;
|
||||||
|
MyMemCpy(buf, state, delta);
|
||||||
|
{
|
||||||
|
SizeT i;
|
||||||
|
for (i = 0; i < size;)
|
||||||
|
{
|
||||||
|
for (j = 0; j < delta && i < size; i++, j++)
|
||||||
|
{
|
||||||
|
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == delta)
|
||||||
|
j = 0;
|
||||||
|
MyMemCpy(state, buf + j, delta - j);
|
||||||
|
MyMemCpy(state + delta - j, buf, j);
|
||||||
|
}
|
||||||
23
C/Delta.h
Executable file
23
C/Delta.h
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
/* Delta.h -- Delta converter
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __DELTA_H
|
||||||
|
#define __DELTA_H
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DELTA_STATE_SIZE 256
|
||||||
|
|
||||||
|
void Delta_Init(Byte *state);
|
||||||
|
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||||
|
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
18
C/HuffEnc.h
18
C/HuffEnc.h
@@ -1,13 +1,15 @@
|
|||||||
/* HuffEnc.h -- functions for Huffman encoding
|
/* HuffEnc.h -- Huffman encoding
|
||||||
2008-03-26
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __HUFFENC_H
|
#ifndef __HUFF_ENC_H
|
||||||
#define __HUFFENC_H
|
#define __HUFF_ENC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
Conditions:
|
||||||
num <= 1024 = 2 ^ NUM_BITS
|
num <= 1024 = 2 ^ NUM_BITS
|
||||||
@@ -18,4 +20,8 @@ Conditions:
|
|||||||
|
|
||||||
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
|
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 num, UInt32 maxLen);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
20
C/LzFind.c
20
C/LzFind.c
@@ -1,5 +1,5 @@
|
|||||||
/* LzFind.c -- Match finder for LZ algorithms
|
/* LzFind.c -- Match finder for LZ algorithms
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-04-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -58,6 +58,17 @@ static void MatchFinder_ReadBlock(CMatchFinder *p)
|
|||||||
{
|
{
|
||||||
if (p->streamEndWasReached || p->result != SZ_OK)
|
if (p->streamEndWasReached || p->result != SZ_OK)
|
||||||
return;
|
return;
|
||||||
|
if (p->directInput)
|
||||||
|
{
|
||||||
|
UInt32 curSize = 0xFFFFFFFF - p->streamPos;
|
||||||
|
if (curSize > p->directInputRem)
|
||||||
|
curSize = (UInt32)p->directInputRem;
|
||||||
|
p->directInputRem -= curSize;
|
||||||
|
p->streamPos += curSize;
|
||||||
|
if (p->directInputRem == 0)
|
||||||
|
p->streamEndWasReached = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
Byte *dest = p->buffer + (p->streamPos - p->pos);
|
||||||
@@ -88,6 +99,8 @@ void MatchFinder_MoveBlock(CMatchFinder *p)
|
|||||||
|
|
||||||
int MatchFinder_NeedMove(CMatchFinder *p)
|
int MatchFinder_NeedMove(CMatchFinder *p)
|
||||||
{
|
{
|
||||||
|
if (p->directInput)
|
||||||
|
return 0;
|
||||||
/* if (p->streamEndWasReached) return 0; */
|
/* if (p->streamEndWasReached) return 0; */
|
||||||
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
||||||
}
|
}
|
||||||
@@ -112,8 +125,6 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
|||||||
p->cutValue = 32;
|
p->cutValue = 32;
|
||||||
p->btMode = 1;
|
p->btMode = 1;
|
||||||
p->numHashBytes = 4;
|
p->numHashBytes = 4;
|
||||||
/* p->skipModeBits = 0; */
|
|
||||||
p->directInput = 0;
|
|
||||||
p->bigHash = 0;
|
p->bigHash = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +188,7 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
|
||||||
if (LzInWindow_Create(p, sizeReserv, alloc))
|
if (LzInWindow_Create(p, sizeReserv, alloc))
|
||||||
{
|
{
|
||||||
UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
|
UInt32 newCyclicBufferSize = historySize + 1;
|
||||||
UInt32 hs;
|
UInt32 hs;
|
||||||
p->matchMaxLen = matchMaxLen;
|
p->matchMaxLen = matchMaxLen;
|
||||||
{
|
{
|
||||||
@@ -192,7 +203,6 @@ int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
|||||||
hs |= (hs >> 4);
|
hs |= (hs >> 4);
|
||||||
hs |= (hs >> 8);
|
hs |= (hs >> 8);
|
||||||
hs >>= 1;
|
hs >>= 1;
|
||||||
/* hs >>= p->skipModeBits; */
|
|
||||||
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
||||||
if (hs > (1 << 24))
|
if (hs > (1 << 24))
|
||||||
{
|
{
|
||||||
|
|||||||
16
C/LzFind.h
16
C/LzFind.h
@@ -1,11 +1,15 @@
|
|||||||
/* LzFind.h -- Match finder for LZ algorithms
|
/* LzFind.h -- Match finder for LZ algorithms
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-04-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZFIND_H
|
#ifndef __LZ_FIND_H
|
||||||
#define __LZFIND_H
|
#define __LZ_FIND_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef UInt32 CLzRef;
|
typedef UInt32 CLzRef;
|
||||||
|
|
||||||
typedef struct _CMatchFinder
|
typedef struct _CMatchFinder
|
||||||
@@ -35,8 +39,8 @@ typedef struct _CMatchFinder
|
|||||||
|
|
||||||
UInt32 numHashBytes;
|
UInt32 numHashBytes;
|
||||||
int directInput;
|
int directInput;
|
||||||
|
size_t directInputRem;
|
||||||
int btMode;
|
int btMode;
|
||||||
/* int skipModeBits; */
|
|
||||||
int bigHash;
|
int bigHash;
|
||||||
UInt32 historySize;
|
UInt32 historySize;
|
||||||
UInt32 fixedHashSize;
|
UInt32 fixedHashSize;
|
||||||
@@ -104,4 +108,8 @@ UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
|||||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-05-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "LzHash.h"
|
#include "LzHash.h"
|
||||||
|
|
||||||
@@ -143,7 +143,7 @@ DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), hashMask = hashMask; crc = crc;
|
|||||||
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask)
|
||||||
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask)
|
||||||
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask)
|
||||||
DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask)
|
/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */
|
||||||
|
|
||||||
void HashThreadFunc(CMatchFinderMt *mt)
|
void HashThreadFunc(CMatchFinderMt *mt)
|
||||||
{
|
{
|
||||||
|
|||||||
16
C/LzFindMt.h
16
C/LzFindMt.h
@@ -1,11 +1,15 @@
|
|||||||
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZFINDMT_H
|
#ifndef __LZ_FIND_MT_H
|
||||||
#define __LZFINDMT_H
|
#define __LZ_FIND_MT_H
|
||||||
|
|
||||||
#include "Threads.h"
|
|
||||||
#include "LzFind.h"
|
#include "LzFind.h"
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define kMtHashBlockSize (1 << 13)
|
#define kMtHashBlockSize (1 << 13)
|
||||||
#define kMtHashNumBlocks (1 << 3)
|
#define kMtHashNumBlocks (1 << 3)
|
||||||
@@ -94,4 +98,8 @@ SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddB
|
|||||||
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable);
|
||||||
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
void MatchFinderMt_ReleaseStream(CMatchFinderMt *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/* LzHash.h -- HASH functions for LZ algorithms
|
/* LzHash.h -- HASH functions for LZ algorithms
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZHASH_H
|
#ifndef __LZ_HASH_H
|
||||||
#define __LZHASH_H
|
#define __LZ_HASH_H
|
||||||
|
|
||||||
#define kHash2Size (1 << 10)
|
#define kHash2Size (1 << 10)
|
||||||
#define kHash3Size (1 << 16)
|
#define kHash3Size (1 << 16)
|
||||||
|
|||||||
356
C/Lzma2Dec.c
Executable file
356
C/Lzma2Dec.c
Executable file
@@ -0,0 +1,356 @@
|
|||||||
|
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||||
|
2009-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
/* #define SHOW_DEBUG_INFO */
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Lzma2Dec.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
00000000 - EOS
|
||||||
|
00000001 U U - Uncompressed Reset Dic
|
||||||
|
00000010 U U - Uncompressed No Reset
|
||||||
|
100uuuuu U U P P - LZMA no reset
|
||||||
|
101uuuuu U U P P - LZMA reset state
|
||||||
|
110uuuuu U U P P S - LZMA reset state + new prop
|
||||||
|
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||||
|
|
||||||
|
u, U - Unpack Size
|
||||||
|
P - Pack Size
|
||||||
|
S - Props
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||||
|
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||||
|
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||||
|
#define LZMA2_CONTROL_EOF 0
|
||||||
|
|
||||||
|
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
|
||||||
|
|
||||||
|
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||||
|
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||||
|
|
||||||
|
#define LZMA2_LCLP_MAX 4
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#ifdef SHOW_DEBUG_INFO
|
||||||
|
#define PRF(x) x
|
||||||
|
#else
|
||||||
|
#define PRF(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
LZMA2_STATE_CONTROL,
|
||||||
|
LZMA2_STATE_UNPACK0,
|
||||||
|
LZMA2_STATE_UNPACK1,
|
||||||
|
LZMA2_STATE_PACK0,
|
||||||
|
LZMA2_STATE_PACK1,
|
||||||
|
LZMA2_STATE_PROP,
|
||||||
|
LZMA2_STATE_DATA,
|
||||||
|
LZMA2_STATE_DATA_CONT,
|
||||||
|
LZMA2_STATE_FINISHED,
|
||||||
|
LZMA2_STATE_ERROR
|
||||||
|
} ELzma2State;
|
||||||
|
|
||||||
|
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||||
|
{
|
||||||
|
UInt32 dicSize;
|
||||||
|
if (prop > 40)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||||
|
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||||
|
props[1] = (Byte)(dicSize);
|
||||||
|
props[2] = (Byte)(dicSize >> 8);
|
||||||
|
props[3] = (Byte)(dicSize >> 16);
|
||||||
|
props[4] = (Byte)(dicSize >> 24);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||||
|
{
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
p->needInitDic = True;
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
LzmaDec_Init(&p->decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||||
|
{
|
||||||
|
switch(p->state)
|
||||||
|
{
|
||||||
|
case LZMA2_STATE_CONTROL:
|
||||||
|
p->control = b;
|
||||||
|
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||||
|
PRF(printf(" %2X", b));
|
||||||
|
if (p->control == 0)
|
||||||
|
return LZMA2_STATE_FINISHED;
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if ((p->control & 0x7F) > 2)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->unpackSize = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
||||||
|
return LZMA2_STATE_UNPACK0;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK0:
|
||||||
|
p->unpackSize |= (UInt32)b << 8;
|
||||||
|
return LZMA2_STATE_UNPACK1;
|
||||||
|
|
||||||
|
case LZMA2_STATE_UNPACK1:
|
||||||
|
p->unpackSize |= (UInt32)b;
|
||||||
|
p->unpackSize++;
|
||||||
|
PRF(printf(" %8d", p->unpackSize));
|
||||||
|
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||||
|
|
||||||
|
case LZMA2_STATE_PACK0:
|
||||||
|
p->packSize = (UInt32)b << 8;
|
||||||
|
return LZMA2_STATE_PACK1;
|
||||||
|
|
||||||
|
case LZMA2_STATE_PACK1:
|
||||||
|
p->packSize |= (UInt32)b;
|
||||||
|
p->packSize++;
|
||||||
|
PRF(printf(" %8d", p->packSize));
|
||||||
|
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||||
|
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||||
|
|
||||||
|
case LZMA2_STATE_PROP:
|
||||||
|
{
|
||||||
|
int lc, lp;
|
||||||
|
if (b >= (9 * 5 * 5))
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
lc = b % 9;
|
||||||
|
b /= 9;
|
||||||
|
p->decoder.prop.pb = b / 5;
|
||||||
|
lp = b % 5;
|
||||||
|
if (lc + lp > LZMA2_LCLP_MAX)
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
p->decoder.prop.lc = lc;
|
||||||
|
p->decoder.prop.lp = lp;
|
||||||
|
p->needInitProp = False;
|
||||||
|
return LZMA2_STATE_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return LZMA2_STATE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||||
|
{
|
||||||
|
memcpy(p->dic + p->dicPos, src, size);
|
||||||
|
p->dicPos += size;
|
||||||
|
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||||
|
p->checkDicSize = p->prop.dicSize;
|
||||||
|
p->processedPos += (UInt32)size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT inSize = *srcLen;
|
||||||
|
*srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
|
||||||
|
while (p->state != LZMA2_STATE_FINISHED)
|
||||||
|
{
|
||||||
|
SizeT dicPos = p->decoder.dicPos;
|
||||||
|
if (p->state == LZMA2_STATE_ERROR)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
(*srcLen)++;
|
||||||
|
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
SizeT destSizeCur = dicLimit - dicPos;
|
||||||
|
SizeT srcSizeCur = inSize - *srcLen;
|
||||||
|
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
|
||||||
|
if (p->unpackSize <= destSizeCur)
|
||||||
|
{
|
||||||
|
destSizeCur = (SizeT)p->unpackSize;
|
||||||
|
curFinishMode = LZMA_FINISH_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
|
{
|
||||||
|
if (*srcLen == inSize)
|
||||||
|
{
|
||||||
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||||
|
if (initDic)
|
||||||
|
p->needInitProp = p->needInitState = True;
|
||||||
|
else if (p->needInitDic)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
p->needInitDic = False;
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcSizeCur > destSizeCur)
|
||||||
|
srcSizeCur = destSizeCur;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
|
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->unpackSize -= (UInt32)srcSizeCur;
|
||||||
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SizeT outSizeProcessed;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
|
{
|
||||||
|
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||||
|
Bool initDic = (mode == 3);
|
||||||
|
Bool initState = (mode > 0);
|
||||||
|
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
|
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||||
|
p->needInitDic = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
|
}
|
||||||
|
if (srcSizeCur > p->packSize)
|
||||||
|
srcSizeCur = (SizeT)p->packSize;
|
||||||
|
|
||||||
|
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
|
||||||
|
src += srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
p->packSize -= (UInt32)srcSizeCur;
|
||||||
|
|
||||||
|
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||||
|
p->unpackSize -= (UInt32)outSizeProcessed;
|
||||||
|
|
||||||
|
RINOK(res);
|
||||||
|
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||||
|
{
|
||||||
|
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||||
|
p->unpackSize != 0 || p->packSize != 0)
|
||||||
|
return SZ_ERROR_DATA;
|
||||||
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
|
}
|
||||||
|
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||||
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
|
{
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
*srcLen = *destLen = 0;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
|
||||||
|
ELzmaFinishMode curFinishMode;
|
||||||
|
SRes res;
|
||||||
|
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||||
|
p->decoder.dicPos = 0;
|
||||||
|
dicPos = p->decoder.dicPos;
|
||||||
|
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||||
|
{
|
||||||
|
outSizeCur = p->decoder.dicBufSize;
|
||||||
|
curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
outSizeCur = dicPos + outSize;
|
||||||
|
curFinishMode = finishMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
src += srcSizeCur;
|
||||||
|
inSize -= srcSizeCur;
|
||||||
|
*srcLen += srcSizeCur;
|
||||||
|
outSizeCur = p->decoder.dicPos - dicPos;
|
||||||
|
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||||
|
dest += outSizeCur;
|
||||||
|
outSize -= outSizeCur;
|
||||||
|
*destLen += outSizeCur;
|
||||||
|
if (res != 0)
|
||||||
|
return res;
|
||||||
|
if (outSizeCur == 0 || outSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CLzma2Dec decoder;
|
||||||
|
SRes res;
|
||||||
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
|
||||||
|
Lzma2Dec_Construct(&decoder);
|
||||||
|
|
||||||
|
*destLen = *srcLen = 0;
|
||||||
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
decoder.decoder.dic = dest;
|
||||||
|
decoder.decoder.dicBufSize = outSize;
|
||||||
|
|
||||||
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
|
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
|
||||||
|
|
||||||
|
*srcLen = inSize;
|
||||||
|
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
|
||||||
|
*destLen = decoder.decoder.dicPos;
|
||||||
|
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
|
res = SZ_ERROR_INPUT_EOF;
|
||||||
|
|
||||||
|
LzmaDec_FreeProbs(&decoder.decoder, alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
84
C/Lzma2Dec.h
Executable file
84
C/Lzma2Dec.h
Executable file
@@ -0,0 +1,84 @@
|
|||||||
|
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||||
|
2009-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_DEC_H
|
||||||
|
#define __LZMA2_DEC_H
|
||||||
|
|
||||||
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------- State Interface ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaDec decoder;
|
||||||
|
UInt32 packSize;
|
||||||
|
UInt32 unpackSize;
|
||||||
|
int state;
|
||||||
|
Byte control;
|
||||||
|
Bool needInitDic;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} CLzma2Dec;
|
||||||
|
|
||||||
|
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||||
|
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||||
|
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
|
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||||
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
|
SZ_ERROR_DATA - Data error
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
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 Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
484
C/Lzma2Enc.c
Executable file
484
C/Lzma2Enc.c
Executable file
@@ -0,0 +1,484 @@
|
|||||||
|
/* Lzma2Enc.c -- LZMA2 Encoder
|
||||||
|
2009-05-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
/* #include <stdio.h> */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "Lzma2Enc.h"
|
||||||
|
|
||||||
|
/* #define COMPRESS_MT */
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
#include "MtCoder.h"
|
||||||
|
#else
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||||
|
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||||
|
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||||
|
#define LZMA2_CONTROL_EOF 0
|
||||||
|
|
||||||
|
#define LZMA2_LCLP_MAX 4
|
||||||
|
|
||||||
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
|
#define LZMA2_PACK_SIZE_MAX (1 << 16)
|
||||||
|
#define LZMA2_COPY_CHUNK_SIZE LZMA2_PACK_SIZE_MAX
|
||||||
|
#define LZMA2_UNPACK_SIZE_MAX (1 << 21)
|
||||||
|
#define LZMA2_KEEP_WINDOW_SIZE LZMA2_UNPACK_SIZE_MAX
|
||||||
|
|
||||||
|
#define LZMA2_CHUNK_SIZE_COMPRESSED_MAX ((1 << 16) + 16)
|
||||||
|
|
||||||
|
|
||||||
|
#define PRF(x) /* x */
|
||||||
|
|
||||||
|
/* ---------- CLzma2EncInt ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncHandle enc;
|
||||||
|
UInt64 srcPos;
|
||||||
|
Byte props;
|
||||||
|
Bool needInitState;
|
||||||
|
Bool needInitProp;
|
||||||
|
} CLzma2EncInt;
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_Init(CLzma2EncInt *p, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
Byte propsEncoded[LZMA_PROPS_SIZE];
|
||||||
|
SizeT propsSize = LZMA_PROPS_SIZE;
|
||||||
|
RINOK(LzmaEnc_SetProps(p->enc, &props->lzmaProps));
|
||||||
|
RINOK(LzmaEnc_WriteProperties(p->enc, propsEncoded, &propsSize));
|
||||||
|
p->srcPos = 0;
|
||||||
|
p->props = propsEncoded[0];
|
||||||
|
p->needInitState = True;
|
||||||
|
p->needInitProp = True;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, ISeqInStream *inStream, UInt32 keepWindowSize,
|
||||||
|
ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||||
|
UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
||||||
|
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize);
|
||||||
|
const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_Finish(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_SaveState(CLzmaEncHandle pp);
|
||||||
|
void LzmaEnc_RestoreState(CLzmaEncHandle pp);
|
||||||
|
|
||||||
|
|
||||||
|
static SRes Lzma2EncInt_EncodeSubblock(CLzma2EncInt *p, Byte *outBuf,
|
||||||
|
size_t *packSizeRes, ISeqOutStream *outStream)
|
||||||
|
{
|
||||||
|
size_t packSizeLimit = *packSizeRes;
|
||||||
|
size_t packSize = packSizeLimit;
|
||||||
|
UInt32 unpackSize = LZMA2_UNPACK_SIZE_MAX;
|
||||||
|
unsigned lzHeaderSize = 5 + (p->needInitProp ? 1 : 0);
|
||||||
|
Bool useCopyBlock;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
*packSizeRes = 0;
|
||||||
|
if (packSize < lzHeaderSize)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
packSize -= lzHeaderSize;
|
||||||
|
|
||||||
|
LzmaEnc_SaveState(p->enc);
|
||||||
|
res = LzmaEnc_CodeOneMemBlock(p->enc, p->needInitState,
|
||||||
|
outBuf + lzHeaderSize, &packSize, LZMA2_PACK_SIZE_MAX, &unpackSize);
|
||||||
|
|
||||||
|
PRF(printf("\npackSize = %7d unpackSize = %7d ", packSize, unpackSize));
|
||||||
|
|
||||||
|
if (unpackSize == 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
useCopyBlock = (packSize + 2 >= unpackSize || packSize > (1 << 16));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (res != SZ_ERROR_OUTPUT_EOF)
|
||||||
|
return res;
|
||||||
|
res = SZ_OK;
|
||||||
|
useCopyBlock = True;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useCopyBlock)
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
PRF(printf("################# COPY "));
|
||||||
|
while (unpackSize > 0)
|
||||||
|
{
|
||||||
|
UInt32 u = (unpackSize < LZMA2_COPY_CHUNK_SIZE) ? unpackSize : LZMA2_COPY_CHUNK_SIZE;
|
||||||
|
if (packSizeLimit - destPos < u + 3)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
outBuf[destPos++] = (Byte)(p->srcPos == 0 ? LZMA2_CONTROL_COPY_RESET_DIC : LZMA2_CONTROL_COPY_NO_RESET);
|
||||||
|
outBuf[destPos++] = (Byte)((u - 1) >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)(u - 1);
|
||||||
|
memcpy(outBuf + destPos, LzmaEnc_GetCurBuf(p->enc) - unpackSize, u);
|
||||||
|
unpackSize -= u;
|
||||||
|
destPos += u;
|
||||||
|
p->srcPos += u;
|
||||||
|
if (outStream)
|
||||||
|
{
|
||||||
|
*packSizeRes += destPos;
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
destPos = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
/* needInitState = True; */
|
||||||
|
}
|
||||||
|
LzmaEnc_RestoreState(p->enc);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
size_t destPos = 0;
|
||||||
|
UInt32 u = unpackSize - 1;
|
||||||
|
UInt32 pm = (UInt32)(packSize - 1);
|
||||||
|
unsigned mode = (p->srcPos == 0) ? 3 : (p->needInitState ? (p->needInitProp ? 2 : 1) : 0);
|
||||||
|
|
||||||
|
PRF(printf(" "));
|
||||||
|
|
||||||
|
outBuf[destPos++] = (Byte)(LZMA2_CONTROL_LZMA | (mode << 5) | (u >> 16) & 0x1F);
|
||||||
|
outBuf[destPos++] = (Byte)(u >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)u;
|
||||||
|
outBuf[destPos++] = (Byte)(pm >> 8);
|
||||||
|
outBuf[destPos++] = (Byte)pm;
|
||||||
|
|
||||||
|
if (p->needInitProp)
|
||||||
|
outBuf[destPos++] = p->props;
|
||||||
|
|
||||||
|
p->needInitProp = False;
|
||||||
|
p->needInitState = False;
|
||||||
|
destPos += packSize;
|
||||||
|
p->srcPos += unpackSize;
|
||||||
|
|
||||||
|
if (outStream)
|
||||||
|
if (outStream->Write(outStream, outBuf, destPos) != destPos)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
*packSizeRes = destPos;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Lzma2 Props ---------- */
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
LzmaEncProps_Init(&p->lzmaProps);
|
||||||
|
p->numTotalThreads = -1;
|
||||||
|
p->numBlockThreads = -1;
|
||||||
|
p->blockSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Lzma2 ---------- */
|
||||||
|
|
||||||
|
extern struct _CLzma2Enc;
|
||||||
|
|
||||||
|
typedef struct _CLzma2Enc
|
||||||
|
{
|
||||||
|
Byte propEncoded;
|
||||||
|
CLzma2EncProps props;
|
||||||
|
|
||||||
|
Byte *outBuf;
|
||||||
|
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
ISzAlloc *allocBig;
|
||||||
|
|
||||||
|
CLzma2EncInt coders[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
CMtCoder mtCoder;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} CLzma2Enc;
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Lzma2EncThread ---------- */
|
||||||
|
|
||||||
|
static SRes Lzma2Enc_EncodeMt1(CLzma2EncInt *p, CLzma2Enc *mainEncoder,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
UInt64 packTotal = 0;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
|
if (mainEncoder->outBuf == 0)
|
||||||
|
{
|
||||||
|
mainEncoder->outBuf = IAlloc_Alloc(mainEncoder->alloc, LZMA2_CHUNK_SIZE_COMPRESSED_MAX);
|
||||||
|
if (mainEncoder->outBuf == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
RINOK(LzmaEnc_PrepareForLzma2(p->enc, inStream, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
size_t packSize = LZMA2_CHUNK_SIZE_COMPRESSED_MAX;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, mainEncoder->outBuf, &packSize, outStream);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
packTotal += packSize;
|
||||||
|
res = Progress(progress, p->srcPos, packTotal);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
if (packSize == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
Byte b = 0;
|
||||||
|
if (outStream->Write(outStream, &b, 1) != 1)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
IMtCoderCallback funcTable;
|
||||||
|
CLzma2Enc *lzma2Enc;
|
||||||
|
} CMtCallbackImp;
|
||||||
|
|
||||||
|
static SRes MtCallbackImp_Code(void *pp, unsigned index, Byte *dest, size_t *destSize,
|
||||||
|
const Byte *src, size_t srcSize, int finished)
|
||||||
|
{
|
||||||
|
CMtCallbackImp *imp = (CMtCallbackImp *)pp;
|
||||||
|
CLzma2Enc *mainEncoder = imp->lzma2Enc;
|
||||||
|
CLzma2EncInt *p = &mainEncoder->coders[index];
|
||||||
|
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
{
|
||||||
|
size_t destLim = *destSize;
|
||||||
|
*destSize = 0;
|
||||||
|
|
||||||
|
if (srcSize != 0)
|
||||||
|
{
|
||||||
|
RINOK(Lzma2EncInt_Init(p, &mainEncoder->props));
|
||||||
|
|
||||||
|
RINOK(LzmaEnc_MemPrepare(p->enc, src, srcSize, LZMA2_KEEP_WINDOW_SIZE,
|
||||||
|
mainEncoder->alloc, mainEncoder->allocBig));
|
||||||
|
|
||||||
|
while (p->srcPos < srcSize)
|
||||||
|
{
|
||||||
|
size_t packSize = destLim - *destSize;
|
||||||
|
res = Lzma2EncInt_EncodeSubblock(p, dest + *destSize, &packSize, NULL);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
break;
|
||||||
|
*destSize += packSize;
|
||||||
|
|
||||||
|
if (packSize == 0)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MtProgress_Set(&mainEncoder->mtCoder.mtProgress, index, p->srcPos, *destSize) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_PROGRESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LzmaEnc_Finish(p->enc);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (finished)
|
||||||
|
{
|
||||||
|
if (*destSize == destLim)
|
||||||
|
return SZ_ERROR_OUTPUT_EOF;
|
||||||
|
dest[(*destSize)++] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------- Lzma2Enc ---------- */
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)alloc->Alloc(alloc, sizeof(CLzma2Enc));
|
||||||
|
if (p == 0)
|
||||||
|
return NULL;
|
||||||
|
Lzma2EncProps_Init(&p->props);
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
p->outBuf = 0;
|
||||||
|
p->alloc = alloc;
|
||||||
|
p->allocBig = allocBig;
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
p->coders[i].enc = 0;
|
||||||
|
}
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
MtCoder_Construct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[i];
|
||||||
|
if (t->enc)
|
||||||
|
{
|
||||||
|
LzmaEnc_Destroy(t->enc, p->alloc, p->allocBig);
|
||||||
|
t->enc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
MtCoder_Destruct(&p->mtCoder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IAlloc_Free(p->alloc, p->outBuf);
|
||||||
|
IAlloc_Free(p->alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p)
|
||||||
|
{
|
||||||
|
int t1, t1n, t2, t3;
|
||||||
|
CLzmaEncProps lzmaProps = p->lzmaProps;
|
||||||
|
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
|
||||||
|
t1 = p->lzmaProps.numThreads;
|
||||||
|
t1n = lzmaProps.numThreads;
|
||||||
|
t2 = p->numBlockThreads;
|
||||||
|
t3 = p->numTotalThreads;
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
if (t2 > NUM_MT_CODER_THREADS_MAX)
|
||||||
|
t2 = NUM_MT_CODER_THREADS_MAX;
|
||||||
|
#else
|
||||||
|
t2 = 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (t3 <= 0)
|
||||||
|
{
|
||||||
|
if (t2 <= 0)
|
||||||
|
t2 = 1;
|
||||||
|
t3 = t1n * t2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (t2 <= 0)
|
||||||
|
{
|
||||||
|
t2 = t3 / t1n;
|
||||||
|
if (t2 == 0)
|
||||||
|
{
|
||||||
|
t1 = 1;
|
||||||
|
t2 = t3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (t1 <= 0)
|
||||||
|
{
|
||||||
|
t1 = t3 / t2;
|
||||||
|
if (t1 == 0)
|
||||||
|
t1 = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
t3 = t1n * t2;
|
||||||
|
}
|
||||||
|
|
||||||
|
p->lzmaProps.numThreads = t1;
|
||||||
|
p->numBlockThreads = t2;
|
||||||
|
p->numTotalThreads = t3;
|
||||||
|
LzmaEncProps_Normalize(&p->lzmaProps);
|
||||||
|
|
||||||
|
if (p->blockSize == 0)
|
||||||
|
{
|
||||||
|
UInt64 blockSize = (UInt64)lzmaProps.dictSize << 2;
|
||||||
|
const UInt32 kMinSize = (UInt32)1 << 20;
|
||||||
|
const UInt32 kMaxSize = (UInt32)1 << 28;
|
||||||
|
if (blockSize < kMinSize) blockSize = kMinSize;
|
||||||
|
if (blockSize > kMaxSize) blockSize = kMaxSize;
|
||||||
|
if (blockSize < lzmaProps.dictSize)
|
||||||
|
blockSize = lzmaProps.dictSize;
|
||||||
|
p->blockSize = (size_t)blockSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle pp, const CLzma2EncProps *props)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
CLzmaEncProps lzmaProps = props->lzmaProps;
|
||||||
|
LzmaEncProps_Normalize(&lzmaProps);
|
||||||
|
if (lzmaProps.lc + lzmaProps.lp > LZMA2_LCLP_MAX)
|
||||||
|
return SZ_ERROR_PARAM;
|
||||||
|
p->props = *props;
|
||||||
|
Lzma2EncProps_Normalize(&p->props);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle pp)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
unsigned i;
|
||||||
|
UInt32 dicSize = LzmaEncProps_GetDictSize(&p->props.lzmaProps);
|
||||||
|
for (i = 0; i < 40; i++)
|
||||||
|
if (dicSize <= LZMA2_DIC_SIZE_FROM_PROP(i))
|
||||||
|
break;
|
||||||
|
return (Byte)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle pp,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
CLzma2Enc *p = (CLzma2Enc *)pp;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < p->props.numBlockThreads; i++)
|
||||||
|
{
|
||||||
|
CLzma2EncInt *t = &p->coders[i];
|
||||||
|
if (t->enc == NULL)
|
||||||
|
{
|
||||||
|
t->enc = LzmaEnc_Create(p->alloc);
|
||||||
|
if (t->enc == NULL)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
if (p->props.numBlockThreads <= 1)
|
||||||
|
#endif
|
||||||
|
return Lzma2Enc_EncodeMt1(&p->coders[0], p, outStream, inStream, progress);
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
|
||||||
|
{
|
||||||
|
CMtCallbackImp mtCallback;
|
||||||
|
|
||||||
|
mtCallback.funcTable.Code = MtCallbackImp_Code;
|
||||||
|
mtCallback.lzma2Enc = p;
|
||||||
|
|
||||||
|
p->mtCoder.progress = progress;
|
||||||
|
p->mtCoder.inStream = inStream;
|
||||||
|
p->mtCoder.outStream = outStream;
|
||||||
|
p->mtCoder.alloc = p->alloc;
|
||||||
|
p->mtCoder.mtCallback = &mtCallback.funcTable;
|
||||||
|
|
||||||
|
p->mtCoder.blockSize = p->props.blockSize;
|
||||||
|
p->mtCoder.destBlockSize = p->props.blockSize + (p->props.blockSize >> 10) + 16;
|
||||||
|
p->mtCoder.numThreads = p->props.numBlockThreads;
|
||||||
|
|
||||||
|
return MtCoder_Code(&p->mtCoder);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
66
C/Lzma2Enc.h
Executable file
66
C/Lzma2Enc.h
Executable file
@@ -0,0 +1,66 @@
|
|||||||
|
/* Lzma2Enc.h -- LZMA2 Encoder
|
||||||
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __LZMA2_ENC_H
|
||||||
|
#define __LZMA2_ENC_H
|
||||||
|
|
||||||
|
#include "LzmaEnc.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CLzmaEncProps lzmaProps;
|
||||||
|
size_t blockSize;
|
||||||
|
int numBlockThreads;
|
||||||
|
int numTotalThreads;
|
||||||
|
} CLzma2EncProps;
|
||||||
|
|
||||||
|
void Lzma2EncProps_Init(CLzma2EncProps *p);
|
||||||
|
void Lzma2EncProps_Normalize(CLzma2EncProps *p);
|
||||||
|
|
||||||
|
/* ---------- CLzmaEnc2Handle Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Enc_* functions can return the following exit codes:
|
||||||
|
Returns:
|
||||||
|
SZ_OK - OK
|
||||||
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
|
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||||
|
SZ_ERROR_WRITE - Write callback error
|
||||||
|
SZ_ERROR_PROGRESS - some break from progress callback
|
||||||
|
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef void * CLzma2EncHandle;
|
||||||
|
|
||||||
|
CLzma2EncHandle Lzma2Enc_Create(ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
void Lzma2Enc_Destroy(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_SetProps(CLzma2EncHandle p, const CLzma2EncProps *props);
|
||||||
|
Byte Lzma2Enc_WriteProperties(CLzma2EncHandle p);
|
||||||
|
SRes Lzma2Enc_Encode(CLzma2EncHandle p,
|
||||||
|
ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress);
|
||||||
|
|
||||||
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
|
/* Lzma2Encode
|
||||||
|
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)
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRes Lzma2Encode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||||
|
const CLzmaEncProps *props, Byte *propsEncoded, int writeEndMark,
|
||||||
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
14
C/LzmaDec.h
14
C/LzmaDec.h
@@ -1,11 +1,15 @@
|
|||||||
/* LzmaDec.h -- LZMA Decoder
|
/* LzmaDec.h -- LZMA Decoder
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMADEC_H
|
#ifndef __LZMA_DEC_H
|
||||||
#define __LZMADEC_H
|
#define __LZMA_DEC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/* #define _LZMA_PROB32 */
|
/* #define _LZMA_PROB32 */
|
||||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||||
@@ -220,4 +224,8 @@ SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
|||||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||||
ELzmaStatus *status, ISzAlloc *alloc);
|
ELzmaStatus *status, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
77
C/LzmaEnc.c
77
C/LzmaEnc.c
@@ -1,5 +1,5 @@
|
|||||||
/* LzmaEnc.c -- LZMA Encoder
|
/* LzmaEnc.c -- LZMA Encoder
|
||||||
2009-02-02 : Igor Pavlov : Public domain */
|
2009-04-22 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ void LzmaEnc_FastPosInit(Byte *g_FastPos)
|
|||||||
|
|
||||||
typedef unsigned CState;
|
typedef unsigned CState;
|
||||||
|
|
||||||
typedef struct _COptimal
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 price;
|
UInt32 price;
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ typedef struct
|
|||||||
UInt32 counters[LZMA_NUM_PB_STATES_MAX];
|
UInt32 counters[LZMA_NUM_PB_STATES_MAX];
|
||||||
} CLenPriceEnc;
|
} CLenPriceEnc;
|
||||||
|
|
||||||
typedef struct _CRangeEnc
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 range;
|
UInt32 range;
|
||||||
Byte cache;
|
Byte cache;
|
||||||
@@ -232,26 +232,6 @@ typedef struct _CRangeEnc
|
|||||||
SRes res;
|
SRes res;
|
||||||
} CRangeEnc;
|
} CRangeEnc;
|
||||||
|
|
||||||
typedef struct _CSeqInStreamBuf
|
|
||||||
{
|
|
||||||
ISeqInStream funcTable;
|
|
||||||
const Byte *data;
|
|
||||||
SizeT rem;
|
|
||||||
} CSeqInStreamBuf;
|
|
||||||
|
|
||||||
static SRes MyRead(void *pp, void *data, size_t *size)
|
|
||||||
{
|
|
||||||
size_t curSize = *size;
|
|
||||||
CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
|
|
||||||
if (p->rem < curSize)
|
|
||||||
curSize = p->rem;
|
|
||||||
memcpy(data, p->data, curSize);
|
|
||||||
p->rem -= curSize;
|
|
||||||
p->data += curSize;
|
|
||||||
*size = curSize;
|
|
||||||
return SZ_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CLzmaProb *litProbs;
|
CLzmaProb *litProbs;
|
||||||
@@ -274,7 +254,7 @@ typedef struct
|
|||||||
UInt32 state;
|
UInt32 state;
|
||||||
} CSaveState;
|
} CSaveState;
|
||||||
|
|
||||||
typedef struct _CLzmaEnc
|
typedef struct
|
||||||
{
|
{
|
||||||
IMatchFinder matchFinder;
|
IMatchFinder matchFinder;
|
||||||
void *matchFinderObj;
|
void *matchFinderObj;
|
||||||
@@ -351,8 +331,7 @@ typedef struct _CLzmaEnc
|
|||||||
UInt32 dictSize;
|
UInt32 dictSize;
|
||||||
UInt32 matchFinderCycles;
|
UInt32 matchFinderCycles;
|
||||||
|
|
||||||
ISeqInStream *inStream;
|
int needInit;
|
||||||
CSeqInStreamBuf seqBufInStream;
|
|
||||||
|
|
||||||
CSaveState saveState;
|
CSaveState saveState;
|
||||||
} CLzmaEnc;
|
} CLzmaEnc;
|
||||||
@@ -1754,11 +1733,10 @@ void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
|
|||||||
static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
|
static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
|
||||||
{
|
{
|
||||||
UInt32 nowPos32, startPos32;
|
UInt32 nowPos32, startPos32;
|
||||||
if (p->inStream != 0)
|
if (p->needInit)
|
||||||
{
|
{
|
||||||
p->matchFinderBase.stream = p->inStream;
|
|
||||||
p->matchFinder.Init(p->matchFinderObj);
|
p->matchFinder.Init(p->matchFinderObj);
|
||||||
p->inStream = 0;
|
p->needInit = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->finished)
|
if (p->finished)
|
||||||
@@ -2056,11 +2034,12 @@ static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *a
|
|||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
|
static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
ISzAlloc *alloc, ISzAlloc *allocBig)
|
ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
{
|
{
|
||||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||||
p->inStream = inStream;
|
p->matchFinderBase.stream = inStream;
|
||||||
|
p->needInit = 1;
|
||||||
p->rc.outStream = outStream;
|
p->rc.outStream = outStream;
|
||||||
return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
|
return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
|
||||||
}
|
}
|
||||||
@@ -2070,15 +2049,16 @@ SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
|
|||||||
ISzAlloc *alloc, ISzAlloc *allocBig)
|
ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
{
|
{
|
||||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||||
p->inStream = inStream;
|
p->matchFinderBase.stream = inStream;
|
||||||
|
p->needInit = 1;
|
||||||
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
|
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
|
static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
|
||||||
{
|
{
|
||||||
p->seqBufInStream.funcTable.Read = MyRead;
|
p->matchFinderBase.directInput = 1;
|
||||||
p->seqBufInStream.data = src;
|
p->matchFinderBase.bufferBase = (Byte *)src;
|
||||||
p->seqBufInStream.rem = srcLen;
|
p->matchFinderBase.directInputRem = srcLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
||||||
@@ -2086,7 +2066,8 @@ SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
|
|||||||
{
|
{
|
||||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||||
LzmaEnc_SetInputBuf(p, src, srcLen);
|
LzmaEnc_SetInputBuf(p, src, srcLen);
|
||||||
p->inStream = &p->seqBufInStream.funcTable;
|
p->needInit = 1;
|
||||||
|
|
||||||
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
|
return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2101,7 +2082,7 @@ void LzmaEnc_Finish(CLzmaEncHandle pp)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _CSeqOutStreamBuf
|
typedef struct
|
||||||
{
|
{
|
||||||
ISeqOutStream funcTable;
|
ISeqOutStream funcTable;
|
||||||
Byte *data;
|
Byte *data;
|
||||||
@@ -2170,10 +2151,8 @@ SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
|
static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress)
|
||||||
ISzAlloc *alloc, ISzAlloc *allocBig)
|
|
||||||
{
|
{
|
||||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
|
||||||
SRes res = SZ_OK;
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
#ifdef COMPRESS_MF_MT
|
#ifdef COMPRESS_MF_MT
|
||||||
@@ -2183,8 +2162,6 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
|
|||||||
allocaDummy[i] = (Byte)i;
|
allocaDummy[i] = (Byte)i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
|
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
|
res = LzmaEnc_CodeOneBlock(p, False, 0, 0);
|
||||||
@@ -2200,10 +2177,17 @@ SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LzmaEnc_Finish(pp);
|
LzmaEnc_Finish(p);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
|
||||||
|
ISzAlloc *alloc, ISzAlloc *allocBig)
|
||||||
|
{
|
||||||
|
RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig));
|
||||||
|
return LzmaEnc_Encode2((CLzmaEnc *)pp, progress);
|
||||||
|
}
|
||||||
|
|
||||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
|
SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
|
||||||
{
|
{
|
||||||
CLzmaEnc *p = (CLzmaEnc *)pp;
|
CLzmaEnc *p = (CLzmaEnc *)pp;
|
||||||
@@ -2249,8 +2233,11 @@ SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte
|
|||||||
outStream.overflow = False;
|
outStream.overflow = False;
|
||||||
|
|
||||||
p->writeEndMark = writeEndMark;
|
p->writeEndMark = writeEndMark;
|
||||||
res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
|
|
||||||
progress, alloc, allocBig);
|
p->rc.outStream = &outStream.funcTable;
|
||||||
|
res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
res = LzmaEnc_Encode2(p, progress);
|
||||||
|
|
||||||
*destLen -= outStream.rem;
|
*destLen -= outStream.rem;
|
||||||
if (outStream.overflow)
|
if (outStream.overflow)
|
||||||
|
|||||||
14
C/LzmaEnc.h
14
C/LzmaEnc.h
@@ -1,11 +1,15 @@
|
|||||||
/* LzmaEnc.h -- LZMA Encoder
|
/* LzmaEnc.h -- LZMA Encoder
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMAENC_H
|
#ifndef __LZMA_ENC_H
|
||||||
#define __LZMAENC_H
|
#define __LZMA_ENC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define LZMA_PROPS_SIZE 5
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
typedef struct _CLzmaEncProps
|
typedef struct _CLzmaEncProps
|
||||||
@@ -69,4 +73,8 @@ SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
|||||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
18
C/LzmaLib.h
18
C/LzmaLib.h
@@ -1,20 +1,16 @@
|
|||||||
/* LzmaLib.h -- LZMA library interface
|
/* LzmaLib.h -- LZMA library interface
|
||||||
2008-08-05
|
2009-04-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __LZMALIB_H
|
#ifndef __LZMA_LIB_H
|
||||||
#define __LZMALIB_H
|
#define __LZMA_LIB_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define MY_EXTERN_C extern "C"
|
extern "C" {
|
||||||
#else
|
|
||||||
#define MY_EXTERN_C extern
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL
|
#define MY_STDAPI int MY_STD_CALL
|
||||||
|
|
||||||
#define LZMA_PROPS_SIZE 5
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
@@ -132,4 +128,8 @@ Returns:
|
|||||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
|
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src, SizeT *srcLen,
|
||||||
const unsigned char *props, size_t propsSize);
|
const unsigned char *props, size_t propsSize);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
|
/* Lzma86Dec.h -- LZMA + x86 (BCJ) Filter Decoder
|
||||||
2008-08-05
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __LZMA86DEC_H
|
#ifndef __LZMA86_DEC_H
|
||||||
#define __LZMA86DEC_H
|
#define __LZMA86_DEC_H
|
||||||
|
|
||||||
#include "../Types.h"
|
#include "../Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Lzma86_GetUnpackSize:
|
Lzma86_GetUnpackSize:
|
||||||
In:
|
In:
|
||||||
@@ -42,4 +44,8 @@ Lzma86_Decode:
|
|||||||
|
|
||||||
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
|
SRes Lzma86_Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder
|
/* Lzma86Enc.h -- LZMA + x86 (BCJ) Filter Encoder
|
||||||
2008-08-05
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __LZMA86ENC_H
|
#ifndef __LZMA86_ENC_H
|
||||||
#define __LZMA86ENC_H
|
#define __LZMA86_ENC_H
|
||||||
|
|
||||||
#include "../Types.h"
|
#include "../Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
It's an example for LZMA + x86 Filter use.
|
It's an example for LZMA + x86 Filter use.
|
||||||
You can use .lzma86 extension, if you write that stream to file.
|
You can use .lzma86 extension, if you write that stream to file.
|
||||||
@@ -69,4 +71,8 @@ enum ESzFilterMode
|
|||||||
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
SRes Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
|
||||||
int level, UInt32 dictSize, int filterMode);
|
int level, UInt32 dictSize, int filterMode);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
327
C/MtCoder.c
Executable file
327
C/MtCoder.c
Executable file
@@ -0,0 +1,327 @@
|
|||||||
|
/* MtCoder.c -- Multi-thread Coder
|
||||||
|
2009-03-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "MtCoder.h"
|
||||||
|
|
||||||
|
void LoopThread_Construct(CLoopThread *p)
|
||||||
|
{
|
||||||
|
Thread_Construct(&p->thread);
|
||||||
|
Event_Construct(&p->startEvent);
|
||||||
|
Event_Construct(&p->finishedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoopThread_Close(CLoopThread *p)
|
||||||
|
{
|
||||||
|
Thread_Close(&p->thread);
|
||||||
|
Event_Close(&p->startEvent);
|
||||||
|
Event_Close(&p->finishedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE LoopThreadFunc(void *pp)
|
||||||
|
{
|
||||||
|
CLoopThread *p = (CLoopThread *)pp;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (Event_Wait(&p->startEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
if (p->stop)
|
||||||
|
return 0;
|
||||||
|
p->res = p->func(p->param);
|
||||||
|
if (Event_Set(&p->finishedEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_Create(CLoopThread *p)
|
||||||
|
{
|
||||||
|
p->stop = 0;
|
||||||
|
RINOK(AutoResetEvent_CreateNotSignaled(&p->startEvent));
|
||||||
|
RINOK(AutoResetEvent_CreateNotSignaled(&p->finishedEvent));
|
||||||
|
return Thread_Create(&p->thread, LoopThreadFunc, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_StopAndWait(CLoopThread *p)
|
||||||
|
{
|
||||||
|
p->stop = 1;
|
||||||
|
if (Event_Set(&p->startEvent) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
return Thread_Wait(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
WRes LoopThread_StartSubThread(CLoopThread *p) { return Event_Set(&p->startEvent); }
|
||||||
|
WRes LoopThread_WaitSubThread(CLoopThread *p) { return Event_Wait(&p->finishedEvent); }
|
||||||
|
|
||||||
|
static SRes Progress(ICompressProgress *p, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
return (p && p->Progress(p, inSize, outSize) != SZ_OK) ? SZ_ERROR_PROGRESS : SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtProgress_Init(CMtProgress *p, ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
p->inSizes[i] = p->outSizes[i] = 0;
|
||||||
|
p->totalInSize = p->totalOutSize = 0;
|
||||||
|
p->progress = progress;
|
||||||
|
p->res = SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtProgress_Reinit(CMtProgress *p, unsigned index)
|
||||||
|
{
|
||||||
|
p->inSizes[index] = 0;
|
||||||
|
p->outSizes[index] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UPDATE_PROGRESS(size, prev, total) \
|
||||||
|
if (size != (UInt64)(Int64)-1) { total += size - prev; prev = size; }
|
||||||
|
|
||||||
|
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
UPDATE_PROGRESS(inSize, p->inSizes[index], p->totalInSize)
|
||||||
|
UPDATE_PROGRESS(outSize, p->outSizes[index], p->totalOutSize)
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
p->res = Progress(p->progress, p->totalInSize, p->totalOutSize);
|
||||||
|
res = p->res;
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtProgress_SetError(CMtProgress *p, SRes res)
|
||||||
|
{
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
p->res = res;
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void MtCoder_SetError(CMtCoder* p, SRes res)
|
||||||
|
{
|
||||||
|
CriticalSection_Enter(&p->cs);
|
||||||
|
if (p->res == SZ_OK)
|
||||||
|
p->res = res;
|
||||||
|
CriticalSection_Leave(&p->cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- MtThread ---------- */
|
||||||
|
|
||||||
|
void CMtThread_Construct(CMtThread *p, CMtCoder *mtCoder)
|
||||||
|
{
|
||||||
|
p->mtCoder = mtCoder;
|
||||||
|
p->outBuf = 0;
|
||||||
|
p->inBuf = 0;
|
||||||
|
Event_Construct(&p->canRead);
|
||||||
|
Event_Construct(&p->canWrite);
|
||||||
|
LoopThread_Construct(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RINOK_THREAD(x) { if((x) != 0) return SZ_ERROR_THREAD; }
|
||||||
|
|
||||||
|
static void CMtThread_CloseEvents(CMtThread *p)
|
||||||
|
{
|
||||||
|
Event_Close(&p->canRead);
|
||||||
|
Event_Close(&p->canWrite);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CMtThread_Destruct(CMtThread *p)
|
||||||
|
{
|
||||||
|
CMtThread_CloseEvents(p);
|
||||||
|
|
||||||
|
if (Thread_WasCreated(&p->thread.thread))
|
||||||
|
{
|
||||||
|
LoopThread_StopAndWait(&p->thread);
|
||||||
|
LoopThread_Close(&p->thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->mtCoder->alloc)
|
||||||
|
IAlloc_Free(p->mtCoder->alloc, p->outBuf);
|
||||||
|
p->outBuf = 0;
|
||||||
|
|
||||||
|
if (p->mtCoder->alloc)
|
||||||
|
IAlloc_Free(p->mtCoder->alloc, p->inBuf);
|
||||||
|
p->inBuf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MY_BUF_ALLOC(buf, size, newSize) \
|
||||||
|
if (buf == 0 || size != newSize) \
|
||||||
|
{ IAlloc_Free(p->mtCoder->alloc, buf); \
|
||||||
|
size = newSize; buf = IAlloc_Alloc(p->mtCoder->alloc, size); \
|
||||||
|
if (buf == 0) return SZ_ERROR_MEM; }
|
||||||
|
|
||||||
|
static SRes CMtThread_Prepare(CMtThread *p)
|
||||||
|
{
|
||||||
|
MY_BUF_ALLOC(p->inBuf, p->inBufSize, p->mtCoder->blockSize)
|
||||||
|
MY_BUF_ALLOC(p->outBuf, p->outBufSize, p->mtCoder->destBlockSize)
|
||||||
|
|
||||||
|
p->stopReading = False;
|
||||||
|
p->stopWriting = False;
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canRead));
|
||||||
|
RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canWrite));
|
||||||
|
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes FullRead(ISeqInStream *stream, Byte *data, size_t *processedSize)
|
||||||
|
{
|
||||||
|
size_t size = *processedSize;
|
||||||
|
*processedSize = 0;
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
size_t curSize = size;
|
||||||
|
SRes res = stream->Read(stream, data, &curSize);
|
||||||
|
*processedSize += curSize;
|
||||||
|
data += curSize;
|
||||||
|
size -= curSize;
|
||||||
|
RINOK(res);
|
||||||
|
if (curSize == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_NEXT_THREAD(p) &p->mtCoder->threads[p->index == p->mtCoder->numThreads - 1 ? 0 : p->index + 1]
|
||||||
|
|
||||||
|
static SRes MtThread_Process(CMtThread *p, Bool *stop)
|
||||||
|
{
|
||||||
|
CMtThread *next;
|
||||||
|
*stop = True;
|
||||||
|
if (Event_Wait(&p->canRead) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
|
||||||
|
next = GET_NEXT_THREAD(p);
|
||||||
|
|
||||||
|
if (p->stopReading)
|
||||||
|
{
|
||||||
|
next->stopReading = True;
|
||||||
|
return Event_Set(&next->canRead) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
size_t size = p->mtCoder->blockSize;
|
||||||
|
size_t destSize = p->outBufSize;
|
||||||
|
|
||||||
|
RINOK(FullRead(p->mtCoder->inStream, p->inBuf, &size));
|
||||||
|
next->stopReading = *stop = (size != p->mtCoder->blockSize);
|
||||||
|
if (Event_Set(&next->canRead) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
|
||||||
|
RINOK(p->mtCoder->mtCallback->Code(p->mtCoder->mtCallback, p->index,
|
||||||
|
p->outBuf, &destSize, p->inBuf, size, *stop));
|
||||||
|
|
||||||
|
MtProgress_Reinit(&p->mtCoder->mtProgress, p->index);
|
||||||
|
|
||||||
|
if (Event_Wait(&p->canWrite) != 0)
|
||||||
|
return SZ_ERROR_THREAD;
|
||||||
|
if (p->stopWriting)
|
||||||
|
return SZ_ERROR_FAIL;
|
||||||
|
if (p->mtCoder->outStream->Write(p->mtCoder->outStream, p->outBuf, destSize) != destSize)
|
||||||
|
return SZ_ERROR_WRITE;
|
||||||
|
return Event_Set(&next->canWrite) == 0 ? SZ_OK : SZ_ERROR_THREAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE ThreadFunc(void *pp)
|
||||||
|
{
|
||||||
|
CMtThread *p = (CMtThread *)pp;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Bool stop;
|
||||||
|
CMtThread *next = GET_NEXT_THREAD(p);
|
||||||
|
SRes res = MtThread_Process(p, &stop);
|
||||||
|
if (res != SZ_OK)
|
||||||
|
{
|
||||||
|
MtCoder_SetError(p->mtCoder, res);
|
||||||
|
MtProgress_SetError(&p->mtCoder->mtProgress, res);
|
||||||
|
next->stopReading = True;
|
||||||
|
next->stopWriting = True;
|
||||||
|
Event_Set(&next->canRead);
|
||||||
|
Event_Set(&next->canWrite);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (stop)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtCoder_Construct(CMtCoder* p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
p->alloc = 0;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
t->index = i;
|
||||||
|
CMtThread_Construct(t, p);
|
||||||
|
}
|
||||||
|
CriticalSection_Init(&p->cs);
|
||||||
|
CriticalSection_Init(&p->mtProgress.cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MtCoder_Destruct(CMtCoder* p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
for (i = 0; i < NUM_MT_CODER_THREADS_MAX; i++)
|
||||||
|
CMtThread_Destruct(&p->threads[i]);
|
||||||
|
CriticalSection_Delete(&p->cs);
|
||||||
|
CriticalSection_Delete(&p->mtProgress.cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes MtCoder_Code(CMtCoder *p)
|
||||||
|
{
|
||||||
|
unsigned i, numThreads = p->numThreads;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
p->res = SZ_OK;
|
||||||
|
|
||||||
|
MtProgress_Init(&p->mtProgress, p->progress);
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
RINOK(CMtThread_Prepare(&p->threads[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
CLoopThread *lt = &t->thread;
|
||||||
|
|
||||||
|
if (!Thread_WasCreated(<->thread))
|
||||||
|
{
|
||||||
|
lt->func = ThreadFunc;
|
||||||
|
lt->param = t;
|
||||||
|
|
||||||
|
if (LoopThread_Create(lt) != SZ_OK)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_THREAD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == SZ_OK)
|
||||||
|
{
|
||||||
|
unsigned j;
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
{
|
||||||
|
CMtThread *t = &p->threads[i];
|
||||||
|
if (LoopThread_StartSubThread(&t->thread) != SZ_OK || i == 10)
|
||||||
|
{
|
||||||
|
res = SZ_ERROR_THREAD;
|
||||||
|
p->threads[0].stopReading = True;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Event_Set(&p->threads[0].canWrite);
|
||||||
|
Event_Set(&p->threads[0].canRead);
|
||||||
|
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
LoopThread_WaitSubThread(&p->threads[j].thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < numThreads; i++)
|
||||||
|
CMtThread_CloseEvents(&p->threads[i]);
|
||||||
|
return (res == SZ_OK) ? p->res : res;
|
||||||
|
}
|
||||||
102
C/MtCoder.h
Executable file
102
C/MtCoder.h
Executable file
@@ -0,0 +1,102 @@
|
|||||||
|
/* MtCoder.h -- Multi-thread Coder
|
||||||
|
2009-03-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __MT_CODER_H
|
||||||
|
#define __MT_CODER_H
|
||||||
|
|
||||||
|
#include "Threads.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CThread thread;
|
||||||
|
CAutoResetEvent startEvent;
|
||||||
|
CAutoResetEvent finishedEvent;
|
||||||
|
int stop;
|
||||||
|
|
||||||
|
THREAD_FUNC_TYPE func;
|
||||||
|
LPVOID param;
|
||||||
|
THREAD_FUNC_RET_TYPE res;
|
||||||
|
} CLoopThread;
|
||||||
|
|
||||||
|
void LoopThread_Construct(CLoopThread *p);
|
||||||
|
void LoopThread_Close(CLoopThread *p);
|
||||||
|
WRes LoopThread_Create(CLoopThread *p);
|
||||||
|
WRes LoopThread_StopAndWait(CLoopThread *p);
|
||||||
|
WRes LoopThread_StartSubThread(CLoopThread *p);
|
||||||
|
WRes LoopThread_WaitSubThread(CLoopThread *p);
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 32
|
||||||
|
#else
|
||||||
|
#define NUM_MT_CODER_THREADS_MAX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 totalInSize;
|
||||||
|
UInt64 totalOutSize;
|
||||||
|
ICompressProgress *progress;
|
||||||
|
SRes res;
|
||||||
|
CCriticalSection cs;
|
||||||
|
UInt64 inSizes[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
UInt64 outSizes[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
} CMtProgress;
|
||||||
|
|
||||||
|
SRes MtProgress_Set(CMtProgress *p, unsigned index, UInt64 inSize, UInt64 outSize);
|
||||||
|
|
||||||
|
struct _CMtCoder;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct _CMtCoder *mtCoder;
|
||||||
|
Byte *outBuf;
|
||||||
|
size_t outBufSize;
|
||||||
|
Byte *inBuf;
|
||||||
|
size_t inBufSize;
|
||||||
|
unsigned index;
|
||||||
|
CLoopThread thread;
|
||||||
|
|
||||||
|
Bool stopReading;
|
||||||
|
Bool stopWriting;
|
||||||
|
CAutoResetEvent canRead;
|
||||||
|
CAutoResetEvent canWrite;
|
||||||
|
} CMtThread;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
SRes (*Code)(void *p, unsigned index, Byte *dest, size_t *destSize,
|
||||||
|
const Byte *src, size_t srcSize, int finished);
|
||||||
|
} IMtCoderCallback;
|
||||||
|
|
||||||
|
typedef struct _CMtCoder
|
||||||
|
{
|
||||||
|
size_t blockSize;
|
||||||
|
size_t destBlockSize;
|
||||||
|
unsigned numThreads;
|
||||||
|
|
||||||
|
ISeqInStream *inStream;
|
||||||
|
ISeqOutStream *outStream;
|
||||||
|
ICompressProgress *progress;
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
|
||||||
|
IMtCoderCallback *mtCallback;
|
||||||
|
CCriticalSection cs;
|
||||||
|
SRes res;
|
||||||
|
|
||||||
|
CMtProgress mtProgress;
|
||||||
|
CMtThread threads[NUM_MT_CODER_THREADS_MAX];
|
||||||
|
} CMtCoder;
|
||||||
|
|
||||||
|
void MtCoder_Construct(CMtCoder* p);
|
||||||
|
void MtCoder_Destruct(CMtCoder* p);
|
||||||
|
SRes MtCoder_Code(CMtCoder *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
/* RotateDefs.h -- Rotate functions
|
/* RotateDefs.h -- Rotate functions
|
||||||
2008-08-05
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __ROTATEDEFS_H
|
#ifndef __ROTATE_DEFS_H
|
||||||
#define __ROTATEDEFS_H
|
#define __ROTATE_DEFS_H
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
|||||||
12
C/Sha256.h
12
C/Sha256.h
@@ -1,11 +1,15 @@
|
|||||||
/* Crypto/Sha256.h -- SHA-256 Hash function
|
/* Sha256.h -- SHA-256 Hash
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __CRYPTO_SHA256_H
|
#ifndef __CRYPTO_SHA256_H
|
||||||
#define __CRYPTO_SHA256_H
|
#define __CRYPTO_SHA256_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SHA256_DIGEST_SIZE 32
|
#define SHA256_DIGEST_SIZE 32
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@@ -19,4 +23,8 @@ void Sha256_Init(CSha256 *p);
|
|||||||
void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
|
void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
|
||||||
void Sha256_Final(CSha256 *p, Byte *digest);
|
void Sha256_Final(CSha256 *p, Byte *digest);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
C/Sort.h
12
C/Sort.h
@@ -1,14 +1,20 @@
|
|||||||
/* Sort.h -- Sort functions
|
/* Sort.h -- Sort functions
|
||||||
2008-03-19
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
|
||||||
|
|
||||||
#ifndef __7Z_SORT_H
|
#ifndef __7Z_SORT_H
|
||||||
#define __7Z_SORT_H
|
#define __7Z_SORT_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
void HeapSort(UInt32 *p, UInt32 size);
|
void HeapSort(UInt32 *p, UInt32 size);
|
||||||
/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
|
/* void HeapSortRef(UInt32 *p, UInt32 *vals, UInt32 size); */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
102
C/Threads.c
102
C/Threads.c
@@ -1,10 +1,9 @@
|
|||||||
/* Threads.c -- multithreading library
|
/* Threads.c -- multithreading library
|
||||||
2008-08-05
|
2009-03-27 : Igor Pavlov : Public domain */
|
||||||
Igor Pavlov
|
|
||||||
Public domain */
|
#include <process.h>
|
||||||
|
|
||||||
#include "Threads.h"
|
#include "Threads.h"
|
||||||
#include <process.h>
|
|
||||||
|
|
||||||
static WRes GetError()
|
static WRes GetError()
|
||||||
{
|
{
|
||||||
@@ -15,85 +14,53 @@ static WRes GetError()
|
|||||||
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
|
WRes HandleToWRes(HANDLE h) { return (h != 0) ? 0 : GetError(); }
|
||||||
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
|
WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); }
|
||||||
|
|
||||||
static WRes MyCloseHandle(HANDLE *h)
|
WRes HandlePtr_Close(HANDLE *p)
|
||||||
{
|
{
|
||||||
if (*h != NULL)
|
if (*p != NULL)
|
||||||
if (!CloseHandle(*h))
|
if (!CloseHandle(*p))
|
||||||
return GetError();
|
return GetError();
|
||||||
*h = NULL;
|
*p = NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter)
|
WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); }
|
||||||
|
|
||||||
|
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||||
{
|
{
|
||||||
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
unsigned threadId; /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||||
thread->handle =
|
*p =
|
||||||
/* CreateThread(0, 0, startAddress, parameter, 0, &threadId); */
|
/* CreateThread(0, 0, startAddress, param, 0, &threadId); */
|
||||||
(HANDLE)_beginthreadex(NULL, 0, startAddress, parameter, 0, &threadId);
|
(HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId);
|
||||||
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
/* maybe we must use errno here, but probably GetLastError() is also OK. */
|
||||||
return HandleToWRes(thread->handle);
|
return HandleToWRes(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
WRes WaitObject(HANDLE h)
|
WRes Event_Create(CEvent *p, BOOL manualReset, int signaled)
|
||||||
{
|
{
|
||||||
return (WRes)WaitForSingleObject(h, INFINITE);
|
*p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL);
|
||||||
|
return HandleToWRes(*p);
|
||||||
}
|
}
|
||||||
|
|
||||||
WRes Thread_Wait(CThread *thread)
|
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); }
|
||||||
|
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); }
|
||||||
|
|
||||||
|
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); }
|
||||||
|
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); }
|
||||||
|
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); }
|
||||||
|
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); }
|
||||||
|
|
||||||
|
|
||||||
|
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount)
|
||||||
{
|
{
|
||||||
if (thread->handle == NULL)
|
*p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL);
|
||||||
return 1;
|
return HandleToWRes(*p);
|
||||||
return WaitObject(thread->handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WRes Thread_Close(CThread *thread)
|
static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
|
||||||
{
|
{ return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); }
|
||||||
return MyCloseHandle(&thread->handle);
|
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num)
|
||||||
}
|
{ return Semaphore_Release(p, (LONG)num, NULL); }
|
||||||
|
WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); }
|
||||||
WRes Event_Create(CEvent *p, BOOL manualReset, int initialSignaled)
|
|
||||||
{
|
|
||||||
p->handle = CreateEvent(NULL, manualReset, (initialSignaled ? TRUE : FALSE), NULL);
|
|
||||||
return HandleToWRes(p->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRes ManualResetEvent_Create(CManualResetEvent *p, int initialSignaled)
|
|
||||||
{ return Event_Create(p, TRUE, initialSignaled); }
|
|
||||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p)
|
|
||||||
{ return ManualResetEvent_Create(p, 0); }
|
|
||||||
|
|
||||||
WRes AutoResetEvent_Create(CAutoResetEvent *p, int initialSignaled)
|
|
||||||
{ return Event_Create(p, FALSE, initialSignaled); }
|
|
||||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p)
|
|
||||||
{ return AutoResetEvent_Create(p, 0); }
|
|
||||||
|
|
||||||
WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(p->handle)); }
|
|
||||||
WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(p->handle)); }
|
|
||||||
WRes Event_Wait(CEvent *p) { return WaitObject(p->handle); }
|
|
||||||
WRes Event_Close(CEvent *p) { return MyCloseHandle(&p->handle); }
|
|
||||||
|
|
||||||
|
|
||||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount)
|
|
||||||
{
|
|
||||||
p->handle = CreateSemaphore(NULL, (LONG)initiallyCount, (LONG)maxCount, NULL);
|
|
||||||
return HandleToWRes(p->handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount)
|
|
||||||
{
|
|
||||||
return BOOLToWRes(ReleaseSemaphore(p->handle, releaseCount, previousCount));
|
|
||||||
}
|
|
||||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 releaseCount)
|
|
||||||
{
|
|
||||||
return Semaphore_Release(p, (LONG)releaseCount, NULL);
|
|
||||||
}
|
|
||||||
WRes Semaphore_Release1(CSemaphore *p)
|
|
||||||
{
|
|
||||||
return Semaphore_ReleaseN(p, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
WRes Semaphore_Wait(CSemaphore *p) { return WaitObject(p->handle); }
|
|
||||||
WRes Semaphore_Close(CSemaphore *p) { return MyCloseHandle(&p->handle); }
|
|
||||||
|
|
||||||
WRes CriticalSection_Init(CCriticalSection *p)
|
WRes CriticalSection_Init(CCriticalSection *p)
|
||||||
{
|
{
|
||||||
@@ -106,4 +73,3 @@ WRes CriticalSection_Init(CCriticalSection *p)
|
|||||||
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
|
__except (EXCEPTION_EXECUTE_HANDLER) { return 1; }
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
77
C/Threads.h
77
C/Threads.h
@@ -1,68 +1,59 @@
|
|||||||
/* Threads.h -- multithreading library
|
/* Threads.h -- multithreading library
|
||||||
2008-11-22 : Igor Pavlov : Public domain */
|
2009-03-27 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_THRESDS_H
|
#ifndef __7Z_THREADS_H
|
||||||
#define __7Z_THRESDS_H
|
#define __7Z_THREADS_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
typedef struct _CThread
|
#ifdef __cplusplus
|
||||||
{
|
extern "C" {
|
||||||
HANDLE handle;
|
#endif
|
||||||
} CThread;
|
|
||||||
|
|
||||||
#define Thread_Construct(thread) (thread)->handle = NULL
|
WRes HandlePtr_Close(HANDLE *h);
|
||||||
#define Thread_WasCreated(thread) ((thread)->handle != NULL)
|
WRes Handle_WaitObject(HANDLE h);
|
||||||
|
|
||||||
|
typedef HANDLE CThread;
|
||||||
|
#define Thread_Construct(p) *(p) = NULL
|
||||||
|
#define Thread_WasCreated(p) (*(p) != NULL)
|
||||||
|
#define Thread_Close(p) HandlePtr_Close(p)
|
||||||
|
#define Thread_Wait(p) Handle_WaitObject(*(p))
|
||||||
typedef unsigned THREAD_FUNC_RET_TYPE;
|
typedef unsigned THREAD_FUNC_RET_TYPE;
|
||||||
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
#define THREAD_FUNC_CALL_TYPE MY_STD_CALL
|
||||||
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE
|
||||||
|
typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *);
|
||||||
|
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param);
|
||||||
|
|
||||||
WRes Thread_Create(CThread *thread, THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE *startAddress)(void *), LPVOID parameter);
|
typedef HANDLE CEvent;
|
||||||
WRes Thread_Wait(CThread *thread);
|
|
||||||
WRes Thread_Close(CThread *thread);
|
|
||||||
|
|
||||||
typedef struct _CEvent
|
|
||||||
{
|
|
||||||
HANDLE handle;
|
|
||||||
} CEvent;
|
|
||||||
|
|
||||||
typedef CEvent CAutoResetEvent;
|
typedef CEvent CAutoResetEvent;
|
||||||
typedef CEvent CManualResetEvent;
|
typedef CEvent CManualResetEvent;
|
||||||
|
#define Event_Construct(p) *(p) = NULL
|
||||||
|
#define Event_IsCreated(p) (*(p) != NULL)
|
||||||
|
#define Event_Close(p) HandlePtr_Close(p)
|
||||||
|
#define Event_Wait(p) Handle_WaitObject(*(p))
|
||||||
|
WRes Event_Set(CEvent *p);
|
||||||
|
WRes Event_Reset(CEvent *p);
|
||||||
|
WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled);
|
||||||
|
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p);
|
||||||
|
WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled);
|
||||||
|
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p);
|
||||||
|
|
||||||
#define Event_Construct(event) (event)->handle = NULL
|
typedef HANDLE CSemaphore;
|
||||||
#define Event_IsCreated(event) ((event)->handle != NULL)
|
#define Semaphore_Construct(p) (*p) = NULL
|
||||||
|
#define Semaphore_Close(p) HandlePtr_Close(p)
|
||||||
WRes ManualResetEvent_Create(CManualResetEvent *event, int initialSignaled);
|
#define Semaphore_Wait(p) Handle_WaitObject(*(p))
|
||||||
WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *event);
|
WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount);
|
||||||
WRes AutoResetEvent_Create(CAutoResetEvent *event, int initialSignaled);
|
|
||||||
WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *event);
|
|
||||||
WRes Event_Set(CEvent *event);
|
|
||||||
WRes Event_Reset(CEvent *event);
|
|
||||||
WRes Event_Wait(CEvent *event);
|
|
||||||
WRes Event_Close(CEvent *event);
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _CSemaphore
|
|
||||||
{
|
|
||||||
HANDLE handle;
|
|
||||||
} CSemaphore;
|
|
||||||
|
|
||||||
#define Semaphore_Construct(p) (p)->handle = NULL
|
|
||||||
|
|
||||||
WRes Semaphore_Create(CSemaphore *p, UInt32 initiallyCount, UInt32 maxCount);
|
|
||||||
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num);
|
||||||
WRes Semaphore_Release1(CSemaphore *p);
|
WRes Semaphore_Release1(CSemaphore *p);
|
||||||
WRes Semaphore_Wait(CSemaphore *p);
|
|
||||||
WRes Semaphore_Close(CSemaphore *p);
|
|
||||||
|
|
||||||
|
|
||||||
typedef CRITICAL_SECTION CCriticalSection;
|
typedef CRITICAL_SECTION CCriticalSection;
|
||||||
|
|
||||||
WRes CriticalSection_Init(CCriticalSection *p);
|
WRes CriticalSection_Init(CCriticalSection *p);
|
||||||
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
|
#define CriticalSection_Delete(p) DeleteCriticalSection(p)
|
||||||
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
#define CriticalSection_Enter(p) EnterCriticalSection(p)
|
||||||
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
#define CriticalSection_Leave(p) LeaveCriticalSection(p)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
10
C/Types.h
10
C/Types.h
@@ -1,5 +1,5 @@
|
|||||||
/* Types.h -- Basic types
|
/* Types.h -- Basic types
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_TYPES_H
|
#ifndef __7Z_TYPES_H
|
||||||
#define __7Z_TYPES_H
|
#define __7Z_TYPES_H
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
#define SZ_OK 0
|
#define SZ_OK 0
|
||||||
|
|
||||||
#define SZ_ERROR_DATA 1
|
#define SZ_ERROR_DATA 1
|
||||||
@@ -205,4 +209,8 @@ typedef struct
|
|||||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
88
C/Xz.c
Executable file
88
C/Xz.c
Executable file
@@ -0,0 +1,88 @@
|
|||||||
|
/* Xz.c - Xz
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
#include "Xz.h"
|
||||||
|
#include "XzCrc64.h"
|
||||||
|
|
||||||
|
Byte XZ_SIG[XZ_SIG_SIZE] = { 0xFD, '7', 'z', 'X', 'Z', 0 };
|
||||||
|
Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE] = { 'Y', 'Z' };
|
||||||
|
|
||||||
|
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v)
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
buf[i++] = (Byte)((v & 0x7F) | 0x80);
|
||||||
|
v >>= 7;
|
||||||
|
}
|
||||||
|
while (v != 0);
|
||||||
|
buf[i - 1] &= 0x7F;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xz_Construct(CXzStream *p)
|
||||||
|
{
|
||||||
|
p->numBlocks = p->numBlocksAllocated = 0;
|
||||||
|
p->blocks = 0;
|
||||||
|
p->flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xz_Free(CXzStream *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, p->blocks);
|
||||||
|
p->numBlocks = p->numBlocksAllocated = 0;
|
||||||
|
p->blocks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned XzFlags_GetCheckSize(CXzStreamFlags f)
|
||||||
|
{
|
||||||
|
int t = XzFlags_GetCheckType(f);
|
||||||
|
return (t == 0) ? 0 : (4 << ((t - 1) / 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void XzCheck_Init(CXzCheck *p, int mode)
|
||||||
|
{
|
||||||
|
p->mode = mode;
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32: p->crc = CRC_INIT_VAL; break;
|
||||||
|
case XZ_CHECK_CRC64: p->crc64 = CRC64_INIT_VAL; break;
|
||||||
|
case XZ_CHECK_SHA256: Sha256_Init(&p->sha); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XzCheck_Update(CXzCheck *p, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
switch (p->mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32: p->crc = CrcUpdate(p->crc, data, size); break;
|
||||||
|
case XZ_CHECK_CRC64: p->crc64 = Crc64Update(p->crc64, data, size); break;
|
||||||
|
case XZ_CHECK_SHA256: Sha256_Update(&p->sha, (const Byte *)data, size); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int XzCheck_Final(CXzCheck *p, Byte *digest)
|
||||||
|
{
|
||||||
|
switch (p->mode)
|
||||||
|
{
|
||||||
|
case XZ_CHECK_CRC32:
|
||||||
|
SetUi32(digest, CRC_GET_DIGEST(p->crc));
|
||||||
|
break;
|
||||||
|
case XZ_CHECK_CRC64:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
UInt64 v = CRC64_GET_DIGEST(p->crc64);
|
||||||
|
for (i = 0; i < 8; i++, v >>= 8)
|
||||||
|
digest[i] = (Byte)(v & 0xFF);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case XZ_CHECK_SHA256:
|
||||||
|
Sha256_Final(&p->sha, digest);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
256
C/Xz.h
Executable file
256
C/Xz.h
Executable file
@@ -0,0 +1,256 @@
|
|||||||
|
/* Xz.h - Xz interface
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __XZ_H
|
||||||
|
#define __XZ_H
|
||||||
|
|
||||||
|
#include "Sha256.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define XZ_ID_Subblock 1
|
||||||
|
#define XZ_ID_Delta 3
|
||||||
|
#define XZ_ID_X86 4
|
||||||
|
#define XZ_ID_PPC 5
|
||||||
|
#define XZ_ID_IA64 6
|
||||||
|
#define XZ_ID_ARM 7
|
||||||
|
#define XZ_ID_ARMT 8
|
||||||
|
#define XZ_ID_SPARC 9
|
||||||
|
#define XZ_ID_LZMA2 0x21
|
||||||
|
|
||||||
|
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value);
|
||||||
|
unsigned Xz_WriteVarInt(Byte *buf, UInt64 v);
|
||||||
|
|
||||||
|
/* ---------- xz block ---------- */
|
||||||
|
|
||||||
|
#define XZ_BLOCK_HEADER_SIZE_MAX 1024
|
||||||
|
|
||||||
|
#define XZ_NUM_FILTERS_MAX 4
|
||||||
|
#define XZ_BF_NUM_FILTERS_MASK 3
|
||||||
|
#define XZ_BF_PACK_SIZE (1 << 6)
|
||||||
|
#define XZ_BF_UNPACK_SIZE (1 << 7)
|
||||||
|
|
||||||
|
#define XZ_FILTER_PROPS_SIZE_MAX 20
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 id;
|
||||||
|
UInt32 propsSize;
|
||||||
|
Byte props[XZ_FILTER_PROPS_SIZE_MAX];
|
||||||
|
} CXzFilter;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 packSize;
|
||||||
|
UInt64 unpackSize;
|
||||||
|
Byte flags;
|
||||||
|
CXzFilter filters[XZ_NUM_FILTERS_MAX];
|
||||||
|
} CXzBlock;
|
||||||
|
|
||||||
|
#define XzBlock_GetNumFilters(p) (((p)->flags & XZ_BF_NUM_FILTERS_MASK) + 1)
|
||||||
|
#define XzBlock_HasPackSize(p) (((p)->flags & XZ_BF_PACK_SIZE) != 0)
|
||||||
|
#define XzBlock_HasUnpackSize(p) (((p)->flags & XZ_BF_UNPACK_SIZE) != 0)
|
||||||
|
|
||||||
|
SRes XzBlock_Parse(CXzBlock *p, const Byte *header);
|
||||||
|
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes);
|
||||||
|
|
||||||
|
/* ---------- xz stream ---------- */
|
||||||
|
|
||||||
|
#define XZ_SIG_SIZE 6
|
||||||
|
#define XZ_FOOTER_SIG_SIZE 2
|
||||||
|
|
||||||
|
extern Byte XZ_SIG[XZ_SIG_SIZE];
|
||||||
|
extern Byte XZ_FOOTER_SIG[XZ_FOOTER_SIG_SIZE];
|
||||||
|
|
||||||
|
#define XZ_STREAM_FLAGS_SIZE 2
|
||||||
|
#define XZ_STREAM_CRC_SIZE 4
|
||||||
|
|
||||||
|
#define XZ_STREAM_HEADER_SIZE (XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE)
|
||||||
|
#define XZ_STREAM_FOOTER_SIZE (XZ_FOOTER_SIG_SIZE + XZ_STREAM_FLAGS_SIZE + XZ_STREAM_CRC_SIZE + 4)
|
||||||
|
|
||||||
|
#define XZ_CHECK_MASK 0xF
|
||||||
|
#define XZ_CHECK_NO 0
|
||||||
|
#define XZ_CHECK_CRC32 1
|
||||||
|
#define XZ_CHECK_CRC64 4
|
||||||
|
#define XZ_CHECK_SHA256 10
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int mode;
|
||||||
|
UInt32 crc;
|
||||||
|
UInt64 crc64;
|
||||||
|
CSha256 sha;
|
||||||
|
} CXzCheck;
|
||||||
|
|
||||||
|
void XzCheck_Init(CXzCheck *p, int mode);
|
||||||
|
void XzCheck_Update(CXzCheck *p, const void *data, size_t size);
|
||||||
|
int XzCheck_Final(CXzCheck *p, Byte *digest);
|
||||||
|
|
||||||
|
typedef UInt16 CXzStreamFlags;
|
||||||
|
|
||||||
|
#define XzFlags_IsSupported(f) ((f) <= XZ_CHECK_MASK)
|
||||||
|
#define XzFlags_GetCheckType(f) ((f) & XZ_CHECK_MASK)
|
||||||
|
#define XzFlags_HasDataCrc32(f) (Xz_GetCheckType(f) == XZ_CHECK_CRC32)
|
||||||
|
unsigned XzFlags_GetCheckSize(CXzStreamFlags f);
|
||||||
|
|
||||||
|
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf);
|
||||||
|
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UInt64 unpackSize;
|
||||||
|
UInt64 totalSize;
|
||||||
|
} CXzBlockSizes;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
CXzStreamFlags flags;
|
||||||
|
size_t numBlocks;
|
||||||
|
size_t numBlocksAllocated;
|
||||||
|
CXzBlockSizes *blocks;
|
||||||
|
UInt64 startOffset;
|
||||||
|
} CXzStream;
|
||||||
|
|
||||||
|
void Xz_Construct(CXzStream *p);
|
||||||
|
void Xz_Free(CXzStream *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
#define XZ_SIZE_OVERFLOW ((UInt64)(Int64)-1)
|
||||||
|
|
||||||
|
UInt64 Xz_GetUnpackSize(const CXzStream *p);
|
||||||
|
UInt64 Xz_GetPackSize(const CXzStream *p);
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t num;
|
||||||
|
size_t numAllocated;
|
||||||
|
CXzStream *streams;
|
||||||
|
} CXzs;
|
||||||
|
|
||||||
|
void Xzs_Construct(CXzs *p);
|
||||||
|
void Xzs_Free(CXzs *p, ISzAlloc *alloc);
|
||||||
|
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *inStream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
UInt64 Xzs_GetNumBlocks(const CXzs *p);
|
||||||
|
UInt64 Xzs_GetUnpackSize(const CXzs *p);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CODER_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||||
|
CODER_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||||
|
CODER_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||||
|
CODER_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||||
|
} ECoderStatus;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CODER_FINISH_ANY, /* finish at any point */
|
||||||
|
CODER_FINISH_END /* block must be finished at the end */
|
||||||
|
} ECoderFinishMode;
|
||||||
|
|
||||||
|
typedef struct _IStateCoder
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
void (*Free)(void *p, ISzAlloc *alloc);
|
||||||
|
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
|
||||||
|
void (*Init)(void *p);
|
||||||
|
SRes (*Code)(void *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished);
|
||||||
|
} IStateCoder;
|
||||||
|
|
||||||
|
#define MIXCODER_NUM_FILTERS_MAX 4
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
Byte *buf;
|
||||||
|
int numCoders;
|
||||||
|
int finished[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||||
|
size_t pos[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||||
|
size_t size[MIXCODER_NUM_FILTERS_MAX - 1];
|
||||||
|
UInt64 ids[MIXCODER_NUM_FILTERS_MAX];
|
||||||
|
IStateCoder coders[MIXCODER_NUM_FILTERS_MAX];
|
||||||
|
} CMixCoder;
|
||||||
|
|
||||||
|
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc);
|
||||||
|
void MixCoder_Free(CMixCoder *p);
|
||||||
|
void MixCoder_Init(CMixCoder *p);
|
||||||
|
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId);
|
||||||
|
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, int srcWasFinished,
|
||||||
|
ECoderFinishMode finishMode, ECoderStatus *status);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
XZ_STATE_STREAM_HEADER,
|
||||||
|
XZ_STATE_STREAM_INDEX,
|
||||||
|
XZ_STATE_STREAM_INDEX_CRC,
|
||||||
|
XZ_STATE_STREAM_FOOTER,
|
||||||
|
XZ_STATE_STREAM_PADDING,
|
||||||
|
XZ_STATE_BLOCK_HEADER,
|
||||||
|
XZ_STATE_BLOCK,
|
||||||
|
XZ_STATE_BLOCK_FOOTER
|
||||||
|
} EXzState;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
EXzState state;
|
||||||
|
UInt32 pos;
|
||||||
|
unsigned alignPos;
|
||||||
|
unsigned indexPreSize;
|
||||||
|
|
||||||
|
CXzStreamFlags streamFlags;
|
||||||
|
|
||||||
|
UInt32 blockHeaderSize;
|
||||||
|
UInt64 packSize;
|
||||||
|
UInt64 unpackSize;
|
||||||
|
|
||||||
|
UInt64 numBlocks;
|
||||||
|
UInt64 indexSize;
|
||||||
|
UInt64 indexPos;
|
||||||
|
UInt64 padSize;
|
||||||
|
|
||||||
|
UInt64 numStreams;
|
||||||
|
|
||||||
|
UInt32 crc;
|
||||||
|
CMixCoder decoder;
|
||||||
|
CXzBlock block;
|
||||||
|
CXzCheck check;
|
||||||
|
CSha256 sha;
|
||||||
|
Byte shaDigest[SHA256_DIGEST_SIZE];
|
||||||
|
Byte buf[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||||
|
} CXzUnpacker;
|
||||||
|
|
||||||
|
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc);
|
||||||
|
void XzUnpacker_Free(CXzUnpacker *p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
finishMode:
|
||||||
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
SZ_OK
|
||||||
|
status:
|
||||||
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
|
LZMA_STATUS_NOT_FINISHED
|
||||||
|
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 XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, /* int srcWasFinished, */ int finishMode,
|
||||||
|
ECoderStatus *status);
|
||||||
|
|
||||||
|
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
33
C/XzCrc64.c
Executable file
33
C/XzCrc64.c
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
/* XzCrc64.c -- CRC64 calculation
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "XzCrc64.h"
|
||||||
|
|
||||||
|
#define kCrc64Poly 0xC96C5795D7870F42
|
||||||
|
UInt64 g_Crc64Table[256];
|
||||||
|
|
||||||
|
void MY_FAST_CALL Crc64GenerateTable(void)
|
||||||
|
{
|
||||||
|
UInt32 i;
|
||||||
|
for (i = 0; i < 256; i++)
|
||||||
|
{
|
||||||
|
UInt64 r = i;
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < 8; j++)
|
||||||
|
r = (r >> 1) ^ ((UInt64)kCrc64Poly & ~((r & 1) - 1));
|
||||||
|
g_Crc64Table[i] = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 MY_FAST_CALL Crc64Update(UInt64 v, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
const Byte *p = (const Byte *)data;
|
||||||
|
for (; size > 0 ; size--, p++)
|
||||||
|
v = CRC64_UPDATE_BYTE(v, *p);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size)
|
||||||
|
{
|
||||||
|
return CRC64_GET_DIGEST(Crc64Update(CRC64_INIT_VAL, data, size));
|
||||||
|
}
|
||||||
30
C/XzCrc64.h
Executable file
30
C/XzCrc64.h
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
/* XzCrc64.c -- CRC64 calculation
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __XZ_CRC64_H
|
||||||
|
#define __XZ_CRC64_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern UInt64 g_Crc64Table[];
|
||||||
|
|
||||||
|
void MY_FAST_CALL Crc64GenerateTable(void);
|
||||||
|
|
||||||
|
#define CRC64_INIT_VAL 0xFFFFFFFFFFFFFFFF
|
||||||
|
#define CRC64_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFFFFFFFFFF)
|
||||||
|
#define CRC64_UPDATE_BYTE(crc, b) (g_Crc64Table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||||
|
|
||||||
|
UInt64 MY_FAST_CALL Crc64Update(UInt64 crc, const void *data, size_t size);
|
||||||
|
UInt64 MY_FAST_CALL Crc64Calc(const void *data, size_t size);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
872
C/XzDec.c
Executable file
872
C/XzDec.c
Executable file
@@ -0,0 +1,872 @@
|
|||||||
|
/* XzDec.c -- Xz Decode
|
||||||
|
2009-05-29 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
/* #define XZ_DUMP */
|
||||||
|
|
||||||
|
#ifdef XZ_DUMP
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "Alloc.h"
|
||||||
|
#include "Bra.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
#include "Delta.h"
|
||||||
|
#include "Lzma2Dec.h"
|
||||||
|
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
#include "SbDec.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "Xz.h"
|
||||||
|
|
||||||
|
#define XZ_CHECK_SIZE_MAX 64
|
||||||
|
|
||||||
|
#define CODER_BUF_SIZE (1 << 17)
|
||||||
|
|
||||||
|
unsigned Xz_ReadVarInt(const Byte *p, size_t maxSize, UInt64 *value)
|
||||||
|
{
|
||||||
|
int i, limit;
|
||||||
|
*value = 0;
|
||||||
|
limit = (maxSize > 9) ? 9 : (int)maxSize;
|
||||||
|
|
||||||
|
for (i = 0; i < limit;)
|
||||||
|
{
|
||||||
|
Byte b = p[i];
|
||||||
|
*value |= (UInt64)(b & 0x7F) << (7 * i++);
|
||||||
|
if ((b & 0x80) == 0)
|
||||||
|
return (b == 0 && i != 1) ? 0 : i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- BraState ---------- */
|
||||||
|
|
||||||
|
#define BRA_BUF_SIZE (1 << 14)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
size_t bufPos;
|
||||||
|
size_t bufConv;
|
||||||
|
size_t bufTotal;
|
||||||
|
|
||||||
|
UInt32 methodId;
|
||||||
|
int encodeMode;
|
||||||
|
UInt32 delta;
|
||||||
|
UInt32 ip;
|
||||||
|
UInt32 x86State;
|
||||||
|
Byte deltaState[DELTA_STATE_SIZE];
|
||||||
|
|
||||||
|
Byte buf[BRA_BUF_SIZE];
|
||||||
|
} CBraState;
|
||||||
|
|
||||||
|
void BraState_Free(void *pp, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
alloc->Free(alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes BraState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CBraState *p = ((CBraState *)pp);
|
||||||
|
alloc = alloc;
|
||||||
|
p->encodeMode = 0;
|
||||||
|
p->ip = 0;
|
||||||
|
if (p->methodId == XZ_ID_Delta)
|
||||||
|
{
|
||||||
|
if (propSize != 1)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
p->delta = (unsigned)props[0] + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (propSize == 4)
|
||||||
|
{
|
||||||
|
UInt32 v = GetUi32(props);
|
||||||
|
switch(p->methodId)
|
||||||
|
{
|
||||||
|
case XZ_ID_PPC:
|
||||||
|
case XZ_ID_ARM:
|
||||||
|
case XZ_ID_SPARC:
|
||||||
|
if ((v & 3) != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
case XZ_ID_ARMT:
|
||||||
|
if ((v & 1) != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
case XZ_ID_IA64:
|
||||||
|
if ((v & 0xF) != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p->ip = v;
|
||||||
|
}
|
||||||
|
else if (propSize != 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BraState_Init(void *pp)
|
||||||
|
{
|
||||||
|
CBraState *p = ((CBraState *)pp);
|
||||||
|
p->bufPos = p->bufConv = p->bufTotal = 0;
|
||||||
|
x86_Convert_Init(p->x86State);
|
||||||
|
if (p->methodId == XZ_ID_Delta)
|
||||||
|
Delta_Init(p->deltaState);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CASE_BRA_CONV(isa) case XZ_ID_ ## isa: p->bufConv = isa ## _Convert(p->buf, p->bufTotal, p->ip, p->encodeMode); break;
|
||||||
|
|
||||||
|
static SRes BraState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
|
||||||
|
{
|
||||||
|
CBraState *p = ((CBraState *)pp);
|
||||||
|
SizeT destLenOrig = *destLen;
|
||||||
|
SizeT srcLenOrig = *srcLen;
|
||||||
|
*destLen = 0;
|
||||||
|
*srcLen = 0;
|
||||||
|
finishMode = finishMode;
|
||||||
|
*wasFinished = 0;
|
||||||
|
while (destLenOrig > 0)
|
||||||
|
{
|
||||||
|
if (p->bufPos != p->bufConv)
|
||||||
|
{
|
||||||
|
size_t curSize = p->bufConv - p->bufPos;
|
||||||
|
if (curSize > destLenOrig)
|
||||||
|
curSize = destLenOrig;
|
||||||
|
memcpy(dest, p->buf + p->bufPos, curSize);
|
||||||
|
p->bufPos += curSize;
|
||||||
|
*destLen += curSize;
|
||||||
|
dest += curSize;
|
||||||
|
destLenOrig -= curSize;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p->bufTotal -= p->bufPos;
|
||||||
|
memmove(p->buf, p->buf + p->bufPos, p->bufTotal);
|
||||||
|
p->bufPos = 0;
|
||||||
|
p->bufConv = 0;
|
||||||
|
{
|
||||||
|
size_t curSize = BRA_BUF_SIZE - p->bufTotal;
|
||||||
|
if (curSize > srcLenOrig)
|
||||||
|
curSize = srcLenOrig;
|
||||||
|
memcpy(p->buf + p->bufTotal, src, curSize);
|
||||||
|
*srcLen += curSize;
|
||||||
|
src += curSize;
|
||||||
|
srcLenOrig -= curSize;
|
||||||
|
p->bufTotal += curSize;
|
||||||
|
}
|
||||||
|
if (p->bufTotal == 0)
|
||||||
|
break;
|
||||||
|
switch(p->methodId)
|
||||||
|
{
|
||||||
|
case XZ_ID_Delta:
|
||||||
|
if (p->encodeMode)
|
||||||
|
Delta_Encode(p->deltaState, p->delta, p->buf, p->bufTotal);
|
||||||
|
else
|
||||||
|
Delta_Decode(p->deltaState, p->delta, p->buf, p->bufTotal);
|
||||||
|
p->bufConv = p->bufTotal;
|
||||||
|
break;
|
||||||
|
case XZ_ID_X86:
|
||||||
|
p->bufConv = x86_Convert(p->buf, p->bufTotal, p->ip, &p->x86State, p->encodeMode);
|
||||||
|
break;
|
||||||
|
CASE_BRA_CONV(PPC)
|
||||||
|
CASE_BRA_CONV(IA64)
|
||||||
|
CASE_BRA_CONV(ARM)
|
||||||
|
CASE_BRA_CONV(ARMT)
|
||||||
|
CASE_BRA_CONV(SPARC)
|
||||||
|
default:
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
p->ip += (UInt32)p->bufConv;
|
||||||
|
|
||||||
|
if (p->bufConv == 0)
|
||||||
|
{
|
||||||
|
if (!srcWasFinished)
|
||||||
|
break;
|
||||||
|
p->bufConv = p->bufTotal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->bufTotal == p->bufPos && srcLenOrig == 0 && srcWasFinished)
|
||||||
|
*wasFinished = 1;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes BraState_SetFromMethod(IStateCoder *p, UInt64 id, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CBraState *decoder;
|
||||||
|
if (id != XZ_ID_Delta &&
|
||||||
|
id != XZ_ID_X86 &&
|
||||||
|
id != XZ_ID_PPC &&
|
||||||
|
id != XZ_ID_IA64 &&
|
||||||
|
id != XZ_ID_ARM &&
|
||||||
|
id != XZ_ID_ARMT &&
|
||||||
|
id != XZ_ID_SPARC)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
p->p = 0;
|
||||||
|
decoder = alloc->Alloc(alloc, sizeof(CBraState));
|
||||||
|
if (decoder == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
decoder->methodId = (UInt32)id;
|
||||||
|
p->p = decoder;
|
||||||
|
p->Free = BraState_Free;
|
||||||
|
p->SetProps = BraState_SetProps;
|
||||||
|
p->Init = BraState_Init;
|
||||||
|
p->Code = BraState_Code;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- SbState ---------- */
|
||||||
|
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
|
||||||
|
static void SbState_Free(void *pp, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CSubblockDec *p = (CSubblockDec *)pp;
|
||||||
|
SubblockDec_Free(p, alloc);
|
||||||
|
alloc->Free(alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SbState_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
pp = pp;
|
||||||
|
props = props;
|
||||||
|
alloc = alloc;
|
||||||
|
return (propSize == 0) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SbState_Init(void *pp)
|
||||||
|
{
|
||||||
|
SubblockDec_Init((CSubblockDec *)pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SbState_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
int srcWasFinished, ECoderFinishMode finishMode, int *wasFinished)
|
||||||
|
{
|
||||||
|
ECoderStatus status;
|
||||||
|
SRes res = SubblockDec_Decode((CSubblockDec *)pp, dest, destLen, src, srcLen, finishMode, &status);
|
||||||
|
srcWasFinished = srcWasFinished;
|
||||||
|
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes SbState_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CSubblockDec *decoder;
|
||||||
|
p->p = 0;
|
||||||
|
decoder = alloc->Alloc(alloc, sizeof(CSubblockDec));
|
||||||
|
if (decoder == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
p->p = decoder;
|
||||||
|
p->Free = SbState_Free;
|
||||||
|
p->SetProps = SbState_SetProps;
|
||||||
|
p->Init = SbState_Init;
|
||||||
|
p->Code = SbState_Code;
|
||||||
|
SubblockDec_Construct(decoder);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------- Lzma2State ---------- */
|
||||||
|
|
||||||
|
static void Lzma2State_Free(void *pp, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Lzma2Dec_Free((CLzma2Dec *)pp, alloc);
|
||||||
|
alloc->Free(alloc, pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Lzma2State_SetProps(void *pp, const Byte *props, size_t propSize, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (propSize != 1)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
return Lzma2Dec_Allocate((CLzma2Dec *)pp, props[0], alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Lzma2State_Init(void *pp)
|
||||||
|
{
|
||||||
|
Lzma2Dec_Init((CLzma2Dec *)pp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Lzma2State_Code(void *pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
|
int srcWasFinished, ELzmaFinishMode finishMode, int *wasFinished)
|
||||||
|
{
|
||||||
|
ELzmaStatus status;
|
||||||
|
SRes res = Lzma2Dec_DecodeToBuf((CLzma2Dec *)pp, dest, destLen, src, srcLen, finishMode, &status);
|
||||||
|
srcWasFinished = srcWasFinished;
|
||||||
|
*wasFinished = (status == LZMA_STATUS_FINISHED_WITH_MARK);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Lzma2State_SetFromMethod(IStateCoder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
CLzma2Dec *decoder = alloc->Alloc(alloc, sizeof(CLzma2Dec));
|
||||||
|
p->p = decoder;
|
||||||
|
if (decoder == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
p->Free = Lzma2State_Free;
|
||||||
|
p->SetProps = Lzma2State_SetProps;
|
||||||
|
p->Init = Lzma2State_Init;
|
||||||
|
p->Code = Lzma2State_Code;
|
||||||
|
Lzma2Dec_Construct(decoder);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MixCoder_Construct(CMixCoder *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
p->alloc = alloc;
|
||||||
|
p->buf = 0;
|
||||||
|
p->numCoders = 0;
|
||||||
|
for (i = 0; i < MIXCODER_NUM_FILTERS_MAX; i++)
|
||||||
|
p->coders[i].p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixCoder_Free(CMixCoder *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < p->numCoders; i++)
|
||||||
|
{
|
||||||
|
IStateCoder *sc = &p->coders[i];
|
||||||
|
if (p->alloc && sc->p)
|
||||||
|
sc->Free(sc->p, p->alloc);
|
||||||
|
}
|
||||||
|
p->numCoders = 0;
|
||||||
|
if (p->buf)
|
||||||
|
p->alloc->Free(p->alloc, p->buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MixCoder_Init(CMixCoder *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < p->numCoders - 1; i++)
|
||||||
|
{
|
||||||
|
p->size[i] = 0;
|
||||||
|
p->pos[i] = 0;
|
||||||
|
p->finished[i] = 0;
|
||||||
|
}
|
||||||
|
for (i = 0; i < p->numCoders; i++)
|
||||||
|
{
|
||||||
|
IStateCoder *coder = &p->coders[i];
|
||||||
|
coder->Init(coder->p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes MixCoder_SetFromMethod(CMixCoder *p, int coderIndex, UInt64 methodId)
|
||||||
|
{
|
||||||
|
IStateCoder *sc = &p->coders[coderIndex];
|
||||||
|
p->ids[coderIndex] = methodId;
|
||||||
|
switch(methodId)
|
||||||
|
{
|
||||||
|
case XZ_ID_LZMA2: return Lzma2State_SetFromMethod(sc, p->alloc);
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
case XZ_ID_Subblock: return SbState_SetFromMethod(sc, p->alloc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (coderIndex == 0)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
return BraState_SetFromMethod(sc, methodId, p->alloc);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes MixCoder_Code(CMixCoder *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, int srcWasFinished,
|
||||||
|
ELzmaFinishMode finishMode, ECoderStatus *status)
|
||||||
|
{
|
||||||
|
SizeT destLenOrig = *destLen;
|
||||||
|
SizeT srcLenOrig = *srcLen;
|
||||||
|
Bool allFinished = True;
|
||||||
|
*destLen = 0;
|
||||||
|
*srcLen = 0;
|
||||||
|
*status = CODER_STATUS_NOT_FINISHED;
|
||||||
|
|
||||||
|
if (p->buf == 0)
|
||||||
|
{
|
||||||
|
p->buf = p->alloc->Alloc(p->alloc, CODER_BUF_SIZE * (MIXCODER_NUM_FILTERS_MAX - 1));
|
||||||
|
if (p->buf == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p->numCoders != 1)
|
||||||
|
finishMode = CODER_FINISH_ANY;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
Bool processed = False;
|
||||||
|
int i;
|
||||||
|
/*
|
||||||
|
if (p->numCoders == 1 && *destLen == destLenOrig && finishMode == LZMA_FINISH_ANY)
|
||||||
|
break;
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i = 0; i < p->numCoders; i++)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
IStateCoder *coder = &p->coders[i];
|
||||||
|
Byte *destCur;
|
||||||
|
SizeT destLenCur, srcLenCur;
|
||||||
|
const Byte *srcCur;
|
||||||
|
int srcFinishedCur;
|
||||||
|
int encodingWasFinished;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
srcCur = src;
|
||||||
|
srcLenCur = srcLenOrig - *srcLen;
|
||||||
|
srcFinishedCur = srcWasFinished;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srcCur = p->buf + (CODER_BUF_SIZE * (i - 1)) + p->pos[i - 1];
|
||||||
|
srcLenCur = p->size[i - 1] - p->pos[i - 1];
|
||||||
|
srcFinishedCur = p->finished[i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == p->numCoders - 1)
|
||||||
|
{
|
||||||
|
destCur = dest;
|
||||||
|
destLenCur = destLenOrig - *destLen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->pos[i] != p->size[i])
|
||||||
|
continue;
|
||||||
|
destCur = p->buf + (CODER_BUF_SIZE * i);
|
||||||
|
destLenCur = CODER_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = coder->Code(coder->p, destCur, &destLenCur, srcCur, &srcLenCur, srcFinishedCur, finishMode, &encodingWasFinished);
|
||||||
|
|
||||||
|
if (!encodingWasFinished)
|
||||||
|
allFinished = False;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
*srcLen += srcLenCur;
|
||||||
|
src += srcLenCur;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->pos[i - 1] += srcLenCur;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == p->numCoders - 1)
|
||||||
|
{
|
||||||
|
*destLen += destLenCur;
|
||||||
|
dest += destLenCur;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->size[i] = destLenCur;
|
||||||
|
p->pos[i] = 0;
|
||||||
|
p->finished[i] = encodingWasFinished;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != SZ_OK)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (destLenCur != 0 || srcLenCur != 0)
|
||||||
|
processed = True;
|
||||||
|
}
|
||||||
|
if (!processed)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (allFinished)
|
||||||
|
*status = CODER_STATUS_FINISHED_WITH_MARK;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_ParseHeader(CXzStreamFlags *p, const Byte *buf)
|
||||||
|
{
|
||||||
|
*p = (CXzStreamFlags)GetBe16(buf + XZ_SIG_SIZE);
|
||||||
|
if (CrcCalc(buf + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE) !=
|
||||||
|
GetUi32(buf + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE))
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
return XzFlags_IsSupported(*p) ? SZ_OK : SZ_ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bool Xz_CheckFooter(CXzStreamFlags flags, UInt64 indexSize, const Byte *buf)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
indexSize == (((UInt64)GetUi32(buf + 4) + 1) << 2) &&
|
||||||
|
(GetUi32(buf) == CrcCalc(buf + 4, 6) &&
|
||||||
|
flags == GetBe16(buf + 8) &&
|
||||||
|
memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
|
||||||
|
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
|
||||||
|
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
|
||||||
|
|
||||||
|
|
||||||
|
SRes XzBlock_Parse(CXzBlock *p, const Byte *header)
|
||||||
|
{
|
||||||
|
unsigned pos;
|
||||||
|
int numFilters, i;
|
||||||
|
UInt32 headerSize = (UInt32)header[0] << 2;
|
||||||
|
|
||||||
|
if (CrcCalc(header, headerSize) != GetUi32(header + headerSize))
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
|
||||||
|
pos = 1;
|
||||||
|
if (pos == headerSize)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
p->flags = header[pos++];
|
||||||
|
|
||||||
|
if (XzBlock_HasPackSize(p))
|
||||||
|
{
|
||||||
|
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->packSize);
|
||||||
|
if (p->packSize == 0 || p->packSize + headerSize >= (UInt64)1 << 63)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XzBlock_HasUnpackSize(p))
|
||||||
|
READ_VARINT_AND_CHECK(header, pos, headerSize, &p->unpackSize);
|
||||||
|
|
||||||
|
numFilters = XzBlock_GetNumFilters(p);
|
||||||
|
for (i = 0; i < numFilters; i++)
|
||||||
|
{
|
||||||
|
CXzFilter *filter = p->filters + i;
|
||||||
|
UInt64 size;
|
||||||
|
READ_VARINT_AND_CHECK(header, pos, headerSize, &filter->id);
|
||||||
|
READ_VARINT_AND_CHECK(header, pos, headerSize, &size);
|
||||||
|
if (size > headerSize - pos || size > XZ_FILTER_PROPS_SIZE_MAX)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
filter->propsSize = (UInt32)size;
|
||||||
|
memcpy(filter->props, header + pos, (size_t)size);
|
||||||
|
pos += (unsigned)size;
|
||||||
|
|
||||||
|
#ifdef XZ_DUMP
|
||||||
|
printf("\nf[%d] = %2X: ", i, filter->id);
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
printf(" %2X", filter->props[i]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
while (pos < headerSize)
|
||||||
|
if (header[pos++] != 0)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes XzDec_Init(CMixCoder *p, const CXzBlock *block)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Bool needReInit = True;
|
||||||
|
int numFilters = XzBlock_GetNumFilters(block);
|
||||||
|
if (numFilters == p->numCoders)
|
||||||
|
{
|
||||||
|
for (i = 0; i < numFilters; i++)
|
||||||
|
if (p->ids[i] != block->filters[numFilters - 1 - i].id)
|
||||||
|
break;
|
||||||
|
needReInit = (i != numFilters);
|
||||||
|
}
|
||||||
|
if (needReInit)
|
||||||
|
{
|
||||||
|
MixCoder_Free(p);
|
||||||
|
p->numCoders = numFilters;
|
||||||
|
for (i = 0; i < numFilters; i++)
|
||||||
|
{
|
||||||
|
const CXzFilter *f = &block->filters[numFilters - 1 - i];
|
||||||
|
RINOK(MixCoder_SetFromMethod(p, i, f->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < numFilters; i++)
|
||||||
|
{
|
||||||
|
const CXzFilter *f = &block->filters[numFilters - 1 - i];
|
||||||
|
IStateCoder *sc = &p->coders[i];
|
||||||
|
RINOK(sc->SetProps(sc->p, f->props, f->propsSize, p->alloc));
|
||||||
|
}
|
||||||
|
MixCoder_Init(p);
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes XzUnpacker_Create(CXzUnpacker *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
MixCoder_Construct(&p->decoder, alloc);
|
||||||
|
p->state = XZ_STATE_STREAM_HEADER;
|
||||||
|
p->pos = 0;
|
||||||
|
p->numStreams = 0;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XzUnpacker_Free(CXzUnpacker *p)
|
||||||
|
{
|
||||||
|
MixCoder_Free(&p->decoder);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||||
|
const Byte *src, SizeT *srcLen, int finishMode, ECoderStatus *status)
|
||||||
|
{
|
||||||
|
SizeT destLenOrig = *destLen;
|
||||||
|
SizeT srcLenOrig = *srcLen;
|
||||||
|
*destLen = 0;
|
||||||
|
*srcLen = 0;
|
||||||
|
*status = CODER_STATUS_NOT_SPECIFIED;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
SizeT srcRem = srcLenOrig - *srcLen;
|
||||||
|
|
||||||
|
if (p->state == XZ_STATE_BLOCK)
|
||||||
|
{
|
||||||
|
SizeT destLen2 = destLenOrig - *destLen;
|
||||||
|
SizeT srcLen2 = srcLenOrig - *srcLen;
|
||||||
|
SRes res;
|
||||||
|
if (srcLen2 == 0 && destLen2 == 0)
|
||||||
|
{
|
||||||
|
*status = CODER_STATUS_NOT_FINISHED;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = MixCoder_Code(&p->decoder, dest, &destLen2, src, &srcLen2, False, finishMode, status);
|
||||||
|
XzCheck_Update(&p->check, dest, destLen2);
|
||||||
|
|
||||||
|
(*srcLen) += srcLen2;
|
||||||
|
src += srcLen2;
|
||||||
|
p->packSize += srcLen2;
|
||||||
|
|
||||||
|
(*destLen) += destLen2;
|
||||||
|
dest += destLen2;
|
||||||
|
p->unpackSize += destLen2;
|
||||||
|
|
||||||
|
RINOK(res);
|
||||||
|
|
||||||
|
if (*status == CODER_STATUS_FINISHED_WITH_MARK)
|
||||||
|
{
|
||||||
|
Byte temp[32];
|
||||||
|
unsigned num = Xz_WriteVarInt(temp, p->packSize + p->blockHeaderSize + XzFlags_GetCheckSize(p->streamFlags));
|
||||||
|
num += Xz_WriteVarInt(temp + num, p->unpackSize);
|
||||||
|
Sha256_Update(&p->sha, temp, num);
|
||||||
|
p->indexSize += num;
|
||||||
|
p->numBlocks++;
|
||||||
|
|
||||||
|
p->state = XZ_STATE_BLOCK_FOOTER;
|
||||||
|
p->pos = 0;
|
||||||
|
p->alignPos = 0;
|
||||||
|
}
|
||||||
|
else if (srcLen2 == 0 && destLen2 == 0)
|
||||||
|
return SZ_OK;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (srcRem == 0)
|
||||||
|
{
|
||||||
|
*status = CODER_STATUS_NEEDS_MORE_INPUT;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(p->state)
|
||||||
|
{
|
||||||
|
case XZ_STATE_STREAM_HEADER:
|
||||||
|
{
|
||||||
|
if (p->pos < XZ_STREAM_HEADER_SIZE)
|
||||||
|
{
|
||||||
|
if (p->pos < XZ_SIG_SIZE && *src != XZ_SIG[p->pos])
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
p->buf[p->pos++] = *src++;
|
||||||
|
(*srcLen)++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RINOK(Xz_ParseHeader(&p->streamFlags, p->buf));
|
||||||
|
p->state = XZ_STATE_BLOCK_HEADER;
|
||||||
|
Sha256_Init(&p->sha);
|
||||||
|
p->indexSize = 0;
|
||||||
|
p->numBlocks = 0;
|
||||||
|
p->pos = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_BLOCK_HEADER:
|
||||||
|
{
|
||||||
|
if (p->pos == 0)
|
||||||
|
{
|
||||||
|
p->buf[p->pos++] = *src++;
|
||||||
|
(*srcLen)++;
|
||||||
|
if (p->buf[0] == 0)
|
||||||
|
{
|
||||||
|
p->indexPreSize = 1 + Xz_WriteVarInt(p->buf + 1, p->numBlocks);
|
||||||
|
p->indexPos = p->indexPreSize;
|
||||||
|
p->indexSize += p->indexPreSize;
|
||||||
|
Sha256_Final(&p->sha, p->shaDigest);
|
||||||
|
Sha256_Init(&p->sha);
|
||||||
|
p->crc = CrcUpdate(CRC_INIT_VAL, p->buf, p->indexPreSize);
|
||||||
|
p->state = XZ_STATE_STREAM_INDEX;
|
||||||
|
}
|
||||||
|
p->blockHeaderSize = ((UInt32)p->buf[0] << 2) + 4;
|
||||||
|
}
|
||||||
|
else if (p->pos != p->blockHeaderSize)
|
||||||
|
{
|
||||||
|
UInt32 cur = p->blockHeaderSize - p->pos;
|
||||||
|
if (cur > srcRem)
|
||||||
|
cur = (UInt32)srcRem;
|
||||||
|
memcpy(p->buf + p->pos, src, cur);
|
||||||
|
p->pos += cur;
|
||||||
|
(*srcLen) += cur;
|
||||||
|
src += cur;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RINOK(XzBlock_Parse(&p->block, p->buf));
|
||||||
|
p->state = XZ_STATE_BLOCK;
|
||||||
|
p->packSize = 0;
|
||||||
|
p->unpackSize = 0;
|
||||||
|
XzCheck_Init(&p->check, XzFlags_GetCheckType(p->streamFlags));
|
||||||
|
RINOK(XzDec_Init(&p->decoder, &p->block));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_BLOCK_FOOTER:
|
||||||
|
{
|
||||||
|
if (((p->packSize + p->alignPos) & 3) != 0)
|
||||||
|
{
|
||||||
|
(*srcLen)++;
|
||||||
|
p->alignPos++;
|
||||||
|
if (*src++ != 0)
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt32 checkSize = XzFlags_GetCheckSize(p->streamFlags);
|
||||||
|
UInt32 cur = checkSize - p->pos;
|
||||||
|
if (cur != 0)
|
||||||
|
{
|
||||||
|
if (cur > srcRem)
|
||||||
|
cur = (UInt32)srcRem;
|
||||||
|
memcpy(p->buf + p->pos, src, cur);
|
||||||
|
p->pos += cur;
|
||||||
|
(*srcLen) += cur;
|
||||||
|
src += cur;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Byte digest[XZ_CHECK_SIZE_MAX];
|
||||||
|
p->state = XZ_STATE_BLOCK_HEADER;
|
||||||
|
p->pos = 0;
|
||||||
|
if (XzCheck_Final(&p->check, digest) && memcmp(digest, p->buf, checkSize) != 0)
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_STREAM_INDEX:
|
||||||
|
{
|
||||||
|
if (p->pos < p->indexPreSize)
|
||||||
|
{
|
||||||
|
(*srcLen)++;
|
||||||
|
if (*src++ != p->buf[p->pos++])
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->indexPos < p->indexSize)
|
||||||
|
{
|
||||||
|
UInt64 cur = p->indexSize - p->indexPos;
|
||||||
|
if (srcRem > cur)
|
||||||
|
srcRem = (SizeT)cur;
|
||||||
|
p->crc = CrcUpdate(p->crc, src, srcRem);
|
||||||
|
Sha256_Update(&p->sha, src, srcRem);
|
||||||
|
(*srcLen) += srcRem;
|
||||||
|
src += srcRem;
|
||||||
|
p->indexPos += srcRem;
|
||||||
|
}
|
||||||
|
else if ((p->indexPos & 3) != 0)
|
||||||
|
{
|
||||||
|
Byte b = *src++;
|
||||||
|
p->crc = CRC_UPDATE_BYTE(p->crc, b);
|
||||||
|
(*srcLen)++;
|
||||||
|
p->indexPos++;
|
||||||
|
p->indexSize++;
|
||||||
|
if (b != 0)
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Byte digest[SHA256_DIGEST_SIZE];
|
||||||
|
p->state = XZ_STATE_STREAM_INDEX_CRC;
|
||||||
|
p->indexSize += 4;
|
||||||
|
p->pos = 0;
|
||||||
|
Sha256_Final(&p->sha, digest);
|
||||||
|
if (memcmp(digest, p->shaDigest, SHA256_DIGEST_SIZE) != 0)
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_STREAM_INDEX_CRC:
|
||||||
|
{
|
||||||
|
if (p->pos < 4)
|
||||||
|
{
|
||||||
|
(*srcLen)++;
|
||||||
|
p->buf[p->pos++] = *src++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->state = XZ_STATE_STREAM_FOOTER;
|
||||||
|
p->pos = 0;
|
||||||
|
if (CRC_GET_DIGEST(p->crc) != GetUi32(p->buf))
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_STREAM_FOOTER:
|
||||||
|
{
|
||||||
|
UInt32 cur = XZ_STREAM_FOOTER_SIZE - p->pos;
|
||||||
|
if (cur > srcRem)
|
||||||
|
cur = (UInt32)srcRem;
|
||||||
|
memcpy(p->buf + p->pos, src, cur);
|
||||||
|
p->pos += cur;
|
||||||
|
(*srcLen) += cur;
|
||||||
|
src += cur;
|
||||||
|
if (p->pos == XZ_STREAM_FOOTER_SIZE)
|
||||||
|
{
|
||||||
|
p->state = XZ_STATE_STREAM_PADDING;
|
||||||
|
p->numStreams++;
|
||||||
|
p->padSize = 0;
|
||||||
|
if (!Xz_CheckFooter(p->streamFlags, p->indexSize, p->buf))
|
||||||
|
return SZ_ERROR_CRC;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case XZ_STATE_STREAM_PADDING:
|
||||||
|
{
|
||||||
|
if (*src != 0)
|
||||||
|
{
|
||||||
|
if (((UInt32)p->padSize & 3) != 0)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
p->pos = 0;
|
||||||
|
p->state = XZ_STATE_STREAM_HEADER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(*srcLen)++;
|
||||||
|
src++;
|
||||||
|
p->padSize++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if (p->state == XZ_STATE_FINISHED)
|
||||||
|
*status = CODER_STATUS_FINISHED_WITH_MARK;
|
||||||
|
return SZ_OK;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool XzUnpacker_IsStreamWasFinished(CXzUnpacker *p)
|
||||||
|
{
|
||||||
|
return (p->state == XZ_STATE_STREAM_PADDING) && (((UInt32)p->padSize & 3) == 0);
|
||||||
|
}
|
||||||
497
C/XzEnc.c
Executable file
497
C/XzEnc.c
Executable file
@@ -0,0 +1,497 @@
|
|||||||
|
/* XzEnc.c -- Xz Encode
|
||||||
|
2009-05-26 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "Alloc.h"
|
||||||
|
#include "Bra.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
#include "SbEnc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "XzEnc.h"
|
||||||
|
|
||||||
|
static void *SzBigAlloc(void *p, size_t size) { p = p; return BigAlloc(size); }
|
||||||
|
static void SzBigFree(void *p, void *address) { p = p; BigFree(address); }
|
||||||
|
static ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||||
|
|
||||||
|
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 };
|
||||||
|
|
||||||
|
#define XzBlock_ClearFlags(p) (p)->flags = 0;
|
||||||
|
#define XzBlock_SetNumFilters(p, n) (p)->flags |= ((n) - 1);
|
||||||
|
#define XzBlock_SetHasPackSize(p) (p)->flags |= XZ_BF_PACK_SIZE;
|
||||||
|
#define XzBlock_SetHasUnpackSize(p) (p)->flags |= XZ_BF_UNPACK_SIZE;
|
||||||
|
|
||||||
|
static SRes WriteBytes(ISeqOutStream *s, const void *buf, UInt32 size)
|
||||||
|
{
|
||||||
|
return (s->Write(s, buf, size) == size) ? SZ_OK : SZ_ERROR_WRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes WriteBytesAndCrc(ISeqOutStream *s, const void *buf, UInt32 size, UInt32 *crc)
|
||||||
|
{
|
||||||
|
*crc = CrcUpdate(*crc, buf, size);
|
||||||
|
return WriteBytes(s, buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_WriteHeader(CXzStreamFlags f, ISeqOutStream *s)
|
||||||
|
{
|
||||||
|
UInt32 crc;
|
||||||
|
Byte header[XZ_STREAM_HEADER_SIZE];
|
||||||
|
memcpy(header, XZ_SIG, XZ_SIG_SIZE);
|
||||||
|
header[XZ_SIG_SIZE] = (Byte)(f >> 8);
|
||||||
|
header[XZ_SIG_SIZE + 1] = (Byte)(f & 0xFF);
|
||||||
|
crc = CrcCalc(header + XZ_SIG_SIZE, XZ_STREAM_FLAGS_SIZE);
|
||||||
|
SetUi32(header + XZ_SIG_SIZE + XZ_STREAM_FLAGS_SIZE, crc);
|
||||||
|
return WriteBytes(s, header, XZ_STREAM_HEADER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes XzBlock_WriteHeader(const CXzBlock *p, ISeqOutStream *s)
|
||||||
|
{
|
||||||
|
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||||
|
|
||||||
|
unsigned pos = 1;
|
||||||
|
int numFilters, i;
|
||||||
|
header[pos++] = p->flags;
|
||||||
|
|
||||||
|
if (XzBlock_HasPackSize(p)) pos += Xz_WriteVarInt(header + pos, p->packSize);
|
||||||
|
if (XzBlock_HasUnpackSize(p)) pos += Xz_WriteVarInt(header + pos, p->unpackSize);
|
||||||
|
numFilters = XzBlock_GetNumFilters(p);
|
||||||
|
for (i = 0; i < numFilters; i++)
|
||||||
|
{
|
||||||
|
const CXzFilter *f = &p->filters[i];
|
||||||
|
pos += Xz_WriteVarInt(header + pos, f->id);
|
||||||
|
pos += Xz_WriteVarInt(header + pos, f->propsSize);
|
||||||
|
memcpy(header + pos, f->props, f->propsSize);
|
||||||
|
pos += f->propsSize;
|
||||||
|
}
|
||||||
|
while((pos & 3) != 0)
|
||||||
|
header[pos++] = 0;
|
||||||
|
header[0] = (Byte)(pos >> 2);
|
||||||
|
SetUi32(header + pos, CrcCalc(header, pos));
|
||||||
|
return WriteBytes(s, header, pos + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_WriteFooter(CXzStream *p, ISeqOutStream *s)
|
||||||
|
{
|
||||||
|
Byte buf[32];
|
||||||
|
UInt64 globalPos;
|
||||||
|
{
|
||||||
|
UInt32 crc = CRC_INIT_VAL;
|
||||||
|
unsigned pos = 1 + Xz_WriteVarInt(buf + 1, p->numBlocks);
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
globalPos = pos;
|
||||||
|
buf[0] = 0;
|
||||||
|
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
|
||||||
|
for (i = 0; i < p->numBlocks; i++)
|
||||||
|
{
|
||||||
|
const CXzBlockSizes *block = &p->blocks[i];
|
||||||
|
pos = Xz_WriteVarInt(buf, block->totalSize);
|
||||||
|
pos += Xz_WriteVarInt(buf + pos, block->unpackSize);
|
||||||
|
globalPos += pos;
|
||||||
|
RINOK(WriteBytesAndCrc(s, buf, pos, &crc));
|
||||||
|
}
|
||||||
|
pos = ((unsigned)globalPos & 3);
|
||||||
|
if (pos != 0)
|
||||||
|
{
|
||||||
|
buf[0] = buf[1] = buf[2] = 0;
|
||||||
|
RINOK(WriteBytesAndCrc(s, buf, 4 - pos, &crc));
|
||||||
|
globalPos += 4 - pos;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
SetUi32(buf, CRC_GET_DIGEST(crc));
|
||||||
|
RINOK(WriteBytes(s, buf, 4));
|
||||||
|
globalPos += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
UInt32 indexSize = (UInt32)((globalPos >> 2) - 1);
|
||||||
|
SetUi32(buf + 4, indexSize);
|
||||||
|
buf[8] = (Byte)(p->flags >> 8);
|
||||||
|
buf[9] = (Byte)(p->flags & 0xFF);
|
||||||
|
SetUi32(buf, CrcCalc(buf + 4, 6));
|
||||||
|
memcpy(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE);
|
||||||
|
return WriteBytes(s, buf, 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_AddIndexRecord(CXzStream *p, UInt64 unpackSize, UInt64 totalSize, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
if (p->blocks == 0 || p->numBlocksAllocated == p->numBlocks)
|
||||||
|
{
|
||||||
|
size_t num = (p->numBlocks + 1) * 2;
|
||||||
|
size_t newSize = sizeof(CXzBlockSizes) * num;
|
||||||
|
CXzBlockSizes *blocks;
|
||||||
|
if (newSize / sizeof(CXzBlockSizes) != num)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
blocks = alloc->Alloc(alloc, newSize);
|
||||||
|
if (blocks == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
if (p->numBlocks != 0)
|
||||||
|
{
|
||||||
|
memcpy(blocks, p->blocks, p->numBlocks * sizeof(CXzBlockSizes));
|
||||||
|
Xz_Free(p, alloc);
|
||||||
|
}
|
||||||
|
p->blocks = blocks;
|
||||||
|
p->numBlocksAllocated = num;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CXzBlockSizes *block = &p->blocks[p->numBlocks++];
|
||||||
|
block->totalSize = totalSize;
|
||||||
|
block->unpackSize = unpackSize;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- CSeqCheckInStream ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream p;
|
||||||
|
ISeqInStream *realStream;
|
||||||
|
UInt64 processed;
|
||||||
|
CXzCheck check;
|
||||||
|
} CSeqCheckInStream;
|
||||||
|
|
||||||
|
void SeqCheckInStream_Init(CSeqCheckInStream *p, int mode)
|
||||||
|
{
|
||||||
|
p->processed = 0;
|
||||||
|
XzCheck_Init(&p->check, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SeqCheckInStream_GetDigest(CSeqCheckInStream *p, Byte *digest)
|
||||||
|
{
|
||||||
|
XzCheck_Final(&p->check, digest);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SeqCheckInStream_Read(void *pp, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
CSeqCheckInStream *p = (CSeqCheckInStream *)pp;
|
||||||
|
SRes res = p->realStream->Read(p->realStream, data, size);
|
||||||
|
XzCheck_Update(&p->check, data, *size);
|
||||||
|
p->processed += *size;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- CSeqSizeOutStream ---------- */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqOutStream p;
|
||||||
|
ISeqOutStream *realStream;
|
||||||
|
UInt64 processed;
|
||||||
|
} CSeqSizeOutStream;
|
||||||
|
|
||||||
|
static size_t MyWrite(void *pp, const void *data, size_t size)
|
||||||
|
{
|
||||||
|
CSeqSizeOutStream *p = (CSeqSizeOutStream *)pp;
|
||||||
|
size = p->realStream->Write(p->realStream, data, size);
|
||||||
|
p->processed += size;
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- CSeqInFilter ---------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct _IFilter
|
||||||
|
{
|
||||||
|
void *p;
|
||||||
|
void (*Free)(void *p, ISzAlloc *alloc);
|
||||||
|
SRes (*SetProps)(void *p, const Byte *props, size_t propSize, ISzAlloc *alloc);
|
||||||
|
void (*Init)(void *p);
|
||||||
|
size_t (*Filter)(void *p, Byte *data, SizeT destLen);
|
||||||
|
} IFilter;
|
||||||
|
|
||||||
|
#define FILT_BUF_SIZE (1 << 19)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream p;
|
||||||
|
ISeqInStream *realStream;
|
||||||
|
UInt32 x86State;
|
||||||
|
UInt32 ip;
|
||||||
|
UInt64 processed;
|
||||||
|
CXzCheck check;
|
||||||
|
Byte buf[FILT_BUF_SIZE];
|
||||||
|
UInt32 bufferPos;
|
||||||
|
UInt32 convertedPosBegin;
|
||||||
|
UInt32 convertedPosEnd;
|
||||||
|
IFilter *filter;
|
||||||
|
} CSeqInFilter;
|
||||||
|
|
||||||
|
static SRes SeqInFilter_Read(void *pp, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
CSeqInFilter *p = (CSeqInFilter *)pp;
|
||||||
|
size_t remSize = *size;
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
while (remSize > 0)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
if (p->convertedPosBegin != p->convertedPosEnd)
|
||||||
|
{
|
||||||
|
UInt32 sizeTemp = p->convertedPosEnd - p->convertedPosBegin;
|
||||||
|
if (remSize < sizeTemp)
|
||||||
|
sizeTemp = (UInt32)remSize;
|
||||||
|
memmove(data, p->buf + p->convertedPosBegin, sizeTemp);
|
||||||
|
p->convertedPosBegin += sizeTemp;
|
||||||
|
data = (void *)((Byte *)data + sizeTemp);
|
||||||
|
remSize -= sizeTemp;
|
||||||
|
*size += sizeTemp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; p->convertedPosEnd + i < p->bufferPos; i++)
|
||||||
|
p->buf[i] = p->buf[i + p->convertedPosEnd];
|
||||||
|
p->bufferPos = i;
|
||||||
|
p->convertedPosBegin = p->convertedPosEnd = 0;
|
||||||
|
{
|
||||||
|
size_t processedSizeTemp = FILT_BUF_SIZE - p->bufferPos;
|
||||||
|
RINOK(p->realStream->Read(p->realStream, p->buf + p->bufferPos, &processedSizeTemp));
|
||||||
|
p->bufferPos = p->bufferPos + (UInt32)processedSizeTemp;
|
||||||
|
}
|
||||||
|
p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);
|
||||||
|
if (p->convertedPosEnd == 0)
|
||||||
|
{
|
||||||
|
if (p->bufferPos == 0)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->convertedPosEnd = p->bufferPos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p->convertedPosEnd > p->bufferPos)
|
||||||
|
{
|
||||||
|
for (; p->bufferPos < p->convertedPosEnd; p->bufferPos++)
|
||||||
|
p->buf[p->bufferPos] = 0;
|
||||||
|
p->convertedPosEnd = (UInt32)p->filter->Filter(p->filter->p, p->buf, p->bufferPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream p;
|
||||||
|
ISeqInStream *realStream;
|
||||||
|
CMixCoder mixCoder;
|
||||||
|
Byte buf[FILT_BUF_SIZE];
|
||||||
|
UInt32 bufPos;
|
||||||
|
UInt32 bufSize;
|
||||||
|
} CMixCoderSeqInStream;
|
||||||
|
|
||||||
|
static SRes CMixCoderSeqInStream_Read(void *pp, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
CMixCoderSeqInStream *p = (CMixCoderSeqInStream *)pp;
|
||||||
|
SRes res = SZ_OK;
|
||||||
|
size_t remSize = *size;
|
||||||
|
*size = 0;
|
||||||
|
while (remSize > 0)
|
||||||
|
{
|
||||||
|
if (p->bufPos == p->bufSize)
|
||||||
|
{
|
||||||
|
size_t curSize;
|
||||||
|
p->bufPos = p->bufSize = 0;
|
||||||
|
if (*size != 0)
|
||||||
|
break;
|
||||||
|
curSize = FILT_BUF_SIZE;
|
||||||
|
RINOK(p->realStream->Read(p->realStream, p->buf, &curSize));
|
||||||
|
p->bufSize = (UInt32)curSize;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
SizeT destLen = remSize;
|
||||||
|
SizeT srcLen = p->bufSize - p->bufPos;
|
||||||
|
res = MixCoder_Code(&p->mixCoder, data, &destLen, p->buf + p->bufPos, &srcLen, 0);
|
||||||
|
data = (void *)((Byte *)data + destLen);
|
||||||
|
remSize -= destLen;
|
||||||
|
*size += destLen;
|
||||||
|
p->bufPos += srcLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
ISeqInStream p;
|
||||||
|
CSubblockEnc sb;
|
||||||
|
UInt64 processed;
|
||||||
|
} CSbEncInStream;
|
||||||
|
|
||||||
|
void SbEncInStream_Init(CSbEncInStream *p)
|
||||||
|
{
|
||||||
|
p->processed = 0;
|
||||||
|
SubblockEnc_Init(&p->sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SbEncInStream_Read(void *pp, void *data, size_t *size)
|
||||||
|
{
|
||||||
|
CSbEncInStream *p = (CSbEncInStream *)pp;
|
||||||
|
SRes res = SubblockEnc_Read(&p->sb, data, size);
|
||||||
|
p->processed += *size;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
/* CMixCoderSeqInStream inStream; */
|
||||||
|
CLzma2EncHandle lzma2;
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
CSbEncInStream sb;
|
||||||
|
#endif
|
||||||
|
ISzAlloc *alloc;
|
||||||
|
ISzAlloc *bigAlloc;
|
||||||
|
} CLzma2WithFilters;
|
||||||
|
|
||||||
|
|
||||||
|
static void Lzma2WithFilters_Construct(CLzma2WithFilters *p, ISzAlloc *alloc, ISzAlloc *bigAlloc)
|
||||||
|
{
|
||||||
|
p->alloc = alloc;
|
||||||
|
p->bigAlloc = bigAlloc;
|
||||||
|
p->lzma2 = NULL;
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
p->sb.p.Read = SbEncInStream_Read;
|
||||||
|
SubblockEnc_Construct(&p->sb.sb, p->alloc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Lzma2WithFilters_Create(CLzma2WithFilters *p)
|
||||||
|
{
|
||||||
|
p->lzma2 = Lzma2Enc_Create(p->alloc, p->bigAlloc);
|
||||||
|
if (p->lzma2 == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Lzma2WithFilters_Free(CLzma2WithFilters *p)
|
||||||
|
{
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
SubblockEnc_Free(&p->sb.sb);
|
||||||
|
#endif
|
||||||
|
if (p->lzma2)
|
||||||
|
{
|
||||||
|
Lzma2Enc_Destroy(p->lzma2);
|
||||||
|
p->lzma2 = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Xz_Compress(CXzStream *xz,
|
||||||
|
CLzma2WithFilters *lzmaf,
|
||||||
|
ISeqOutStream *outStream,
|
||||||
|
ISeqInStream *inStream,
|
||||||
|
const CLzma2EncProps *lzma2Props,
|
||||||
|
Bool useSubblock,
|
||||||
|
ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
xz->flags = XZ_CHECK_CRC32;
|
||||||
|
|
||||||
|
RINOK(Lzma2Enc_SetProps(lzmaf->lzma2, lzma2Props));
|
||||||
|
RINOK(Xz_WriteHeader(xz->flags, outStream));
|
||||||
|
|
||||||
|
{
|
||||||
|
CSeqCheckInStream checkInStream;
|
||||||
|
CSeqSizeOutStream seqSizeOutStream;
|
||||||
|
CXzBlock block;
|
||||||
|
int filterIndex = 0;
|
||||||
|
|
||||||
|
XzBlock_ClearFlags(&block);
|
||||||
|
XzBlock_SetNumFilters(&block, 1 + (useSubblock ? 1 : 0));
|
||||||
|
|
||||||
|
if (useSubblock)
|
||||||
|
{
|
||||||
|
CXzFilter *f = &block.filters[filterIndex++];
|
||||||
|
f->id = XZ_ID_Subblock;
|
||||||
|
f->propsSize = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CXzFilter *f = &block.filters[filterIndex++];
|
||||||
|
f->id = XZ_ID_LZMA2;
|
||||||
|
f->propsSize = 1;
|
||||||
|
f->props[0] = Lzma2Enc_WriteProperties(lzmaf->lzma2);
|
||||||
|
}
|
||||||
|
|
||||||
|
seqSizeOutStream.p.Write = MyWrite;
|
||||||
|
seqSizeOutStream.realStream = outStream;
|
||||||
|
seqSizeOutStream.processed = 0;
|
||||||
|
|
||||||
|
RINOK(XzBlock_WriteHeader(&block, &seqSizeOutStream.p));
|
||||||
|
|
||||||
|
checkInStream.p.Read = SeqCheckInStream_Read;
|
||||||
|
checkInStream.realStream = inStream;
|
||||||
|
SeqCheckInStream_Init(&checkInStream, XzFlags_GetCheckType(xz->flags));
|
||||||
|
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
if (useSubblock)
|
||||||
|
{
|
||||||
|
lzmaf->sb.sb.inStream = &checkInStream.p;
|
||||||
|
SubblockEnc_Init(&lzmaf->sb.sb);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
{
|
||||||
|
UInt64 packPos = seqSizeOutStream.processed;
|
||||||
|
HRESULT res = Lzma2Enc_Encode(lzmaf->lzma2, &seqSizeOutStream.p,
|
||||||
|
#ifdef USE_SUBBLOCK
|
||||||
|
useSubblock ? &lzmaf->sb.p:
|
||||||
|
#endif
|
||||||
|
&checkInStream.p,
|
||||||
|
progress);
|
||||||
|
RINOK(res);
|
||||||
|
block.unpackSize = checkInStream.processed;
|
||||||
|
block.packSize = seqSizeOutStream.processed - packPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
unsigned padSize = 0;
|
||||||
|
Byte buf[128];
|
||||||
|
while((((unsigned)block.packSize + padSize) & 3) != 0)
|
||||||
|
buf[padSize++] = 0;
|
||||||
|
SeqCheckInStream_GetDigest(&checkInStream, buf + padSize);
|
||||||
|
RINOK(WriteBytes(&seqSizeOutStream.p, buf, padSize + XzFlags_GetCheckSize(xz->flags)));
|
||||||
|
RINOK(Xz_AddIndexRecord(xz, block.unpackSize, seqSizeOutStream.processed - padSize, &g_Alloc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Xz_WriteFooter(xz, outStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
|
const CLzma2EncProps *lzma2Props, Bool useSubblock,
|
||||||
|
ICompressProgress *progress)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
CXzStream xz;
|
||||||
|
CLzma2WithFilters lzmaf;
|
||||||
|
Xz_Construct(&xz);
|
||||||
|
Lzma2WithFilters_Construct(&lzmaf, &g_Alloc, &g_BigAlloc);
|
||||||
|
res = Lzma2WithFilters_Create(&lzmaf);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
res = Xz_Compress(&xz, &lzmaf, outStream, inStream,
|
||||||
|
lzma2Props, useSubblock, progress);
|
||||||
|
Lzma2WithFilters_Free(&lzmaf);
|
||||||
|
Xz_Free(&xz, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
SRes Xz_EncodeEmpty(ISeqOutStream *outStream)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
CXzStream xz;
|
||||||
|
Xz_Construct(&xz);
|
||||||
|
res = Xz_WriteHeader(xz.flags, outStream);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
res = Xz_WriteFooter(&xz, outStream);
|
||||||
|
Xz_Free(&xz, &g_Alloc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
25
C/XzEnc.h
Executable file
25
C/XzEnc.h
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
/* XzEnc.h -- Xz Encode
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#ifndef __XZ_ENC_H
|
||||||
|
#define __XZ_ENC_H
|
||||||
|
|
||||||
|
#include "Lzma2Enc.h"
|
||||||
|
|
||||||
|
#include "Xz.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SRes Xz_Encode(ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||||
|
const CLzma2EncProps *lzma2Props, Bool useSubblock,
|
||||||
|
ICompressProgress *progress);
|
||||||
|
|
||||||
|
SRes Xz_EncodeEmpty(ISeqOutStream *outStream);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
305
C/XzIn.c
Executable file
305
C/XzIn.c
Executable file
@@ -0,0 +1,305 @@
|
|||||||
|
/* XzIn.c - Xz input
|
||||||
|
2009-04-15 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
|
#include "Xz.h"
|
||||||
|
|
||||||
|
#include "7zCrc.h"
|
||||||
|
#include "CpuArch.h"
|
||||||
|
|
||||||
|
SRes Xz_ReadHeader(CXzStreamFlags *p, ISeqInStream *inStream)
|
||||||
|
{
|
||||||
|
Byte sig[XZ_STREAM_HEADER_SIZE];
|
||||||
|
RINOK(SeqInStream_Read2(inStream, sig, XZ_STREAM_HEADER_SIZE, SZ_ERROR_NO_ARCHIVE));
|
||||||
|
if (memcmp(sig, XZ_SIG, XZ_SIG_SIZE) != 0)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
return Xz_ParseHeader(p, sig);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define READ_VARINT_AND_CHECK(buf, pos, size, res) \
|
||||||
|
{ unsigned s = Xz_ReadVarInt(buf + pos, size - pos, res); \
|
||||||
|
if (s == 0) return SZ_ERROR_ARCHIVE; pos += s; }
|
||||||
|
|
||||||
|
SRes XzBlock_ReadHeader(CXzBlock *p, ISeqInStream *inStream, Bool *isIndex, UInt32 *headerSizeRes)
|
||||||
|
{
|
||||||
|
Byte header[XZ_BLOCK_HEADER_SIZE_MAX];
|
||||||
|
unsigned headerSize;
|
||||||
|
*headerSizeRes = 0;
|
||||||
|
RINOK(SeqInStream_ReadByte(inStream, &header[0]));
|
||||||
|
headerSize = ((unsigned)header[0] << 2) + 4;
|
||||||
|
if (headerSize == 0)
|
||||||
|
{
|
||||||
|
*headerSizeRes = 1;
|
||||||
|
*isIndex = True;
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*isIndex = False;
|
||||||
|
*headerSizeRes = headerSize;
|
||||||
|
RINOK(SeqInStream_Read(inStream, header + 1, headerSize - 1));
|
||||||
|
return XzBlock_Parse(p, header);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ADD_SIZE_CHECH(size, val) \
|
||||||
|
{ UInt64 newSize = size + (val); if (newSize < size) return XZ_SIZE_OVERFLOW; size = newSize; }
|
||||||
|
|
||||||
|
UInt64 Xz_GetUnpackSize(const CXzStream *p)
|
||||||
|
{
|
||||||
|
UInt64 size = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->numBlocks; i++)
|
||||||
|
ADD_SIZE_CHECH(size, p->blocks[i].unpackSize);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 Xz_GetPackSize(const CXzStream *p)
|
||||||
|
{
|
||||||
|
UInt64 size = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->numBlocks; i++)
|
||||||
|
ADD_SIZE_CHECH(size, (p->blocks[i].totalSize + 3) & ~(UInt64)3);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
SRes XzBlock_ReadFooter(CXzBlock *p, CXzStreamFlags f, ISeqInStream *inStream)
|
||||||
|
{
|
||||||
|
return SeqInStream_Read(inStream, p->check, XzFlags_GetCheckSize(f));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static SRes Xz_ReadIndex2(CXzStream *p, const Byte *buf, size_t size, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
size_t i, numBlocks, crcStartPos, pos = 1;
|
||||||
|
UInt32 crc;
|
||||||
|
|
||||||
|
if (size < 5 || buf[0] != 0)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
|
||||||
|
size -= 4;
|
||||||
|
crc = CrcCalc(buf, size);
|
||||||
|
if (crc != GetUi32(buf + size))
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
|
||||||
|
{
|
||||||
|
UInt64 numBlocks64;
|
||||||
|
READ_VARINT_AND_CHECK(buf, pos, size, &numBlocks64);
|
||||||
|
numBlocks = (size_t)numBlocks64;
|
||||||
|
if (numBlocks != numBlocks64 || numBlocks * 2 > size)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
crcStartPos = pos;
|
||||||
|
Xz_Free(p, alloc);
|
||||||
|
if (numBlocks != 0)
|
||||||
|
{
|
||||||
|
p->numBlocks = numBlocks;
|
||||||
|
p->numBlocksAllocated = numBlocks;
|
||||||
|
p->blocks = alloc->Alloc(alloc, sizeof(CXzBlockSizes) * numBlocks);
|
||||||
|
if (p->blocks == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
for (i = 0; i < numBlocks; i++)
|
||||||
|
{
|
||||||
|
CXzBlockSizes *block = &p->blocks[i];
|
||||||
|
READ_VARINT_AND_CHECK(buf, pos, size, &block->totalSize);
|
||||||
|
READ_VARINT_AND_CHECK(buf, pos, size, &block->unpackSize);
|
||||||
|
if (block->totalSize == 0)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while ((pos & 3) != 0)
|
||||||
|
if (buf[pos++] != 0)
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Xz_ReadIndex(CXzStream *p, ILookInStream *stream, UInt64 indexSize, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
SRes res;
|
||||||
|
size_t size;
|
||||||
|
Byte *buf;
|
||||||
|
if (indexSize > ((UInt32)1 << 31))
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
size = (size_t)indexSize;
|
||||||
|
if (size != indexSize)
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
buf = alloc->Alloc(alloc, size);
|
||||||
|
if (buf == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
res = LookInStream_Read2(stream, buf, size, SZ_ERROR_UNSUPPORTED);
|
||||||
|
if (res == SZ_OK)
|
||||||
|
res = Xz_ReadIndex2(p, buf, size, alloc);
|
||||||
|
alloc->Free(alloc, buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes SeekFromCur(ILookInStream *inStream, Int64 *res)
|
||||||
|
{
|
||||||
|
return inStream->Seek(inStream, res, SZ_SEEK_CUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static SRes Xz_ReadBackward(CXzStream *p, ILookInStream *stream, Int64 *startOffset, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
UInt64 indexSize;
|
||||||
|
Byte buf[XZ_STREAM_FOOTER_SIZE];
|
||||||
|
|
||||||
|
if ((*startOffset & 3) != 0 || *startOffset < XZ_STREAM_FOOTER_SIZE)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
*startOffset = -XZ_STREAM_FOOTER_SIZE;
|
||||||
|
RINOK(SeekFromCur(stream, startOffset));
|
||||||
|
|
||||||
|
RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
|
||||||
|
|
||||||
|
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
|
||||||
|
{
|
||||||
|
Int64 i = 0;
|
||||||
|
*startOffset += XZ_STREAM_FOOTER_SIZE;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
size_t processedSize;
|
||||||
|
#define TEMP_BUF_SIZE (1 << 10)
|
||||||
|
Byte tempBuf[TEMP_BUF_SIZE];
|
||||||
|
if (*startOffset < XZ_STREAM_FOOTER_SIZE || i > (1 << 16))
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
processedSize = (*startOffset > TEMP_BUF_SIZE) ? TEMP_BUF_SIZE : (size_t)*startOffset;
|
||||||
|
i += processedSize;
|
||||||
|
*startOffset = -(Int64)processedSize;
|
||||||
|
RINOK(SeekFromCur(stream, startOffset));
|
||||||
|
RINOK(LookInStream_Read2(stream, tempBuf, processedSize, SZ_ERROR_NO_ARCHIVE));
|
||||||
|
for (j = (int)processedSize; j >= 0; j--)
|
||||||
|
if (tempBuf[j -1] != 0)
|
||||||
|
break;
|
||||||
|
if (j != 0)
|
||||||
|
{
|
||||||
|
if ((j & 3) != 0)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
*startOffset += j;
|
||||||
|
if (*startOffset < XZ_STREAM_FOOTER_SIZE)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
*startOffset -= XZ_STREAM_FOOTER_SIZE;
|
||||||
|
RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
|
||||||
|
RINOK(LookInStream_Read2(stream, buf, XZ_STREAM_FOOTER_SIZE, SZ_ERROR_NO_ARCHIVE));
|
||||||
|
if (memcmp(buf + 10, XZ_FOOTER_SIG, XZ_FOOTER_SIG_SIZE) != 0)
|
||||||
|
return SZ_ERROR_NO_ARCHIVE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p->flags = (CXzStreamFlags)GetBe16(buf + 8);
|
||||||
|
|
||||||
|
if (!XzFlags_IsSupported(p->flags))
|
||||||
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
|
||||||
|
if (GetUi32(buf) != CrcCalc(buf + 4, 6))
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
|
||||||
|
indexSize = ((UInt64)GetUi32(buf + 4) + 1) << 2;
|
||||||
|
|
||||||
|
*startOffset = -(Int64)(indexSize + XZ_STREAM_FOOTER_SIZE);
|
||||||
|
RINOK(SeekFromCur(stream, startOffset));
|
||||||
|
|
||||||
|
RINOK(Xz_ReadIndex(p, stream, indexSize, alloc));
|
||||||
|
|
||||||
|
{
|
||||||
|
UInt64 totalSize = Xz_GetPackSize(p);
|
||||||
|
UInt64 sum = XZ_STREAM_HEADER_SIZE + totalSize + indexSize;
|
||||||
|
if (totalSize == XZ_SIZE_OVERFLOW ||
|
||||||
|
sum >= ((UInt64)1 << 63) ||
|
||||||
|
totalSize >= ((UInt64)1 << 63))
|
||||||
|
return SZ_ERROR_ARCHIVE;
|
||||||
|
*startOffset = -(Int64)sum;
|
||||||
|
RINOK(SeekFromCur(stream, startOffset));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
CXzStreamFlags headerFlags;
|
||||||
|
CSecToRead secToRead;
|
||||||
|
SecToRead_CreateVTable(&secToRead);
|
||||||
|
secToRead.realStream = stream;
|
||||||
|
|
||||||
|
RINOK(Xz_ReadHeader(&headerFlags, &secToRead.s));
|
||||||
|
return (p->flags == headerFlags) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ---------- Xz Streams ---------- */
|
||||||
|
|
||||||
|
void Xzs_Construct(CXzs *p)
|
||||||
|
{
|
||||||
|
p->num = p->numAllocated = 0;
|
||||||
|
p->streams = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xzs_Free(CXzs *p, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->num; i++)
|
||||||
|
Xz_Free(&p->streams[i], alloc);
|
||||||
|
alloc->Free(alloc, p->streams);
|
||||||
|
p->num = p->numAllocated = 0;
|
||||||
|
p->streams = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 Xzs_GetNumBlocks(const CXzs *p)
|
||||||
|
{
|
||||||
|
UInt64 num = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->num; i++)
|
||||||
|
num += p->streams[i].numBlocks;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt64 Xzs_GetUnpackSize(const CXzs *p)
|
||||||
|
{
|
||||||
|
UInt64 size = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->num; i++)
|
||||||
|
ADD_SIZE_CHECH(size, Xz_GetUnpackSize(&p->streams[i]));
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
UInt64 Xzs_GetPackSize(const CXzs *p)
|
||||||
|
{
|
||||||
|
UInt64 size = 0;
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < p->num; i++)
|
||||||
|
ADD_SIZE_CHECH(size, Xz_GetTotalSize(&p->streams[i]));
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
SRes Xzs_ReadBackward(CXzs *p, ILookInStream *stream, Int64 *startOffset, ICompressProgress *progress, ISzAlloc *alloc)
|
||||||
|
{
|
||||||
|
Int64 endOffset = 0;
|
||||||
|
RINOK(stream->Seek(stream, &endOffset, SZ_SEEK_END));
|
||||||
|
*startOffset = endOffset;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
CXzStream st;
|
||||||
|
SRes res;
|
||||||
|
Xz_Construct(&st);
|
||||||
|
res = Xz_ReadBackward(&st, stream, startOffset, alloc);
|
||||||
|
st.startOffset = *startOffset;
|
||||||
|
RINOK(res);
|
||||||
|
if (p->num == p->numAllocated)
|
||||||
|
{
|
||||||
|
size_t newNum = p->num + p->num / 4 + 1;
|
||||||
|
Byte *data = (Byte *)alloc->Alloc(alloc, newNum * sizeof(CXzStream));
|
||||||
|
if (data == 0)
|
||||||
|
return SZ_ERROR_MEM;
|
||||||
|
p->numAllocated = newNum;
|
||||||
|
memcpy(data, p->streams, p->num * sizeof(CXzStream));
|
||||||
|
alloc->Free(alloc, p->streams);
|
||||||
|
p->streams = (CXzStream *)data;
|
||||||
|
}
|
||||||
|
p->streams[p->num++] = st;
|
||||||
|
if (*startOffset == 0)
|
||||||
|
break;
|
||||||
|
RINOK(stream->Seek(stream, startOffset, SZ_SEEK_SET));
|
||||||
|
if (progress && progress->Progress(progress, endOffset - *startOffset, (UInt64)(Int64)-1) != SZ_OK)
|
||||||
|
return SZ_ERROR_PROGRESS;
|
||||||
|
}
|
||||||
|
return SZ_OK;
|
||||||
|
}
|
||||||
@@ -598,11 +598,11 @@ SOURCE=..\..\..\Windows\Thread.h
|
|||||||
# PROP Default_Filter ""
|
# PROP Default_Filter ""
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Copy\CopyCoder.cpp
|
SOURCE=..\..\Compress\CopyCoder.cpp
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=..\..\Compress\Copy\CopyCoder.h
|
SOURCE=..\..\Compress\CopyCoder.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# End Group
|
# End Group
|
||||||
# Begin Group "C"
|
# Begin Group "C"
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
// Encode.cpp
|
// 7zEncode.cpp
|
||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../Common/CreateCoder.h"
|
||||||
|
#include "../../Common/FilterCoder.h"
|
||||||
|
#include "../../Common/LimitedStreams.h"
|
||||||
|
#include "../../Common/InOutTempBuffer.h"
|
||||||
|
#include "../../Common/ProgressUtils.h"
|
||||||
|
#include "../../Common/StreamObjects.h"
|
||||||
|
|
||||||
#include "7zEncode.h"
|
#include "7zEncode.h"
|
||||||
#include "7zSpecStream.h"
|
#include "7zSpecStream.h"
|
||||||
|
|
||||||
#include "../../IPassword.h"
|
static const UInt64 k_Delta = 0x03;
|
||||||
#include "../../Common/ProgressUtils.h"
|
|
||||||
#include "../../Common/LimitedStreams.h"
|
|
||||||
#include "../../Common/InOutTempBuffer.h"
|
|
||||||
#include "../../Common/StreamObjects.h"
|
|
||||||
#include "../../Common/CreateCoder.h"
|
|
||||||
#include "../../Common/FilterCoder.h"
|
|
||||||
|
|
||||||
static const UInt64 k_AES = 0x06F10701;
|
|
||||||
static const UInt64 k_BCJ = 0x03030103;
|
static const UInt64 k_BCJ = 0x03030103;
|
||||||
static const UInt64 k_BCJ2 = 0x0303011B;
|
static const UInt64 k_BCJ2 = 0x0303011B;
|
||||||
|
static const UInt64 k_AES = 0x06F10701;
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
namespace N7z {
|
namespace N7z {
|
||||||
@@ -240,10 +240,10 @@ HRESULT CEncoder::Encode(
|
|||||||
|
|
||||||
UInt32 progressIndex = mainCoderIndex;
|
UInt32 progressIndex = mainCoderIndex;
|
||||||
|
|
||||||
for (i = 0; i < _codersInfo.Size(); i++)
|
for (i = 0; i + 1 < _codersInfo.Size(); i++)
|
||||||
{
|
{
|
||||||
const CCoderInfo &e = _codersInfo[i];
|
UInt64 m = _codersInfo[i].MethodID;
|
||||||
if ((e.MethodID == k_BCJ || e.MethodID == k_BCJ2) && i + 1 < _codersInfo.Size())
|
if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
|
||||||
progressIndex = i + 1;
|
progressIndex = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,156 +9,132 @@ namespace N7z {
|
|||||||
|
|
||||||
CFolderOutStream::CFolderOutStream()
|
CFolderOutStream::CFolderOutStream()
|
||||||
{
|
{
|
||||||
_outStreamWithHashSpec = new COutStreamWithCRC;
|
_crcStreamSpec = new COutStreamWithCRC;
|
||||||
_outStreamWithHash = _outStreamWithHashSpec;
|
_crcStream = _crcStreamSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFolderOutStream::Init(
|
HRESULT CFolderOutStream::Init(
|
||||||
const CArchiveDatabaseEx *archiveDatabase,
|
const CArchiveDatabaseEx *archiveDatabase,
|
||||||
UInt32 ref2Offset,
|
UInt32 ref2Offset, UInt32 startIndex,
|
||||||
UInt32 startIndex,
|
|
||||||
const CBoolVector *extractStatuses,
|
const CBoolVector *extractStatuses,
|
||||||
IArchiveExtractCallback *extractCallback,
|
IArchiveExtractCallback *extractCallback,
|
||||||
bool testMode,
|
bool testMode, bool checkCrc)
|
||||||
bool checkCrc)
|
|
||||||
{
|
{
|
||||||
_archiveDatabase = archiveDatabase;
|
_db = archiveDatabase;
|
||||||
_ref2Offset = ref2Offset;
|
_ref2Offset = ref2Offset;
|
||||||
_startIndex = startIndex;
|
_startIndex = startIndex;
|
||||||
|
|
||||||
_extractStatuses = extractStatuses;
|
_extractStatuses = extractStatuses;
|
||||||
_extractCallback = extractCallback;
|
_extractCallback = extractCallback;
|
||||||
_testMode = testMode;
|
_testMode = testMode;
|
||||||
|
|
||||||
_checkCrc = checkCrc;
|
_checkCrc = checkCrc;
|
||||||
|
|
||||||
_currentIndex = 0;
|
_currentIndex = 0;
|
||||||
_fileIsOpen = false;
|
_fileIsOpen = false;
|
||||||
return WriteEmptyFiles();
|
return ProcessEmptyFiles();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFolderOutStream::OpenFile()
|
HRESULT CFolderOutStream::OpenFile()
|
||||||
{
|
{
|
||||||
Int32 askMode;
|
Int32 askMode = ((*_extractStatuses)[_currentIndex]) ? (_testMode ?
|
||||||
if((*_extractStatuses)[_currentIndex])
|
|
||||||
askMode = _testMode ?
|
|
||||||
NArchive::NExtract::NAskMode::kTest :
|
NArchive::NExtract::NAskMode::kTest :
|
||||||
NArchive::NExtract::NAskMode::kExtract;
|
NArchive::NExtract::NAskMode::kExtract):
|
||||||
else
|
NArchive::NExtract::NAskMode::kSkip;
|
||||||
askMode = NArchive::NExtract::NAskMode::kSkip;
|
|
||||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||||
|
|
||||||
UInt32 index = _startIndex + _currentIndex;
|
UInt32 index = _startIndex + _currentIndex;
|
||||||
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
|
RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
|
||||||
|
_crcStreamSpec->SetStream(realOutStream);
|
||||||
_outStreamWithHashSpec->SetStream(realOutStream);
|
_crcStreamSpec->Init(_checkCrc);
|
||||||
_outStreamWithHashSpec->Init(_checkCrc);
|
_fileIsOpen = true;
|
||||||
if (askMode == NArchive::NExtract::NAskMode::kExtract &&
|
const CFileItem &fi = _db->Files[index];
|
||||||
(!realOutStream))
|
_rem = fi.Size;
|
||||||
{
|
if (askMode == NArchive::NExtract::NAskMode::kExtract && !realOutStream &&
|
||||||
const CFileItem &fi = _archiveDatabase->Files[index];
|
!_db->IsItemAnti(index) && !fi.IsDir)
|
||||||
if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir)
|
|
||||||
askMode = NArchive::NExtract::NAskMode::kSkip;
|
askMode = NArchive::NExtract::NAskMode::kSkip;
|
||||||
}
|
|
||||||
return _extractCallback->PrepareOperation(askMode);
|
return _extractCallback->PrepareOperation(askMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFolderOutStream::WriteEmptyFiles()
|
HRESULT CFolderOutStream::CloseFileAndSetResult(Int32 res)
|
||||||
{
|
{
|
||||||
for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
|
_crcStreamSpec->ReleaseStream();
|
||||||
|
_fileIsOpen = false;
|
||||||
|
_currentIndex++;
|
||||||
|
return _extractCallback->SetOperationResult(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CFolderOutStream::CloseFileAndSetResult()
|
||||||
|
{
|
||||||
|
const CFileItem &fi = _db->Files[_startIndex + _currentIndex];
|
||||||
|
return CloseFileAndSetResult(
|
||||||
|
(fi.IsDir || !fi.CrcDefined || !_checkCrc || fi.Crc == _crcStreamSpec->GetCRC()) ?
|
||||||
|
NArchive::NExtract::NOperationResult::kOK :
|
||||||
|
NArchive::NExtract::NOperationResult::kCRCError);
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CFolderOutStream::ProcessEmptyFiles()
|
||||||
|
{
|
||||||
|
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
|
||||||
{
|
{
|
||||||
UInt32 index = _startIndex + _currentIndex;
|
|
||||||
const CFileItem &fi = _archiveDatabase->Files[index];
|
|
||||||
if (!_archiveDatabase->IsItemAnti(index) && !fi.IsDir && fi.Size != 0)
|
|
||||||
return S_OK;
|
|
||||||
RINOK(OpenFile());
|
RINOK(OpenFile());
|
||||||
RINOK(_extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
RINOK(CloseFileAndSetResult());
|
||||||
_outStreamWithHashSpec->ReleaseStream();
|
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP CFolderOutStream::Write(const void *data,
|
STDMETHODIMP CFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
UInt32 size, UInt32 *processedSize)
|
|
||||||
{
|
{
|
||||||
UInt32 realProcessedSize = 0;
|
if (processedSize != NULL)
|
||||||
while(_currentIndex < _extractStatuses->Size())
|
*processedSize = 0;
|
||||||
|
while (size != 0)
|
||||||
{
|
{
|
||||||
if (_fileIsOpen)
|
if (_fileIsOpen)
|
||||||
{
|
{
|
||||||
UInt32 index = _startIndex + _currentIndex;
|
UInt32 cur = size < _rem ? size : (UInt32)_rem;
|
||||||
const CFileItem &fi = _archiveDatabase->Files[index];
|
RINOK(_crcStream->Write(data, cur, &cur));
|
||||||
UInt64 fileSize = fi.Size;
|
if (cur == 0)
|
||||||
|
break;
|
||||||
UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
|
data = (const Byte *)data + cur;
|
||||||
UInt64(size - realProcessedSize));
|
size -= cur;
|
||||||
|
_rem -= cur;
|
||||||
UInt32 processedSizeLocal;
|
|
||||||
RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
|
|
||||||
numBytesToWrite, &processedSizeLocal));
|
|
||||||
|
|
||||||
_filePos += processedSizeLocal;
|
|
||||||
realProcessedSize += processedSizeLocal;
|
|
||||||
if (_filePos == fileSize)
|
|
||||||
{
|
|
||||||
bool digestsAreEqual;
|
|
||||||
if (fi.CrcDefined && _checkCrc)
|
|
||||||
digestsAreEqual = fi.Crc == _outStreamWithHashSpec->GetCRC();
|
|
||||||
else
|
|
||||||
digestsAreEqual = true;
|
|
||||||
|
|
||||||
RINOK(_extractCallback->SetOperationResult(
|
|
||||||
digestsAreEqual ?
|
|
||||||
NArchive::NExtract::NOperationResult::kOK :
|
|
||||||
NArchive::NExtract::NOperationResult::kCRCError));
|
|
||||||
_outStreamWithHashSpec->ReleaseStream();
|
|
||||||
_fileIsOpen = false;
|
|
||||||
_currentIndex++;
|
|
||||||
}
|
|
||||||
if (realProcessedSize == size)
|
|
||||||
{
|
|
||||||
if (processedSize != NULL)
|
if (processedSize != NULL)
|
||||||
*processedSize = realProcessedSize;
|
*processedSize += cur;
|
||||||
return WriteEmptyFiles();
|
if (_rem == 0)
|
||||||
|
{
|
||||||
|
RINOK(CloseFileAndSetResult());
|
||||||
|
RINOK(ProcessEmptyFiles());
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
RINOK(ProcessEmptyFiles());
|
||||||
|
if (_currentIndex == _extractStatuses->Size())
|
||||||
|
{
|
||||||
|
// we support partial extracting
|
||||||
|
if (processedSize != NULL)
|
||||||
|
*processedSize += size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
RINOK(OpenFile());
|
RINOK(OpenFile());
|
||||||
_fileIsOpen = true;
|
|
||||||
_filePos = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (processedSize != NULL)
|
|
||||||
*processedSize = size;
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
|
HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
|
||||||
{
|
{
|
||||||
while(_currentIndex < _extractStatuses->Size())
|
while (_currentIndex < _extractStatuses->Size())
|
||||||
{
|
{
|
||||||
if (_fileIsOpen)
|
if (_fileIsOpen)
|
||||||
{
|
{
|
||||||
RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
|
RINOK(CloseFileAndSetResult(resultEOperationResult));
|
||||||
_outStreamWithHashSpec->ReleaseStream();
|
|
||||||
_fileIsOpen = false;
|
|
||||||
_currentIndex++;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RINOK(OpenFile());
|
RINOK(OpenFile());
|
||||||
_fileIsOpen = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CFolderOutStream::WasWritingFinished()
|
|
||||||
{
|
|
||||||
if (_currentIndex == _extractStatuses->Size())
|
|
||||||
return S_OK;
|
|
||||||
return E_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// 7zFolderOutStream.h
|
// 7zFolderOutStream.h
|
||||||
|
|
||||||
#ifndef __7Z_FOLDEROUTSTREAM_H
|
#ifndef __7Z_FOLDER_OUT_STREAM_H
|
||||||
#define __7Z_FOLDEROUTSTREAM_H
|
#define __7Z_FOLDER_OUT_STREAM_H
|
||||||
|
|
||||||
#include "7zIn.h"
|
#include "7zIn.h"
|
||||||
|
|
||||||
@@ -16,43 +16,39 @@ class CFolderOutStream:
|
|||||||
public ISequentialOutStream,
|
public ISequentialOutStream,
|
||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
{
|
{
|
||||||
|
COutStreamWithCRC *_crcStreamSpec;
|
||||||
|
CMyComPtr<ISequentialOutStream> _crcStream;
|
||||||
|
const CArchiveDatabaseEx *_db;
|
||||||
|
const CBoolVector *_extractStatuses;
|
||||||
|
CMyComPtr<IArchiveExtractCallback> _extractCallback;
|
||||||
|
UInt32 _ref2Offset;
|
||||||
|
UInt32 _startIndex;
|
||||||
|
int _currentIndex;
|
||||||
|
bool _testMode;
|
||||||
|
bool _checkCrc;
|
||||||
|
bool _fileIsOpen;
|
||||||
|
UInt64 _rem;
|
||||||
|
|
||||||
|
HRESULT OpenFile();
|
||||||
|
HRESULT CloseFileAndSetResult(Int32 res);
|
||||||
|
HRESULT CloseFileAndSetResult();
|
||||||
|
HRESULT ProcessEmptyFiles();
|
||||||
public:
|
public:
|
||||||
MY_UNKNOWN_IMP
|
MY_UNKNOWN_IMP
|
||||||
|
|
||||||
CFolderOutStream();
|
CFolderOutStream();
|
||||||
|
|
||||||
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||||
private:
|
|
||||||
|
|
||||||
COutStreamWithCRC *_outStreamWithHashSpec;
|
|
||||||
CMyComPtr<ISequentialOutStream> _outStreamWithHash;
|
|
||||||
const CArchiveDatabaseEx *_archiveDatabase;
|
|
||||||
const CBoolVector *_extractStatuses;
|
|
||||||
UInt32 _startIndex;
|
|
||||||
UInt32 _ref2Offset;
|
|
||||||
int _currentIndex;
|
|
||||||
// UInt64 _currentDataPos;
|
|
||||||
CMyComPtr<IArchiveExtractCallback> _extractCallback;
|
|
||||||
bool _testMode;
|
|
||||||
|
|
||||||
bool _fileIsOpen;
|
|
||||||
|
|
||||||
bool _checkCrc;
|
|
||||||
UInt64 _filePos;
|
|
||||||
|
|
||||||
HRESULT OpenFile();
|
|
||||||
HRESULT WriteEmptyFiles();
|
|
||||||
public:
|
|
||||||
HRESULT Init(
|
HRESULT Init(
|
||||||
const CArchiveDatabaseEx *archiveDatabase,
|
const CArchiveDatabaseEx *archiveDatabase,
|
||||||
UInt32 ref2Offset,
|
UInt32 ref2Offset, UInt32 startIndex,
|
||||||
UInt32 startIndex,
|
|
||||||
const CBoolVector *extractStatuses,
|
const CBoolVector *extractStatuses,
|
||||||
IArchiveExtractCallback *extractCallback,
|
IArchiveExtractCallback *extractCallback,
|
||||||
bool testMode,
|
bool testMode, bool checkCrc);
|
||||||
bool checkCrc);
|
|
||||||
HRESULT FlushCorrupted(Int32 resultEOperationResult);
|
HRESULT FlushCorrupted(Int32 resultEOperationResult);
|
||||||
HRESULT WasWritingFinished();
|
HRESULT WasWritingFinished() const
|
||||||
|
{ return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
extern "C"
|
#include "../../../../C/CpuArch.h"
|
||||||
{
|
|
||||||
#include "../../../../C/CpuArch.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "../../../Common/ComTry.h"
|
#include "../../../Common/ComTry.h"
|
||||||
#include "../../../Common/IntToString.h"
|
#include "../../../Common/IntToString.h"
|
||||||
@@ -176,6 +173,8 @@ static UString GetStringForSizeValue(UInt32 value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const UInt64 k_Copy = 0x0;
|
static const UInt64 k_Copy = 0x0;
|
||||||
|
static const UInt64 k_Delta = 3;
|
||||||
|
static const UInt64 k_LZMA2 = 0x21;
|
||||||
static const UInt64 k_LZMA = 0x030101;
|
static const UInt64 k_LZMA = 0x030101;
|
||||||
static const UInt64 k_PPMD = 0x030401;
|
static const UInt64 k_PPMD = 0x030401;
|
||||||
|
|
||||||
@@ -183,12 +182,10 @@ static wchar_t GetHex(Byte value)
|
|||||||
{
|
{
|
||||||
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
|
return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
|
||||||
}
|
}
|
||||||
static inline UString GetHex2(Byte value)
|
static inline void AddHexToString(UString &res, Byte value)
|
||||||
{
|
{
|
||||||
UString result;
|
res += GetHex((Byte)(value >> 4));
|
||||||
result += GetHex((Byte)(value >> 4));
|
res += GetHex((Byte)(value & 0xF));
|
||||||
result += GetHex((Byte)(value & 0xF));
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -273,57 +270,54 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
|||||||
UString methodsString;
|
UString methodsString;
|
||||||
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
|
for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
const CCoderInfo &coderInfo = folderInfo.Coders[i];
|
const CCoderInfo &coder = folderInfo.Coders[i];
|
||||||
if (!methodsString.IsEmpty())
|
if (!methodsString.IsEmpty())
|
||||||
methodsString += L' ';
|
methodsString += L' ';
|
||||||
|
|
||||||
{
|
UString methodName, propsString;
|
||||||
UString methodName;
|
|
||||||
bool methodIsKnown = FindMethod(
|
bool methodIsKnown = FindMethod(
|
||||||
EXTERNAL_CODECS_VARS
|
EXTERNAL_CODECS_VARS
|
||||||
coderInfo.MethodID, methodName);
|
coder.MethodID, methodName);
|
||||||
|
|
||||||
if (methodIsKnown)
|
if (!methodIsKnown)
|
||||||
|
methodsString += ConvertMethodIdToString(coder.MethodID);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
methodsString += methodName;
|
methodsString += methodName;
|
||||||
if (coderInfo.MethodID == k_LZMA)
|
if (coder.MethodID == k_Delta && coder.Props.GetCapacity() == 1)
|
||||||
|
propsString = ConvertUInt32ToString((UInt32)coder.Props[0] + 1);
|
||||||
|
else if (coder.MethodID == k_LZMA && coder.Props.GetCapacity() == 5)
|
||||||
{
|
{
|
||||||
if (coderInfo.Props.GetCapacity() >= 5)
|
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
|
||||||
{
|
propsString = GetStringForSizeValue(dicSize);
|
||||||
methodsString += L":";
|
|
||||||
UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);
|
|
||||||
methodsString += GetStringForSizeValue(dicSize);
|
|
||||||
}
|
}
|
||||||
|
else if (coder.MethodID == k_LZMA2 && coder.Props.GetCapacity() == 1)
|
||||||
|
{
|
||||||
|
Byte p = coder.Props[0];
|
||||||
|
UInt32 dicSize = (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11));
|
||||||
|
propsString = GetStringForSizeValue(dicSize);
|
||||||
}
|
}
|
||||||
else if (coderInfo.MethodID == k_PPMD)
|
else if (coder.MethodID == k_PPMD && coder.Props.GetCapacity() == 5)
|
||||||
{
|
{
|
||||||
if (coderInfo.Props.GetCapacity() >= 5)
|
Byte order = *(const Byte *)coder.Props;
|
||||||
{
|
methodsString += L'o';
|
||||||
Byte order = *(const Byte *)coderInfo.Props;
|
|
||||||
methodsString += L":o";
|
|
||||||
methodsString += ConvertUInt32ToString(order);
|
methodsString += ConvertUInt32ToString(order);
|
||||||
methodsString += L":mem";
|
methodsString += L":mem";
|
||||||
UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1);
|
UInt32 dicSize = GetUi32((const Byte *)coder.Props + 1);
|
||||||
methodsString += GetStringForSizeValue(dicSize);
|
propsString = GetStringForSizeValue(dicSize);
|
||||||
}
|
}
|
||||||
}
|
else if (coder.MethodID == k_AES && coder.Props.GetCapacity() >= 1)
|
||||||
else if (coderInfo.MethodID == k_AES)
|
|
||||||
{
|
{
|
||||||
if (coderInfo.Props.GetCapacity() >= 1)
|
const Byte *data = (const Byte *)coder.Props;
|
||||||
{
|
|
||||||
methodsString += L":";
|
|
||||||
const Byte *data = (const Byte *)coderInfo.Props;
|
|
||||||
Byte firstByte = *data++;
|
Byte firstByte = *data++;
|
||||||
UInt32 numCyclesPower = firstByte & 0x3F;
|
UInt32 numCyclesPower = firstByte & 0x3F;
|
||||||
methodsString += ConvertUInt32ToString(numCyclesPower);
|
propsString = ConvertUInt32ToString(numCyclesPower);
|
||||||
/*
|
/*
|
||||||
if ((firstByte & 0xC0) != 0)
|
if ((firstByte & 0xC0) != 0)
|
||||||
{
|
{
|
||||||
methodsString += L":";
|
|
||||||
return S_OK;
|
|
||||||
UInt32 saltSize = (firstByte >> 7) & 1;
|
UInt32 saltSize = (firstByte >> 7) & 1;
|
||||||
UInt32 ivSize = (firstByte >> 6) & 1;
|
UInt32 ivSize = (firstByte >> 6) & 1;
|
||||||
if (coderInfo.Props.GetCapacity() >= 2)
|
if (coder.Props.GetCapacity() >= 2)
|
||||||
{
|
{
|
||||||
Byte secondByte = *data++;
|
Byte secondByte = *data++;
|
||||||
saltSize += (secondByte >> 4);
|
saltSize += (secondByte >> 4);
|
||||||
@@ -333,29 +327,25 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *va
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
if (!propsString.IsEmpty())
|
||||||
{
|
{
|
||||||
if (coderInfo.Props.GetCapacity() > 0)
|
methodsString += L':';
|
||||||
|
methodsString += propsString;
|
||||||
|
}
|
||||||
|
else if (coder.Props.GetCapacity() > 0)
|
||||||
{
|
{
|
||||||
methodsString += L":[";
|
methodsString += L":[";
|
||||||
for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++)
|
for (size_t bi = 0; bi < coder.Props.GetCapacity(); bi++)
|
||||||
{
|
{
|
||||||
if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity())
|
if (bi > 5 && bi + 1 < coder.Props.GetCapacity())
|
||||||
{
|
{
|
||||||
methodsString += L"..";
|
methodsString += L"..";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
methodsString += GetHex2(coderInfo.Props[bi]);
|
AddHexToString(methodsString, coder.Props[bi]);
|
||||||
}
|
|
||||||
methodsString += L"]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
methodsString += ConvertMethodIdToString(coderInfo.MethodID);
|
|
||||||
}
|
}
|
||||||
|
methodsString += L']';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prop = methodsString;
|
prop = methodsString;
|
||||||
|
|||||||
@@ -5,9 +5,6 @@
|
|||||||
|
|
||||||
#include "../../ICoder.h"
|
#include "../../ICoder.h"
|
||||||
#include "../IArchive.h"
|
#include "../IArchive.h"
|
||||||
#include "7zIn.h"
|
|
||||||
|
|
||||||
#include "7zCompressionMode.h"
|
|
||||||
|
|
||||||
#include "../../Common/CreateCoder.h"
|
#include "../../Common/CreateCoder.h"
|
||||||
|
|
||||||
@@ -15,6 +12,9 @@
|
|||||||
#include "../Common/HandlerOut.h"
|
#include "../Common/HandlerOut.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "7zCompressionMode.h"
|
||||||
|
#include "7zIn.h"
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
namespace N7z {
|
namespace N7z {
|
||||||
|
|
||||||
@@ -90,8 +90,6 @@ private:
|
|||||||
|
|
||||||
CRecordVector<CBind> _binds;
|
CRecordVector<CBind> _binds;
|
||||||
|
|
||||||
HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
|
|
||||||
|
|
||||||
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
|
HRESULT SetCompressionMethod(CCompressionMethodMode &method,
|
||||||
CObjectVector<COneMethodInfo> &methodsInfo
|
CObjectVector<COneMethodInfo> &methodsInfo
|
||||||
#ifdef COMPRESS_MT
|
#ifdef COMPRESS_MT
|
||||||
|
|||||||
@@ -40,31 +40,6 @@ STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
|
|
||||||
IArchiveUpdateCallback *updateCallback)
|
|
||||||
{
|
|
||||||
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
|
|
||||||
if (!getTextPassword)
|
|
||||||
{
|
|
||||||
CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback);
|
|
||||||
udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getTextPassword)
|
|
||||||
{
|
|
||||||
CMyComBSTR password;
|
|
||||||
Int32 passwordIsDefined;
|
|
||||||
RINOK(getTextPassword->CryptoGetTextPassword2(
|
|
||||||
&passwordIsDefined, &password));
|
|
||||||
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
|
||||||
if (methodMode.PasswordIsDefined)
|
|
||||||
methodMode.Password = password;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
methodMode.PasswordIsDefined = false;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT CHandler::SetCompressionMethod(
|
HRESULT CHandler::SetCompressionMethod(
|
||||||
CCompressionMethodMode &methodMode,
|
CCompressionMethodMode &methodMode,
|
||||||
CCompressionMethodMode &headerMethod)
|
CCompressionMethodMode &headerMethod)
|
||||||
@@ -210,7 +185,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
|
|
||||||
const CArchiveDatabaseEx *db = 0;
|
const CArchiveDatabaseEx *db = 0;
|
||||||
#ifdef _7Z_VOL
|
#ifdef _7Z_VOL
|
||||||
if(_volumes.Size() > 1)
|
if (_volumes.Size() > 1)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
const CVolume *volume = 0;
|
const CVolume *volume = 0;
|
||||||
if (_volumes.Size() == 1)
|
if (_volumes.Size() == 1)
|
||||||
@@ -227,14 +202,13 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
|
|
||||||
for (UInt32 i = 0; i < numItems; i++)
|
for (UInt32 i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
Int32 newData;
|
Int32 newData, newProps;
|
||||||
Int32 newProperties;
|
|
||||||
UInt32 indexInArchive;
|
UInt32 indexInArchive;
|
||||||
if (!updateCallback)
|
if (!updateCallback)
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProperties, &indexInArchive));
|
RINOK(updateCallback->GetUpdateItemInfo(i, &newData, &newProps, &indexInArchive));
|
||||||
CUpdateItem ui;
|
CUpdateItem ui;
|
||||||
ui.NewProperties = IntToBool(newProperties);
|
ui.NewProps = IntToBool(newProps);
|
||||||
ui.NewData = IntToBool(newData);
|
ui.NewData = IntToBool(newData);
|
||||||
ui.IndexInArchive = indexInArchive;
|
ui.IndexInArchive = indexInArchive;
|
||||||
ui.IndexInClient = i;
|
ui.IndexInClient = i;
|
||||||
@@ -243,6 +217,8 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
|
|
||||||
if (ui.IndexInArchive != -1)
|
if (ui.IndexInArchive != -1)
|
||||||
{
|
{
|
||||||
|
if (db == 0 || ui.IndexInArchive >= db->Files.Size())
|
||||||
|
return E_INVALIDARG;
|
||||||
const CFileItem &fi = db->Files[ui.IndexInArchive];
|
const CFileItem &fi = db->Files[ui.IndexInArchive];
|
||||||
ui.Name = fi.Name;
|
ui.Name = fi.Name;
|
||||||
ui.IsDir = fi.IsDir;
|
ui.IsDir = fi.IsDir;
|
||||||
@@ -254,7 +230,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
ui.MTimeDefined = db->MTime.GetItem(ui.IndexInArchive, ui.MTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ui.NewProperties)
|
if (ui.NewProps)
|
||||||
{
|
{
|
||||||
bool nameIsDefined;
|
bool nameIsDefined;
|
||||||
bool folderStatusIsDefined;
|
bool folderStatusIsDefined;
|
||||||
@@ -350,7 +326,20 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
headerMethod.NumThreads = 1;
|
headerMethod.NumThreads = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
RINOK(SetPassword(methodMode, updateCallback));
|
CMyComPtr<ICryptoGetTextPassword2> getPassword2;
|
||||||
|
updateCallback->QueryInterface(IID_ICryptoGetTextPassword2, (void **)&getPassword2);
|
||||||
|
|
||||||
|
if (getPassword2)
|
||||||
|
{
|
||||||
|
CMyComBSTR password;
|
||||||
|
Int32 passwordIsDefined;
|
||||||
|
RINOK(getPassword2->CryptoGetTextPassword2(&passwordIsDefined, &password));
|
||||||
|
methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
|
||||||
|
if (methodMode.PasswordIsDefined)
|
||||||
|
methodMode.Password = password;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
methodMode.PasswordIsDefined = false;
|
||||||
|
|
||||||
bool compressMainHeader = _compressHeaders; // check it
|
bool compressMainHeader = _compressHeaders; // check it
|
||||||
|
|
||||||
@@ -365,8 +354,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
encryptHeaders = _passwordIsDefined;
|
encryptHeaders = _passwordIsDefined;
|
||||||
#endif
|
#endif
|
||||||
compressMainHeader = true;
|
compressMainHeader = true;
|
||||||
if(encryptHeaders)
|
if (encryptHeaders)
|
||||||
RINOK(SetPassword(headerMethod, updateCallback));
|
{
|
||||||
|
headerMethod.PasswordIsDefined = methodMode.PasswordIsDefined;
|
||||||
|
headerMethod.Password = methodMode.Password;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numItems < 2)
|
if (numItems < 2)
|
||||||
@@ -391,6 +383,10 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
|
|
||||||
COutArchive archive;
|
COutArchive archive;
|
||||||
CArchiveDatabase newDatabase;
|
CArchiveDatabase newDatabase;
|
||||||
|
|
||||||
|
CMyComPtr<ICryptoGetTextPassword> getPassword;
|
||||||
|
updateCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getPassword);
|
||||||
|
|
||||||
HRESULT res = Update(
|
HRESULT res = Update(
|
||||||
EXTERNAL_CODECS_VARS
|
EXTERNAL_CODECS_VARS
|
||||||
#ifdef _7Z_VOL
|
#ifdef _7Z_VOL
|
||||||
@@ -401,7 +397,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt
|
|||||||
db,
|
db,
|
||||||
#endif
|
#endif
|
||||||
updateItems,
|
updateItems,
|
||||||
archive, newDatabase, outStream, updateCallback, options);
|
archive, newDatabase, outStream, updateCallback, options
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
, getPassword
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
RINOK(res);
|
RINOK(res);
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,8 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
extern "C"
|
#include "../../../../C/7zCrc.h"
|
||||||
{
|
#include "../../../../C/CpuArch.h"
|
||||||
#include "../../../../C/7zCrc.h"
|
|
||||||
#include "../../../../C/CpuArch.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
#include "../../Common/StreamObjects.h"
|
#include "../../Common/StreamObjects.h"
|
||||||
#include "../../Common/StreamUtils.h"
|
#include "../../Common/StreamUtils.h"
|
||||||
@@ -198,16 +195,16 @@ void CInByte2::ReadBytes(Byte *data, size_t size)
|
|||||||
data[i] = _buffer[_pos++];
|
data[i] = _buffer[_pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInByte2::SkeepData(UInt64 size)
|
void CInByte2::SkipData(UInt64 size)
|
||||||
{
|
{
|
||||||
if (size > _size - _pos)
|
if (size > _size - _pos)
|
||||||
ThrowEndOfData();
|
ThrowEndOfData();
|
||||||
_pos += (size_t)size;
|
_pos += (size_t)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInByte2::SkeepData()
|
void CInByte2::SkipData()
|
||||||
{
|
{
|
||||||
SkeepData(ReadNumber());
|
SkipData(ReadNumber());
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt64 CInByte2::ReadNumber()
|
UInt64 CInByte2::ReadNumber()
|
||||||
@@ -363,7 +360,7 @@ void CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
|
|||||||
{
|
{
|
||||||
if (ReadID() == NID::kEnd)
|
if (ReadID() == NID::kEnd)
|
||||||
break;
|
break;
|
||||||
SkeepData();
|
SkipData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,7 +453,7 @@ void CInArchive::WaitAttribute(UInt64 attribute)
|
|||||||
return;
|
return;
|
||||||
if (type == NID::kEnd)
|
if (type == NID::kEnd)
|
||||||
ThrowIncorrect();
|
ThrowIncorrect();
|
||||||
SkeepData();
|
SkipData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,7 +499,7 @@ void CInArchive::ReadPackInfo(
|
|||||||
ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
|
ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SkeepData();
|
SkipData();
|
||||||
}
|
}
|
||||||
if (packCRCsDefined.IsEmpty())
|
if (packCRCsDefined.IsEmpty())
|
||||||
{
|
{
|
||||||
@@ -563,7 +560,7 @@ void CInArchive::ReadUnpackInfo(
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SkeepData();
|
SkipData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -590,7 +587,7 @@ void CInArchive::ReadSubStreamsInfo(
|
|||||||
break;
|
break;
|
||||||
if (type == NID::kEnd)
|
if (type == NID::kEnd)
|
||||||
break;
|
break;
|
||||||
SkeepData();
|
SkipData();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numUnpackStreamsInFolders.IsEmpty())
|
if (numUnpackStreamsInFolders.IsEmpty())
|
||||||
@@ -665,7 +662,7 @@ void CInArchive::ReadSubStreamsInfo(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SkeepData();
|
SkipData();
|
||||||
type = ReadID();
|
type = ReadID();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1003,7 @@ HRESULT CInArchive::ReadHeader(
|
|||||||
db.ArchiveInfo.FileInfoPopIDs.Add(type);
|
db.ArchiveInfo.FileInfoPopIDs.Add(type);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SkeepData(size);
|
SkipData(size);
|
||||||
bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||
|
bool checkRecordsSize = (db.ArchiveInfo.Version.Major > 0 ||
|
||||||
db.ArchiveInfo.Version.Minor > 2);
|
db.ArchiveInfo.Version.Minor > 2);
|
||||||
if (checkRecordsSize && _inByteBack->_pos - ppp != size)
|
if (checkRecordsSize && _inByteBack->_pos - ppp != size)
|
||||||
|
|||||||
@@ -110,8 +110,8 @@ public:
|
|||||||
}
|
}
|
||||||
Byte ReadByte();
|
Byte ReadByte();
|
||||||
void ReadBytes(Byte *data, size_t size);
|
void ReadBytes(Byte *data, size_t size);
|
||||||
void SkeepData(UInt64 size);
|
void SkipData(UInt64 size);
|
||||||
void SkeepData();
|
void SkipData();
|
||||||
UInt64 ReadNumber();
|
UInt64 ReadNumber();
|
||||||
CNum ReadNum();
|
CNum ReadNum();
|
||||||
UInt32 ReadUInt32();
|
UInt32 ReadUInt32();
|
||||||
@@ -162,8 +162,8 @@ private:
|
|||||||
UInt64 ReadID() { return _inByteBack->ReadNumber(); }
|
UInt64 ReadID() { return _inByteBack->ReadNumber(); }
|
||||||
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
|
UInt32 ReadUInt32() { return _inByteBack->ReadUInt32(); }
|
||||||
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
|
UInt64 ReadUInt64() { return _inByteBack->ReadUInt64(); }
|
||||||
void SkeepData(UInt64 size) { _inByteBack->SkeepData(size); }
|
void SkipData(UInt64 size) { _inByteBack->SkipData(size); }
|
||||||
void SkeepData() { _inByteBack->SkeepData(); }
|
void SkipData() { _inByteBack->SkipData(); }
|
||||||
void WaitAttribute(UInt64 attribute);
|
void WaitAttribute(UInt64 attribute);
|
||||||
|
|
||||||
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
|
void ReadArchiveProperties(CInArchiveInfo &archiveInfo);
|
||||||
|
|||||||
@@ -2,16 +2,14 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../../C/7zCrc.h"
|
||||||
|
|
||||||
#include "../../../Common/AutoPtr.h"
|
#include "../../../Common/AutoPtr.h"
|
||||||
|
|
||||||
#include "../../Common/StreamObjects.h"
|
#include "../../Common/StreamObjects.h"
|
||||||
|
|
||||||
#include "7zOut.h"
|
#include "7zOut.h"
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "../../../../C/7zCrc.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
|
static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
while (size > 0)
|
while (size > 0)
|
||||||
@@ -141,7 +139,7 @@ void COutArchive::Close()
|
|||||||
Stream.Release();
|
Stream.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT COutArchive::SkeepPrefixArchiveHeader()
|
HRESULT COutArchive::SkipPrefixArchiveHeader()
|
||||||
{
|
{
|
||||||
#ifdef _7Z_VOL
|
#ifdef _7Z_VOL
|
||||||
if (_endMarker)
|
if (_endMarker)
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
// 7z/Out.h
|
// 7zOut.h
|
||||||
|
|
||||||
#ifndef __7Z_OUT_H
|
#ifndef __7Z_OUT_H
|
||||||
#define __7Z_OUT_H
|
#define __7Z_OUT_H
|
||||||
|
|
||||||
#include "7zHeader.h"
|
|
||||||
#include "7zItem.h"
|
|
||||||
#include "7zCompressionMode.h"
|
#include "7zCompressionMode.h"
|
||||||
#include "7zEncode.h"
|
#include "7zEncode.h"
|
||||||
|
#include "7zHeader.h"
|
||||||
|
#include "7zItem.h"
|
||||||
|
|
||||||
#include "../../Common/OutBuffer.h"
|
#include "../../Common/OutBuffer.h"
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ public:
|
|||||||
CMyComPtr<ISequentialOutStream> SeqStream;
|
CMyComPtr<ISequentialOutStream> SeqStream;
|
||||||
HRESULT Create(ISequentialOutStream *stream, bool endMarker);
|
HRESULT Create(ISequentialOutStream *stream, bool endMarker);
|
||||||
void Close();
|
void Close();
|
||||||
HRESULT SkeepPrefixArchiveHeader();
|
HRESULT SkipPrefixArchiveHeader();
|
||||||
HRESULT WriteDatabase(
|
HRESULT WriteDatabase(
|
||||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||||
const CArchiveDatabase &db,
|
const CArchiveDatabase &db,
|
||||||
|
|||||||
@@ -5,10 +5,14 @@
|
|||||||
#include "../../Common/LimitedStreams.h"
|
#include "../../Common/LimitedStreams.h"
|
||||||
#include "../../Common/ProgressUtils.h"
|
#include "../../Common/ProgressUtils.h"
|
||||||
|
|
||||||
|
#include "../../Common/CreateCoder.h"
|
||||||
|
|
||||||
#include "../../Compress/CopyCoder.h"
|
#include "../../Compress/CopyCoder.h"
|
||||||
|
|
||||||
#include "../Common/ItemNameUtils.h"
|
#include "../Common/ItemNameUtils.h"
|
||||||
|
#include "../Common/OutStreamWithCRC.h"
|
||||||
|
|
||||||
|
#include "7zDecode.h"
|
||||||
#include "7zEncode.h"
|
#include "7zEncode.h"
|
||||||
#include "7zFolderInStream.h"
|
#include "7zFolderInStream.h"
|
||||||
#include "7zHandler.h"
|
#include "7zHandler.h"
|
||||||
@@ -18,6 +22,11 @@
|
|||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
namespace N7z {
|
namespace N7z {
|
||||||
|
|
||||||
|
static const UInt64 k_LZMA = 0x030101;
|
||||||
|
static const UInt64 k_BCJ = 0x03030103;
|
||||||
|
static const UInt64 k_BCJ2 = 0x0303011B;
|
||||||
|
static const UInt64 k_AES = 0x06F10701;
|
||||||
|
|
||||||
static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
|
static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
|
||||||
static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
|
static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
|
||||||
static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
|
static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
|
||||||
@@ -64,27 +73,29 @@ UString CUpdateItem::GetExtension() const
|
|||||||
|
|
||||||
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
|
||||||
|
|
||||||
|
#define RINOZ_COMP(a, b) RINOZ(MyCompare(a, b))
|
||||||
|
|
||||||
static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
|
static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
|
||||||
{
|
{
|
||||||
size_t c1 = a1.GetCapacity();
|
size_t c1 = a1.GetCapacity();
|
||||||
size_t c2 = a2.GetCapacity();
|
size_t c2 = a2.GetCapacity();
|
||||||
RINOZ(MyCompare(c1, c2));
|
RINOZ_COMP(c1, c2);
|
||||||
for (size_t i = 0; i < c1; i++)
|
for (size_t i = 0; i < c1; i++)
|
||||||
RINOZ(MyCompare(a1[i], a2[i]));
|
RINOZ_COMP(a1[i], a2[i]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
|
static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
|
||||||
{
|
{
|
||||||
RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams));
|
RINOZ_COMP(c1.NumInStreams, c2.NumInStreams);
|
||||||
RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams));
|
RINOZ_COMP(c1.NumOutStreams, c2.NumOutStreams);
|
||||||
RINOZ(MyCompare(c1.MethodID, c2.MethodID));
|
RINOZ_COMP(c1.MethodID, c2.MethodID);
|
||||||
return CompareBuffers(c1.Props, c2.Props);
|
return CompareBuffers(c1.Props, c2.Props);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
|
static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
|
||||||
{
|
{
|
||||||
RINOZ(MyCompare(b1.InIndex, b2.InIndex));
|
RINOZ_COMP(b1.InIndex, b2.InIndex);
|
||||||
return MyCompare(b1.OutIndex, b2.OutIndex);
|
return MyCompare(b1.OutIndex, b2.OutIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,39 +103,52 @@ static int CompareFolders(const CFolder &f1, const CFolder &f2)
|
|||||||
{
|
{
|
||||||
int s1 = f1.Coders.Size();
|
int s1 = f1.Coders.Size();
|
||||||
int s2 = f2.Coders.Size();
|
int s2 = f2.Coders.Size();
|
||||||
RINOZ(MyCompare(s1, s2));
|
RINOZ_COMP(s1, s2);
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < s1; i++)
|
for (i = 0; i < s1; i++)
|
||||||
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
|
RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
|
||||||
s1 = f1.BindPairs.Size();
|
s1 = f1.BindPairs.Size();
|
||||||
s2 = f2.BindPairs.Size();
|
s2 = f2.BindPairs.Size();
|
||||||
RINOZ(MyCompare(s1, s2));
|
RINOZ_COMP(s1, s2);
|
||||||
for (i = 0; i < s1; i++)
|
for (i = 0; i < s1; i++)
|
||||||
RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
|
RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
|
static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
|
||||||
{
|
{
|
||||||
return MyStringCompareNoCase(f1.Name, f2.Name);
|
return MyStringCompareNoCase(f1.Name, f2.Name);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
static int CompareFolderRefs(const int *p1, const int *p2, void *param)
|
const struct CFolderRepack
|
||||||
{
|
{
|
||||||
int i1 = *p1;
|
int FolderIndex;
|
||||||
int i2 = *p2;
|
int Group;
|
||||||
|
CNum NumCopyFiles;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int CompareFolderRepacks(const CFolderRepack *p1, const CFolderRepack *p2, void *param)
|
||||||
|
{
|
||||||
|
RINOZ_COMP(p1->Group, p2->Group);
|
||||||
|
int i1 = p1->FolderIndex;
|
||||||
|
int i2 = p2->FolderIndex;
|
||||||
const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
|
const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
|
||||||
RINOZ(CompareFolders(
|
RINOZ(CompareFolders(
|
||||||
db.Folders[i1],
|
db.Folders[i1],
|
||||||
db.Folders[i2]));
|
db.Folders[i2]));
|
||||||
RINOZ(MyCompare(
|
return MyCompare(i1, i2);
|
||||||
|
/*
|
||||||
|
RINOZ_COMP(
|
||||||
db.NumUnpackStreamsVector[i1],
|
db.NumUnpackStreamsVector[i1],
|
||||||
db.NumUnpackStreamsVector[i2]));
|
db.NumUnpackStreamsVector[i2]);
|
||||||
if (db.NumUnpackStreamsVector[i1] == 0)
|
if (db.NumUnpackStreamsVector[i1] == 0)
|
||||||
return 0;
|
return 0;
|
||||||
return CompareFiles(
|
return CompareFiles(
|
||||||
db.Files[db.FolderStartFileIndex[i1]],
|
db.Files[db.FolderStartFileIndex[i1]],
|
||||||
db.Files[db.FolderStartFileIndex[i2]]);
|
db.Files[db.FolderStartFileIndex[i2]]);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
@@ -277,20 +301,19 @@ static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *para
|
|||||||
bool sortByType = *(bool *)param;
|
bool sortByType = *(bool *)param;
|
||||||
if (sortByType)
|
if (sortByType)
|
||||||
{
|
{
|
||||||
RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex))
|
RINOZ_COMP(a1.ExtensionIndex, a2.ExtensionIndex);
|
||||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
|
RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
|
||||||
RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
|
RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
|
||||||
if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
|
if (!u1.MTimeDefined && u2.MTimeDefined) return 1;
|
||||||
if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
|
if (u1.MTimeDefined && !u2.MTimeDefined) return -1;
|
||||||
if (u1.MTimeDefined && u2.MTimeDefined) RINOZ(MyCompare(u1.MTime, u2.MTime));
|
if (u1.MTimeDefined && u2.MTimeDefined) RINOZ_COMP(u1.MTime, u2.MTime);
|
||||||
RINOZ(MyCompare(u1.Size, u2.Size))
|
RINOZ_COMP(u1.Size, u2.Size);
|
||||||
}
|
}
|
||||||
return MyStringCompareNoCase(u1.Name, u2.Name);
|
return MyStringCompareNoCase(u1.Name, u2.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CSolidGroup
|
struct CSolidGroup
|
||||||
{
|
{
|
||||||
CCompressionMethodMode Method;
|
|
||||||
CRecordVector<UInt32> Indices;
|
CRecordVector<UInt32> Indices;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -303,7 +326,7 @@ static wchar_t *g_ExeExts[] =
|
|||||||
L"sys"
|
L"sys"
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool IsExeFile(const UString &ext)
|
static bool IsExeExt(const UString &ext)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
|
for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
|
||||||
if (ext.CompareNoCase(g_ExeExts[i]) == 0)
|
if (ext.CompareNoCase(g_ExeExts[i]) == 0)
|
||||||
@@ -311,31 +334,23 @@ static bool IsExeFile(const UString &ext)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const UInt64 k_LZMA = 0x030101;
|
static void GetMethodFull(UInt64 methodID, UInt32 numInStreams, CMethodFull &methodResult)
|
||||||
static const UInt64 k_BCJ = 0x03030103;
|
|
||||||
static const UInt64 k_BCJ2 = 0x0303011B;
|
|
||||||
|
|
||||||
static bool GetMethodFull(UInt64 methodID,
|
|
||||||
UInt32 numInStreams, CMethodFull &methodResult)
|
|
||||||
{
|
{
|
||||||
methodResult.Id = methodID;
|
methodResult.Id = methodID;
|
||||||
methodResult.NumInStreams = numInStreams;
|
methodResult.NumInStreams = numInStreams;
|
||||||
methodResult.NumOutStreams = 1;
|
methodResult.NumOutStreams = 1;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool MakeExeMethod(const CCompressionMethodMode &method,
|
static void MakeExeMethod(const CCompressionMethodMode &method,
|
||||||
bool bcj2Filter, CCompressionMethodMode &exeMethod)
|
bool bcj2Filter, CCompressionMethodMode &exeMethod)
|
||||||
{
|
{
|
||||||
exeMethod = method;
|
exeMethod = method;
|
||||||
if (bcj2Filter)
|
if (bcj2Filter)
|
||||||
{
|
{
|
||||||
CMethodFull methodFull;
|
CMethodFull methodFull;
|
||||||
if (!GetMethodFull(k_BCJ2, 4, methodFull))
|
GetMethodFull(k_BCJ2, 4, methodFull);
|
||||||
return false;
|
|
||||||
exeMethod.Methods.Insert(0, methodFull);
|
exeMethod.Methods.Insert(0, methodFull);
|
||||||
if (!GetMethodFull(k_LZMA, 1, methodFull))
|
GetMethodFull(k_LZMA, 1, methodFull);
|
||||||
return false;
|
|
||||||
{
|
{
|
||||||
CProp prop;
|
CProp prop;
|
||||||
prop.Id = NCoderPropID::kAlgorithm;
|
prop.Id = NCoderPropID::kAlgorithm;
|
||||||
@@ -383,8 +398,7 @@ static bool MakeExeMethod(const CCompressionMethodMode &method,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
CMethodFull methodFull;
|
CMethodFull methodFull;
|
||||||
if (!GetMethodFull(k_BCJ, 1, methodFull))
|
GetMethodFull(k_BCJ, 1, methodFull);
|
||||||
return false;
|
|
||||||
exeMethod.Methods.Insert(0, methodFull);
|
exeMethod.Methods.Insert(0, methodFull);
|
||||||
CBind bind;
|
CBind bind;
|
||||||
bind.OutCoder = 0;
|
bind.OutCoder = 0;
|
||||||
@@ -393,55 +407,6 @@ static bool MakeExeMethod(const CCompressionMethodMode &method,
|
|||||||
bind.OutStream = 0;
|
bind.OutStream = 0;
|
||||||
exeMethod.Binds.Add(bind);
|
exeMethod.Binds.Add(bind);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void SplitFilesToGroups(
|
|
||||||
const CCompressionMethodMode &method,
|
|
||||||
bool useFilters, bool maxFilter,
|
|
||||||
const CObjectVector<CUpdateItem> &updateItems,
|
|
||||||
CObjectVector<CSolidGroup> &groups)
|
|
||||||
{
|
|
||||||
if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
|
|
||||||
useFilters = false;
|
|
||||||
groups.Clear();
|
|
||||||
groups.Add(CSolidGroup());
|
|
||||||
groups.Add(CSolidGroup());
|
|
||||||
CSolidGroup &generalGroup = groups[0];
|
|
||||||
CSolidGroup &exeGroup = groups[1];
|
|
||||||
generalGroup.Method = method;
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < updateItems.Size(); i++)
|
|
||||||
{
|
|
||||||
const CUpdateItem &ui = updateItems[i];
|
|
||||||
if (!ui.NewData)
|
|
||||||
continue;
|
|
||||||
if (!ui.HasStream())
|
|
||||||
continue;
|
|
||||||
if (useFilters)
|
|
||||||
{
|
|
||||||
const UString name = ui.Name;
|
|
||||||
int dotPos = name.ReverseFind(L'.');
|
|
||||||
if (dotPos >= 0)
|
|
||||||
{
|
|
||||||
UString ext = name.Mid(dotPos + 1);
|
|
||||||
if (IsExeFile(ext))
|
|
||||||
{
|
|
||||||
exeGroup.Indices.Add(i);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
generalGroup.Indices.Add(i);
|
|
||||||
}
|
|
||||||
if (exeGroup.Indices.Size() > 0)
|
|
||||||
if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
|
|
||||||
exeGroup.Method = method;
|
|
||||||
for (i = 0; i < groups.Size();)
|
|
||||||
if (groups[i].Indices.Size() == 0)
|
|
||||||
groups.Delete(i);
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
|
static void FromUpdateItemToFileItem(const CUpdateItem &ui,
|
||||||
@@ -462,7 +427,250 @@ static void FromUpdateItemToFileItem(const CUpdateItem &ui,
|
|||||||
file.HasStream = ui.HasStream();
|
file.HasStream = ui.HasStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT Update2(
|
class CFolderOutStream2:
|
||||||
|
public ISequentialOutStream,
|
||||||
|
public CMyUnknownImp
|
||||||
|
{
|
||||||
|
COutStreamWithCRC *_crcStreamSpec;
|
||||||
|
CMyComPtr<ISequentialOutStream> _crcStream;
|
||||||
|
const CArchiveDatabaseEx *_db;
|
||||||
|
const CBoolVector *_extractStatuses;
|
||||||
|
CMyComPtr<ISequentialOutStream> _outStream;
|
||||||
|
UInt32 _startIndex;
|
||||||
|
int _currentIndex;
|
||||||
|
bool _fileIsOpen;
|
||||||
|
UInt64 _rem;
|
||||||
|
|
||||||
|
void OpenFile();
|
||||||
|
void CloseFile();
|
||||||
|
HRESULT CloseFileAndSetResult();
|
||||||
|
HRESULT ProcessEmptyFiles();
|
||||||
|
public:
|
||||||
|
MY_UNKNOWN_IMP
|
||||||
|
|
||||||
|
CFolderOutStream2()
|
||||||
|
{
|
||||||
|
_crcStreamSpec = new COutStreamWithCRC;
|
||||||
|
_crcStream = _crcStreamSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Init(const CArchiveDatabaseEx *db, UInt32 startIndex,
|
||||||
|
const CBoolVector *extractStatuses, ISequentialOutStream *outStream);
|
||||||
|
void ReleaseOutStream();
|
||||||
|
HRESULT CheckFinishedState() const { return (_currentIndex == _extractStatuses->Size()) ? S_OK: E_FAIL; }
|
||||||
|
|
||||||
|
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT CFolderOutStream2::Init(const CArchiveDatabaseEx *db, UInt32 startIndex,
|
||||||
|
const CBoolVector *extractStatuses, ISequentialOutStream *outStream)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_startIndex = startIndex;
|
||||||
|
_extractStatuses = extractStatuses;
|
||||||
|
_outStream = outStream;
|
||||||
|
|
||||||
|
_currentIndex = 0;
|
||||||
|
_fileIsOpen = false;
|
||||||
|
return ProcessEmptyFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFolderOutStream2::ReleaseOutStream()
|
||||||
|
{
|
||||||
|
_outStream.Release();
|
||||||
|
_crcStreamSpec->ReleaseStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFolderOutStream2::OpenFile()
|
||||||
|
{
|
||||||
|
_crcStreamSpec->SetStream((*_extractStatuses)[_currentIndex] ? _outStream : NULL);
|
||||||
|
_crcStreamSpec->Init(true);
|
||||||
|
_fileIsOpen = true;
|
||||||
|
_rem = _db->Files[_startIndex + _currentIndex].Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFolderOutStream2::CloseFile()
|
||||||
|
{
|
||||||
|
_crcStreamSpec->ReleaseStream();
|
||||||
|
_fileIsOpen = false;
|
||||||
|
_currentIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CFolderOutStream2::CloseFileAndSetResult()
|
||||||
|
{
|
||||||
|
const CFileItem &file = _db->Files[_startIndex + _currentIndex];
|
||||||
|
CloseFile();
|
||||||
|
return (file.IsDir || !file.CrcDefined || file.Crc == _crcStreamSpec->GetCRC()) ? S_OK: S_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT CFolderOutStream2::ProcessEmptyFiles()
|
||||||
|
{
|
||||||
|
while (_currentIndex < _extractStatuses->Size() && _db->Files[_startIndex + _currentIndex].Size == 0)
|
||||||
|
{
|
||||||
|
OpenFile();
|
||||||
|
RINOK(CloseFileAndSetResult());
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CFolderOutStream2::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
|
{
|
||||||
|
if (processedSize != NULL)
|
||||||
|
*processedSize = 0;
|
||||||
|
while (size != 0)
|
||||||
|
{
|
||||||
|
if (_fileIsOpen)
|
||||||
|
{
|
||||||
|
UInt32 cur = size < _rem ? size : (UInt32)_rem;
|
||||||
|
RINOK(_crcStream->Write(data, cur, &cur));
|
||||||
|
if (cur == 0)
|
||||||
|
break;
|
||||||
|
data = (const Byte *)data + cur;
|
||||||
|
size -= cur;
|
||||||
|
_rem -= cur;
|
||||||
|
if (processedSize != NULL)
|
||||||
|
*processedSize += cur;
|
||||||
|
if (_rem == 0)
|
||||||
|
{
|
||||||
|
RINOK(CloseFileAndSetResult());
|
||||||
|
RINOK(ProcessEmptyFiles());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RINOK(ProcessEmptyFiles());
|
||||||
|
if (_currentIndex == _extractStatuses->Size())
|
||||||
|
{
|
||||||
|
// we don't support partial extracting
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
OpenFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CThreadDecoder: public CVirtThread
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HRESULT Result;
|
||||||
|
CMyComPtr<IInStream> InStream;
|
||||||
|
|
||||||
|
CFolderOutStream2 *FosSpec;
|
||||||
|
CMyComPtr<ISequentialOutStream> Fos;
|
||||||
|
|
||||||
|
UInt64 StartPos;
|
||||||
|
const UInt64 *PackSizes;
|
||||||
|
const CFolder *Folder;
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
CMyComPtr<ICryptoGetTextPassword> GetTextPassword;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DECL_EXTERNAL_CODECS_VARS
|
||||||
|
CDecoder Decoder;
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
bool MtMode;
|
||||||
|
UInt32 NumThreads;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CThreadDecoder():
|
||||||
|
Decoder(true)
|
||||||
|
{
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
MtMode = false;
|
||||||
|
NumThreads = 1;
|
||||||
|
#endif
|
||||||
|
FosSpec = new CFolderOutStream2;
|
||||||
|
Fos = FosSpec;
|
||||||
|
Result = E_FAIL;
|
||||||
|
}
|
||||||
|
virtual void Execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
void CThreadDecoder::Execute()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
bool passwordIsDefined;
|
||||||
|
#endif
|
||||||
|
Result = Decoder.Decode(
|
||||||
|
EXTERNAL_CODECS_VARS
|
||||||
|
InStream,
|
||||||
|
StartPos,
|
||||||
|
PackSizes,
|
||||||
|
*Folder,
|
||||||
|
Fos,
|
||||||
|
NULL
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
, GetTextPassword, passwordIsDefined
|
||||||
|
#endif
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
, MtMode, NumThreads
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
Result = E_FAIL;
|
||||||
|
}
|
||||||
|
if (Result == S_OK)
|
||||||
|
Result = FosSpec->CheckFinishedState();
|
||||||
|
FosSpec->ReleaseOutStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool static Is86FilteredFolder(const CFolder &f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < f.Coders.Size(); i++)
|
||||||
|
{
|
||||||
|
CMethodId m = f.Coders[i].MethodID;
|
||||||
|
if (m == k_BCJ || m == k_BCJ2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool static IsEncryptedFolder(const CFolder &f)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < f.Coders.Size(); i++)
|
||||||
|
{
|
||||||
|
CMethodId m = f.Coders[i].MethodID;
|
||||||
|
if (m == k_AES)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
|
||||||
|
class CCryptoGetTextPassword:
|
||||||
|
public ICryptoGetTextPassword,
|
||||||
|
public CMyUnknownImp
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UString Password;
|
||||||
|
|
||||||
|
MY_UNKNOWN_IMP
|
||||||
|
STDMETHOD(CryptoGetTextPassword)(BSTR *password);
|
||||||
|
};
|
||||||
|
|
||||||
|
STDMETHODIMP CCryptoGetTextPassword::CryptoGetTextPassword(BSTR *password)
|
||||||
|
{
|
||||||
|
return StringToBstr(Password, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const int kNumGroupsMax = 4;
|
||||||
|
|
||||||
|
static bool Is86Group(int group) { return (group & 1) != 0; }
|
||||||
|
static bool IsEncryptedGroup(int group) { return (group & 2) != 0; }
|
||||||
|
static int GetGroupIndex(bool encrypted, int bcjFiltered)
|
||||||
|
{ return (encrypted ? 2 : 0) + (bcjFiltered ? 1 : 0); }
|
||||||
|
|
||||||
|
HRESULT Update(
|
||||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
DECL_EXTERNAL_CODECS_LOC_VARS
|
||||||
IInStream *inStream,
|
IInStream *inStream,
|
||||||
const CArchiveDatabaseEx *db,
|
const CArchiveDatabaseEx *db,
|
||||||
@@ -471,7 +679,11 @@ static HRESULT Update2(
|
|||||||
CArchiveDatabase &newDatabase,
|
CArchiveDatabase &newDatabase,
|
||||||
ISequentialOutStream *seqOutStream,
|
ISequentialOutStream *seqOutStream,
|
||||||
IArchiveUpdateCallback *updateCallback,
|
IArchiveUpdateCallback *updateCallback,
|
||||||
const CUpdateOptions &options)
|
const CUpdateOptions &options
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
, ICryptoGetTextPassword *getDecoderPassword
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
UInt64 numSolidFiles = options.NumSolidFiles;
|
UInt64 numSolidFiles = options.NumSolidFiles;
|
||||||
if (numSolidFiles == 0)
|
if (numSolidFiles == 0)
|
||||||
@@ -490,92 +702,206 @@ static HRESULT Update2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CRecordVector<int> fileIndexToUpdateIndexMap;
|
CRecordVector<int> fileIndexToUpdateIndexMap;
|
||||||
|
CRecordVector<CFolderRepack> folderRefs;
|
||||||
|
UInt64 complexity = 0;
|
||||||
|
UInt64 inSizeForReduce2 = 0;
|
||||||
|
bool needEncryptedRepack = false;
|
||||||
if (db != 0)
|
if (db != 0)
|
||||||
{
|
{
|
||||||
fileIndexToUpdateIndexMap.Reserve(db->Files.Size());
|
fileIndexToUpdateIndexMap.Reserve(db->Files.Size());
|
||||||
for (int i = 0; i < db->Files.Size(); i++)
|
|
||||||
fileIndexToUpdateIndexMap.Add(-1);
|
|
||||||
}
|
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < updateItems.Size(); i++)
|
for (i = 0; i < db->Files.Size(); i++)
|
||||||
|
fileIndexToUpdateIndexMap.Add(-1);
|
||||||
|
|
||||||
|
for (i = 0; i < updateItems.Size(); i++)
|
||||||
{
|
{
|
||||||
int index = updateItems[i].IndexInArchive;
|
int index = updateItems[i].IndexInArchive;
|
||||||
if (index != -1)
|
if (index != -1)
|
||||||
fileIndexToUpdateIndexMap[index] = i;
|
fileIndexToUpdateIndexMap[index] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
CRecordVector<int> folderRefs;
|
for (i = 0; i < db->Folders.Size(); i++)
|
||||||
if (db != 0)
|
|
||||||
{
|
|
||||||
for(i = 0; i < db->Folders.Size(); i++)
|
|
||||||
{
|
{
|
||||||
CNum indexInFolder = 0;
|
CNum indexInFolder = 0;
|
||||||
CNum numCopyItems = 0;
|
CNum numCopyItems = 0;
|
||||||
CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
|
CNum numUnpackStreams = db->NumUnpackStreamsVector[i];
|
||||||
for (CNum fileIndex = db->FolderStartFileIndex[i];
|
UInt64 repackSize = 0;
|
||||||
indexInFolder < numUnpackStreams; fileIndex++)
|
for (CNum fi = db->FolderStartFileIndex[i]; indexInFolder < numUnpackStreams; fi++)
|
||||||
{
|
{
|
||||||
if (db->Files[fileIndex].HasStream)
|
const CFileItem &file = db->Files[fi];
|
||||||
|
if (file.HasStream)
|
||||||
{
|
{
|
||||||
indexInFolder++;
|
indexInFolder++;
|
||||||
int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
|
int updateIndex = fileIndexToUpdateIndexMap[fi];
|
||||||
if (updateIndex >= 0)
|
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
|
||||||
if (!updateItems[updateIndex].NewData)
|
{
|
||||||
numCopyItems++;
|
numCopyItems++;
|
||||||
|
repackSize += file.Size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (numCopyItems != numUnpackStreams && numCopyItems != 0)
|
|
||||||
return E_NOTIMPL; // It needs repacking !!!
|
|
||||||
if (numCopyItems > 0)
|
|
||||||
folderRefs.Add(i);
|
|
||||||
}
|
|
||||||
folderRefs.Sort(CompareFolderRefs, (void *)db);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////
|
if (numCopyItems == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CFolderRepack rep;
|
||||||
|
rep.FolderIndex = i;
|
||||||
|
rep.NumCopyFiles = numCopyItems;
|
||||||
|
const CFolder &f = db->Folders[i];
|
||||||
|
bool isEncrypted = IsEncryptedFolder(f);
|
||||||
|
rep.Group = GetGroupIndex(isEncrypted, Is86FilteredFolder(f));
|
||||||
|
folderRefs.Add(rep);
|
||||||
|
if (numCopyItems == numUnpackStreams)
|
||||||
|
complexity += db->GetFolderFullPackSize(i);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
complexity += repackSize;
|
||||||
|
if (repackSize > inSizeForReduce2)
|
||||||
|
inSizeForReduce2 = repackSize;
|
||||||
|
if (isEncrypted)
|
||||||
|
needEncryptedRepack = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
folderRefs.Sort(CompareFolderRepacks, (void *)db);
|
||||||
|
}
|
||||||
|
|
||||||
RINOK(archive.Create(seqOutStream, false));
|
|
||||||
RINOK(archive.SkeepPrefixArchiveHeader());
|
|
||||||
UInt64 complexity = 0;
|
|
||||||
for(i = 0; i < folderRefs.Size(); i++)
|
|
||||||
complexity += db->GetFolderFullPackSize(folderRefs[i]);
|
|
||||||
UInt64 inSizeForReduce = 0;
|
UInt64 inSizeForReduce = 0;
|
||||||
for(i = 0; i < updateItems.Size(); i++)
|
int i;
|
||||||
|
for (i = 0; i < updateItems.Size(); i++)
|
||||||
{
|
{
|
||||||
const CUpdateItem &ui = updateItems[i];
|
const CUpdateItem &ui = updateItems[i];
|
||||||
if (ui.NewData)
|
if (ui.NewData)
|
||||||
{
|
{
|
||||||
complexity += ui.Size;
|
complexity += ui.Size;
|
||||||
if (numSolidFiles == 1)
|
if (numSolidFiles != 1)
|
||||||
{
|
inSizeForReduce += ui.Size;
|
||||||
if (ui.Size > inSizeForReduce)
|
else if (ui.Size > inSizeForReduce)
|
||||||
inSizeForReduce = ui.Size;
|
inSizeForReduce = ui.Size;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
inSizeForReduce += ui.Size;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
RINOK(updateCallback->SetTotal(complexity));
|
|
||||||
complexity = 0;
|
|
||||||
RINOK(updateCallback->SetCompleted(&complexity));
|
|
||||||
|
|
||||||
|
if (inSizeForReduce2 > inSizeForReduce)
|
||||||
|
inSizeForReduce = inSizeForReduce2;
|
||||||
|
|
||||||
|
const UInt32 kMinReduceSize = (1 << 16);
|
||||||
|
if (inSizeForReduce < kMinReduceSize)
|
||||||
|
inSizeForReduce = kMinReduceSize;
|
||||||
|
|
||||||
|
RINOK(updateCallback->SetTotal(complexity));
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
CLocalProgress *lps = new CLocalProgress;
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||||
lps->Init(updateCallback, true);
|
lps->Init(updateCallback, true);
|
||||||
|
|
||||||
/////////////////////////////////////////
|
CThreadDecoder threadDecoder;
|
||||||
// Write Copy Items
|
if (!folderRefs.IsEmpty())
|
||||||
|
|
||||||
for(i = 0; i < folderRefs.Size(); i++)
|
|
||||||
{
|
{
|
||||||
int folderIndex = folderRefs[i];
|
#ifdef EXTERNAL_CODECS
|
||||||
|
threadDecoder._codecsInfo = codecsInfo;
|
||||||
|
threadDecoder._externalCodecs = *externalCodecs;
|
||||||
|
#endif
|
||||||
|
RINOK(threadDecoder.Create());
|
||||||
|
}
|
||||||
|
|
||||||
lps->ProgressOffset = complexity;
|
CObjectVector<CSolidGroup> groups;
|
||||||
|
for (i = 0; i < kNumGroupsMax; i++)
|
||||||
|
groups.Add(CSolidGroup());
|
||||||
|
|
||||||
|
{
|
||||||
|
// ---------- Split files to 2 groups ----------
|
||||||
|
|
||||||
|
bool useFilters = options.UseFilters;
|
||||||
|
const CCompressionMethodMode &method = *options.Method;
|
||||||
|
if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
|
||||||
|
useFilters = false;
|
||||||
|
for (i = 0; i < updateItems.Size(); i++)
|
||||||
|
{
|
||||||
|
const CUpdateItem &ui = updateItems[i];
|
||||||
|
if (!ui.NewData || !ui.HasStream())
|
||||||
|
continue;
|
||||||
|
bool filteredGroup = false;
|
||||||
|
if (useFilters)
|
||||||
|
{
|
||||||
|
int dotPos = ui.Name.ReverseFind(L'.');
|
||||||
|
if (dotPos >= 0)
|
||||||
|
filteredGroup = IsExeExt(ui.Name.Mid(dotPos + 1));
|
||||||
|
}
|
||||||
|
groups[GetGroupIndex(method.PasswordIsDefined, filteredGroup)].Indices.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
|
||||||
|
CCryptoGetTextPassword *getPasswordSpec = NULL;
|
||||||
|
if (needEncryptedRepack)
|
||||||
|
{
|
||||||
|
getPasswordSpec = new CCryptoGetTextPassword;
|
||||||
|
threadDecoder.GetTextPassword = getPasswordSpec;
|
||||||
|
|
||||||
|
if (options.Method->PasswordIsDefined)
|
||||||
|
getPasswordSpec->Password = options.Method->Password;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!getDecoderPassword)
|
||||||
|
return E_NOTIMPL;
|
||||||
|
CMyComBSTR password;
|
||||||
|
RINOK(getDecoderPassword->CryptoGetTextPassword(&password));
|
||||||
|
getPasswordSpec->Password = password;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ---------- Compress ----------
|
||||||
|
|
||||||
|
RINOK(archive.Create(seqOutStream, false));
|
||||||
|
RINOK(archive.SkipPrefixArchiveHeader());
|
||||||
|
|
||||||
|
int folderRefIndex = 0;
|
||||||
|
lps->ProgressOffset = 0;
|
||||||
|
|
||||||
|
for (int groupIndex = 0; groupIndex < kNumGroupsMax; groupIndex++)
|
||||||
|
{
|
||||||
|
const CSolidGroup &group = groups[groupIndex];
|
||||||
|
|
||||||
|
CCompressionMethodMode method;
|
||||||
|
if (Is86Group(groupIndex))
|
||||||
|
MakeExeMethod(*options.Method, options.MaxFilter, method);
|
||||||
|
else
|
||||||
|
method = *options.Method;
|
||||||
|
|
||||||
|
if (IsEncryptedGroup(groupIndex))
|
||||||
|
{
|
||||||
|
if (!method.PasswordIsDefined)
|
||||||
|
{
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
if (getPasswordSpec)
|
||||||
|
method.Password = getPasswordSpec->Password;
|
||||||
|
#endif
|
||||||
|
method.PasswordIsDefined = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
method.PasswordIsDefined = false;
|
||||||
|
method.Password.Empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
CEncoder encoder(method);
|
||||||
|
|
||||||
|
for (; folderRefIndex < folderRefs.Size(); folderRefIndex++)
|
||||||
|
{
|
||||||
|
const CFolderRepack &rep = folderRefs[folderRefIndex];
|
||||||
|
if (rep.Group != groupIndex)
|
||||||
|
break;
|
||||||
|
int folderIndex = rep.FolderIndex;
|
||||||
|
|
||||||
|
if (rep.NumCopyFiles == db->NumUnpackStreamsVector[folderIndex])
|
||||||
|
{
|
||||||
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
|
UInt64 packSize = db->GetFolderFullPackSize(folderIndex);
|
||||||
RINOK(WriteRange(inStream, archive.SeqStream,
|
RINOK(WriteRange(inStream, archive.SeqStream,
|
||||||
db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
|
db->GetFolderStreamPos(folderIndex, 0), packSize, progress));
|
||||||
complexity += packSize;
|
lps->ProgressOffset += packSize;
|
||||||
|
|
||||||
const CFolder &folder = db->Folders[folderIndex];
|
const CFolder &folder = db->Folders[folderIndex];
|
||||||
CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];
|
CNum startIndex = db->FolderStartPackStreamIndex[folderIndex];
|
||||||
@@ -586,13 +912,66 @@ static HRESULT Update2(
|
|||||||
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
|
// newDatabase.PackCRCs.Add(db.PackCRCs[startIndex + j]);
|
||||||
}
|
}
|
||||||
newDatabase.Folders.Add(folder);
|
newDatabase.Folders.Add(folder);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CStreamBinder sb;
|
||||||
|
RINOK(sb.CreateEvents());
|
||||||
|
CMyComPtr<ISequentialOutStream> sbOutStream;
|
||||||
|
CMyComPtr<ISequentialInStream> sbInStream;
|
||||||
|
sb.CreateStreams(&sbInStream, &sbOutStream);
|
||||||
|
CBoolVector extractStatuses;
|
||||||
|
|
||||||
|
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
|
||||||
|
CNum indexInFolder = 0;
|
||||||
|
|
||||||
|
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
|
||||||
|
{
|
||||||
|
bool needExtract = false;
|
||||||
|
if (db->Files[fi].HasStream)
|
||||||
|
{
|
||||||
|
indexInFolder++;
|
||||||
|
int updateIndex = fileIndexToUpdateIndexMap[fi];
|
||||||
|
if (updateIndex >= 0 && !updateItems[updateIndex].NewData)
|
||||||
|
needExtract = true;
|
||||||
|
}
|
||||||
|
extractStatuses.Add(needExtract);
|
||||||
|
}
|
||||||
|
|
||||||
|
RINOK(threadDecoder.FosSpec->Init(db, db->FolderStartFileIndex[folderIndex], &extractStatuses, sbOutStream));
|
||||||
|
sbOutStream.Release();
|
||||||
|
|
||||||
|
threadDecoder.InStream = inStream;
|
||||||
|
threadDecoder.Folder = &db->Folders[folderIndex];
|
||||||
|
threadDecoder.StartPos = db->GetFolderStreamPos(folderIndex, 0);
|
||||||
|
threadDecoder.PackSizes = &db->PackSizes[db->FolderStartPackStreamIndex[folderIndex]];
|
||||||
|
|
||||||
|
threadDecoder.Start();
|
||||||
|
|
||||||
|
int startPackIndex = newDatabase.PackSizes.Size();
|
||||||
|
CFolder newFolder;
|
||||||
|
RINOK(encoder.Encode(
|
||||||
|
EXTERNAL_CODECS_LOC_VARS
|
||||||
|
sbInStream, NULL, &inSizeForReduce, newFolder,
|
||||||
|
archive.SeqStream, newDatabase.PackSizes, progress));
|
||||||
|
|
||||||
|
threadDecoder.WaitFinish();
|
||||||
|
|
||||||
|
RINOK(threadDecoder.Result);
|
||||||
|
|
||||||
|
for (; startPackIndex < newDatabase.PackSizes.Size(); startPackIndex++)
|
||||||
|
lps->OutSize += newDatabase.PackSizes[startPackIndex];
|
||||||
|
lps->InSize += newFolder.GetUnpackSize();
|
||||||
|
|
||||||
|
newDatabase.Folders.Add(newFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
newDatabase.NumUnpackStreamsVector.Add(rep.NumCopyFiles);
|
||||||
|
|
||||||
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
|
CNum numUnpackStreams = db->NumUnpackStreamsVector[folderIndex];
|
||||||
newDatabase.NumUnpackStreamsVector.Add(numUnpackStreams);
|
|
||||||
|
|
||||||
CNum indexInFolder = 0;
|
CNum indexInFolder = 0;
|
||||||
for (CNum fi = db->FolderStartFileIndex[folderIndex];
|
for (CNum fi = db->FolderStartFileIndex[folderIndex]; indexInFolder < numUnpackStreams; fi++)
|
||||||
indexInFolder < numUnpackStreams; fi++)
|
|
||||||
{
|
{
|
||||||
CFileItem file;
|
CFileItem file;
|
||||||
CFileItem2 file2;
|
CFileItem2 file2;
|
||||||
@@ -604,7 +983,9 @@ static HRESULT Update2(
|
|||||||
if (updateIndex >= 0)
|
if (updateIndex >= 0)
|
||||||
{
|
{
|
||||||
const CUpdateItem &ui = updateItems[updateIndex];
|
const CUpdateItem &ui = updateItems[updateIndex];
|
||||||
if (ui.NewProperties)
|
if (ui.NewData)
|
||||||
|
continue;
|
||||||
|
if (ui.NewProps)
|
||||||
{
|
{
|
||||||
CFileItem uf;
|
CFileItem uf;
|
||||||
FromUpdateItemToFileItem(ui, uf, file2);
|
FromUpdateItemToFileItem(ui, uf, file2);
|
||||||
@@ -614,29 +995,12 @@ static HRESULT Update2(
|
|||||||
uf.HasStream = file.HasStream;
|
uf.HasStream = file.HasStream;
|
||||||
file = uf;
|
file = uf;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
newDatabase.AddFile(file, file2);
|
newDatabase.AddFile(file, file2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
folderRefs.ClearAndFree();
|
|
||||||
fileIndexToUpdateIndexMap.ClearAndFree();
|
|
||||||
|
|
||||||
/////////////////////////////////////////
|
|
||||||
// Compress New Files
|
|
||||||
|
|
||||||
CObjectVector<CSolidGroup> groups;
|
|
||||||
SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter,
|
|
||||||
updateItems, groups);
|
|
||||||
|
|
||||||
const UInt32 kMinReduceSize = (1 << 16);
|
|
||||||
if (inSizeForReduce < kMinReduceSize)
|
|
||||||
inSizeForReduce = kMinReduceSize;
|
|
||||||
|
|
||||||
for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
|
|
||||||
{
|
|
||||||
const CSolidGroup &group = groups[groupIndex];
|
|
||||||
int numFiles = group.Indices.Size();
|
int numFiles = group.Indices.Size();
|
||||||
if (numFiles == 0)
|
if (numFiles == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -657,7 +1021,7 @@ static HRESULT Update2(
|
|||||||
/*
|
/*
|
||||||
const CUpdateItem &ui = updateItems[index];
|
const CUpdateItem &ui = updateItems[index];
|
||||||
CFileItem file;
|
CFileItem file;
|
||||||
if (ui.NewProperties)
|
if (ui.NewProps)
|
||||||
FromUpdateItemToFileItem(ui, file);
|
FromUpdateItemToFileItem(ui, file);
|
||||||
else
|
else
|
||||||
file = db.Files[ui.IndexInArchive];
|
file = db.Files[ui.IndexInArchive];
|
||||||
@@ -667,8 +1031,6 @@ static HRESULT Update2(
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
CEncoder encoder(group.Method);
|
|
||||||
|
|
||||||
for (i = 0; i < numFiles;)
|
for (i = 0; i < numFiles;)
|
||||||
{
|
{
|
||||||
UInt64 totalSize = 0;
|
UInt64 totalSize = 0;
|
||||||
@@ -710,7 +1072,7 @@ static HRESULT Update2(
|
|||||||
lps->OutSize += newDatabase.PackSizes[startPackIndex];
|
lps->OutSize += newDatabase.PackSizes[startPackIndex];
|
||||||
|
|
||||||
lps->InSize += folderItem.GetUnpackSize();
|
lps->InSize += folderItem.GetUnpackSize();
|
||||||
// for()
|
// for ()
|
||||||
// newDatabase.PackCRCsDefined.Add(false);
|
// newDatabase.PackCRCsDefined.Add(false);
|
||||||
// newDatabase.PackCRCs.Add(0);
|
// newDatabase.PackCRCs.Add(0);
|
||||||
|
|
||||||
@@ -722,7 +1084,7 @@ static HRESULT Update2(
|
|||||||
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
|
const CUpdateItem &ui = updateItems[indices[i + subIndex]];
|
||||||
CFileItem file;
|
CFileItem file;
|
||||||
CFileItem2 file2;
|
CFileItem2 file2;
|
||||||
if (ui.NewProperties)
|
if (ui.NewProps)
|
||||||
FromUpdateItemToFileItem(ui, file, file2);
|
FromUpdateItemToFileItem(ui, file, file2);
|
||||||
else
|
else
|
||||||
db->GetFile(ui.IndexInArchive, file, file2);
|
db->GetFile(ui.IndexInArchive, file, file2);
|
||||||
@@ -761,14 +1123,20 @@ static HRESULT Update2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (folderRefIndex != folderRefs.Size())
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
folderRefs.ClearAndFree();
|
||||||
|
fileIndexToUpdateIndexMap.ClearAndFree();
|
||||||
groups.ClearAndFree();
|
groups.ClearAndFree();
|
||||||
|
*/
|
||||||
|
|
||||||
{
|
{
|
||||||
/////////////////////////////////////////
|
// ---------- Write Folders & Empty Files ----------
|
||||||
// Write Empty Files & Folders
|
|
||||||
|
|
||||||
CRecordVector<int> emptyRefs;
|
CRecordVector<int> emptyRefs;
|
||||||
for(i = 0; i < updateItems.Size(); i++)
|
for (i = 0; i < updateItems.Size(); i++)
|
||||||
{
|
{
|
||||||
const CUpdateItem &ui = updateItems[i];
|
const CUpdateItem &ui = updateItems[i];
|
||||||
if (ui.NewData)
|
if (ui.NewData)
|
||||||
@@ -776,9 +1144,7 @@ static HRESULT Update2(
|
|||||||
if (ui.HasStream())
|
if (ui.HasStream())
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else if (ui.IndexInArchive != -1 && db->Files[ui.IndexInArchive].HasStream)
|
||||||
if (ui.IndexInArchive != -1)
|
|
||||||
if (db->Files[ui.IndexInArchive].HasStream)
|
|
||||||
continue;
|
continue;
|
||||||
emptyRefs.Add(i);
|
emptyRefs.Add(i);
|
||||||
}
|
}
|
||||||
@@ -788,7 +1154,7 @@ static HRESULT Update2(
|
|||||||
const CUpdateItem &ui = updateItems[emptyRefs[i]];
|
const CUpdateItem &ui = updateItems[emptyRefs[i]];
|
||||||
CFileItem file;
|
CFileItem file;
|
||||||
CFileItem2 file2;
|
CFileItem2 file2;
|
||||||
if (ui.NewProperties)
|
if (ui.NewProps)
|
||||||
FromUpdateItemToFileItem(ui, file, file2);
|
FromUpdateItemToFileItem(ui, file, file2);
|
||||||
else
|
else
|
||||||
db->GetFile(ui.IndexInArchive, file, file2);
|
db->GetFile(ui.IndexInArchive, file, file2);
|
||||||
@@ -800,21 +1166,4 @@ static HRESULT Update2(
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Update(
|
|
||||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
|
||||||
IInStream *inStream,
|
|
||||||
const CArchiveDatabaseEx *db,
|
|
||||||
const CObjectVector<CUpdateItem> &updateItems,
|
|
||||||
COutArchive &archive,
|
|
||||||
CArchiveDatabase &newDatabase,
|
|
||||||
ISequentialOutStream *seqOutStream,
|
|
||||||
IArchiveUpdateCallback *updateCallback,
|
|
||||||
const CUpdateOptions &options)
|
|
||||||
{
|
|
||||||
return Update2(
|
|
||||||
EXTERNAL_CODECS_LOC_VARS
|
|
||||||
inStream, db, updateItems,
|
|
||||||
archive, newDatabase, seqOutStream, updateCallback, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
#ifndef __7Z_UPDATE_H
|
#ifndef __7Z_UPDATE_H
|
||||||
#define __7Z_UPDATE_H
|
#define __7Z_UPDATE_H
|
||||||
|
|
||||||
|
#include "7zCompressionMode.h"
|
||||||
#include "7zIn.h"
|
#include "7zIn.h"
|
||||||
#include "7zOut.h"
|
#include "7zOut.h"
|
||||||
#include "7zCompressionMode.h"
|
|
||||||
|
|
||||||
#include "../IArchive.h"
|
#include "../IArchive.h"
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ struct CUpdateItem
|
|||||||
UInt32 Attrib;
|
UInt32 Attrib;
|
||||||
|
|
||||||
bool NewData;
|
bool NewData;
|
||||||
bool NewProperties;
|
bool NewProps;
|
||||||
|
|
||||||
bool IsAnti;
|
bool IsAnti;
|
||||||
bool IsDir;
|
bool IsDir;
|
||||||
@@ -78,7 +78,11 @@ HRESULT Update(
|
|||||||
CArchiveDatabase &newDatabase,
|
CArchiveDatabase &newDatabase,
|
||||||
ISequentialOutStream *seqOutStream,
|
ISequentialOutStream *seqOutStream,
|
||||||
IArchiveUpdateCallback *updateCallback,
|
IArchiveUpdateCallback *updateCallback,
|
||||||
const CUpdateOptions &options);
|
const CUpdateOptions &options
|
||||||
|
#ifndef _NO_CRYPTO
|
||||||
|
, ICryptoGetTextPassword *getDecoderPassword
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ $(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
|
|||||||
$(COMPL)
|
$(COMPL)
|
||||||
$(AR_COMMON_OBJS): ../Common/$(*B).cpp
|
$(AR_COMMON_OBJS): ../Common/$(*B).cpp
|
||||||
$(COMPL)
|
$(COMPL)
|
||||||
$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
|
$O\CopyCoder.obj: ../../Compress/$(*B).cpp
|
||||||
$(COMPL)
|
$(COMPL)
|
||||||
$(C_OBJS): ../../../../C/$(*B).c
|
$(C_OBJS): ../../../../C/$(*B).c
|
||||||
$(COMPL_O2)
|
$(COMPL_O2)
|
||||||
|
|||||||
@@ -3,15 +3,12 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
#include "../../Common/ComTry.h"
|
#include "../../Common/ComTry.h"
|
||||||
#include "../../Common/Types.h"
|
|
||||||
#include "../../Windows/PropVariant.h"
|
#include "../../Windows/PropVariant.h"
|
||||||
|
|
||||||
#include "../Common/RegisterArc.h"
|
#include "../Common/RegisterArc.h"
|
||||||
|
|
||||||
#include "IArchive.h"
|
static const unsigned int kNumArcsMax = 48;
|
||||||
#include "../ICoder.h"
|
|
||||||
#include "../IPassword.h"
|
|
||||||
|
|
||||||
static const unsigned int kNumArcsMax = 32;
|
|
||||||
static unsigned int g_NumArcs = 0;
|
static unsigned int g_NumArcs = 0;
|
||||||
static const CArcInfo *g_Arcs[kNumArcsMax];
|
static const CArcInfo *g_Arcs[kNumArcsMax];
|
||||||
void RegisterArc(const CArcInfo *arcInfo)
|
void RegisterArc(const CArcInfo *arcInfo)
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "../../../C/CpuArch.h"
|
||||||
|
|
||||||
#include "Common/ComTry.h"
|
#include "Common/ComTry.h"
|
||||||
#include "Common/StringConvert.h"
|
#include "Common/StringConvert.h"
|
||||||
|
|
||||||
#include "Windows/PropVariant.h"
|
#include "Windows/PropVariant.h"
|
||||||
#include "Windows/Time.h"
|
#include "Windows/Time.h"
|
||||||
|
|
||||||
#include "../../../C/CpuArch.h"
|
|
||||||
|
|
||||||
#include "../Common/LimitedStreams.h"
|
#include "../Common/LimitedStreams.h"
|
||||||
#include "../Common/ProgressUtils.h"
|
#include "../Common/ProgressUtils.h"
|
||||||
#include "../Common/RegisterArc.h"
|
#include "../Common/RegisterArc.h"
|
||||||
@@ -180,6 +180,7 @@ struct CItem
|
|||||||
UInt32 PackSize;
|
UInt32 PackSize;
|
||||||
UInt32 Size;
|
UInt32 Size;
|
||||||
UInt32 FileCRC;
|
UInt32 FileCRC;
|
||||||
|
UInt32 SplitPos;
|
||||||
|
|
||||||
Byte Version;
|
Byte Version;
|
||||||
Byte ExtractVersion;
|
Byte ExtractVersion;
|
||||||
@@ -197,6 +198,8 @@ struct CItem
|
|||||||
|
|
||||||
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }
|
bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }
|
||||||
bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); }
|
bool IsDir() const { return (FileType == NFileHeader::NFileType::kDirectory); }
|
||||||
|
bool IsSplitAfter() const { return (Flags & NFileHeader::NFlags::kVolume) != 0; }
|
||||||
|
bool IsSplitBefore() const { return (Flags & NFileHeader::NFlags::kExtFile) != 0; }
|
||||||
UInt32 GetWinAttributes() const
|
UInt32 GetWinAttributes() const
|
||||||
{
|
{
|
||||||
UInt32 winAtrributes;
|
UInt32 winAtrributes;
|
||||||
@@ -240,6 +243,10 @@ HRESULT CItem::Parse(const Byte *p, unsigned size)
|
|||||||
// FirstChapter = p[28];
|
// FirstChapter = p[28];
|
||||||
// FirstChapter = p[29];
|
// FirstChapter = p[29];
|
||||||
|
|
||||||
|
SplitPos = 0;
|
||||||
|
if (IsSplitBefore() && firstHeaderSize >= 34)
|
||||||
|
SplitPos = Get32(p + 30);
|
||||||
|
|
||||||
unsigned pos = firstHeaderSize;
|
unsigned pos = firstHeaderSize;
|
||||||
unsigned size1 = size - pos;
|
unsigned size1 = size - pos;
|
||||||
RINOK(ReadString(p + pos, size1, Name));
|
RINOK(ReadString(p + pos, size1, Name));
|
||||||
@@ -270,7 +277,7 @@ class CInArchive
|
|||||||
|
|
||||||
HRESULT ReadBlock(bool &filled);
|
HRESULT ReadBlock(bool &filled);
|
||||||
HRESULT ReadSignatureAndBlock(bool &filled);
|
HRESULT ReadSignatureAndBlock(bool &filled);
|
||||||
HRESULT SkeepExtendedHeaders();
|
HRESULT SkipExtendedHeaders();
|
||||||
|
|
||||||
HRESULT SafeReadBytes(void *data, UInt32 size);
|
HRESULT SafeReadBytes(void *data, UInt32 size);
|
||||||
|
|
||||||
@@ -389,7 +396,7 @@ HRESULT CInArchive::ReadSignatureAndBlock(bool &filled)
|
|||||||
return ReadBlock(filled);
|
return ReadBlock(filled);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CInArchive::SkeepExtendedHeaders()
|
HRESULT CInArchive::SkipExtendedHeaders()
|
||||||
{
|
{
|
||||||
for (UInt32 i = 0;; i++)
|
for (UInt32 i = 0;; i++)
|
||||||
{
|
{
|
||||||
@@ -412,7 +419,7 @@ HRESULT CInArchive::Open(const UInt64 *searchHeaderSizeLimit)
|
|||||||
if (!filled)
|
if (!filled)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
RINOK(Header.Parse(_block, _blockSize));
|
RINOK(Header.Parse(_block, _blockSize));
|
||||||
return SkeepExtendedHeaders();
|
return SkipExtendedHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
|
HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
|
||||||
@@ -428,7 +435,7 @@ HRESULT CInArchive::GetNextItem(bool &filled, CItem &item)
|
|||||||
extraData = GetUi32(_block + pos);
|
extraData = GetUi32(_block + pos);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
RINOK(SkeepExtendedHeaders());
|
RINOK(SkipExtendedHeaders());
|
||||||
filled = true;
|
filled = true;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -482,8 +489,9 @@ STATPROPSTG kProps[] =
|
|||||||
{
|
{
|
||||||
{ NULL, kpidPath, VT_BSTR},
|
{ NULL, kpidPath, VT_BSTR},
|
||||||
{ NULL, kpidIsDir, VT_BOOL},
|
{ NULL, kpidIsDir, VT_BOOL},
|
||||||
{ NULL, kpidSize, VT_UI8},
|
{ NULL, kpidSize, VT_UI4},
|
||||||
{ NULL, kpidPackSize, VT_UI8},
|
{ NULL, kpidPosition, VT_UI8},
|
||||||
|
{ NULL, kpidPackSize, VT_UI4},
|
||||||
{ NULL, kpidMTime, VT_FILETIME},
|
{ NULL, kpidMTime, VT_FILETIME},
|
||||||
{ NULL, kpidAttrib, VT_UI4},
|
{ NULL, kpidAttrib, VT_UI4},
|
||||||
{ NULL, kpidEncrypted, VT_BOOL},
|
{ NULL, kpidEncrypted, VT_BOOL},
|
||||||
@@ -556,6 +564,7 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
|||||||
case kpidIsDir: prop = item.IsDir(); break;
|
case kpidIsDir: prop = item.IsDir(); break;
|
||||||
case kpidSize: prop = item.Size; break;
|
case kpidSize: prop = item.Size; break;
|
||||||
case kpidPackSize: prop = item.PackSize; break;
|
case kpidPackSize: prop = item.PackSize; break;
|
||||||
|
case kpidPosition: if (item.IsSplitBefore() || item.IsSplitAfter()) prop = (UInt64)item.SplitPos; break;
|
||||||
case kpidAttrib: prop = item.GetWinAttributes(); break;
|
case kpidAttrib: prop = item.GetWinAttributes(); break;
|
||||||
case kpidEncrypted: prop = item.IsEncrypted(); break;
|
case kpidEncrypted: prop = item.IsEncrypted(); break;
|
||||||
case kpidCRC: prop = item.FileCRC; break;
|
case kpidCRC: prop = item.FileCRC; break;
|
||||||
|
|||||||
@@ -1,216 +0,0 @@
|
|||||||
// BZip2Handler.cpp
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "Common/ComTry.h"
|
|
||||||
|
|
||||||
#include "Windows/PropVariant.h"
|
|
||||||
|
|
||||||
#include "../../Common/CreateCoder.h"
|
|
||||||
#include "../../Common/ProgressUtils.h"
|
|
||||||
#include "../../Common/StreamUtils.h"
|
|
||||||
|
|
||||||
#include "../Common/DummyOutStream.h"
|
|
||||||
|
|
||||||
#include "BZip2Handler.h"
|
|
||||||
|
|
||||||
using namespace NWindows;
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
static const CMethodId kMethodId_BZip2 = 0x040202;
|
|
||||||
|
|
||||||
STATPROPSTG kProps[] =
|
|
||||||
{
|
|
||||||
{ NULL, kpidPackSize, VT_UI8}
|
|
||||||
};
|
|
||||||
|
|
||||||
IMP_IInArchive_Props
|
|
||||||
IMP_IInArchive_ArcProps_NO
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
|
||||||
{
|
|
||||||
*numItems = 1;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
|
||||||
{
|
|
||||||
NWindows::NCOM::CPropVariant prop;
|
|
||||||
switch(propID)
|
|
||||||
{
|
|
||||||
case kpidPackSize: prop = _item.PackSize; break;
|
|
||||||
}
|
|
||||||
prop.Detach(value);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
|
||||||
const UInt64 * /* maxCheckStartPosition */,
|
|
||||||
IArchiveOpenCallback * /* openArchiveCallback */)
|
|
||||||
{
|
|
||||||
COM_TRY_BEGIN
|
|
||||||
try
|
|
||||||
{
|
|
||||||
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));
|
|
||||||
const int kSignatureSize = 3;
|
|
||||||
Byte buffer[kSignatureSize];
|
|
||||||
RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize));
|
|
||||||
if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
|
|
||||||
return S_FALSE;
|
|
||||||
|
|
||||||
UInt64 endPosition;
|
|
||||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
|
|
||||||
_item.PackSize = endPosition - _streamStartPosition;
|
|
||||||
|
|
||||||
_stream = stream;
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
COM_TRY_END
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Close()
|
|
||||||
{
|
|
||||||
_stream.Release();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
|
||||||
Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
|
|
||||||
{
|
|
||||||
COM_TRY_BEGIN
|
|
||||||
bool allFilesMode = (numItems == UInt32(-1));
|
|
||||||
if (!allFilesMode)
|
|
||||||
{
|
|
||||||
if (numItems == 0)
|
|
||||||
return S_OK;
|
|
||||||
if (numItems != 1)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
if (indices[0] != 0)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool testMode = (testModeSpec != 0);
|
|
||||||
|
|
||||||
extractCallback->SetTotal(_item.PackSize);
|
|
||||||
|
|
||||||
UInt64 currentTotalPacked = 0;
|
|
||||||
|
|
||||||
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
|
||||||
|
|
||||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
|
||||||
Int32 askMode;
|
|
||||||
askMode = testMode ? NExtract::NAskMode::kTest :
|
|
||||||
NExtract::NAskMode::kExtract;
|
|
||||||
|
|
||||||
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
|
|
||||||
|
|
||||||
if(!testMode && !realOutStream)
|
|
||||||
return S_OK;
|
|
||||||
|
|
||||||
|
|
||||||
extractCallback->PrepareOperation(askMode);
|
|
||||||
|
|
||||||
CMyComPtr<ICompressCoder> decoder;
|
|
||||||
HRESULT loadResult = CreateCoder(
|
|
||||||
EXTERNAL_CODECS_VARS
|
|
||||||
kMethodId_BZip2, decoder, false);
|
|
||||||
if (loadResult != S_OK || !decoder)
|
|
||||||
{
|
|
||||||
RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod));
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
{
|
|
||||||
CMyComPtr<ICompressSetCoderMt> setCoderMt;
|
|
||||||
decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
|
|
||||||
if (setCoderMt)
|
|
||||||
{
|
|
||||||
RINOK(setCoderMt->SetNumberOfThreads(_numThreads));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
CDummyOutStream *outStreamSpec = new CDummyOutStream;
|
|
||||||
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
|
||||||
outStreamSpec->SetStream(realOutStream);
|
|
||||||
outStreamSpec->Init();
|
|
||||||
|
|
||||||
realOutStream.Release();
|
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
|
||||||
lps->Init(extractCallback, true);
|
|
||||||
|
|
||||||
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
|
|
||||||
|
|
||||||
HRESULT result = S_OK;
|
|
||||||
|
|
||||||
bool firstItem = true;
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
lps->InSize = currentTotalPacked;
|
|
||||||
lps->OutSize = outStreamSpec->GetSize();
|
|
||||||
|
|
||||||
RINOK(lps->SetCur());
|
|
||||||
|
|
||||||
const int kSignatureSize = 3;
|
|
||||||
Byte buffer[kSignatureSize];
|
|
||||||
size_t processedSize = kSignatureSize;
|
|
||||||
RINOK(ReadStream(_stream, buffer, &processedSize));
|
|
||||||
if (processedSize != kSignatureSize)
|
|
||||||
{
|
|
||||||
if (firstItem)
|
|
||||||
return E_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
|
|
||||||
{
|
|
||||||
if (firstItem)
|
|
||||||
return E_FAIL;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
firstItem = false;
|
|
||||||
|
|
||||||
UInt64 dataStartPos;
|
|
||||||
RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos));
|
|
||||||
|
|
||||||
result = decoder->Code(_stream, outStream, NULL, NULL, progress);
|
|
||||||
|
|
||||||
if (result != S_OK)
|
|
||||||
break;
|
|
||||||
|
|
||||||
CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
|
|
||||||
decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize);
|
|
||||||
if (!getInStreamProcessedSize)
|
|
||||||
break;
|
|
||||||
UInt64 packSize;
|
|
||||||
RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize));
|
|
||||||
UInt64 pos;
|
|
||||||
RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos));
|
|
||||||
currentTotalPacked = pos - _streamStartPosition;
|
|
||||||
}
|
|
||||||
outStream.Release();
|
|
||||||
|
|
||||||
Int32 retResult;
|
|
||||||
if (result == S_OK)
|
|
||||||
retResult = NExtract::NOperationResult::kOK;
|
|
||||||
else if (result == S_FALSE)
|
|
||||||
retResult = NExtract::NOperationResult::kDataError;
|
|
||||||
else
|
|
||||||
return result;
|
|
||||||
return extractCallback->SetOperationResult(retResult);
|
|
||||||
|
|
||||||
COM_TRY_END
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPL_ISetCompressCodecsInfo
|
|
||||||
|
|
||||||
}}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
// BZip2/Handler.h
|
|
||||||
|
|
||||||
#ifndef __BZIP2_HANDLER_H
|
|
||||||
#define __BZIP2_HANDLER_H
|
|
||||||
|
|
||||||
#include "Common/MyCom.h"
|
|
||||||
#include "../IArchive.h"
|
|
||||||
#include "../../Common/CreateCoder.h"
|
|
||||||
#include "BZip2Item.h"
|
|
||||||
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
#include "../../../Windows/System.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
class CHandler:
|
|
||||||
public IInArchive,
|
|
||||||
public IOutArchive,
|
|
||||||
public ISetProperties,
|
|
||||||
PUBLIC_ISetCompressCodecsInfo
|
|
||||||
public CMyUnknownImp
|
|
||||||
{
|
|
||||||
CMyComPtr<IInStream> _stream;
|
|
||||||
NArchive::NBZip2::CItem _item;
|
|
||||||
UInt64 _streamStartPosition;
|
|
||||||
|
|
||||||
UInt32 _level;
|
|
||||||
UInt32 _dicSize;
|
|
||||||
UInt32 _numPasses;
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
UInt32 _numThreads;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DECL_EXTERNAL_CODECS_VARS
|
|
||||||
|
|
||||||
void InitMethodProperties()
|
|
||||||
{
|
|
||||||
_level = 5;
|
|
||||||
_dicSize =
|
|
||||||
_numPasses = 0xFFFFFFFF;
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
MY_QUERYINTERFACE_BEGIN2(IInArchive)
|
|
||||||
MY_QUERYINTERFACE_ENTRY(IOutArchive)
|
|
||||||
MY_QUERYINTERFACE_ENTRY(ISetProperties)
|
|
||||||
QUERY_ENTRY_ISetCompressCodecsInfo
|
|
||||||
MY_QUERYINTERFACE_END
|
|
||||||
MY_ADDREF_RELEASE
|
|
||||||
|
|
||||||
INTERFACE_IInArchive(;)
|
|
||||||
INTERFACE_IOutArchive(;)
|
|
||||||
|
|
||||||
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
|
|
||||||
|
|
||||||
DECL_ISetCompressCodecsInfo
|
|
||||||
|
|
||||||
CHandler() { InitMethodProperties(); }
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
// BZip2HandlerOut.cpp
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "BZip2Handler.h"
|
|
||||||
#include "BZip2Update.h"
|
|
||||||
|
|
||||||
#include "Common/Defs.h"
|
|
||||||
|
|
||||||
#include "Windows/PropVariant.h"
|
|
||||||
|
|
||||||
#include "../../Compress/CopyCoder.h"
|
|
||||||
|
|
||||||
#include "../Common/ParseProperties.h"
|
|
||||||
|
|
||||||
using namespace NWindows;
|
|
||||||
|
|
||||||
static const UInt32 kNumPassesX1 = 1;
|
|
||||||
static const UInt32 kNumPassesX7 = 2;
|
|
||||||
static const UInt32 kNumPassesX9 = 7;
|
|
||||||
|
|
||||||
static const UInt32 kDicSizeX1 = 100000;
|
|
||||||
static const UInt32 kDicSizeX3 = 500000;
|
|
||||||
static const UInt32 kDicSizeX5 = 900000;
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
|
||||||
{
|
|
||||||
*type = NFileTimeType::kUnix;
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
|
|
||||||
{
|
|
||||||
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
|
|
||||||
return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
|
||||||
IArchiveUpdateCallback *updateCallback)
|
|
||||||
{
|
|
||||||
if (numItems != 1)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
Int32 newData;
|
|
||||||
Int32 newProperties;
|
|
||||||
UInt32 indexInArchive;
|
|
||||||
if (!updateCallback)
|
|
||||||
return E_FAIL;
|
|
||||||
RINOK(updateCallback->GetUpdateItemInfo(0,&newData, &newProperties, &indexInArchive));
|
|
||||||
|
|
||||||
if (IntToBool(newProperties))
|
|
||||||
{
|
|
||||||
{
|
|
||||||
NCOM::CPropVariant prop;
|
|
||||||
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
|
|
||||||
if (prop.vt == VT_BOOL)
|
|
||||||
{
|
|
||||||
if (prop.boolVal != VARIANT_FALSE)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
else if (prop.vt != VT_EMPTY)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IntToBool(newData))
|
|
||||||
{
|
|
||||||
UInt64 size;
|
|
||||||
{
|
|
||||||
NCOM::CPropVariant prop;
|
|
||||||
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
|
|
||||||
if (prop.vt != VT_UI8)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
size = prop.uhVal.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
UInt32 dicSize = _dicSize;
|
|
||||||
if (dicSize == 0xFFFFFFFF)
|
|
||||||
dicSize = (_level >= 5 ? kDicSizeX5 :
|
|
||||||
(_level >= 3 ? kDicSizeX3 :
|
|
||||||
kDicSizeX1));
|
|
||||||
|
|
||||||
UInt32 numPasses = _numPasses;
|
|
||||||
if (numPasses == 0xFFFFFFFF)
|
|
||||||
numPasses = (_level >= 9 ? kNumPassesX9 :
|
|
||||||
(_level >= 7 ? kNumPassesX7 :
|
|
||||||
kNumPassesX1));
|
|
||||||
|
|
||||||
return UpdateArchive(
|
|
||||||
EXTERNAL_CODECS_VARS
|
|
||||||
size, outStream, 0, dicSize, numPasses,
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
_numThreads,
|
|
||||||
#endif
|
|
||||||
updateCallback);
|
|
||||||
}
|
|
||||||
if (indexInArchive != 0)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
|
|
||||||
return CopyStreams(_stream, outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
|
|
||||||
{
|
|
||||||
InitMethodProperties();
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
|
||||||
_numThreads = numProcessors;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (int i = 0; i < numProperties; i++)
|
|
||||||
{
|
|
||||||
UString name = UString(names[i]);
|
|
||||||
name.MakeUpper();
|
|
||||||
if (name.IsEmpty())
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
const PROPVARIANT &prop = values[i];
|
|
||||||
|
|
||||||
if (name[0] == 'X')
|
|
||||||
{
|
|
||||||
UInt32 level = 9;
|
|
||||||
RINOK(ParsePropValue(name.Mid(1), prop, level));
|
|
||||||
_level = level;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (name[0] == 'D')
|
|
||||||
{
|
|
||||||
UInt32 dicSize = kDicSizeX5;
|
|
||||||
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
|
|
||||||
_dicSize = dicSize;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (name.Left(4) == L"PASS")
|
|
||||||
{
|
|
||||||
UInt32 num = kNumPassesX9;
|
|
||||||
RINOK(ParsePropValue(name.Mid(4), prop, num));
|
|
||||||
_numPasses = num;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (name.Left(2) == L"MT")
|
|
||||||
{
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
return E_INVALIDARG;
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// Archive/BZip2Item.h
|
|
||||||
|
|
||||||
#ifndef __ARCHIVE_BZIP2_ITEM_H
|
|
||||||
#define __ARCHIVE_BZIP2_ITEM_H
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
struct CItem
|
|
||||||
{
|
|
||||||
UInt64 PackSize;
|
|
||||||
UInt64 UnPackSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
// BZip2Update.cpp
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "../../Common/ProgressUtils.h"
|
|
||||||
#include "../../Common/CreateCoder.h"
|
|
||||||
#include "Windows/PropVariant.h"
|
|
||||||
|
|
||||||
#include "BZip2Update.h"
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
static const CMethodId kMethodId_BZip2 = 0x040202;
|
|
||||||
|
|
||||||
HRESULT UpdateArchive(
|
|
||||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
|
||||||
UInt64 unpackSize,
|
|
||||||
ISequentialOutStream *outStream,
|
|
||||||
int indexInClient,
|
|
||||||
UInt32 dictionary,
|
|
||||||
UInt32 numPasses,
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
UInt32 numThreads,
|
|
||||||
#endif
|
|
||||||
IArchiveUpdateCallback *updateCallback)
|
|
||||||
{
|
|
||||||
RINOK(updateCallback->SetTotal(unpackSize));
|
|
||||||
UInt64 complexity = 0;
|
|
||||||
RINOK(updateCallback->SetCompleted(&complexity));
|
|
||||||
|
|
||||||
CMyComPtr<ISequentialInStream> fileInStream;
|
|
||||||
|
|
||||||
RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
|
|
||||||
|
|
||||||
CLocalProgress *localProgressSpec = new CLocalProgress;
|
|
||||||
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
|
||||||
localProgressSpec->Init(updateCallback, true);
|
|
||||||
|
|
||||||
CMyComPtr<ICompressCoder> encoder;
|
|
||||||
RINOK(CreateCoder(
|
|
||||||
EXTERNAL_CODECS_LOC_VARS
|
|
||||||
kMethodId_BZip2, encoder, true));
|
|
||||||
if (!encoder)
|
|
||||||
return E_NOTIMPL;
|
|
||||||
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
|
|
||||||
encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
|
|
||||||
if (setCoderProperties)
|
|
||||||
{
|
|
||||||
NWindows::NCOM::CPropVariant properties[] =
|
|
||||||
{
|
|
||||||
dictionary,
|
|
||||||
numPasses
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
, numThreads
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
PROPID propIDs[] =
|
|
||||||
{
|
|
||||||
NCoderPropID::kDictionarySize,
|
|
||||||
NCoderPropID::kNumPasses
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
, NCoderPropID::kNumThreads
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
|
|
||||||
}
|
|
||||||
|
|
||||||
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
|
|
||||||
|
|
||||||
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
// BZip2Update.h
|
|
||||||
|
|
||||||
#ifndef __BZIP2_UPDATE_H
|
|
||||||
#define __BZIP2_UPDATE_H
|
|
||||||
|
|
||||||
#include "../IArchive.h"
|
|
||||||
#include "../../Common/CreateCoder.h"
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NBZip2 {
|
|
||||||
|
|
||||||
HRESULT UpdateArchive(
|
|
||||||
DECL_EXTERNAL_CODECS_LOC_VARS
|
|
||||||
UInt64 unpackSize,
|
|
||||||
ISequentialOutStream *outStream,
|
|
||||||
int indexInClient,
|
|
||||||
UInt32 dictionary,
|
|
||||||
UInt32 numPasses,
|
|
||||||
#ifdef COMPRESS_MT
|
|
||||||
UInt32 numThreads,
|
|
||||||
#endif
|
|
||||||
IArchiveUpdateCallback *updateCallback);
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// StdAfx.h
|
|
||||||
|
|
||||||
#ifndef __STDAFX_H
|
|
||||||
#define __STDAFX_H
|
|
||||||
|
|
||||||
#include "../../../Common/MyWindows.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// BZip2Register.cpp
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "../../Common/RegisterArc.h"
|
|
||||||
|
|
||||||
#include "BZip2Handler.h"
|
|
||||||
static IInArchive *CreateArc() { return new NArchive::NBZip2::CHandler; }
|
|
||||||
#ifndef EXTRACT_ONLY
|
|
||||||
static IOutArchive *CreateArcOut() { return new NArchive::NBZip2::CHandler; }
|
|
||||||
#else
|
|
||||||
#define CreateArcOut 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static CArcInfo g_ArcInfo =
|
|
||||||
{ L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
|
|
||||||
|
|
||||||
REGISTER_ARC(BZip2)
|
|
||||||
428
CPP/7zip/Archive/Bz2Handler.cpp
Executable file
428
CPP/7zip/Archive/Bz2Handler.cpp
Executable file
@@ -0,0 +1,428 @@
|
|||||||
|
// Bz2Handler.cpp
|
||||||
|
|
||||||
|
#include "StdAfx.h"
|
||||||
|
|
||||||
|
#include "Common/ComTry.h"
|
||||||
|
|
||||||
|
#include "Windows/PropVariant.h"
|
||||||
|
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
#include "../../Windows/System.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../Common/CreateCoder.h"
|
||||||
|
#include "../Common/ProgressUtils.h"
|
||||||
|
#include "../Common/RegisterArc.h"
|
||||||
|
#include "../Common/StreamUtils.h"
|
||||||
|
|
||||||
|
#include "../Compress/BZip2Decoder.h"
|
||||||
|
#include "../Compress/BZip2Encoder.h"
|
||||||
|
#include "../Compress/CopyCoder.h"
|
||||||
|
|
||||||
|
#include "Common/DummyOutStream.h"
|
||||||
|
#include "Common/ParseProperties.h"
|
||||||
|
|
||||||
|
using namespace NWindows;
|
||||||
|
|
||||||
|
namespace NArchive {
|
||||||
|
namespace NBz2 {
|
||||||
|
|
||||||
|
static const UInt32 kNumPassesX1 = 1;
|
||||||
|
static const UInt32 kNumPassesX7 = 2;
|
||||||
|
static const UInt32 kNumPassesX9 = 7;
|
||||||
|
|
||||||
|
static const UInt32 kDicSizeX1 = 100000;
|
||||||
|
static const UInt32 kDicSizeX3 = 500000;
|
||||||
|
static const UInt32 kDicSizeX5 = 900000;
|
||||||
|
|
||||||
|
class CHandler:
|
||||||
|
public IInArchive,
|
||||||
|
public IArchiveOpenSeq,
|
||||||
|
public IOutArchive,
|
||||||
|
public ISetProperties,
|
||||||
|
public CMyUnknownImp
|
||||||
|
{
|
||||||
|
CMyComPtr<IInStream> _stream;
|
||||||
|
CMyComPtr<ISequentialInStream> _seqStream;
|
||||||
|
UInt64 _packSize;
|
||||||
|
UInt64 _startPosition;
|
||||||
|
bool _packSizeDefined;
|
||||||
|
|
||||||
|
UInt32 _level;
|
||||||
|
UInt32 _dicSize;
|
||||||
|
UInt32 _numPasses;
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
UInt32 _numThreads;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void InitMethodProperties()
|
||||||
|
{
|
||||||
|
_level = 5;
|
||||||
|
_dicSize =
|
||||||
|
_numPasses = 0xFFFFFFFF;
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
_numThreads = NWindows::NSystem::GetNumberOfProcessors();;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
|
||||||
|
|
||||||
|
INTERFACE_IInArchive(;)
|
||||||
|
INTERFACE_IOutArchive(;)
|
||||||
|
STDMETHOD(OpenSeq)(ISequentialInStream *stream);
|
||||||
|
STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps);
|
||||||
|
|
||||||
|
CHandler() { InitMethodProperties(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
STATPROPSTG kProps[] =
|
||||||
|
{
|
||||||
|
{ NULL, kpidPackSize, VT_UI8}
|
||||||
|
};
|
||||||
|
|
||||||
|
IMP_IInArchive_Props
|
||||||
|
IMP_IInArchive_ArcProps_NO_Table
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
||||||
|
{
|
||||||
|
NCOM::CPropVariant prop;
|
||||||
|
switch(propID)
|
||||||
|
{
|
||||||
|
case kpidPhySize: if (_packSizeDefined) prop = _packSize; break;
|
||||||
|
}
|
||||||
|
prop.Detach(value);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
||||||
|
{
|
||||||
|
*numItems = 1;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
|
||||||
|
{
|
||||||
|
NWindows::NCOM::CPropVariant prop;
|
||||||
|
switch(propID)
|
||||||
|
{
|
||||||
|
case kpidPackSize: if (_packSizeDefined) prop = _packSize; break;
|
||||||
|
}
|
||||||
|
prop.Detach(value);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Open(IInStream *stream,
|
||||||
|
const UInt64 * /* maxCheckStartPosition */,
|
||||||
|
IArchiveOpenCallback * /* openArchiveCallback */)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
|
||||||
|
const int kSignatureSize = 3;
|
||||||
|
Byte buf[kSignatureSize];
|
||||||
|
RINOK(ReadStream_FALSE(stream, buf, kSignatureSize));
|
||||||
|
if (buf[0] != 'B' || buf[1] != 'Z' || buf[2] != 'h')
|
||||||
|
return S_FALSE;
|
||||||
|
|
||||||
|
UInt64 endPosition;
|
||||||
|
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
|
||||||
|
_packSize = endPosition - _startPosition;
|
||||||
|
_packSizeDefined = true;
|
||||||
|
_stream = stream;
|
||||||
|
_seqStream = stream;
|
||||||
|
}
|
||||||
|
catch(...) { return S_FALSE; }
|
||||||
|
return S_OK;
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
_seqStream = stream;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Close()
|
||||||
|
{
|
||||||
|
_packSizeDefined = false;
|
||||||
|
_seqStream.Release();
|
||||||
|
_stream.Release();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
||||||
|
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
bool allFilesMode = (numItems == (UInt32)-1);
|
||||||
|
if (!allFilesMode)
|
||||||
|
{
|
||||||
|
if (numItems == 0)
|
||||||
|
return S_OK;
|
||||||
|
if (numItems != 1 || indices[0] != 0)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool testMode = (_aTestMode != 0);
|
||||||
|
if (_stream)
|
||||||
|
extractCallback->SetTotal(_packSize);
|
||||||
|
UInt64 currentTotalPacked = 0;
|
||||||
|
RINOK(extractCallback->SetCompleted(¤tTotalPacked));
|
||||||
|
CMyComPtr<ISequentialOutStream> realOutStream;
|
||||||
|
Int32 askMode = testMode ?
|
||||||
|
NArchive::NExtract::NAskMode::kTest :
|
||||||
|
NArchive::NExtract::NAskMode::kExtract;
|
||||||
|
RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
|
||||||
|
if (!testMode && !realOutStream)
|
||||||
|
return S_OK;
|
||||||
|
|
||||||
|
extractCallback->PrepareOperation(askMode);
|
||||||
|
|
||||||
|
NCompress::NBZip2::CDecoder *decoderSpec = new NCompress::NBZip2::CDecoder;
|
||||||
|
CMyComPtr<ICompressCoder> decoder = decoderSpec;
|
||||||
|
|
||||||
|
if (_stream)
|
||||||
|
{
|
||||||
|
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
decoderSpec->SetInStream(_seqStream);
|
||||||
|
|
||||||
|
#if defined( COMPRESS_MT) && defined( COMPRESS_BZIP2_MT)
|
||||||
|
RINOK(decoderSpec->SetNumberOfThreads(_numThreads));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CDummyOutStream *outStreamSpec = new CDummyOutStream;
|
||||||
|
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
|
||||||
|
outStreamSpec->SetStream(realOutStream);
|
||||||
|
outStreamSpec->Init();
|
||||||
|
|
||||||
|
realOutStream.Release();
|
||||||
|
|
||||||
|
CLocalProgress *lps = new CLocalProgress;
|
||||||
|
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||||
|
lps->Init(extractCallback, true);
|
||||||
|
|
||||||
|
HRESULT result = S_OK;
|
||||||
|
|
||||||
|
bool firstItem = true;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
lps->InSize = currentTotalPacked;
|
||||||
|
lps->OutSize = outStreamSpec->GetSize();
|
||||||
|
|
||||||
|
RINOK(lps->SetCur());
|
||||||
|
|
||||||
|
bool isBz2;
|
||||||
|
result = decoderSpec->CodeResume(outStream, isBz2, progress);
|
||||||
|
|
||||||
|
if (result != S_OK)
|
||||||
|
break;
|
||||||
|
if (!isBz2)
|
||||||
|
{
|
||||||
|
if (firstItem)
|
||||||
|
result = S_FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
firstItem = false;
|
||||||
|
|
||||||
|
_packSize = currentTotalPacked = decoderSpec->GetInputProcessedSize();
|
||||||
|
_packSizeDefined = true;
|
||||||
|
}
|
||||||
|
decoderSpec->ReleaseInStream();
|
||||||
|
outStream.Release();
|
||||||
|
|
||||||
|
Int32 retResult;
|
||||||
|
if (result == S_OK)
|
||||||
|
retResult = NExtract::NOperationResult::kOK;
|
||||||
|
else if (result == S_FALSE)
|
||||||
|
retResult = NExtract::NOperationResult::kDataError;
|
||||||
|
else
|
||||||
|
return result;
|
||||||
|
return extractCallback->SetOperationResult(retResult);
|
||||||
|
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT UpdateArchive(
|
||||||
|
UInt64 unpackSize,
|
||||||
|
ISequentialOutStream *outStream,
|
||||||
|
int indexInClient,
|
||||||
|
UInt32 dictionary,
|
||||||
|
UInt32 numPasses,
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
UInt32 numThreads,
|
||||||
|
#endif
|
||||||
|
IArchiveUpdateCallback *updateCallback)
|
||||||
|
{
|
||||||
|
RINOK(updateCallback->SetTotal(unpackSize));
|
||||||
|
UInt64 complexity = 0;
|
||||||
|
RINOK(updateCallback->SetCompleted(&complexity));
|
||||||
|
|
||||||
|
CMyComPtr<ISequentialInStream> fileInStream;
|
||||||
|
|
||||||
|
RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
|
||||||
|
|
||||||
|
CLocalProgress *localProgressSpec = new CLocalProgress;
|
||||||
|
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
|
||||||
|
localProgressSpec->Init(updateCallback, true);
|
||||||
|
|
||||||
|
NCompress::NBZip2::CEncoder *encoderSpec = new NCompress::NBZip2::CEncoder;
|
||||||
|
CMyComPtr<ICompressCoder> encoder = encoderSpec;
|
||||||
|
{
|
||||||
|
NWindows::NCOM::CPropVariant properties[] =
|
||||||
|
{
|
||||||
|
dictionary,
|
||||||
|
numPasses
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
, numThreads
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
PROPID propIDs[] =
|
||||||
|
{
|
||||||
|
NCoderPropID::kDictionarySize,
|
||||||
|
NCoderPropID::kNumPasses
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
, NCoderPropID::kNumThreads
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
RINOK(encoderSpec->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
|
||||||
|
|
||||||
|
return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
|
||||||
|
{
|
||||||
|
*type = NFileTimeType::kUnix;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
|
||||||
|
IArchiveUpdateCallback *updateCallback)
|
||||||
|
{
|
||||||
|
if (numItems != 1)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
Int32 newData, newProps;
|
||||||
|
UInt32 indexInArchive;
|
||||||
|
if (!updateCallback)
|
||||||
|
return E_FAIL;
|
||||||
|
RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive));
|
||||||
|
|
||||||
|
if (IntToBool(newProps))
|
||||||
|
{
|
||||||
|
{
|
||||||
|
NCOM::CPropVariant prop;
|
||||||
|
RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop));
|
||||||
|
if (prop.vt == VT_BOOL)
|
||||||
|
{
|
||||||
|
if (prop.boolVal != VARIANT_FALSE)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
else if (prop.vt != VT_EMPTY)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IntToBool(newData))
|
||||||
|
{
|
||||||
|
UInt64 size;
|
||||||
|
{
|
||||||
|
NCOM::CPropVariant prop;
|
||||||
|
RINOK(updateCallback->GetProperty(0, kpidSize, &prop));
|
||||||
|
if (prop.vt != VT_UI8)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
size = prop.uhVal.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 dicSize = _dicSize;
|
||||||
|
if (dicSize == 0xFFFFFFFF)
|
||||||
|
dicSize = (_level >= 5 ? kDicSizeX5 :
|
||||||
|
(_level >= 3 ? kDicSizeX3 :
|
||||||
|
kDicSizeX1));
|
||||||
|
|
||||||
|
UInt32 numPasses = _numPasses;
|
||||||
|
if (numPasses == 0xFFFFFFFF)
|
||||||
|
numPasses = (_level >= 9 ? kNumPassesX9 :
|
||||||
|
(_level >= 7 ? kNumPassesX7 :
|
||||||
|
kNumPassesX1));
|
||||||
|
|
||||||
|
return UpdateArchive(
|
||||||
|
size, outStream, 0, dicSize, numPasses,
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
_numThreads,
|
||||||
|
#endif
|
||||||
|
updateCallback);
|
||||||
|
}
|
||||||
|
if (indexInArchive != 0)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
if (_stream)
|
||||||
|
RINOK(_stream->Seek(_startPosition, STREAM_SEEK_SET, NULL));
|
||||||
|
return NCompress::CopyStream(_stream, outStream, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps)
|
||||||
|
{
|
||||||
|
InitMethodProperties();
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
|
||||||
|
_numThreads = numProcessors;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = 0; i < numProps; i++)
|
||||||
|
{
|
||||||
|
UString name = names[i];
|
||||||
|
name.MakeUpper();
|
||||||
|
if (name.IsEmpty())
|
||||||
|
return E_INVALIDARG;
|
||||||
|
const PROPVARIANT &prop = values[i];
|
||||||
|
if (name[0] == L'X')
|
||||||
|
{
|
||||||
|
UInt32 level = 9;
|
||||||
|
RINOK(ParsePropValue(name.Mid(1), prop, level));
|
||||||
|
_level = level;
|
||||||
|
}
|
||||||
|
else if (name[0] == L'D')
|
||||||
|
{
|
||||||
|
UInt32 dicSize = kDicSizeX5;
|
||||||
|
RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
|
||||||
|
_dicSize = dicSize;
|
||||||
|
}
|
||||||
|
else if (name.Left(4) == L"PASS")
|
||||||
|
{
|
||||||
|
UInt32 num = kNumPassesX9;
|
||||||
|
RINOK(ParsePropValue(name.Mid(4), prop, num));
|
||||||
|
_numPasses = num;
|
||||||
|
}
|
||||||
|
else if (name.Left(2) == L"MT")
|
||||||
|
{
|
||||||
|
#ifdef COMPRESS_MT
|
||||||
|
RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IInArchive *CreateArc() { return new CHandler; }
|
||||||
|
#ifndef EXTRACT_ONLY
|
||||||
|
static IOutArchive *CreateArcOut() { return new CHandler; }
|
||||||
|
#else
|
||||||
|
#define CreateArcOut 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static CArcInfo g_ArcInfo =
|
||||||
|
{ L"BZip2", L"bz2 bzip2 tbz2 tbz", L"* * .tar .tar", 2, { 'B', 'Z', 'h' }, 3, true, CreateArc, CreateArcOut };
|
||||||
|
|
||||||
|
REGISTER_ARC(BZip2)
|
||||||
|
|
||||||
|
}}
|
||||||
@@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "../../../../C/Alloc.h"
|
#include "../../../../C/Alloc.h"
|
||||||
}
|
|
||||||
|
|
||||||
#include "Common/Defs.h"
|
#include "Common/Defs.h"
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ void CInArchive::ReadOtherArchive(COtherArchive &oa)
|
|||||||
oa.DiskName = SafeReadName();
|
oa.DiskName = SafeReadName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInArchive::Skeep(size_t size)
|
void CInArchive::Skip(size_t size)
|
||||||
{
|
{
|
||||||
while (size-- != 0)
|
while (size-- != 0)
|
||||||
ReadByte();
|
ReadByte();
|
||||||
@@ -104,7 +104,7 @@ HRESULT CInArchive::Open2(IInStream *stream,
|
|||||||
ai.PerFolderAreaSize = ReadByte();
|
ai.PerFolderAreaSize = ReadByte();
|
||||||
ai.PerDataBlockAreaSize = ReadByte();
|
ai.PerDataBlockAreaSize = ReadByte();
|
||||||
|
|
||||||
Skeep(ai.PerCabinetAreaSize);
|
Skip(ai.PerCabinetAreaSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -124,7 +124,7 @@ HRESULT CInArchive::Open2(IInStream *stream,
|
|||||||
folder.CompressionTypeMajor = ReadByte();
|
folder.CompressionTypeMajor = ReadByte();
|
||||||
folder.CompressionTypeMinor = ReadByte();
|
folder.CompressionTypeMinor = ReadByte();
|
||||||
|
|
||||||
Skeep(ai.PerFolderAreaSize);
|
Skip(ai.PerFolderAreaSize);
|
||||||
database.Folders.Add(folder);
|
database.Folders.Add(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ class CInArchive
|
|||||||
UInt16 ReadUInt16();
|
UInt16 ReadUInt16();
|
||||||
UInt32 ReadUInt32();
|
UInt32 ReadUInt32();
|
||||||
AString SafeReadName();
|
AString SafeReadName();
|
||||||
void Skeep(size_t size);
|
void Skip(size_t size);
|
||||||
void ReadOtherArchive(COtherArchive &oa);
|
void ReadOtherArchive(COtherArchive &oa);
|
||||||
|
|
||||||
HRESULT Open2(IInStream *inStream,
|
HRESULT Open2(IInStream *inStream,
|
||||||
|
|||||||
@@ -2,13 +2,11 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
#include "Common/StringConvert.h"
|
|
||||||
#include "Common/MyCom.h"
|
|
||||||
#include "Common/UTFConvert.h"
|
|
||||||
#include "Common/IntToString.h"
|
#include "Common/IntToString.h"
|
||||||
#include "Windows/Defs.h"
|
#include "Common/UTFConvert.h"
|
||||||
|
|
||||||
#include "../../Common/LimitedStreams.h"
|
#include "../../Common/LimitedStreams.h"
|
||||||
|
|
||||||
#include "ChmIn.h"
|
#include "ChmIn.h"
|
||||||
|
|
||||||
namespace NArchive{
|
namespace NArchive{
|
||||||
@@ -96,9 +94,8 @@ UString CMethodInfo::GetName() const
|
|||||||
if (IsLzx())
|
if (IsLzx())
|
||||||
{
|
{
|
||||||
s = L"LZX:";
|
s = L"LZX:";
|
||||||
UInt32 numDictBits = LzxInfo.GetNumDictBits();
|
wchar_t temp[16];
|
||||||
wchar_t temp[32];
|
ConvertUInt32ToString(LzxInfo.GetNumDictBits(), temp);
|
||||||
ConvertUInt64ToString(numDictBits, temp);
|
|
||||||
s += temp;
|
s += temp;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -111,7 +108,7 @@ UString CMethodInfo::GetName() const
|
|||||||
s2 = GetGuidString();
|
s2 = GetGuidString();
|
||||||
if (ControlData.GetCapacity() > 0)
|
if (ControlData.GetCapacity() > 0)
|
||||||
{
|
{
|
||||||
s2 += ":";
|
s2 += ':';
|
||||||
for (size_t i = 0; i < ControlData.GetCapacity(); i++)
|
for (size_t i = 0; i < ControlData.GetCapacity(); i++)
|
||||||
PrintByte(ControlData[i], s2);
|
PrintByte(ControlData[i], s2);
|
||||||
}
|
}
|
||||||
@@ -141,7 +138,7 @@ UString CSectionInfo::GetMethodName() const
|
|||||||
for (int i = 0; i < Methods.Size(); i++)
|
for (int i = 0; i < Methods.Size(); i++)
|
||||||
{
|
{
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
s += L" ";
|
s += L' ';
|
||||||
s += Methods[i].GetName();
|
s += Methods[i].GetName();
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
@@ -155,7 +152,7 @@ Byte CInArchive::ReadByte()
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CInArchive::Skeep(size_t size)
|
void CInArchive::Skip(size_t size)
|
||||||
{
|
{
|
||||||
while (size-- != 0)
|
while (size-- != 0)
|
||||||
ReadByte();
|
ReadByte();
|
||||||
@@ -221,7 +218,7 @@ void CInArchive::ReadString(int size, AString &s)
|
|||||||
char c = (char)ReadByte();
|
char c = (char)ReadByte();
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
{
|
{
|
||||||
Skeep(size);
|
Skip(size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s += c;
|
s += c;
|
||||||
@@ -236,7 +233,7 @@ void CInArchive::ReadUString(int size, UString &s)
|
|||||||
wchar_t c = ReadUInt16();
|
wchar_t c = ReadUInt16();
|
||||||
if (c == 0)
|
if (c == 0)
|
||||||
{
|
{
|
||||||
Skeep(2 * size);
|
Skip(2 * size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s += c;
|
s += c;
|
||||||
@@ -372,12 +369,12 @@ HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
|
|||||||
RINOK(ReadDirEntry(database));
|
RINOK(ReadDirEntry(database));
|
||||||
numItems++;
|
numItems++;
|
||||||
}
|
}
|
||||||
Skeep(quickrefLength - 2);
|
Skip(quickrefLength - 2);
|
||||||
if (ReadUInt16() != numItems)
|
if (ReadUInt16() != numItems)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Skeep(dirChunkSize - 4);
|
Skip(dirChunkSize - 4);
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@@ -579,7 +576,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
|||||||
}
|
}
|
||||||
numItems++;
|
numItems++;
|
||||||
}
|
}
|
||||||
Skeep(quickrefLength - 2);
|
Skip(quickrefLength - 2);
|
||||||
if (ReadUInt16() != numItems)
|
if (ReadUInt16() != numItems)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
if (numItems > numDirEntries)
|
if (numItems > numDirEntries)
|
||||||
@@ -587,7 +584,7 @@ HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
|
|||||||
numDirEntries -= numItems;
|
numDirEntries -= numItems;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Skeep(dirChunkSize - 4);
|
Skip(dirChunkSize - 4);
|
||||||
}
|
}
|
||||||
return numDirEntries == 0 ? S_OK : S_FALSE;
|
return numDirEntries == 0 ? S_OK : S_FALSE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
#ifndef __ARCHIVE_CHM_IN_H
|
#ifndef __ARCHIVE_CHM_IN_H
|
||||||
#define __ARCHIVE_CHM_IN_H
|
#define __ARCHIVE_CHM_IN_H
|
||||||
|
|
||||||
#include "Common/MyString.h"
|
|
||||||
#include "Common/Buffer.h"
|
#include "Common/Buffer.h"
|
||||||
|
#include "Common/MyString.h"
|
||||||
|
|
||||||
#include "../../IStream.h"
|
#include "../../IStream.h"
|
||||||
#include "../../Common/InBuffer.h"
|
#include "../../Common/InBuffer.h"
|
||||||
|
|
||||||
#include "ChmHeader.h"
|
#include "ChmHeader.h"
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
@@ -215,7 +217,7 @@ class CInArchive
|
|||||||
|
|
||||||
Byte ReadByte();
|
Byte ReadByte();
|
||||||
void ReadBytes(Byte *data, UInt32 size);
|
void ReadBytes(Byte *data, UInt32 size);
|
||||||
void Skeep(size_t size);
|
void Skip(size_t size);
|
||||||
UInt16 ReadUInt16();
|
UInt16 ReadUInt16();
|
||||||
UInt32 ReadUInt32();
|
UInt32 ReadUInt32();
|
||||||
UInt64 ReadUInt64();
|
UInt64 ReadUInt64();
|
||||||
|
|||||||
@@ -3,8 +3,15 @@
|
|||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
#include "Common/ComTry.h"
|
#include "Common/ComTry.h"
|
||||||
|
|
||||||
#include "Windows/PropVariant.h"
|
#include "Windows/PropVariant.h"
|
||||||
|
|
||||||
|
#include "../../Common/LimitedStreams.h"
|
||||||
|
#include "../../Common/ProgressUtils.h"
|
||||||
#include "../../Common/StreamUtils.h"
|
#include "../../Common/StreamUtils.h"
|
||||||
|
|
||||||
|
#include "../../Compress/CopyCoder.h"
|
||||||
|
|
||||||
#include "ComHandler.h"
|
#include "ComHandler.h"
|
||||||
|
|
||||||
namespace NArchive {
|
namespace NArchive {
|
||||||
@@ -15,16 +22,15 @@ STATPROPSTG kProps[] =
|
|||||||
{ NULL, kpidPath, VT_BSTR},
|
{ NULL, kpidPath, VT_BSTR},
|
||||||
{ NULL, kpidIsDir, VT_BOOL},
|
{ NULL, kpidIsDir, VT_BOOL},
|
||||||
{ NULL, kpidSize, VT_UI8},
|
{ NULL, kpidSize, VT_UI8},
|
||||||
// { NULL, kpidAttributes, VT_UI4},
|
|
||||||
{ NULL, kpidPackSize, VT_UI8},
|
{ NULL, kpidPackSize, VT_UI8},
|
||||||
{ NULL, kpidCTime, VT_FILETIME},
|
{ NULL, kpidCTime, VT_FILETIME},
|
||||||
{ NULL, kpidMTime, VT_FILETIME}
|
{ NULL, kpidMTime, VT_FILETIME}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
STATPROPSTG kArcProps[] =
|
STATPROPSTG kArcProps[] =
|
||||||
{
|
{
|
||||||
{ NULL, kpidClusterSize, VT_UI4}
|
{ NULL, kpidClusterSize, VT_UI4},
|
||||||
|
{ NULL, kpidSectorSize, VT_UI4}
|
||||||
};
|
};
|
||||||
|
|
||||||
IMP_IInArchive_Props
|
IMP_IInArchive_Props
|
||||||
@@ -37,6 +43,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
|
|||||||
switch(propID)
|
switch(propID)
|
||||||
{
|
{
|
||||||
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
case kpidClusterSize: prop = (UInt32)1 << _db.SectorSizeBits; break;
|
||||||
|
case kpidSectorSize: prop = (UInt32)1 << _db.MiniSectorSizeBits; break;
|
||||||
}
|
}
|
||||||
prop.Detach(value);
|
prop.Detach(value);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -52,33 +59,12 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
|
|||||||
|
|
||||||
switch(propID)
|
switch(propID)
|
||||||
{
|
{
|
||||||
case kpidPath:
|
case kpidPath: prop = _db.GetItemPath(index); break;
|
||||||
{
|
|
||||||
UString name = _db.GetItemPath(index);
|
|
||||||
prop = name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kpidIsDir: prop = item.IsDir(); break;
|
case kpidIsDir: prop = item.IsDir(); break;
|
||||||
case kpidCTime: prop = item.CTime; break;
|
case kpidCTime: prop = item.CTime; break;
|
||||||
case kpidMTime: prop = item.MTime; break;
|
case kpidMTime: prop = item.MTime; break;
|
||||||
/*
|
case kpidPackSize: if (!item.IsDir()) prop = _db.GetItemPackSize(item.Size); break;
|
||||||
case kpidAttributes:
|
case kpidSize: if (!item.IsDir()) prop = item.Size; break;
|
||||||
prop = item.Falgs;
|
|
||||||
break;
|
|
||||||
*/
|
|
||||||
case kpidPackSize:
|
|
||||||
if (!item.IsDir())
|
|
||||||
{
|
|
||||||
int numBits = _db.IsLargeStream(item.Size) ?
|
|
||||||
_db.SectorSizeBits :
|
|
||||||
_db.MiniSectorSizeBits;
|
|
||||||
prop = (item.Size + ((UInt64)1 << numBits) - 1) >> numBits << numBits;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kpidSize:
|
|
||||||
if (!item.IsDir())
|
|
||||||
prop = (UInt64)item.Size;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
prop.Detach(value);
|
prop.Detach(value);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -93,7 +79,7 @@ STDMETHODIMP CHandler::Open(IInStream *inStream,
|
|||||||
Close();
|
Close();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (OpenArchive(inStream, _db) != S_OK)
|
if (_db.Open(inStream) != S_OK)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
_stream = inStream;
|
_stream = inStream;
|
||||||
}
|
}
|
||||||
@@ -129,25 +115,29 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
|||||||
}
|
}
|
||||||
RINOK(extractCallback->SetTotal(totalSize));
|
RINOK(extractCallback->SetTotal(totalSize));
|
||||||
|
|
||||||
UInt64 currentTotalSize = 0, currentItemSize = 0;
|
UInt64 totalPackSize;
|
||||||
|
totalSize = totalPackSize = 0;
|
||||||
|
|
||||||
CByteBuffer sect;
|
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
||||||
sect.SetCapacity((UInt32)1 << _db.SectorSizeBits);
|
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
||||||
|
|
||||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
CLocalProgress *lps = new CLocalProgress;
|
||||||
|
CMyComPtr<ICompressProgressInfo> progress = lps;
|
||||||
|
lps->Init(extractCallback, false);
|
||||||
|
|
||||||
|
for (i = 0; i < numItems; i++)
|
||||||
{
|
{
|
||||||
RINOK(extractCallback->SetCompleted(¤tTotalSize));
|
lps->InSize = totalPackSize;
|
||||||
|
lps->OutSize = totalSize;
|
||||||
|
RINOK(lps->SetCur());
|
||||||
Int32 index = allFilesMode ? i : indices[i];
|
Int32 index = allFilesMode ? i : indices[i];
|
||||||
const CItem &item = _db.Items[_db.Refs[index].Did];
|
const CItem &item = _db.Items[_db.Refs[index].Did];
|
||||||
currentItemSize = 0;
|
|
||||||
if (!item.IsDir())
|
|
||||||
currentItemSize = item.Size;
|
|
||||||
|
|
||||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
CMyComPtr<ISequentialOutStream> outStream;
|
||||||
Int32 askMode = testMode ?
|
Int32 askMode = testMode ?
|
||||||
NArchive::NExtract::NAskMode::kTest :
|
NArchive::NExtract::NAskMode::kTest :
|
||||||
NArchive::NExtract::NAskMode::kExtract;
|
NArchive::NExtract::NAskMode::kExtract;
|
||||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
RINOK(extractCallback->GetStream(index, &outStream, askMode));
|
||||||
|
|
||||||
if (item.IsDir())
|
if (item.IsDir())
|
||||||
{
|
{
|
||||||
@@ -155,75 +145,31 @@ STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
|||||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!testMode && (!realOutStream))
|
|
||||||
|
totalPackSize += _db.GetItemPackSize(item.Size);
|
||||||
|
totalSize += item.Size;
|
||||||
|
|
||||||
|
if (!testMode && (!outStream))
|
||||||
continue;
|
continue;
|
||||||
RINOK(extractCallback->PrepareOperation(askMode));
|
RINOK(extractCallback->PrepareOperation(askMode));
|
||||||
Int32 res = NArchive::NExtract::NOperationResult::kDataError;
|
Int32 res = NArchive::NExtract::NOperationResult::kDataError;
|
||||||
{
|
CMyComPtr<ISequentialInStream> inStream;
|
||||||
UInt32 sid = item.Sid;
|
HRESULT hres = GetStream(index, &inStream);
|
||||||
UInt64 prev = 0;
|
if (hres == S_FALSE)
|
||||||
for (UInt64 pos = 0;;)
|
res = NArchive::NExtract::NOperationResult::kDataError;
|
||||||
{
|
else if (hres == E_NOTIMPL)
|
||||||
if (sid == NFatID::kEndOfChain)
|
res = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
|
||||||
{
|
|
||||||
if (pos != item.Size)
|
|
||||||
break;
|
|
||||||
res = NArchive::NExtract::NOperationResult::kOK;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (pos >= item.Size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
UInt64 offset;
|
|
||||||
UInt32 size;
|
|
||||||
|
|
||||||
if (_db.IsLargeStream(item.Size))
|
|
||||||
{
|
|
||||||
if (pos - prev > (1 << 20))
|
|
||||||
{
|
|
||||||
UInt64 processed = currentTotalSize + pos;
|
|
||||||
RINOK(extractCallback->SetCompleted(&processed));
|
|
||||||
prev = pos;
|
|
||||||
}
|
|
||||||
size = 1 << _db.SectorSizeBits;
|
|
||||||
offset = ((UInt64)sid + 1) << _db.SectorSizeBits;
|
|
||||||
if (sid >= _db.FatSize)
|
|
||||||
break;
|
|
||||||
sid = _db.Fat[sid];
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int subBits = (_db.SectorSizeBits - _db.MiniSectorSizeBits);
|
RINOK(hres);
|
||||||
UInt32 fid = sid >> subBits;
|
if (inStream)
|
||||||
if (fid >= _db.NumSectorsInMiniStream)
|
|
||||||
break;
|
|
||||||
size = 1 << _db.MiniSectorSizeBits;
|
|
||||||
offset = (((UInt64)_db.MiniSids[fid] + 1) << _db.SectorSizeBits) +
|
|
||||||
((sid & ((1 << subBits) - 1)) << _db.MiniSectorSizeBits);
|
|
||||||
if (sid >= _db.MatSize)
|
|
||||||
break;
|
|
||||||
sid = _db.Mat[sid];
|
|
||||||
}
|
|
||||||
|
|
||||||
// last sector can be smaller than sector size (it can contain requied data only).
|
|
||||||
UInt64 rem = item.Size - pos;
|
|
||||||
if (size > rem)
|
|
||||||
size = (UInt32)rem;
|
|
||||||
|
|
||||||
RINOK(_stream->Seek(offset, STREAM_SEEK_SET, NULL));
|
|
||||||
size_t realProcessedSize = size;
|
|
||||||
RINOK(ReadStream(_stream, sect, &realProcessedSize));
|
|
||||||
if (realProcessedSize != size)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (realOutStream)
|
|
||||||
{
|
{
|
||||||
RINOK(WriteStream(realOutStream, sect, size));
|
RINOK(copyCoder->Code(inStream, outStream, NULL, NULL, progress));
|
||||||
}
|
if (copyCoderSpec->TotalSize == item.Size)
|
||||||
pos += size;
|
res = NArchive::NExtract::NOperationResult::kOK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
realOutStream.Release();
|
outStream.Release();
|
||||||
RINOK(extractCallback->SetOperationResult(res));
|
RINOK(extractCallback->SetOperationResult(res));
|
||||||
}
|
}
|
||||||
return S_OK;
|
return S_OK;
|
||||||
@@ -236,4 +182,58 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
|
||||||
|
{
|
||||||
|
COM_TRY_BEGIN
|
||||||
|
*stream = 0;
|
||||||
|
const CItem &item = _db.Items[_db.Refs[index].Did];
|
||||||
|
CClusterInStream *streamSpec = new CClusterInStream;
|
||||||
|
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
|
||||||
|
streamSpec->Stream = _stream;
|
||||||
|
streamSpec->StartOffset = 0;
|
||||||
|
|
||||||
|
bool isLargeStream = _db.IsLargeStream(item.Size);
|
||||||
|
int bsLog = isLargeStream ? _db.SectorSizeBits : _db.MiniSectorSizeBits;
|
||||||
|
streamSpec->BlockSizeLog = bsLog;
|
||||||
|
streamSpec->Size = item.Size;
|
||||||
|
|
||||||
|
UInt32 clusterSize = (UInt32)1 << bsLog;
|
||||||
|
UInt64 numClusters64 = (item.Size + clusterSize - 1) >> bsLog;
|
||||||
|
if (numClusters64 >= ((UInt32)1 << 31))
|
||||||
|
return E_NOTIMPL;
|
||||||
|
streamSpec->Vector.Reserve((int)numClusters64);
|
||||||
|
UInt32 sid = item.Sid;
|
||||||
|
UInt64 size = item.Size;
|
||||||
|
|
||||||
|
if (size != 0)
|
||||||
|
{
|
||||||
|
for (;; size -= clusterSize)
|
||||||
|
{
|
||||||
|
if (isLargeStream)
|
||||||
|
{
|
||||||
|
if (sid >= _db.FatSize)
|
||||||
|
return S_FALSE;
|
||||||
|
streamSpec->Vector.Add(sid + 1);
|
||||||
|
sid = _db.Fat[sid];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UInt64 val;
|
||||||
|
if (sid >= _db.MatSize || !_db.GetMiniCluster(sid, val) || val >= (UInt64)1 << 32)
|
||||||
|
return S_FALSE;
|
||||||
|
streamSpec->Vector.Add((UInt32)val);
|
||||||
|
sid = _db.Mat[sid];
|
||||||
|
}
|
||||||
|
if (size <= clusterSize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sid != NFatID::kEndOfChain)
|
||||||
|
return S_FALSE;
|
||||||
|
RINOK(streamSpec->InitAndSeek());
|
||||||
|
*stream = streamTemp.Detach();
|
||||||
|
return S_OK;
|
||||||
|
COM_TRY_END
|
||||||
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -12,15 +12,15 @@ namespace NCom {
|
|||||||
|
|
||||||
class CHandler:
|
class CHandler:
|
||||||
public IInArchive,
|
public IInArchive,
|
||||||
|
public IInArchiveGetStream,
|
||||||
public CMyUnknownImp
|
public CMyUnknownImp
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
MY_UNKNOWN_IMP1(IInArchive)
|
|
||||||
INTERFACE_IInArchive(;)
|
|
||||||
|
|
||||||
private:
|
|
||||||
CMyComPtr<IInStream> _stream;
|
CMyComPtr<IInStream> _stream;
|
||||||
CDatabase _db;
|
CDatabase _db;
|
||||||
|
public:
|
||||||
|
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
|
||||||
|
INTERFACE_IInArchive(;)
|
||||||
|
STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -2,19 +2,19 @@
|
|||||||
|
|
||||||
#include "StdAfx.h"
|
#include "StdAfx.h"
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "../../../../C/Alloc.h"
|
#include "../../../../C/Alloc.h"
|
||||||
}
|
|
||||||
|
|
||||||
#include "../../../../C/CpuArch.h"
|
#include "../../../../C/CpuArch.h"
|
||||||
|
|
||||||
#include "Common/MyCom.h"
|
|
||||||
#include "../../Common/StreamUtils.h"
|
|
||||||
#include "Common/IntToString.h"
|
#include "Common/IntToString.h"
|
||||||
|
#include "Common/MyCom.h"
|
||||||
|
|
||||||
|
#include "../../Common/StreamUtils.h"
|
||||||
|
|
||||||
#include "ComIn.h"
|
#include "ComIn.h"
|
||||||
|
|
||||||
|
#define Get16(p) GetUi16(p)
|
||||||
|
#define Get32(p) GetUi32(p)
|
||||||
|
|
||||||
namespace NArchive{
|
namespace NArchive{
|
||||||
namespace NCom{
|
namespace NCom{
|
||||||
|
|
||||||
@@ -50,31 +50,40 @@ static HRESULT ReadIDs(IInStream *inStream, Byte *buf, int sectorSizeBits, UInt3
|
|||||||
RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));
|
RINOK(ReadSector(inStream, buf, sectorSizeBits, sid));
|
||||||
UInt32 sectorSize = (UInt32)1 << sectorSizeBits;
|
UInt32 sectorSize = (UInt32)1 << sectorSizeBits;
|
||||||
for (UInt32 t = 0; t < sectorSize; t += 4)
|
for (UInt32 t = 0; t < sectorSize; t += 4)
|
||||||
*dest++ = GetUi32(buf + t);
|
*dest++ = Get32(buf + t);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
|
static void GetFileTimeFromMem(const Byte *p, FILETIME *ft)
|
||||||
{
|
{
|
||||||
ft->dwLowDateTime = GetUi32(p);
|
ft->dwLowDateTime = Get32(p);
|
||||||
ft->dwHighDateTime = GetUi32(p + 4);
|
ft->dwHighDateTime = Get32(p + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReadItem(Byte *p, CItem &item, bool mode64bit)
|
void CItem::Parse(const Byte *p, bool mode64bit)
|
||||||
{
|
{
|
||||||
memcpy(item.Name, p, 64);
|
memcpy(Name, p, kNameSizeMax);
|
||||||
// item.NameSize = GetUi16(p + 64);
|
// NameSize = Get16(p + 64);
|
||||||
item.Type = p[66];
|
Type = p[66];
|
||||||
item.LeftDid = GetUi32(p + 68);
|
LeftDid = Get32(p + 68);
|
||||||
item.RightDid = GetUi32(p + 72);
|
RightDid = Get32(p + 72);
|
||||||
item.SonDid = GetUi32(p + 76);
|
SonDid = Get32(p + 76);
|
||||||
// item.Flags = GetUi32(p + 96);
|
// Flags = Get32(p + 96);
|
||||||
GetFileTimeFromMem(p + 100, &item.CTime);
|
GetFileTimeFromMem(p + 100, &CTime);
|
||||||
GetFileTimeFromMem(p + 108, &item.MTime);
|
GetFileTimeFromMem(p + 108, &MTime);
|
||||||
item.Sid = GetUi32(p + 116);
|
Sid = Get32(p + 116);
|
||||||
item.Size = GetUi32(p + 120);
|
Size = Get32(p + 120);
|
||||||
if (mode64bit)
|
if (mode64bit)
|
||||||
item.Size |= ((UInt64)GetUi32(p + 124) << 32);
|
Size |= ((UInt64)Get32(p + 124) << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CDatabase::Clear()
|
||||||
|
{
|
||||||
|
Fat.Free();
|
||||||
|
MiniSids.Free();
|
||||||
|
Mat.Free();
|
||||||
|
Items.Clear();
|
||||||
|
Refs.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static const UInt32 kNoDid = 0xFFFFFFFF;
|
static const UInt32 kNoDid = 0xFFFFFFFF;
|
||||||
@@ -106,13 +115,6 @@ HRESULT CDatabase::AddNode(int parent, UInt32 did)
|
|||||||
static const char kCharOpenBracket = '[';
|
static const char kCharOpenBracket = '[';
|
||||||
static const char kCharCloseBracket = ']';
|
static const char kCharCloseBracket = ']';
|
||||||
|
|
||||||
UString DWORDToString(UInt32 val)
|
|
||||||
{
|
|
||||||
wchar_t buf[32];
|
|
||||||
ConvertUInt64ToString(val, buf);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static UString CompoundNameToFileName(const UString &s)
|
static UString CompoundNameToFileName(const UString &s)
|
||||||
{
|
{
|
||||||
UString res;
|
UString res;
|
||||||
@@ -122,7 +124,9 @@ static UString CompoundNameToFileName(const UString &s)
|
|||||||
if (c < 0x20)
|
if (c < 0x20)
|
||||||
{
|
{
|
||||||
res += kCharOpenBracket;
|
res += kCharOpenBracket;
|
||||||
res += DWORDToString(c);
|
wchar_t buf[32];
|
||||||
|
ConvertUInt32ToString(c, buf);
|
||||||
|
res += buf;
|
||||||
res += kCharCloseBracket;
|
res += kCharCloseBracket;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -201,31 +205,30 @@ UString CDatabase::GetItemPath(UInt32 index) const
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
HRESULT CDatabase::Open(IInStream *inStream)
|
||||||
{
|
{
|
||||||
static const UInt32 kHeaderSize = 512;
|
static const UInt32 kHeaderSize = 512;
|
||||||
Byte p[kHeaderSize];
|
Byte p[kHeaderSize];
|
||||||
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
RINOK(ReadStream_FALSE(inStream, p, kHeaderSize));
|
||||||
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
if (memcmp(p, kSignature, kSignatureSize) != 0)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt16 majorVer = GetUi16(p + 0x1A);
|
if (Get16(p + 0x1A) > 4) // majorVer
|
||||||
if (majorVer > 4)
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
if (GetUi16(p + 0x1C) != 0xFFFE)
|
if (Get16(p + 0x1C) != 0xFFFE)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt16 sectorSizeBits = GetUi16(p + 0x1E);
|
int sectorSizeBits = Get16(p + 0x1E);
|
||||||
bool mode64bit = (sectorSizeBits >= 12);
|
bool mode64bit = (sectorSizeBits >= 12);
|
||||||
UInt16 miniSectorSizeBits = GetUi16(p + 0x20);
|
int miniSectorSizeBits = Get16(p + 0x20);
|
||||||
db.SectorSizeBits = sectorSizeBits;
|
SectorSizeBits = sectorSizeBits;
|
||||||
db.MiniSectorSizeBits = miniSectorSizeBits;
|
MiniSectorSizeBits = miniSectorSizeBits;
|
||||||
|
|
||||||
if (sectorSizeBits > 28 || miniSectorSizeBits > 28 ||
|
if (sectorSizeBits > 28 || miniSectorSizeBits > 28 ||
|
||||||
sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits)
|
sectorSizeBits < 7 || miniSectorSizeBits < 2 || miniSectorSizeBits > sectorSizeBits)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt32 numSectorsForFAT = GetUi32(p + 0x2C);
|
UInt32 numSectorsForFAT = Get32(p + 0x2C);
|
||||||
db.LongStreamMinSize = GetUi32(p + 0x38);
|
LongStreamMinSize = Get32(p + 0x38);
|
||||||
|
|
||||||
UInt32 sectSize = (UInt32)1 << (int)(sectorSizeBits);
|
UInt32 sectSize = (UInt32)1 << (int)sectorSizeBits;
|
||||||
|
|
||||||
CByteBuffer sect;
|
CByteBuffer sect;
|
||||||
sect.SetCapacity(sectSize);
|
sect.SetCapacity(sectSize);
|
||||||
@@ -235,11 +238,11 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
UInt32 numFatItems = numSectorsForFAT << ssb2;
|
UInt32 numFatItems = numSectorsForFAT << ssb2;
|
||||||
if ((numFatItems >> ssb2) != numSectorsForFAT)
|
if ((numFatItems >> ssb2) != numSectorsForFAT)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
db.FatSize = numFatItems;
|
FatSize = numFatItems;
|
||||||
|
|
||||||
{
|
{
|
||||||
CUInt32Buf bat;
|
CUInt32Buf bat;
|
||||||
UInt32 numSectorsForBat = GetUi32(p + 0x48);
|
UInt32 numSectorsForBat = Get32(p + 0x48);
|
||||||
const UInt32 kNumHeaderBatItems = 109;
|
const UInt32 kNumHeaderBatItems = 109;
|
||||||
UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);
|
UInt32 numBatItems = kNumHeaderBatItems + (numSectorsForBat << ssb2);
|
||||||
if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)
|
if (numBatItems < kNumHeaderBatItems || ((numBatItems - kNumHeaderBatItems) >> ssb2) != numSectorsForBat)
|
||||||
@@ -248,8 +251,8 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < kNumHeaderBatItems; i++)
|
for (i = 0; i < kNumHeaderBatItems; i++)
|
||||||
bat[i] = GetUi32(p + 0x4c + i * 4);
|
bat[i] = Get32(p + 0x4c + i * 4);
|
||||||
UInt32 sid = GetUi32(p + 0x44);
|
UInt32 sid = Get32(p + 0x44);
|
||||||
for (UInt32 s = 0; s < numSectorsForBat; s++)
|
for (UInt32 s = 0; s < numSectorsForBat; s++)
|
||||||
{
|
{
|
||||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));
|
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, bat + i));
|
||||||
@@ -258,7 +261,7 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
}
|
}
|
||||||
numBatItems = i;
|
numBatItems = i;
|
||||||
|
|
||||||
if (!db.Fat.Allocate(numFatItems))
|
if (!Fat.Allocate(numFatItems))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt32 j = 0;
|
UInt32 j = 0;
|
||||||
|
|
||||||
@@ -266,33 +269,33 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
{
|
{
|
||||||
if (j >= numBatItems)
|
if (j >= numBatItems)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], db.Fat + i));
|
RINOK(ReadIDs(inStream, sect, sectorSizeBits, bat[j], Fat + i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 numMatItems;
|
UInt32 numMatItems;
|
||||||
{
|
{
|
||||||
UInt32 numSectorsForMat = GetUi32(p + 0x40);
|
UInt32 numSectorsForMat = Get32(p + 0x40);
|
||||||
numMatItems = (UInt32)numSectorsForMat << ssb2;
|
numMatItems = (UInt32)numSectorsForMat << ssb2;
|
||||||
if ((numMatItems >> ssb2) != numSectorsForMat)
|
if ((numMatItems >> ssb2) != numSectorsForMat)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
if (!db.Mat.Allocate(numMatItems))
|
if (!Mat.Allocate(numMatItems))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
UInt32 sid = GetUi32(p + 0x3C);
|
UInt32 sid = Get32(p + 0x3C);
|
||||||
for (i = 0; i < numMatItems; i += numSidsInSec)
|
for (i = 0; i < numMatItems; i += numSidsInSec)
|
||||||
{
|
{
|
||||||
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, db.Mat + i));
|
RINOK(ReadIDs(inStream, sect, sectorSizeBits, sid, Mat + i));
|
||||||
if (sid >= numFatItems)
|
if (sid >= numFatItems)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
sid = db.Fat[sid];
|
sid = Fat[sid];
|
||||||
}
|
}
|
||||||
if (sid != NFatID::kEndOfChain)
|
if (sid != NFatID::kEndOfChain)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
UInt32 sid = GetUi32(p + 0x30);
|
UInt32 sid = Get32(p + 0x30);
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if (sid >= numFatItems)
|
if (sid >= numFatItems)
|
||||||
@@ -301,16 +304,16 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
for (UInt32 i = 0; i < sectSize; i += 128)
|
for (UInt32 i = 0; i < sectSize; i += 128)
|
||||||
{
|
{
|
||||||
CItem item;
|
CItem item;
|
||||||
ReadItem(sect + i, item, mode64bit);
|
item.Parse(sect + i, mode64bit);
|
||||||
db.Items.Add(item);
|
Items.Add(item);
|
||||||
}
|
}
|
||||||
sid = db.Fat[sid];
|
sid = Fat[sid];
|
||||||
if (sid == NFatID::kEndOfChain)
|
if (sid == NFatID::kEndOfChain)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CItem root = db.Items[0];
|
CItem root = Items[0];
|
||||||
|
|
||||||
{
|
{
|
||||||
UInt32 numSectorsInMiniStream;
|
UInt32 numSectorsInMiniStream;
|
||||||
@@ -320,19 +323,18 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
numSectorsInMiniStream = (UInt32)numSatSects64;
|
numSectorsInMiniStream = (UInt32)numSatSects64;
|
||||||
}
|
}
|
||||||
db.NumSectorsInMiniStream = numSectorsInMiniStream;
|
NumSectorsInMiniStream = numSectorsInMiniStream;
|
||||||
if (!db.MiniSids.Allocate(numSectorsInMiniStream))
|
if (!MiniSids.Allocate(numSectorsInMiniStream))
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
{
|
{
|
||||||
UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;
|
UInt64 matSize64 = (root.Size + ((UInt64)1 << miniSectorSizeBits) - 1) >> miniSectorSizeBits;
|
||||||
if (matSize64 > NFatID::kMaxValue)
|
if (matSize64 > NFatID::kMaxValue)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
db.MatSize = (UInt32)matSize64;
|
MatSize = (UInt32)matSize64;
|
||||||
if (numMatItems < db.MatSize)
|
if (numMatItems < MatSize)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
UInt32 sid = root.Sid;
|
UInt32 sid = root.Sid;
|
||||||
for (UInt32 i = 0; ; i++)
|
for (UInt32 i = 0; ; i++)
|
||||||
{
|
{
|
||||||
@@ -344,14 +346,14 @@ HRESULT OpenArchive(IInStream *inStream, CDatabase &db)
|
|||||||
}
|
}
|
||||||
if (i >= numSectorsInMiniStream)
|
if (i >= numSectorsInMiniStream)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
db.MiniSids[i] = sid;
|
MiniSids[i] = sid;
|
||||||
if (sid >= numFatItems)
|
if (sid >= numFatItems)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
sid = db.Fat[sid];
|
sid = Fat[sid];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.AddNode(-1, root.SonDid);
|
return AddNode(-1, root.SonDid);
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -57,6 +57,8 @@ struct CItem
|
|||||||
|
|
||||||
bool IsEmpty() const { return Type == NItemType::kEmpty; }
|
bool IsEmpty() const { return Type == NItemType::kEmpty; }
|
||||||
bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }
|
bool IsDir() const { return Type == NItemType::kStorage || Type == NItemType::kRootStorage; }
|
||||||
|
|
||||||
|
void Parse(const Byte *p, bool mode64bit);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CRef
|
struct CRef
|
||||||
@@ -67,15 +69,15 @@ struct CRef
|
|||||||
|
|
||||||
class CDatabase
|
class CDatabase
|
||||||
{
|
{
|
||||||
public:
|
UInt32 NumSectorsInMiniStream;
|
||||||
|
CUInt32Buf MiniSids;
|
||||||
|
|
||||||
HRESULT AddNode(int parent, UInt32 did);
|
HRESULT AddNode(int parent, UInt32 did);
|
||||||
|
public:
|
||||||
|
|
||||||
CUInt32Buf Fat;
|
CUInt32Buf Fat;
|
||||||
UInt32 FatSize;
|
UInt32 FatSize;
|
||||||
|
|
||||||
CUInt32Buf MiniSids;
|
|
||||||
UInt32 NumSectorsInMiniStream;
|
|
||||||
|
|
||||||
CUInt32Buf Mat;
|
CUInt32Buf Mat;
|
||||||
UInt32 MatSize;
|
UInt32 MatSize;
|
||||||
|
|
||||||
@@ -86,20 +88,29 @@ public:
|
|||||||
int SectorSizeBits;
|
int SectorSizeBits;
|
||||||
int MiniSectorSizeBits;
|
int MiniSectorSizeBits;
|
||||||
|
|
||||||
void Clear()
|
void Clear();
|
||||||
|
bool IsLargeStream(UInt64 size) const { return size >= LongStreamMinSize; }
|
||||||
|
UString GetItemPath(UInt32 index) const;
|
||||||
|
|
||||||
|
UInt64 GetItemPackSize(UInt64 size) const
|
||||||
{
|
{
|
||||||
Fat.Free();
|
UInt64 mask = ((UInt64)1 << (IsLargeStream(size) ? SectorSizeBits : MiniSectorSizeBits)) - 1;
|
||||||
MiniSids.Free();
|
return (size + mask) & ~mask;
|
||||||
Mat.Free();
|
|
||||||
Items.Clear();
|
|
||||||
Refs.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsLargeStream(UInt64 size) { return size >= LongStreamMinSize; }
|
bool GetMiniCluster(UInt32 sid, UInt64 &res) const
|
||||||
UString GetItemPath(UInt32 index) const;
|
{
|
||||||
|
int subBits = SectorSizeBits - MiniSectorSizeBits;
|
||||||
|
UInt32 fid = sid >> subBits;
|
||||||
|
if (fid >= NumSectorsInMiniStream)
|
||||||
|
return false;
|
||||||
|
res = (((UInt64)MiniSids[fid] + 1) << subBits) + (sid & ((1 << subBits) - 1));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT Open(IInStream *inStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT OpenArchive(IInStream *inStream, CDatabase &database);
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -82,11 +82,11 @@ static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
|
|||||||
static bool AreEqual(const UString &methodName, const wchar_t *s)
|
static bool AreEqual(const UString &methodName, const wchar_t *s)
|
||||||
{ return (methodName.CompareNoCase(s) == 0); }
|
{ return (methodName.CompareNoCase(s) == 0); }
|
||||||
|
|
||||||
static inline bool IsLZMAMethod(const UString &methodName)
|
bool COneMethodInfo::IsLzma() const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
AreEqual(methodName, kLZMAMethodName) ||
|
AreEqual(MethodName, kLZMAMethodName) ||
|
||||||
AreEqual(methodName, kLZMA2MethodName);
|
AreEqual(MethodName, kLZMA2MethodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsBZip2Method(const UString &methodName)
|
static inline bool IsBZip2Method(const UString &methodName)
|
||||||
@@ -109,8 +109,12 @@ struct CNameToPropID
|
|||||||
const wchar_t *Name;
|
const wchar_t *Name;
|
||||||
};
|
};
|
||||||
|
|
||||||
CNameToPropID g_NameToPropID[] =
|
static CNameToPropID g_NameToPropID[] =
|
||||||
{
|
{
|
||||||
|
{ NCoderPropID::kBlockSize, VT_UI4, L"C" },
|
||||||
|
{ NCoderPropID::kDictionarySize, VT_UI4, L"D" },
|
||||||
|
{ NCoderPropID::kUsedMemorySize, VT_UI4, L"MEM" },
|
||||||
|
|
||||||
{ NCoderPropID::kOrder, VT_UI4, L"O" },
|
{ NCoderPropID::kOrder, VT_UI4, L"O" },
|
||||||
{ NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
|
{ NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
|
||||||
{ NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
|
{ NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
|
||||||
@@ -122,7 +126,8 @@ CNameToPropID g_NameToPropID[] =
|
|||||||
{ NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
|
{ NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
|
||||||
{ NCoderPropID::kAlgorithm, VT_UI4, L"a" },
|
{ NCoderPropID::kAlgorithm, VT_UI4, L"a" },
|
||||||
{ NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
|
{ NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
|
||||||
{ NCoderPropID::kNumThreads, VT_UI4, L"mt" }
|
{ NCoderPropID::kNumThreads, VT_UI4, L"mt" },
|
||||||
|
{ NCoderPropID::kDefaultProp, VT_UI4, L"" }
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
|
static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
|
||||||
@@ -154,7 +159,7 @@ static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVar
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int FindPropIdFromStringName(const UString &name)
|
static int FindPropIdExact(const UString &name)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
|
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
|
||||||
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
|
if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
|
||||||
@@ -162,16 +167,26 @@ static int FindPropIdFromStringName(const UString &name)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
|
static int FindPropIdStart(const UString &name)
|
||||||
const NWindows::NCOM::CPropVariant &value)
|
|
||||||
{
|
{
|
||||||
for (int j = 0; j < oneMethodInfo.Props.Size(); j++)
|
for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
|
||||||
if (oneMethodInfo.Props[j].Id == propID)
|
{
|
||||||
|
UString t = g_NameToPropID[i].Name;
|
||||||
|
if (t.CompareNoCase(name.Left(t.Length())) == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMethodProp(COneMethodInfo &m, PROPID propID, const NCOM::CPropVariant &value)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < m.Props.Size(); j++)
|
||||||
|
if (m.Props[j].Id == propID)
|
||||||
return;
|
return;
|
||||||
CProp prop;
|
CProp prop;
|
||||||
prop.Id = propID;
|
prop.Id = propID;
|
||||||
prop.Value = value;
|
prop.Value = value;
|
||||||
oneMethodInfo.Props.Add(prop);
|
m.Props.Add(prop);
|
||||||
}
|
}
|
||||||
|
|
||||||
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
||||||
@@ -184,7 +199,7 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
|||||||
if (oneMethodInfo.MethodName.IsEmpty())
|
if (oneMethodInfo.MethodName.IsEmpty())
|
||||||
oneMethodInfo.MethodName = kDefaultMethodName;
|
oneMethodInfo.MethodName = kDefaultMethodName;
|
||||||
|
|
||||||
if (IsLZMAMethod(oneMethodInfo.MethodName))
|
if (oneMethodInfo.IsLzma())
|
||||||
{
|
{
|
||||||
UInt32 dicSize =
|
UInt32 dicSize =
|
||||||
(level >= 9 ? kLzmaDicSizeX9 :
|
(level >= 9 ? kLzmaDicSizeX9 :
|
||||||
@@ -205,12 +220,12 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
|||||||
(level >= 5 ? kLzmaMatchFinderX5 :
|
(level >= 5 ? kLzmaMatchFinderX5 :
|
||||||
kLzmaMatchFinderX1);
|
kLzmaMatchFinderX1);
|
||||||
|
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
|
||||||
#ifdef COMPRESS_MT
|
#ifdef COMPRESS_MT
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (IsDeflateMethod(oneMethodInfo.MethodName))
|
else if (IsDeflateMethod(oneMethodInfo.MethodName))
|
||||||
@@ -229,9 +244,9 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
|||||||
(level >= 5 ? kDeflateAlgoX5 :
|
(level >= 5 ? kDeflateAlgoX5 :
|
||||||
kDeflateAlgoX1);
|
kDeflateAlgoX1);
|
||||||
|
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
|
||||||
}
|
}
|
||||||
else if (IsBZip2Method(oneMethodInfo.MethodName))
|
else if (IsBZip2Method(oneMethodInfo.MethodName))
|
||||||
{
|
{
|
||||||
@@ -245,10 +260,10 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
|||||||
(level >= 3 ? kBZip2DicSizeX3 :
|
(level >= 3 ? kBZip2DicSizeX3 :
|
||||||
kBZip2DicSizeX1));
|
kBZip2DicSizeX1));
|
||||||
|
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
|
||||||
#ifdef COMPRESS_MT
|
#ifdef COMPRESS_MT
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if (IsPpmdMethod(oneMethodInfo.MethodName))
|
else if (IsPpmdMethod(oneMethodInfo.MethodName))
|
||||||
@@ -265,8 +280,8 @@ void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
|
|||||||
(level >= 5 ? kPpmdOrderX5 :
|
(level >= 5 ? kPpmdOrderX5 :
|
||||||
kPpmdOrderX1)));
|
kPpmdOrderX1)));
|
||||||
|
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
|
||||||
SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
|
SetMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,25 +331,22 @@ static void SplitParam(const UString ¶m, UString &name, UString &value)
|
|||||||
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
|
HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
|
||||||
{
|
{
|
||||||
CProp prop;
|
CProp prop;
|
||||||
if (name.CompareNoCase(L"D") == 0 ||
|
int index = FindPropIdExact(name);
|
||||||
name.CompareNoCase(L"MEM") == 0)
|
if (index < 0)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
||||||
|
prop.Id = nameToPropID.PropID;
|
||||||
|
|
||||||
|
if (prop.Id == NCoderPropID::kBlockSize ||
|
||||||
|
prop.Id == NCoderPropID::kDictionarySize ||
|
||||||
|
prop.Id == NCoderPropID::kUsedMemorySize)
|
||||||
{
|
{
|
||||||
UInt32 dicSize;
|
UInt32 dicSize;
|
||||||
RINOK(ParsePropDictionaryValue(value, dicSize));
|
RINOK(ParsePropDictionaryValue(value, dicSize));
|
||||||
prop.Id = (name.CompareNoCase(L"D") == 0) ?
|
|
||||||
NCoderPropID::kDictionarySize :
|
|
||||||
NCoderPropID::kUsedMemorySize;
|
|
||||||
prop.Value = dicSize;
|
prop.Value = dicSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = FindPropIdFromStringName(name);
|
|
||||||
if (index < 0)
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
|
||||||
prop.Id = nameToPropID.PropID;
|
|
||||||
|
|
||||||
NCOM::CPropVariant propValue;
|
NCOM::CPropVariant propValue;
|
||||||
|
|
||||||
if (nameToPropID.VarType == VT_BSTR)
|
if (nameToPropID.VarType == VT_BSTR)
|
||||||
@@ -465,7 +477,7 @@ void COutHandler::Init()
|
|||||||
WriteMTime = true;
|
WriteMTime = true;
|
||||||
|
|
||||||
#ifdef COMPRESS_MT
|
#ifdef COMPRESS_MT
|
||||||
_numThreads = NWindows::NSystem::GetNumberOfProcessors();
|
_numThreads = NSystem::GetNumberOfProcessors();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
_level = 5;
|
_level = 5;
|
||||||
@@ -576,35 +588,26 @@ HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &val
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
int index = FindPropIdStart(realName);
|
||||||
|
if (index < 0)
|
||||||
|
return E_INVALIDARG;
|
||||||
|
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
||||||
CProp prop;
|
CProp prop;
|
||||||
if (realName.Left(1).CompareNoCase(L"D") == 0)
|
prop.Id = nameToPropID.PropID;
|
||||||
|
|
||||||
|
if (prop.Id == NCoderPropID::kBlockSize ||
|
||||||
|
prop.Id == NCoderPropID::kDictionarySize ||
|
||||||
|
prop.Id == NCoderPropID::kUsedMemorySize)
|
||||||
{
|
{
|
||||||
UInt32 dicSize;
|
UInt32 dicSize;
|
||||||
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
|
RINOK(ParsePropDictionaryValue(realName.Mid(MyStringLen(nameToPropID.Name)), value, dicSize));
|
||||||
prop.Id = NCoderPropID::kDictionarySize;
|
|
||||||
prop.Value = dicSize;
|
|
||||||
if (number <= mainDicMethodIndex)
|
|
||||||
mainDicSize = dicSize;
|
|
||||||
}
|
|
||||||
else if (realName.Left(1).CompareNoCase(L"C") == 0)
|
|
||||||
{
|
|
||||||
UInt32 blockSize;
|
|
||||||
RINOK(ParsePropDictionaryValue(realName.Mid(1), value, blockSize));
|
|
||||||
prop.Id = NCoderPropID::kBlockSize;
|
|
||||||
prop.Value = blockSize;
|
|
||||||
}
|
|
||||||
else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
|
|
||||||
{
|
|
||||||
UInt32 dicSize;
|
|
||||||
RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
|
|
||||||
prop.Id = NCoderPropID::kUsedMemorySize;
|
|
||||||
prop.Value = dicSize;
|
prop.Value = dicSize;
|
||||||
if (number <= mainDicMethodIndex)
|
if (number <= mainDicMethodIndex)
|
||||||
mainDicSize = dicSize;
|
mainDicSize = dicSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int index = FindPropIdFromStringName(realName);
|
int index = FindPropIdExact(realName);
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
const CNameToPropID &nameToPropID = g_NameToPropID[index];
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ struct COneMethodInfo
|
|||||||
{
|
{
|
||||||
CObjectVector<CProp> Props;
|
CObjectVector<CProp> Props;
|
||||||
UString MethodName;
|
UString MethodName;
|
||||||
|
|
||||||
|
bool IsLzma() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class COutHandler
|
class COutHandler
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
// InStreamWithCRC.h
|
// InStreamWithCRC.h
|
||||||
|
|
||||||
#ifndef __INSTREAMWITHCRC_H
|
#ifndef __IN_STREAM_WITH_CRC_H
|
||||||
#define __INSTREAMWITHCRC_H
|
#define __IN_STREAM_WITH_CRC_H
|
||||||
|
|
||||||
|
#include "../../../../C/7zCrc.h"
|
||||||
|
|
||||||
#include "../../../Common/MyCom.h"
|
#include "../../../Common/MyCom.h"
|
||||||
#include "../../IStream.h"
|
|
||||||
|
|
||||||
extern "C"
|
#include "../../IStream.h"
|
||||||
{
|
|
||||||
#include "../../../../C/7zCrc.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
class CSequentialInStreamWithCRC:
|
class CSequentialInStreamWithCRC:
|
||||||
public ISequentialInStream,
|
public ISequentialInStream,
|
||||||
|
|||||||
@@ -6,19 +6,13 @@
|
|||||||
|
|
||||||
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
{
|
{
|
||||||
UInt32 realProcessedSize;
|
HRESULT result = S_OK;
|
||||||
HRESULT result;
|
if (_stream)
|
||||||
if(!_stream)
|
result = _stream->Write(data, size, &size);
|
||||||
{
|
|
||||||
realProcessedSize = size;
|
|
||||||
result = S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = _stream->Write(data, size, &realProcessedSize);
|
|
||||||
if (_calculate)
|
if (_calculate)
|
||||||
_crc = CrcUpdate(_crc, data, realProcessedSize);
|
_crc = CrcUpdate(_crc, data, size);
|
||||||
_size += realProcessedSize;
|
_size += size;
|
||||||
if(processedSize != NULL)
|
if (processedSize != NULL)
|
||||||
*processedSize = realProcessedSize;
|
*processedSize = size;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,11 @@
|
|||||||
#ifndef __OUT_STREAM_WITH_CRC_H
|
#ifndef __OUT_STREAM_WITH_CRC_H
|
||||||
#define __OUT_STREAM_WITH_CRC_H
|
#define __OUT_STREAM_WITH_CRC_H
|
||||||
|
|
||||||
#include "../../../Common/MyCom.h"
|
|
||||||
#include "../../IStream.h"
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "../../../../C/7zCrc.h"
|
#include "../../../../C/7zCrc.h"
|
||||||
}
|
|
||||||
|
#include "../../../Common/MyCom.h"
|
||||||
|
|
||||||
|
#include "../../IStream.h"
|
||||||
|
|
||||||
class COutStreamWithCRC:
|
class COutStreamWithCRC:
|
||||||
public ISequentialOutStream,
|
public ISequentialOutStream,
|
||||||
|
|||||||
@@ -6,19 +6,13 @@
|
|||||||
|
|
||||||
STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *processedSize)
|
||||||
{
|
{
|
||||||
UInt32 realProcessedSize;
|
HRESULT result = S_OK;
|
||||||
HRESULT result;
|
if (_stream)
|
||||||
if(!_stream)
|
result = _stream->Write(data, size, &size);
|
||||||
{
|
|
||||||
realProcessedSize = size;
|
|
||||||
result = S_OK;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
result = _stream->Write(data, size, &realProcessedSize);
|
|
||||||
if (_calculate)
|
if (_calculate)
|
||||||
_sha.Update((const Byte *)data, realProcessedSize);
|
_sha.Update((const Byte *)data, size);
|
||||||
_size += realProcessedSize;
|
_size += size;
|
||||||
if(processedSize != NULL)
|
if (processedSize != NULL)
|
||||||
*processedSize = realProcessedSize;
|
*processedSize = size;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,11 @@
|
|||||||
#ifndef __OUT_STREAM_WITH_SHA1_H
|
#ifndef __OUT_STREAM_WITH_SHA1_H
|
||||||
#define __OUT_STREAM_WITH_SHA1_H
|
#define __OUT_STREAM_WITH_SHA1_H
|
||||||
|
|
||||||
#include "../../../Common/MyCom.h"
|
|
||||||
#include "../../IStream.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "../../Crypto/Sha1.h"
|
#include "../../Crypto/Sha1.h"
|
||||||
|
|
||||||
|
#include "../../../Common/MyCom.h"
|
||||||
|
|
||||||
|
#include "../../IStream.h"
|
||||||
|
|
||||||
class COutStreamWithSha1:
|
class COutStreamWithSha1:
|
||||||
public ISequentialOutStream,
|
public ISequentialOutStream,
|
||||||
|
|||||||
@@ -1,240 +0,0 @@
|
|||||||
// CpioHandler.cpp
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "Common/ComTry.h"
|
|
||||||
#include "Common/Defs.h"
|
|
||||||
#include "Common/NewHandler.h"
|
|
||||||
#include "Common/StringConvert.h"
|
|
||||||
|
|
||||||
#include "Windows/PropVariant.h"
|
|
||||||
#include "Windows/Time.h"
|
|
||||||
|
|
||||||
#include "../../Common/LimitedStreams.h"
|
|
||||||
#include "../../Common/ProgressUtils.h"
|
|
||||||
|
|
||||||
#include "../../Compress/CopyCoder.h"
|
|
||||||
|
|
||||||
#include "../Common/ItemNameUtils.h"
|
|
||||||
|
|
||||||
#include "CpioHandler.h"
|
|
||||||
#include "CpioIn.h"
|
|
||||||
|
|
||||||
using namespace NWindows;
|
|
||||||
using namespace NTime;
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NCpio {
|
|
||||||
|
|
||||||
/*
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kpidinode = kpidUserDefined,
|
|
||||||
kpidiChkSum
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
STATPROPSTG kProps[] =
|
|
||||||
{
|
|
||||||
{ NULL, kpidPath, VT_BSTR},
|
|
||||||
{ NULL, kpidIsDir, VT_BOOL},
|
|
||||||
{ NULL, kpidSize, VT_UI8},
|
|
||||||
{ NULL, kpidPackSize, VT_UI8},
|
|
||||||
{ NULL, kpidMTime, VT_FILETIME},
|
|
||||||
// { NULL, kpidUser, VT_BSTR},
|
|
||||||
// { NULL, kpidGroup, VT_BSTR},
|
|
||||||
// { L"inode", kpidinode, VT_UI4}
|
|
||||||
// { L"CheckSum", kpidiChkSum, VT_UI4}
|
|
||||||
};
|
|
||||||
|
|
||||||
IMP_IInArchive_Props
|
|
||||||
IMP_IInArchive_ArcProps_NO
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Open(IInStream *stream,
|
|
||||||
const UInt64 * /* maxCheckStartPosition */,
|
|
||||||
IArchiveOpenCallback *callback)
|
|
||||||
{
|
|
||||||
COM_TRY_BEGIN
|
|
||||||
// try
|
|
||||||
{
|
|
||||||
CInArchive archive;
|
|
||||||
|
|
||||||
UInt64 endPos = 0;
|
|
||||||
bool needSetTotal = true;
|
|
||||||
|
|
||||||
if (callback != NULL)
|
|
||||||
{
|
|
||||||
RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos));
|
|
||||||
RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
RINOK(archive.Open(stream));
|
|
||||||
|
|
||||||
_items.Clear();
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
CItemEx item;
|
|
||||||
bool filled;
|
|
||||||
HRESULT result = archive.GetNextItem(filled, item);
|
|
||||||
if (result == S_FALSE)
|
|
||||||
return S_FALSE;
|
|
||||||
if (result != S_OK)
|
|
||||||
return S_FALSE;
|
|
||||||
if (!filled)
|
|
||||||
break;
|
|
||||||
_items.Add(item);
|
|
||||||
archive.SkeepDataRecords(item.Size, item.Align);
|
|
||||||
if (callback != NULL)
|
|
||||||
{
|
|
||||||
if (needSetTotal)
|
|
||||||
{
|
|
||||||
RINOK(callback->SetTotal(NULL, &endPos));
|
|
||||||
needSetTotal = false;
|
|
||||||
}
|
|
||||||
if (_items.Size() % 100 == 0)
|
|
||||||
{
|
|
||||||
UInt64 numFiles = _items.Size();
|
|
||||||
UInt64 numBytes = item.HeaderPosition;
|
|
||||||
RINOK(callback->SetCompleted(&numFiles, &numBytes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (_items.Size() == 0)
|
|
||||||
return S_FALSE;
|
|
||||||
|
|
||||||
_inStream = stream;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
return S_FALSE;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return S_OK;
|
|
||||||
COM_TRY_END
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Close()
|
|
||||||
{
|
|
||||||
_items.Clear();
|
|
||||||
_inStream.Release();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
|
|
||||||
{
|
|
||||||
*numItems = _items.Size();
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
|
|
||||||
{
|
|
||||||
COM_TRY_BEGIN
|
|
||||||
NWindows::NCOM::CPropVariant prop;
|
|
||||||
const CItemEx &item = _items[index];
|
|
||||||
|
|
||||||
switch(propID)
|
|
||||||
{
|
|
||||||
case kpidPath:
|
|
||||||
prop = NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP));
|
|
||||||
break;
|
|
||||||
case kpidIsDir:
|
|
||||||
prop = item.IsDir();
|
|
||||||
break;
|
|
||||||
case kpidSize:
|
|
||||||
case kpidPackSize:
|
|
||||||
prop = (UInt64)item.Size;
|
|
||||||
break;
|
|
||||||
case kpidMTime:
|
|
||||||
{
|
|
||||||
FILETIME utcFileTime;
|
|
||||||
if (item.ModificationTime != 0)
|
|
||||||
NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
utcFileTime.dwLowDateTime = 0;
|
|
||||||
utcFileTime.dwHighDateTime = 0;
|
|
||||||
}
|
|
||||||
prop = utcFileTime;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
case kpidinode: prop = item.inode; break;
|
|
||||||
case kpidiChkSum: prop = item.ChkSum; break;
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
prop.Detach(value);
|
|
||||||
return S_OK;
|
|
||||||
COM_TRY_END
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
|
|
||||||
Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
|
|
||||||
{
|
|
||||||
COM_TRY_BEGIN
|
|
||||||
bool testMode = (_aTestMode != 0);
|
|
||||||
bool allFilesMode = (numItems == UInt32(-1));
|
|
||||||
if (allFilesMode)
|
|
||||||
numItems = _items.Size();
|
|
||||||
if (numItems == 0)
|
|
||||||
return S_OK;
|
|
||||||
UInt64 totalSize = 0;
|
|
||||||
UInt32 i;
|
|
||||||
for (i = 0; i < numItems; i++)
|
|
||||||
totalSize += _items[allFilesMode ? i : indices[i]].Size;
|
|
||||||
extractCallback->SetTotal(totalSize);
|
|
||||||
|
|
||||||
UInt64 currentTotalSize = 0;
|
|
||||||
UInt64 currentItemSize;
|
|
||||||
|
|
||||||
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
|
|
||||||
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
|
|
||||||
|
|
||||||
CLocalProgress *lps = new CLocalProgress;
|
|
||||||
CMyComPtr<ICompressProgressInfo> progress = lps;
|
|
||||||
lps->Init(extractCallback, false);
|
|
||||||
|
|
||||||
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
|
|
||||||
CMyComPtr<ISequentialInStream> inStream(streamSpec);
|
|
||||||
streamSpec->SetStream(_inStream);
|
|
||||||
|
|
||||||
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
|
|
||||||
{
|
|
||||||
lps->InSize = lps->OutSize = currentTotalSize;
|
|
||||||
RINOK(lps->SetCur());
|
|
||||||
CMyComPtr<ISequentialOutStream> realOutStream;
|
|
||||||
Int32 askMode = testMode ?
|
|
||||||
NArchive::NExtract::NAskMode::kTest :
|
|
||||||
NArchive::NExtract::NAskMode::kExtract;
|
|
||||||
Int32 index = allFilesMode ? i : indices[i];
|
|
||||||
const CItemEx &item = _items[index];
|
|
||||||
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
|
|
||||||
currentItemSize = item.Size;
|
|
||||||
if (item.IsDir())
|
|
||||||
{
|
|
||||||
RINOK(extractCallback->PrepareOperation(askMode));
|
|
||||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!testMode && (!realOutStream))
|
|
||||||
continue;
|
|
||||||
RINOK(extractCallback->PrepareOperation(askMode));
|
|
||||||
if (testMode)
|
|
||||||
{
|
|
||||||
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
|
|
||||||
streamSpec->Init(item.Size);
|
|
||||||
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
|
|
||||||
realOutStream.Release();
|
|
||||||
RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
|
|
||||||
NArchive::NExtract::NOperationResult::kOK:
|
|
||||||
NArchive::NExtract::NOperationResult::kDataError));
|
|
||||||
}
|
|
||||||
return S_OK;
|
|
||||||
COM_TRY_END
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
// Archive/cpio/Handler.h
|
|
||||||
|
|
||||||
#ifndef __ARCHIVE_CPIO_HANDLER_H
|
|
||||||
#define __ARCHIVE_CPIO_HANDLER_H
|
|
||||||
|
|
||||||
#include "Common/MyCom.h"
|
|
||||||
#include "../IArchive.h"
|
|
||||||
|
|
||||||
#include "CpioItem.h"
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NCpio {
|
|
||||||
|
|
||||||
class CHandler:
|
|
||||||
public IInArchive,
|
|
||||||
public CMyUnknownImp
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MY_UNKNOWN_IMP1(IInArchive)
|
|
||||||
|
|
||||||
INTERFACE_IInArchive(;)
|
|
||||||
|
|
||||||
private:
|
|
||||||
CObjectVector<CItemEx> _items;
|
|
||||||
CMyComPtr<IInStream> _inStream;
|
|
||||||
};
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
// Archive/cpio/Header.h
|
|
||||||
|
|
||||||
#include "StdAfx.h"
|
|
||||||
|
|
||||||
#include "CpioHeader.h"
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NCpio {
|
|
||||||
namespace NFileHeader {
|
|
||||||
|
|
||||||
namespace NMagic
|
|
||||||
{
|
|
||||||
extern const char *kMagic1 = "070701";
|
|
||||||
extern const char *kMagic2 = "070702";
|
|
||||||
extern const char *kMagic3 = "070707";
|
|
||||||
extern const char *kEndName = "TRAILER!!!";
|
|
||||||
|
|
||||||
const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };
|
|
||||||
// unsigned short kMagicForRecord2BE = 0xC771;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}}
|
|
||||||
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
// Archive/cpio/Header.h
|
|
||||||
|
|
||||||
#ifndef __ARCHIVE_CPIO_HEADER_H
|
|
||||||
#define __ARCHIVE_CPIO_HEADER_H
|
|
||||||
|
|
||||||
#include "Common/Types.h"
|
|
||||||
|
|
||||||
namespace NArchive {
|
|
||||||
namespace NCpio {
|
|
||||||
|
|
||||||
namespace NFileHeader
|
|
||||||
{
|
|
||||||
namespace NMagic
|
|
||||||
{
|
|
||||||
extern const char *kMagic1;
|
|
||||||
extern const char *kMagic2;
|
|
||||||
extern const char *kMagic3;
|
|
||||||
extern const char *kEndName;
|
|
||||||
extern const Byte kMagicForRecord2[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
const UInt32 kRecord2Size = 26;
|
|
||||||
/*
|
|
||||||
struct CRecord2
|
|
||||||
{
|
|
||||||
unsigned short c_magic;
|
|
||||||
short c_dev;
|
|
||||||
unsigned short c_ino;
|
|
||||||
unsigned short c_mode;
|
|
||||||
unsigned short c_uid;
|
|
||||||
unsigned short c_gid;
|
|
||||||
unsigned short c_nlink;
|
|
||||||
short c_rdev;
|
|
||||||
unsigned short c_mtimes[2];
|
|
||||||
unsigned short c_namesize;
|
|
||||||
unsigned short c_filesizes[2];
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
const UInt32 kRecordSize = 110;
|
|
||||||
/*
|
|
||||||
struct CRecord
|
|
||||||
{
|
|
||||||
char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format
|
|
||||||
char inode[8];
|
|
||||||
char Mode[8];
|
|
||||||
char UID[8];
|
|
||||||
char GID[8];
|
|
||||||
char nlink[8];
|
|
||||||
char mtime[8];
|
|
||||||
char Size[8]; // must be 0 for FIFOs and directories
|
|
||||||
char DevMajor[8];
|
|
||||||
char DevMinor[8];
|
|
||||||
char RDevMajor[8]; //only valid for chr and blk special files
|
|
||||||
char RDevMinor[8]; //only valid for chr and blk special files
|
|
||||||
char NameSize[8]; // count includes terminating NUL in pathname
|
|
||||||
char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file
|
|
||||||
bool CheckMagic() const
|
|
||||||
{ return memcmp(Magic, NMagic::kMagic1, 6) == 0 ||
|
|
||||||
memcmp(Magic, NMagic::kMagic2, 6) == 0; };
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
|
|
||||||
const UInt32 kOctRecordSize = 76;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user