LZMA2 support for file_extractor by Kode54

git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@968 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
Squall-Leonhart 2011-01-01 14:51:12 +00:00
parent e2fb52a7f6
commit 858e4fd90e
31 changed files with 2206 additions and 371 deletions

203
fex/7z_C/7z.h Normal file
View File

@ -0,0 +1,203 @@
/* 7z.h -- 7z interface
2010-03-11 : Igor Pavlov : Public domain */
#ifndef __7Z_H
#define __7Z_H
#include "7zBuf.h"
EXTERN_C_BEGIN
#define k7zStartHeaderSize 0x20
#define k7zSignatureSize 6
extern Byte k7zSignature[k7zSignatureSize];
#define k7zMajorVersion 0
enum EIdEnum
{
k7zIdEnd,
k7zIdHeader,
k7zIdArchiveProperties,
k7zIdAdditionalStreamsInfo,
k7zIdMainStreamsInfo,
k7zIdFilesInfo,
k7zIdPackInfo,
k7zIdUnpackInfo,
k7zIdSubStreamsInfo,
k7zIdSize,
k7zIdCRC,
k7zIdFolder,
k7zIdCodersUnpackSize,
k7zIdNumUnpackStream,
k7zIdEmptyStream,
k7zIdEmptyFile,
k7zIdAnti,
k7zIdName,
k7zIdCTime,
k7zIdATime,
k7zIdMTime,
k7zIdWinAttributes,
k7zIdComment,
k7zIdEncodedHeader,
k7zIdStartPos,
k7zIdDummy
};
typedef struct
{
UInt32 NumInStreams;
UInt32 NumOutStreams;
UInt64 MethodID;
CBuf Props;
} CSzCoderInfo;
void SzCoderInfo_Init(CSzCoderInfo *p);
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
typedef struct
{
UInt32 InIndex;
UInt32 OutIndex;
} CSzBindPair;
typedef struct
{
CSzCoderInfo *Coders;
CSzBindPair *BindPairs;
UInt32 *PackStreams;
UInt64 *UnpackSizes;
UInt32 NumCoders;
UInt32 NumBindPairs;
UInt32 NumPackStreams;
int UnpackCRCDefined;
UInt32 UnpackCRC;
UInt32 NumUnpackStreams;
} CSzFolder;
void SzFolder_Init(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *stream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
typedef struct
{
UInt32 Low;
UInt32 High;
} CNtfsFileTime;
typedef struct
{
CNtfsFileTime MTime;
UInt64 Size;
UInt32 Crc;
UInt32 Attrib;
Byte HasStream;
Byte IsDir;
Byte IsAnti;
Byte CrcDefined;
Byte MTimeDefined;
Byte AttribDefined;
} CSzFileItem;
void SzFile_Init(CSzFileItem *p);
typedef struct
{
UInt64 *PackSizes;
Byte *PackCRCsDefined;
UInt32 *PackCRCs;
CSzFolder *Folders;
CSzFileItem *Files;
UInt32 NumPackStreams;
UInt32 NumFolders;
UInt32 NumFiles;
} CSzAr;
void SzAr_Init(CSzAr *p);
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
/*
SzExtract extracts file from archive
*outBuffer must be 0 before first call for each new archive.
Extracting cache:
If you need to decompress more than one file, you can send
these values from previous call:
*blockIndex,
*outBuffer,
*outBufferSize
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
it will increase decompression speed.
If you use external function, you can declare these 3 cache variables
(blockIndex, outBuffer, outBufferSize) as static in that external function.
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
*/
typedef struct
{
CSzAr db;
UInt64 startPosAfterHeader;
UInt64 dataPos;
UInt32 *FolderStartPackStreamIndex;
UInt64 *PackStreamStartPositions;
UInt32 *FolderStartFileIndex;
UInt32 *FileIndexToFolderIndexMap;
size_t *FileNameOffsets; /* in 2-byte steps */
CBuf FileNames; /* UTF-16-LE */
} CSzArEx;
void SzArEx_Init(CSzArEx *p);
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
/*
if dest == NULL, the return value specifies the required size of the buffer,
in 16-bit characters, including the null-terminating character.
if dest != NULL, the return value specifies the number of 16-bit characters that
are written to the dest, including the null-terminating character. */
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
SRes SzArEx_Extract(
const CSzArEx *db,
ILookInStream *inStream,
UInt32 fileIndex, /* index of file */
UInt32 *blockIndex, /* index of solid block */
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
size_t *outBufferSize, /* buffer size for output buffer */
size_t *offset, /* offset of stream for required file in *outBuffer */
size_t *outSizeProcessed, /* size of file in *outBuffer */
ISzAlloc *allocMain,
ISzAlloc *allocTemp);
/*
SzArEx_Open Errors:
SZ_ERROR_NO_ARCHIVE
SZ_ERROR_ARCHIVE
SZ_ERROR_UNSUPPORTED
SZ_ERROR_MEM
SZ_ERROR_CRC
SZ_ERROR_INPUT_EOF
SZ_ERROR_FAIL
*/
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
EXTERN_C_END
#endif

View File

@ -1,7 +1,6 @@
/* 7zAlloc.c -- Allocation functions /* 7zAlloc.c -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#include <stdlib.h>
#include "7zAlloc.h" #include "7zAlloc.h"
/* #define _SZ_ALLOC_DEBUG */ /* #define _SZ_ALLOC_DEBUG */

View File

@ -1,14 +1,10 @@
/* 7zAlloc.h -- Allocation functions /* 7zAlloc.h -- Allocation functions
2008-10-04 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#ifndef __7Z_ALLOC_H #ifndef __7Z_ALLOC_H
#define __7Z_ALLOC_H #define __7Z_ALLOC_H
#include <stddef.h> #include <stdlib.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);
@ -16,8 +12,4 @@ 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

View File

@ -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

View File

@ -1,35 +1,74 @@
/* 7zCrc.c -- CRC32 calculation /* 7zCrc.c -- CRC32 calculation
2008-08-05 2009-11-23 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h"
#define kCrcPoly 0xEDB88320 #define kCrcPoly 0xEDB88320
UInt32 g_CrcTable[256];
void MY_FAST_CALL CrcGenerateTable(void) #ifdef MY_CPU_LE
#define CRC_NUM_TABLES 8
#else
#define CRC_NUM_TABLES 1
#endif
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
static CRC_FUNC g_CrcUpdate;
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
#if CRC_NUM_TABLES == 1
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
#else
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
#endif
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
{
return g_CrcUpdate(v, data, size, g_CrcTable);
}
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
{
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
}
void MY_FAST_CALL CrcGenerateTable()
{ {
UInt32 i; UInt32 i;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
UInt32 r = i; UInt32 r = i;
int j; unsigned j;
for (j = 0; j < 8; j++) for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
g_CrcTable[i] = r; g_CrcTable[i] = r;
} }
} #if CRC_NUM_TABLES == 1
g_CrcUpdate = CrcUpdateT1;
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) #else
{ for (; i < 256 * CRC_NUM_TABLES; i++)
const Byte *p = (const Byte *)data; {
for (; size > 0 ; size--, p++) UInt32 r = g_CrcTable[i - 256];
v = CRC_UPDATE_BYTE(v, *p); g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
return v; }
} g_CrcUpdate = CrcUpdateT4;
#ifdef MY_CPU_X86_OR_AMD64
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) if (!CPU_Is_InOrder())
{ g_CrcUpdate = CrcUpdateT8;
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; #endif
#endif
} }

View File

@ -1,32 +1,25 @@
/* 7zCrc.h -- CRC32 calculation /* 7zCrc.h -- CRC32 calculation
2008-03-13 2009-11-21 : Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __7Z_CRC_H #ifndef __7Z_CRC_H
#define __7Z_CRC_H #define __7Z_CRC_H
#include <stddef.h>
#include "Types.h" #include "Types.h"
#ifdef __cplusplus EXTERN_C_BEGIN
extern "C" {
#endif
extern UInt32 g_CrcTable[]; extern UInt32 g_CrcTable[];
/* Call CrcGenerateTable one time before other CRC functions */
void MY_FAST_CALL CrcGenerateTable(void); void MY_FAST_CALL CrcGenerateTable(void);
#define CRC_INIT_VAL 0xFFFFFFFF #define CRC_INIT_VAL 0xFFFFFFFF
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) #define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) #define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
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 EXTERN_C_END
}
#endif
#endif #endif

34
fex/7z_C/7zCrcOpt.c Normal file
View File

@ -0,0 +1,34 @@
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
2009-11-23 : Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_LE
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
const Byte *p = (const Byte *)data;
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
for (; size >= 4; size -= 4, p += 4)
{
v ^= *(const UInt32 *)p;
v =
table[0x300 + (v & 0xFF)] ^
table[0x200 + ((v >> 8) & 0xFF)] ^
table[0x100 + ((v >> 16) & 0xFF)] ^
table[0x000 + ((v >> 24))];
}
for (; size > 0; size--, p++)
v = CRC_UPDATE_BYTE_2(v, *p);
return v;
}
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
{
return CrcUpdateT4(v, data, size, table);
}
#endif

View File

@ -1,18 +1,129 @@
/* 7zDecode.c -- Decoding from 7z folder /* 7zDec.c -- Decoding from 7z folder
2008-11-23 : Igor Pavlov : Public domain */ 2010-11-02 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
/* #define _7ZIP_PPMD_SUPPPORT */
#include "7z.h"
#include "Bcj2.h" #include "Bcj2.h"
#include "Bra.h" #include "Bra.h"
#include "CpuArch.h"
#include "LzmaDec.h" #include "LzmaDec.h"
#include "7zDecode.h" #include "Lzma2Dec.h"
#ifdef _7ZIP_PPMD_SUPPPORT
#include "Ppmd7.h"
#endif
#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_PPC 0x03030205
#define k_ARM 0x03030501
#define k_ARMT 0x03030701
#define k_SPARC 0x03030805
#define k_BCJ2 0x0303011B #define k_BCJ2 0x0303011B
#ifdef _7ZIP_PPMD_SUPPPORT
#define k_PPMD 0x30401
typedef struct
{
IByteIn p;
const Byte *cur;
const Byte *end;
const Byte *begin;
UInt64 processed;
Bool extra;
SRes res;
ILookInStream *inStream;
} CByteInToLook;
static Byte ReadByte(void *pp)
{
CByteInToLook *p = (CByteInToLook *)pp;
if (p->cur != p->end)
return *p->cur++;
if (p->res == SZ_OK)
{
size_t size = p->cur - p->begin;
p->processed += size;
p->res = p->inStream->Skip(p->inStream, size);
size = (1 << 25);
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
p->cur = p->begin;
p->end = p->begin + size;
if (size != 0)
return *p->cur++;;
}
p->extra = True;
return 0;
}
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{
CPpmd7 ppmd;
CByteInToLook s;
SRes res = SZ_OK;
s.p.Read = ReadByte;
s.inStream = inStream;
s.begin = s.end = s.cur = NULL;
s.extra = False;
s.res = SZ_OK;
s.processed = 0;
if (coder->Props.size != 5)
return SZ_ERROR_UNSUPPORTED;
{
unsigned order = coder->Props.data[0];
UInt32 memSize = GetUi32(coder->Props.data + 1);
if (order < PPMD7_MIN_ORDER ||
order > PPMD7_MAX_ORDER ||
memSize < PPMD7_MIN_MEM_SIZE ||
memSize > PPMD7_MAX_MEM_SIZE)
return SZ_ERROR_UNSUPPORTED;
Ppmd7_Construct(&ppmd);
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
return SZ_ERROR_MEM;
Ppmd7_Init(&ppmd, order);
}
{
CPpmd7z_RangeDec rc;
Ppmd7z_RangeDec_CreateVTable(&rc);
rc.Stream = &s.p;
if (!Ppmd7z_RangeDec_Init(&rc))
res = SZ_ERROR_DATA;
else if (s.extra)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else
{
SizeT i;
for (i = 0; i < outSize; i++)
{
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
if (s.extra || sym < 0)
break;
outBuffer[i] = (Byte)sym;
}
if (i != outSize)
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
res = SZ_ERROR_DATA;
}
}
Ppmd7_Free(&ppmd, allocMain);
return res;
}
#endif
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
{ {
@ -31,7 +142,7 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inSt
size_t lookahead = (1 << 18); size_t lookahead = (1 << 18);
if (lookahead > inSize) if (lookahead > inSize)
lookahead = (size_t)inSize; lookahead = (size_t)inSize;
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
if (res != SZ_OK) if (res != SZ_OK)
break; break;
@ -61,6 +172,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, (const 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)
@ -69,7 +229,7 @@ static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer
size_t curSize = (1 << 18); size_t curSize = (1 << 18);
if (curSize > inSize) if (curSize > inSize)
curSize = (size_t)inSize; curSize = (size_t)inSize;
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); RINOK(inStream->Look((void *)inStream, (const void **)&inBuf, &curSize));
if (curSize == 0) if (curSize == 0)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
memcpy(outBuffer, inBuf, curSize); memcpy(outBuffer, inBuf, curSize);
@ -80,17 +240,37 @@ 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) static Bool IS_MAIN_METHOD(UInt32 m)
#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) switch(m)
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) {
case k_Copy:
case k_LZMA:
case k_LZMA2:
#ifdef _7ZIP_PPMD_SUPPPORT
case k_PPMD:
#endif
return True;
}
return False;
}
static static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
SRes CheckSupportedFolder(const CSzFolder *f) {
return
c->NumInStreams == 1 &&
c->NumOutStreams == 1 &&
c->MethodID <= (UInt32)0xFFFFFFFF &&
IS_MAIN_METHOD((UInt32)c->MethodID);
}
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
static SRes CheckSupportedFolder(const CSzFolder *f)
{ {
if (f->NumCoders < 1 || f->NumCoders > 4) if (f->NumCoders < 1 || f->NumCoders > 4)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (IS_UNSUPPORTED_CODER(f->Coders[0])) if (!IS_SUPPORTED_CODER(&f->Coders[0]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumCoders == 1) if (f->NumCoders == 1)
{ {
@ -100,18 +280,31 @@ SRes CheckSupportedFolder(const CSzFolder *f)
} }
if (f->NumCoders == 2) if (f->NumCoders == 2)
{ {
if (IS_NO_BCJ(f->Coders[1]) || CSzCoderInfo *c = &f->Coders[1];
f->NumPackStreams != 1 || f->PackStreams[0] != 0 || if (c->MethodID > (UInt32)0xFFFFFFFF ||
c->NumInStreams != 1 ||
c->NumOutStreams != 1 ||
f->NumPackStreams != 1 ||
f->PackStreams[0] != 0 ||
f->NumBindPairs != 1 || f->NumBindPairs != 1 ||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) f->BindPairs[0].InIndex != 1 ||
f->BindPairs[0].OutIndex != 0)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch ((UInt32)c->MethodID)
{
case k_BCJ:
case k_ARM:
break;
default:
return SZ_ERROR_UNSUPPORTED;
}
return SZ_OK; return SZ_OK;
} }
if (f->NumCoders == 4) if (f->NumCoders == 4)
{ {
if (IS_UNSUPPORTED_CODER(f->Coders[1]) || if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
IS_UNSUPPORTED_CODER(f->Coders[2]) || !IS_SUPPORTED_CODER(&f->Coders[2]) ||
IS_NO_BCJ2(f->Coders[3])) !IS_BCJ2(&f->Coders[3]))
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
if (f->NumPackStreams != 4 || if (f->NumPackStreams != 4 ||
f->PackStreams[0] != 2 || f->PackStreams[0] != 2 ||
@ -128,8 +321,7 @@ SRes CheckSupportedFolder(const CSzFolder *f)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
} }
static static UInt64 GetSum(const UInt64 *values, UInt32 index)
UInt64 GetSum(const UInt64 *values, UInt32 index)
{ {
UInt64 sum = 0; UInt64 sum = 0;
UInt32 i; UInt32 i;
@ -138,8 +330,9 @@ UInt64 GetSum(const UInt64 *values, UInt32 index)
return sum; return sum;
} }
static #define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
Byte *tempBuf[]) Byte *tempBuf[])
@ -155,7 +348,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 (IS_MAIN_METHOD((UInt32)coder->MethodID))
{ {
UInt32 si = 0; UInt32 si = 0;
UInt64 offset; UInt64 offset;
@ -199,18 +392,22 @@ 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 if (coder->MethodID == k_LZMA2)
else if (coder->MethodID == k_BCJ)
{ {
UInt32 state; RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
if (ci != 1) }
else
{
#ifdef _7ZIP_PPMD_SUPPPORT
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
#else
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
x86_Convert_Init(state); #endif
x86_Convert(outBuffer, outSize, 0, &state, 0); }
} }
else if (coder->MethodID == k_BCJ2) else if (coder->MethodID == k_BCJ2)
{ {
@ -238,18 +435,34 @@ SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
RINOK(res) RINOK(res)
} }
else else
{
if (ci != 1)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
switch(coder->MethodID)
{
case k_BCJ:
{
UInt32 state;
x86_Convert_Init(state);
x86_Convert(outBuffer, outSize, 0, &state, 0);
break;
}
CASE_BRA_CONV(ARM)
default:
return SZ_ERROR_UNSUPPORTED;
}
}
} }
return SZ_OK; return SZ_OK;
} }
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
ILookInStream *inStream, UInt64 startPos, ILookInStream *inStream, UInt64 startPos,
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
{ {
Byte *tempBuf[3] = { 0, 0, 0}; Byte *tempBuf[3] = { 0, 0, 0};
int i; int i;
SRes res = SzDecode2(packSizes, folder, inStream, startPos, SRes res = SzFolder_Decode2(folder, packSizes, inStream, startPos,
outBuffer, (SizeT)outSize, allocMain, tempBuf); outBuffer, (SizeT)outSize, allocMain, tempBuf);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
IAlloc_Free(allocMain, tempBuf[i]); IAlloc_Free(allocMain, tempBuf[i]);

View File

@ -1,17 +1,134 @@
/* 7zIn.c -- 7z Input functions /* 7zIn.c -- 7z Input functions
2008-12-31 : Igor Pavlov : Public domain */ 2010-10-29 : Igor Pavlov : Public domain */
#include <string.h>
#include "7z.h"
#include "7zCrc.h" #include "7zCrc.h"
#include "CpuArch.h" #include "CpuArch.h"
#include "7zDecode.h" Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
#include "7zIn.h"
#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } #define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; }
#define NUM_FOLDER_CODERS_MAX 32 #define NUM_FOLDER_CODERS_MAX 32
#define NUM_CODER_STREAMS_MAX 32 #define NUM_CODER_STREAMS_MAX 32
void SzCoderInfo_Init(CSzCoderInfo *p)
{
Buf_Init(&p->Props);
}
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
{
Buf_Free(&p->Props, alloc);
SzCoderInfo_Init(p);
}
void SzFolder_Init(CSzFolder *p)
{
p->Coders = 0;
p->BindPairs = 0;
p->PackStreams = 0;
p->UnpackSizes = 0;
p->NumCoders = 0;
p->NumBindPairs = 0;
p->NumPackStreams = 0;
p->UnpackCRCDefined = 0;
p->UnpackCRC = 0;
p->NumUnpackStreams = 0;
}
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Coders)
for (i = 0; i < p->NumCoders; i++)
SzCoderInfo_Free(&p->Coders[i], alloc);
IAlloc_Free(alloc, p->Coders);
IAlloc_Free(alloc, p->BindPairs);
IAlloc_Free(alloc, p->PackStreams);
IAlloc_Free(alloc, p->UnpackSizes);
SzFolder_Init(p);
}
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
{
UInt32 result = 0;
UInt32 i;
for (i = 0; i < p->NumCoders; i++)
result += p->Coders[i].NumOutStreams;
return result;
}
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].InIndex == inStreamIndex)
return i;
return -1;
}
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
{
UInt32 i;
for (i = 0; i < p->NumBindPairs; i++)
if (p->BindPairs[i].OutIndex == outStreamIndex)
return i;
return -1;
}
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
{
int i = (int)SzFolder_GetNumOutStreams(p);
if (i == 0)
return 0;
for (i--; i >= 0; i--)
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
return p->UnpackSizes[i];
/* throw 1; */
return 0;
}
void SzFile_Init(CSzFileItem *p)
{
p->HasStream = 1;
p->IsDir = 0;
p->IsAnti = 0;
p->CrcDefined = 0;
p->MTimeDefined = 0;
}
void SzAr_Init(CSzAr *p)
{
p->PackSizes = 0;
p->PackCRCsDefined = 0;
p->PackCRCs = 0;
p->Folders = 0;
p->Files = 0;
p->NumPackStreams = 0;
p->NumFolders = 0;
p->NumFiles = 0;
}
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
UInt32 i;
if (p->Folders)
for (i = 0; i < p->NumFolders; i++)
SzFolder_Free(&p->Folders[i], alloc);
IAlloc_Free(alloc, p->PackSizes);
IAlloc_Free(alloc, p->PackCRCsDefined);
IAlloc_Free(alloc, p->PackCRCs);
IAlloc_Free(alloc, p->Folders);
IAlloc_Free(alloc, p->Files);
SzAr_Init(p);
}
void SzArEx_Init(CSzArEx *p) void SzArEx_Init(CSzArEx *p)
{ {
SzAr_Init(&p->db); SzAr_Init(&p->db);
@ -19,6 +136,8 @@ void SzArEx_Init(CSzArEx *p)
p->PackStreamStartPositions = 0; p->PackStreamStartPositions = 0;
p->FolderStartFileIndex = 0; p->FolderStartFileIndex = 0;
p->FileIndexToFolderIndexMap = 0; p->FileIndexToFolderIndexMap = 0;
p->FileNameOffsets = 0;
Buf_Init(&p->FileNames);
} }
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
@ -27,6 +146,10 @@ void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
IAlloc_Free(alloc, p->PackStreamStartPositions); IAlloc_Free(alloc, p->PackStreamStartPositions);
IAlloc_Free(alloc, p->FolderStartFileIndex); IAlloc_Free(alloc, p->FolderStartFileIndex);
IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
IAlloc_Free(alloc, p->FileNameOffsets);
Buf_Free(&p->FileNames, alloc);
SzAr_Free(&p->db, alloc); SzAr_Free(&p->db, alloc);
SzArEx_Init(p); SzArEx_Init(p);
} }
@ -488,11 +611,11 @@ static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc)
return SZ_ERROR_UNSUPPORTED; return SZ_ERROR_UNSUPPORTED;
folder->NumBindPairs = numBindPairs = numOutStreams - 1; folder->NumBindPairs = numBindPairs = numOutStreams - 1;
MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); MY_ALLOC(CSzBindPair, folder->BindPairs, (size_t)numBindPairs, alloc);
for (i = 0; i < numBindPairs; i++) for (i = 0; i < numBindPairs; i++)
{ {
CBindPair *bp = folder->BindPairs + i; CSzBindPair *bp = folder->BindPairs + i;
RINOK(SzReadNumber32(sd, &bp->InIndex)); RINOK(SzReadNumber32(sd, &bp->InIndex));
RINOK(SzReadNumber32(sd, &bp->OutIndex)); RINOK(SzReadNumber32(sd, &bp->OutIndex));
} }
@ -780,81 +903,38 @@ static SRes SzReadStreamsInfo(
} }
} }
Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
{
size_t len = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
if (dest != 0)
{
size_t i;
const Byte *src = p->FileNames.data + (p->FileNameOffsets[fileIndex] * 2);
for (i = 0; i < len; i++)
dest[i] = GetUi16(src + i * 2);
}
return len;
}
static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) static SRes SzReadFileNames(const Byte *p, size_t size, UInt32 numFiles, size_t *sizes)
{ {
UInt32 i; UInt32 i;
size_t pos = 0;
for (i = 0; i < numFiles; i++) for (i = 0; i < numFiles; i++)
{ {
UInt32 len = 0; sizes[i] = pos;
UInt32 pos = 0; for (;;)
CSzFileItem *file = files + i;
while (pos + 2 <= sd->Size)
{ {
int numAdds; if (pos >= size)
UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
len++;
if (value == 0)
break;
if (value < 0x80)
continue;
if (value >= 0xD800 && value < 0xE000)
{
UInt32 c2;
if (value >= 0xDC00)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
if (pos + 2 > sd->Size) if (p[pos * 2] == 0 && p[pos * 2 + 1] == 0)
return SZ_ERROR_ARCHIVE;
c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8));
pos += 2;
if (c2 < 0xDC00 || c2 >= 0xE000)
return SZ_ERROR_ARCHIVE;
value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break; break;
len += numAdds; pos++;
} }
pos++;
MY_ALLOC(char, file->Name, (size_t)len, alloc);
len = 0;
while (2 <= sd->Size)
{
int numAdds;
UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
SzSkeepDataSize(sd, 2);
if (value < 0x80)
{
file->Name[len++] = (char)value;
if (value == 0)
break;
continue;
} }
if (value >= 0xD800 && value < 0xE000) sizes[i] = pos;
{ return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8));
SzSkeepDataSize(sd, 2);
value = ((value - 0xD800) << 10) | (c2 - 0xDC00);
}
for (numAdds = 1; numAdds < 5; numAdds++)
if (value < (((UInt32)1) << (numAdds * 5 + 6)))
break;
file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
do
{
numAdds--;
file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
}
while (numAdds > 0);
len += numAdds;
}
}
return SZ_OK;
} }
static SRes SzReadHeader2( static SRes SzReadHeader2(
@ -869,23 +949,23 @@ static SRes SzReadHeader2(
ISzAlloc *allocMain, ISzAlloc *allocMain,
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
UInt64 htype; UInt64 type;
UInt32 numUnpackStreams = 0; UInt32 numUnpackStreams = 0;
UInt32 numFiles = 0; UInt32 numFiles = 0;
CSzFileItem *files = 0; CSzFileItem *files = 0;
UInt32 numEmptyStreams = 0; UInt32 numEmptyStreams = 0;
UInt32 i; UInt32 i;
RINOK(SzReadID(sd, &htype)); RINOK(SzReadID(sd, &type));
if (htype == k7zIdArchiveProperties) if (type == k7zIdArchiveProperties)
{ {
RINOK(SzReadArchiveProperties(sd)); RINOK(SzReadArchiveProperties(sd));
RINOK(SzReadID(sd, &htype)); RINOK(SzReadID(sd, &type));
} }
if (htype == k7zIdMainStreamsInfo) if (type == k7zIdMainStreamsInfo)
{ {
RINOK(SzReadStreamsInfo(sd, RINOK(SzReadStreamsInfo(sd,
&p->dataPos, &p->dataPos,
@ -895,12 +975,12 @@ static SRes SzReadHeader2(
digestsDefined, digestsDefined,
digests, allocMain, allocTemp)); digests, allocMain, allocTemp));
p->dataPos += p->startPosAfterHeader; p->dataPos += p->startPosAfterHeader;
RINOK(SzReadID(sd, &htype)); RINOK(SzReadID(sd, &type));
} }
if (htype == k7zIdEnd) if (type == k7zIdEnd)
return SZ_OK; return SZ_OK;
if (htype != k7zIdFilesInfo) if (type != k7zIdFilesInfo)
return SZ_ERROR_ARCHIVE; return SZ_ERROR_ARCHIVE;
RINOK(SzReadNumber32(sd, &numFiles)); RINOK(SzReadNumber32(sd, &numFiles));
@ -920,7 +1000,8 @@ static SRes SzReadHeader2(
if (type == k7zIdEnd) if (type == k7zIdEnd)
break; break;
RINOK(SzReadNumber(sd, &size)); RINOK(SzReadNumber(sd, &size));
if (size > sd->Size)
return SZ_ERROR_ARCHIVE;
if ((UInt64)(int)type != type) if ((UInt64)(int)type != type)
{ {
RINOK(SzSkeepDataSize(sd, size)); RINOK(SzSkeepDataSize(sd, size));
@ -930,8 +1011,17 @@ static SRes SzReadHeader2(
{ {
case k7zIdName: case k7zIdName:
{ {
size_t namesSize;
RINOK(SzReadSwitch(sd)); RINOK(SzReadSwitch(sd));
RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) namesSize = (size_t)size - 1;
if ((namesSize & 1) != 0)
return SZ_ERROR_ARCHIVE;
if (!Buf_Create(&p->FileNames, namesSize, allocMain))
return SZ_ERROR_MEM;
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
memcpy(p->FileNames.data, sd->Data, namesSize);
RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
RINOK(SzSkeepDataSize(sd, namesSize));
break; break;
} }
case k7zIdEmptyStream: case k7zIdEmptyStream:
@ -948,6 +1038,25 @@ static SRes SzReadHeader2(
RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
break; break;
} }
case k7zIdWinAttributes:
{
RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
RINOK(SzReadSwitch(sd));
for (i = 0; i < numFiles; i++)
{
CSzFileItem *f = &files[i];
Byte defined = (*lwtVector)[i];
f->AttribDefined = defined;
f->Attrib = 0;
if (defined)
{
RINOK(SzReadUInt32(sd, &f->Attrib));
}
}
IAlloc_Free(allocTemp, *lwtVector);
*lwtVector = NULL;
break;
}
case k7zIdMTime: case k7zIdMTime:
{ {
RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
@ -964,6 +1073,8 @@ static SRes SzReadHeader2(
RINOK(SzReadUInt32(sd, &f->MTime.High)); RINOK(SzReadUInt32(sd, &f->MTime.High));
} }
} }
IAlloc_Free(allocTemp, *lwtVector);
*lwtVector = NULL;
break; break;
} }
default: default:
@ -988,8 +1099,8 @@ static SRes SzReadHeader2(
{ {
file->IsDir = 0; file->IsDir = 0;
file->Size = (*unpackSizes)[sizeIndex]; file->Size = (*unpackSizes)[sizeIndex];
file->FileCRC = (*digests)[sizeIndex]; file->Crc = (*digests)[sizeIndex];
file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; file->CrcDefined = (Byte)(*digestsDefined)[sizeIndex];
sizeIndex++; sizeIndex++;
} }
else else
@ -1000,7 +1111,8 @@ static SRes SzReadHeader2(
file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
emptyFileIndex++; emptyFileIndex++;
file->Size = 0; file->Size = 0;
file->FileCRCDefined = 0; file->Crc = 0;
file->CrcDefined = 0;
} }
} }
} }
@ -1066,7 +1178,7 @@ static SRes SzReadAndDecodePackedStreams2(
if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
res = SzDecode(p->PackSizes, folder, res = SzFolder_Decode(folder, p->PackSizes,
inStream, dataStartPos, inStream, dataStartPos,
outBuffer->data, (size_t)unpackSize, allocTemp); outBuffer->data, (size_t)unpackSize, allocTemp);
RINOK(res); RINOK(res);
@ -1106,12 +1218,16 @@ static SRes SzArEx_Open2(
ISzAlloc *allocTemp) ISzAlloc *allocTemp)
{ {
Byte header[k7zStartHeaderSize]; Byte header[k7zStartHeaderSize];
Int64 startArcPos;
UInt64 nextHeaderOffset, nextHeaderSize; UInt64 nextHeaderOffset, nextHeaderSize;
size_t nextHeaderSizeT; size_t nextHeaderSizeT;
UInt32 nextHeaderCRC; UInt32 nextHeaderCRC;
CBuf buffer; CBuf buffer;
SRes res; SRes res;
startArcPos = 0;
RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
if (!TestSignatureCandidate(header)) if (!TestSignatureCandidate(header))
@ -1123,7 +1239,7 @@ static SRes SzArEx_Open2(
nextHeaderSize = GetUi64(header + 20); nextHeaderSize = GetUi64(header + 20);
nextHeaderCRC = GetUi32(header + 28); nextHeaderCRC = GetUi32(header + 28);
p->startPosAfterHeader = k7zStartHeaderSize; p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
return SZ_ERROR_CRC; return SZ_ERROR_CRC;
@ -1140,13 +1256,13 @@ static SRes SzArEx_Open2(
{ {
Int64 pos = 0; Int64 pos = 0;
RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
if ((UInt64)pos < nextHeaderOffset || if ((UInt64)pos < startArcPos + nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
(UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
return SZ_ERROR_INPUT_EOF; return SZ_ERROR_INPUT_EOF;
} }
RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp))
return SZ_ERROR_MEM; return SZ_ERROR_MEM;
@ -1202,3 +1318,85 @@ SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAl
SzArEx_Free(p, allocMain); SzArEx_Free(p, allocMain);
return res; return res;
} }
SRes SzArEx_Extract(
const CSzArEx *p,
ILookInStream *inStream,
UInt32 fileIndex,
UInt32 *blockIndex,
Byte **outBuffer,
size_t *outBufferSize,
size_t *offset,
size_t *outSizeProcessed,
ISzAlloc *allocMain,
ISzAlloc *allocTemp)
{
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
SRes res = SZ_OK;
*offset = 0;
*outSizeProcessed = 0;
if (folderIndex == (UInt32)-1)
{
IAlloc_Free(allocMain, *outBuffer);
*blockIndex = folderIndex;
*outBuffer = 0;
*outBufferSize = 0;
return SZ_OK;
}
if (*outBuffer == 0 || *blockIndex != folderIndex)
{
CSzFolder *folder = p->db.Folders + folderIndex;
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
size_t unpackSize = (size_t)unpackSizeSpec;
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
if (unpackSize != unpackSizeSpec)
return SZ_ERROR_MEM;
*blockIndex = folderIndex;
IAlloc_Free(allocMain, *outBuffer);
*outBuffer = 0;
RINOK(LookInStream_SeekTo(inStream, startOffset));
if (res == SZ_OK)
{
*outBufferSize = unpackSize;
if (unpackSize != 0)
{
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
if (*outBuffer == 0)
res = SZ_ERROR_MEM;
}
if (res == SZ_OK)
{
res = SzFolder_Decode(folder,
p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
inStream, startOffset,
*outBuffer, unpackSize, allocTemp);
if (res == SZ_OK)
{
if (folder->UnpackCRCDefined)
{
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
res = SZ_ERROR_CRC;
}
}
}
}
}
if (res == SZ_OK)
{
UInt32 i;
CSzFileItem *fileItem = p->db.Files + fileIndex;
*offset = 0;
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
*offset += (UInt32)p->db.Files[i].Size;
*outSizeProcessed = (size_t)fileItem->Size;
if (*offset + *outSizeProcessed > *outBufferSize)
return SZ_ERROR_FAIL;
if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
res = SZ_ERROR_CRC;
}
return res;
}

View File

@ -1,11 +1,10 @@
/* 7zStream.c -- 7z Stream functions /* 7zStream.c -- 7z Stream functions
2008-11-23 : Igor Pavlov : Public domain */ 2010-03-11 : Igor Pavlov : Public domain */
#include <string.h> #include <string.h>
#include "Types.h" #include "Types.h"
#if NEVER_CALLED
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
{ {
while (size != 0) while (size != 0)
@ -31,7 +30,6 @@ SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
RINOK(stream->Read(stream, buf, &processed)); RINOK(stream->Read(stream, buf, &processed));
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
} }
#endif
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
{ {
@ -39,17 +37,15 @@ SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
return stream->Seek(stream, &t, SZ_SEEK_SET); return stream->Seek(stream, &t, SZ_SEEK_SET);
} }
#if NEVER_CALLED
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
{ {
void *lookBuf; const void *lookBuf;
if (*size == 0) if (*size == 0)
return SZ_OK; return SZ_OK;
RINOK(stream->Look(stream, &lookBuf, size)); RINOK(stream->Look(stream, &lookBuf, size));
memcpy(buf, lookBuf, *size); memcpy(buf, lookBuf, *size);
return stream->Skip(stream, *size); return stream->Skip(stream, *size);
} }
#endif
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
{ {
@ -70,14 +66,9 @@ SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
} }
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) static SRes LookToRead_Look_Lookahead(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
#if !NEVER_CALLED
(void)pp;
(void)buf;
(void)size;
#else
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
size_t size2 = p->size - p->pos; size_t size2 = p->size - p->pos;
if (size2 == 0 && *size > 0) if (size2 == 0 && *size > 0)
@ -90,11 +81,10 @@ static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
if (size2 < *size) if (size2 < *size)
*size = size2; *size = size2;
*buf = p->buf + p->pos; *buf = p->buf + p->pos;
#endif
return res; return res;
} }
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
{ {
SRes res = SZ_OK; SRes res = SZ_OK;
CLookToRead *p = (CLookToRead *)pp; CLookToRead *p = (CLookToRead *)pp;
@ -143,9 +133,6 @@ static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
void LookToRead_CreateVTable(CLookToRead *p, int lookahead) void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
{ {
#if !NEVER_CALLED
lookahead = 0;
#endif
p->s.Look = lookahead ? p->s.Look = lookahead ?
LookToRead_Look_Lookahead : LookToRead_Look_Lookahead :
LookToRead_Look_Exact; LookToRead_Look_Exact;
@ -159,7 +146,6 @@ void LookToRead_Init(CLookToRead *p)
p->pos = p->size = 0; p->pos = p->size = 0;
} }
#if NEVER_CALLED
static SRes SecToLook_Read(void *pp, void *buf, size_t *size) static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
{ {
CSecToLook *p = (CSecToLook *)pp; CSecToLook *p = (CSecToLook *)pp;
@ -181,4 +167,3 @@ void SecToRead_CreateVTable(CSecToRead *p)
{ {
p->s.Read = SecToRead_Read; p->s.Read = SecToRead_Read;
} }
#endif

View File

@ -43,11 +43,11 @@ int Bcj2_Decode(
const Byte *buffer, *bufferLim; const Byte *buffer, *bufferLim;
UInt32 range, code; UInt32 range, code;
Byte prevByte = 0; Byte prevByte = 0;
{
unsigned int i; unsigned int i;
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
p[i] = kBitModelTotal >> 1; p[i] = kBitModelTotal >> 1;
}
buffer = buf3; buffer = buf3;
bufferLim = buffer + size3; bufferLim = buffer + size3;
RC_INIT2 RC_INIT2
@ -67,12 +67,12 @@ int Bcj2_Decode(
limit = outSize - outPos; limit = outSize - outPos;
while (limit != 0) while (limit != 0)
{ {
Byte bb = buf0[inPos]; Byte b = buf0[inPos];
outBuf[outPos++] = bb; outBuf[outPos++] = b;
if (IsJ(prevByte, bb)) if (IsJ(prevByte, b))
break; break;
inPos++; inPos++;
prevByte = bb; prevByte = b;
limit--; limit--;
} }

View File

@ -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

133
fex/7z_C/Bra.c Normal file
View File

@ -0,0 +1,133 @@
/* Bra.c -- Converters for RISC code
2010-04-16 : Igor Pavlov : Public domain */
#include "Bra.h"
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 8;
for (i = 0; i <= size; i += 4)
{
if (data[i + 3] == 0xEB)
{
UInt32 dest;
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
src <<= 2;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 2;
data[i + 2] = (Byte)(dest >> 16);
data[i + 1] = (Byte)(dest >> 8);
data[i + 0] = (Byte)dest;
}
}
return i;
}
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
ip += 4;
for (i = 0; i <= size; i += 2)
{
if ((data[i + 1] & 0xF8) == 0xF0 &&
(data[i + 3] & 0xF8) == 0xF8)
{
UInt32 dest;
UInt32 src =
(((UInt32)data[i + 1] & 0x7) << 19) |
((UInt32)data[i + 0] << 11) |
(((UInt32)data[i + 3] & 0x7) << 8) |
(data[i + 2]);
src <<= 1;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
dest >>= 1;
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
data[i + 0] = (Byte)(dest >> 11);
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
data[i + 2] = (Byte)dest;
i += 2;
}
}
return i;
}
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
SizeT i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
{
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3] & (~3));
UInt32 dest;
if (encoding)
dest = ip + (UInt32)i + src;
else
dest = src - (ip + (UInt32)i);
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] &= 0x3;
data[i + 3] |= dest;
}
}
return i;
}
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
{
UInt32 i;
if (size < 4)
return 0;
size -= 4;
for (i = 0; i <= size; i += 4)
{
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
{
UInt32 src =
((UInt32)data[i + 0] << 24) |
((UInt32)data[i + 1] << 16) |
((UInt32)data[i + 2] << 8) |
((UInt32)data[i + 3]);
UInt32 dest;
src <<= 2;
if (encoding)
dest = ip + i + src;
else
dest = src - (ip + i);
dest >>= 2;
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
data[i + 0] = (Byte)(dest >> 24);
data[i + 1] = (Byte)(dest >> 16);
data[i + 2] = (Byte)(dest >> 8);
data[i + 3] = (Byte)dest;
}
}
return i;
}

View File

@ -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

168
fex/7z_C/CpuArch.c Normal file
View File

@ -0,0 +1,168 @@
/* CpuArch.c -- CPU specific code
2010-10-26: Igor Pavlov : Public domain */
#include "CpuArch.h"
#ifdef MY_CPU_X86_OR_AMD64
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
#define USE_ASM
#endif
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
static UInt32 CheckFlag(UInt32 flag)
{
#ifdef _MSC_VER
__asm pushfd;
__asm pop EAX;
__asm mov EDX, EAX;
__asm xor EAX, flag;
__asm push EAX;
__asm popfd;
__asm pushfd;
__asm pop EAX;
__asm xor EAX, EDX;
__asm push EDX;
__asm popfd;
__asm and flag, EAX;
#else
__asm__ __volatile__ (
"pushf\n\t"
"pop %%EAX\n\t"
"movl %%EAX,%%EDX\n\t"
"xorl %0,%%EAX\n\t"
"push %%EAX\n\t"
"popf\n\t"
"pushf\n\t"
"pop %%EAX\n\t"
"xorl %%EDX,%%EAX\n\t"
"push %%EDX\n\t"
"popf\n\t"
"andl %%EAX, %0\n\t":
"=c" (flag) : "c" (flag));
#endif
return flag;
}
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
#else
#define CHECK_CPUID_IS_SUPPORTED
#endif
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
{
#ifdef USE_ASM
#ifdef _MSC_VER
UInt32 a2, b2, c2, d2;
__asm xor EBX, EBX;
__asm xor ECX, ECX;
__asm xor EDX, EDX;
__asm mov EAX, function;
__asm cpuid;
__asm mov a2, EAX;
__asm mov b2, EBX;
__asm mov c2, ECX;
__asm mov d2, EDX;
*a = a2;
*b = b2;
*c = c2;
*d = d2;
#else
__asm__ __volatile__ (
"cpuid"
: "=a" (*a) ,
"=b" (*b) ,
"=c" (*c) ,
"=d" (*d)
: "0" (function)) ;
#endif
#else
int CPUInfo[4];
__cpuid(CPUInfo, function);
*a = CPUInfo[0];
*b = CPUInfo[1];
*c = CPUInfo[2];
*d = CPUInfo[3];
#endif
}
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
{
CHECK_CPUID_IS_SUPPORTED
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
return True;
}
static UInt32 kVendors[][3] =
{
{ 0x756E6547, 0x49656E69, 0x6C65746E},
{ 0x68747541, 0x69746E65, 0x444D4163},
{ 0x746E6543, 0x48727561, 0x736C7561}
};
int x86cpuid_GetFirm(const Cx86cpuid *p)
{
unsigned i;
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
{
const UInt32 *v = kVendors[i];
if (v[0] == p->vendor[0] &&
v[1] == p->vendor[1] &&
v[2] == p->vendor[2])
return (int)i;
}
return -1;
}
Bool CPU_Is_InOrder()
{
Cx86cpuid p;
int firm;
UInt32 family, model;
if (!x86cpuid_CheckAndRead(&p))
return True;
family = x86cpuid_GetFamily(&p);
model = x86cpuid_GetModel(&p);
firm = x86cpuid_GetFirm(&p);
switch (firm)
{
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
}
return True;
}
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
static Bool CPU_Sys_Is_SSE_Supported()
{
OSVERSIONINFO vi;
vi.dwOSVersionInfoSize = sizeof(vi);
if (!GetVersionEx(&vi))
return False;
return (vi.dwMajorVersion >= 5);
}
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
#else
#define CHECK_SYS_SSE_SUPPORT
#endif
Bool CPU_Is_Aes_Supported()
{
Cx86cpuid p;
CHECK_SYS_SSE_SUPPORT
if (!x86cpuid_CheckAndRead(&p))
return False;
return (p.c >> 25) & 1;
}
#endif

View File

@ -1,29 +1,73 @@
/* CpuArch.h /* CpuArch.h -- CPU specific code
2008-08-05 2010-10-26: Igor Pavlov : Public domain */
Igor Pavlov
Public domain */
#ifndef __CPUARCH_H #ifndef __CPU_ARCH_H
#define __CPUARCH_H #define __CPU_ARCH_H
#include "Types.h"
EXTERN_C_BEGIN
/* /*
LITTLE_ENDIAN_UNALIGN means: MY_CPU_LE means that CPU is LITTLE ENDIAN.
1) CPU is LITTLE_ENDIAN If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
2) it's allowed to make unaligned memory accesses
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
about these properties of platform. If MY_CPU_LE_UNALIGN is not defined, we don't know about these properties of platform.
*/ */
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) #if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
#define LITTLE_ENDIAN_UNALIGN #define MY_CPU_AMD64
#endif #endif
#ifdef LITTLE_ENDIAN_UNALIGN #if defined(MY_CPU_AMD64) || defined(_M_IA64)
#define MY_CPU_64BIT
#endif
#if defined(_M_IX86) || defined(__i386__)
#define MY_CPU_X86
#endif
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
#define MY_CPU_X86_OR_AMD64
#endif
#if defined(MY_CPU_X86) || defined(_M_ARM)
#define MY_CPU_32BIT
#endif
#if defined(_WIN32) && defined(_M_ARM)
#define MY_CPU_ARM_LE
#endif
#if defined(_WIN32) && defined(_M_IA64)
#define MY_CPU_IA64_LE
#endif
#if defined(MY_CPU_X86_OR_AMD64)
#define MY_CPU_LE_UNALIGN
#endif
#if defined(MY_CPU_X86_OR_AMD64) || defined(MY_CPU_ARM_LE) || defined(MY_CPU_IA64_LE) || defined(__ARMEL__) || defined(__MIPSEL__) || defined(__LITTLE_ENDIAN__)
#define MY_CPU_LE
#endif
#if defined(__BIG_ENDIAN__)
#define MY_CPU_BE
#endif
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
Stop_Compiling_Bad_Endian
#endif
#ifdef MY_CPU_LE_UNALIGN
#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);
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
#else #else
@ -37,15 +81,23 @@ 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); \
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
((Byte *)(p))[3] = (Byte)(_x_ >> 24); } ((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
SetUi32(p, (UInt32)_x64_); \
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
#endif #endif
#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) #if defined(MY_CPU_LE_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
#pragma intrinsic(_byteswap_ulong) #pragma intrinsic(_byteswap_ulong)
#pragma intrinsic(_byteswap_uint64) #pragma intrinsic(_byteswap_uint64)
@ -66,4 +118,38 @@ 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 MY_CPU_X86_OR_AMD64
typedef struct
{
UInt32 maxFunc;
UInt32 vendor[3];
UInt32 ver;
UInt32 b;
UInt32 c;
UInt32 d;
} Cx86cpuid;
enum
{
CPU_FIRM_INTEL,
CPU_FIRM_AMD,
CPU_FIRM_VIA
};
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
Bool CPU_Is_InOrder();
Bool CPU_Is_Aes_Supported();
#endif
EXTERN_C_END
#endif #endif

371
fex/7z_C/Lzma2Dec.c Normal file
View File

@ -0,0 +1,371 @@
/* 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;
}
static
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
{
p->needFlush = 1;
p->remainLen = 0;
p->tempBufSize = 0;
if (initDic)
{
p->processedPos = 0;
p->checkDicSize = 0;
p->needInitState = 1;
}
if (initState)
p->needInitState = 1;
}
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
fex/7z_C/Lzma2Dec.h Normal file
View 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

View File

@ -1,5 +1,5 @@
/* LzmaDec.c -- LZMA Decoder /* LzmaDec.c -- LZMA Decoder
2008-11-06 : Igor Pavlov : Public domain */ 2009-09-20 : Igor Pavlov : Public domain */
#include "LzmaDec.h" #include "LzmaDec.h"
@ -113,12 +113,6 @@
StopCompilingDueBUG StopCompilingDueBUG
#endif #endif
static const Byte kLiteralNextStates[kNumStates * 2] =
{
0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
};
#define LZMA_DIC_MIN (1 << 12) #define LZMA_DIC_MIN (1 << 12)
/* First LZMA-symbol is always decoded. /* First LZMA-symbol is always decoded.
@ -175,6 +169,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
if (state < kNumLitStates) if (state < kNumLitStates)
{ {
state -= (state < 4) ? state : 3;
symbol = 1; symbol = 1;
do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
} }
@ -182,6 +177,7 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
{ {
unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
unsigned offs = 0x100; unsigned offs = 0x100;
state -= (state < 10) ? 3 : 6;
symbol = 1; symbol = 1;
do do
{ {
@ -196,9 +192,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
} }
dic[dicPos++] = (Byte)symbol; dic[dicPos++] = (Byte)symbol;
processedPos++; processedPos++;
state = kLiteralNextStates[state];
/* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
continue; continue;
} }
else else
@ -266,14 +259,14 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
prob = probs + RepLenCoder; prob = probs + RepLenCoder;
} }
{ {
unsigned limit2, offset; unsigned limit, offset;
CLzmaProb *probLen = prob + LenChoice; CLzmaProb *probLen = prob + LenChoice;
IF_BIT_0(probLen) IF_BIT_0(probLen)
{ {
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenLow + (posState << kLenNumLowBits); probLen = prob + LenLow + (posState << kLenNumLowBits);
offset = 0; offset = 0;
limit2 = (1 << kLenNumLowBits); limit = (1 << kLenNumLowBits);
} }
else else
{ {
@ -284,17 +277,17 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
UPDATE_0(probLen); UPDATE_0(probLen);
probLen = prob + LenMid + (posState << kLenNumMidBits); probLen = prob + LenMid + (posState << kLenNumMidBits);
offset = kLenNumLowSymbols; offset = kLenNumLowSymbols;
limit2 = (1 << kLenNumMidBits); limit = (1 << kLenNumMidBits);
} }
else else
{ {
UPDATE_1(probLen); UPDATE_1(probLen);
probLen = prob + LenHigh; probLen = prob + LenHigh;
offset = kLenNumLowSymbols + kLenNumMidSymbols; offset = kLenNumLowSymbols + kLenNumMidSymbols;
limit2 = (1 << kLenNumHighBits); limit = (1 << kLenNumHighBits);
} }
} }
TREE_DECODE(probLen, limit2, len); TREE_DECODE(probLen, limit, len);
len += offset; len += offset;
} }
@ -378,7 +371,6 @@ static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte
else if (distance >= checkDicSize) else if (distance >= checkDicSize)
return SZ_ERROR_DATA; return SZ_ERROR_DATA;
state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
/* state = kLiteralNextStates[state]; */
} }
len += kMatchMinLen; len += kMatchMinLen;
@ -846,7 +838,6 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
} }
#if NEVER_CALLED
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
{ {
SizeT outSize = *destLen; SizeT outSize = *destLen;
@ -886,7 +877,6 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *sr
return SZ_OK; return SZ_OK;
} }
} }
#endif
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
{ {

View File

@ -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

View File

@ -1,15 +1,27 @@
/* Types.h -- Basic types /* Types.h -- Basic types
2008-11-23 : Igor Pavlov : Public domain */ 2010-10-09 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H #ifndef __7Z_TYPES_H
#define __7Z_TYPES_H #define __7Z_TYPES_H
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus #ifdef _WIN32
extern "C" { #include <windows.h>
#endif #endif
#ifndef EXTERN_C_BEGIN
#ifdef __cplusplus
#define EXTERN_C_BEGIN extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif
#endif
EXTERN_C_BEGIN
#define SZ_OK 0 #define SZ_OK 0
#define SZ_ERROR_DATA 1 #define SZ_ERROR_DATA 1
@ -30,6 +42,12 @@
typedef int SRes; typedef int SRes;
#ifdef _WIN32
typedef DWORD WRes;
#else
typedef int WRes;
#endif
#ifndef RINOK #ifndef RINOK
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } #define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
#endif #endif
@ -59,9 +77,11 @@ typedef unsigned long UInt64;
#if defined(_MSC_VER) || defined(__BORLANDC__) #if defined(_MSC_VER) || defined(__BORLANDC__)
typedef __int64 Int64; typedef __int64 Int64;
typedef unsigned __int64 UInt64; typedef unsigned __int64 UInt64;
#define UINT64_CONST(n) n
#else #else
typedef long long int Int64; typedef long long int Int64;
typedef unsigned long long int UInt64; typedef unsigned long long int UInt64;
#define UINT64_CONST(n) n ## ULL
#endif #endif
#endif #endif
@ -77,6 +97,12 @@ typedef int Bool;
#define False 0 #define False 0
#ifdef _WIN32
#define MY_STD_CALL __stdcall
#else
#define MY_STD_CALL
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#if _MSC_VER >= 1300 #if _MSC_VER >= 1300
@ -86,13 +112,11 @@ typedef int Bool;
#endif #endif
#define MY_CDECL __cdecl #define MY_CDECL __cdecl
#define MY_STD_CALL __stdcall #define MY_FAST_CALL __fastcall
#define MY_FAST_CALL MY_NO_INLINE __fastcall
#else #else
#define MY_CDECL #define MY_CDECL
#define MY_STD_CALL
#define MY_FAST_CALL #define MY_FAST_CALL
#endif #endif
@ -100,6 +124,16 @@ typedef int Bool;
/* The following interfaces use first parameter as pointer to structure */ /* The following interfaces use first parameter as pointer to structure */
typedef struct
{
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
} IByteIn;
typedef struct
{
void (*Write)(void *p, Byte b);
} IByteOut;
typedef struct typedef struct
{ {
SRes (*Read)(void *p, void *buf, size_t *size); SRes (*Read)(void *p, void *buf, size_t *size);
@ -134,7 +168,7 @@ typedef struct
typedef struct typedef struct
{ {
SRes (*Look)(void *p, void **buf, size_t *size); SRes (*Look)(void *p, const void **buf, size_t *size);
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
(output(*size) > input(*size)) is not allowed (output(*size) > input(*size)) is not allowed
(output(*size) < input(*size)) is allowed */ (output(*size) < input(*size)) is allowed */
@ -199,8 +233,22 @@ 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 #ifdef _WIN32
}
#endif #define CHAR_PATH_SEPARATOR '\\'
#define WCHAR_PATH_SEPARATOR L'\\'
#define STRING_PATH_SEPARATOR "\\"
#define WSTRING_PATH_SEPARATOR L"\\"
#else
#define CHAR_PATH_SEPARATOR '/'
#define WCHAR_PATH_SEPARATOR L'/'
#define STRING_PATH_SEPARATOR "/"
#define WSTRING_PATH_SEPARATOR L"/"
#endif
EXTERN_C_END
#endif #endif

View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "File_Extractor", "File_Extractor2010.vcxproj", "{7AEC599C-7C82-4F00-AA60-411E0A359CB0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7AEC599C-7C82-4F00-AA60-411E0A359CB0}.Debug|Win32.ActiveCfg = Debug|Win32
{7AEC599C-7C82-4F00-AA60-411E0A359CB0}.Debug|Win32.Build.0 = Debug|Win32
{7AEC599C-7C82-4F00-AA60-411E0A359CB0}.Release|Win32.ActiveCfg = Release|Win32
{7AEC599C-7C82-4F00-AA60-411E0A359CB0}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

BIN
fex/File_Extractor2010.suo Normal file

Binary file not shown.

View File

@ -79,6 +79,7 @@
<ClCompile Include="7z_C\7zAlloc.c" /> <ClCompile Include="7z_C\7zAlloc.c" />
<ClCompile Include="7z_C\7zBuf.c" /> <ClCompile Include="7z_C\7zBuf.c" />
<ClCompile Include="7z_C\7zCrc.c" /> <ClCompile Include="7z_C\7zCrc.c" />
<ClCompile Include="7z_C\7zCrcOpt.c" />
<ClCompile Include="7z_C\7zDecode.c" /> <ClCompile Include="7z_C\7zDecode.c" />
<ClCompile Include="7z_C\7zExtract.c" /> <ClCompile Include="7z_C\7zExtract.c" />
<ClCompile Include="7z_C\7zHeader.c" /> <ClCompile Include="7z_C\7zHeader.c" />
@ -86,7 +87,10 @@
<ClCompile Include="7z_C\7zItem.c" /> <ClCompile Include="7z_C\7zItem.c" />
<ClCompile Include="7z_C\7zStream.c" /> <ClCompile Include="7z_C\7zStream.c" />
<ClCompile Include="7z_C\Bcj2.c" /> <ClCompile Include="7z_C\Bcj2.c" />
<ClCompile Include="7z_C\Bra.c" />
<ClCompile Include="7z_C\Bra86.c" /> <ClCompile Include="7z_C\Bra86.c" />
<ClCompile Include="7z_C\CpuArch.c" />
<ClCompile Include="7z_C\Lzma2Dec.c" />
<ClCompile Include="7z_C\LzmaDec.c" /> <ClCompile Include="7z_C\LzmaDec.c" />
<ClCompile Include="fex\Binary_Extractor.cpp" /> <ClCompile Include="fex\Binary_Extractor.cpp" />
<ClCompile Include="fex\blargg_common.cpp" /> <ClCompile Include="fex\blargg_common.cpp" />
@ -105,7 +109,6 @@
<ClInclude Include="7z_C\7zAlloc.h" /> <ClInclude Include="7z_C\7zAlloc.h" />
<ClInclude Include="7z_C\7zBuf.h" /> <ClInclude Include="7z_C\7zBuf.h" />
<ClInclude Include="7z_C\7zCrc.h" /> <ClInclude Include="7z_C\7zCrc.h" />
<ClInclude Include="7z_C\7zDecode.h" />
<ClInclude Include="7z_C\7zExtract.h" /> <ClInclude Include="7z_C\7zExtract.h" />
<ClInclude Include="7z_C\7zHeader.h" /> <ClInclude Include="7z_C\7zHeader.h" />
<ClInclude Include="7z_C\7zIn.h" /> <ClInclude Include="7z_C\7zIn.h" />
@ -113,6 +116,7 @@
<ClInclude Include="7z_C\Bcj2.h" /> <ClInclude Include="7z_C\Bcj2.h" />
<ClInclude Include="7z_C\Bra.h" /> <ClInclude Include="7z_C\Bra.h" />
<ClInclude Include="7z_C\CpuArch.h" /> <ClInclude Include="7z_C\CpuArch.h" />
<ClInclude Include="7z_C\Lzma2Dec.h" />
<ClInclude Include="7z_C\LzmaDec.h" /> <ClInclude Include="7z_C\LzmaDec.h" />
<ClInclude Include="7z_C\Types.h" /> <ClInclude Include="7z_C\Types.h" />
<ClInclude Include="fex\Binary_Extractor.h" /> <ClInclude Include="fex\Binary_Extractor.h" />
@ -134,7 +138,6 @@
<ItemGroup> <ItemGroup>
<None Include="7z_C\7zC.txt" /> <None Include="7z_C\7zC.txt" />
<None Include="7z_C\lzma.txt" /> <None Include="7z_C\lzma.txt" />
<None Include="7z_C\readme.txt" />
<None Include="changes.txt" /> <None Include="changes.txt" />
<None Include="fex.txt" /> <None Include="fex.txt" />
<None Include="internals.txt" /> <None Include="internals.txt" />

View File

@ -9,42 +9,6 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="7z_C\7zAlloc.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zBuf.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zCrc.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zDecode.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zExtract.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zHeader.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zIn.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zItem.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zStream.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Bcj2.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Bra86.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\LzmaDec.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="fex\Binary_Extractor.cpp"> <ClCompile Include="fex\Binary_Extractor.cpp">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClCompile> </ClCompile>
@ -72,56 +36,65 @@
<ClCompile Include="fex\Rar_Extractor.cpp"> <ClCompile Include="fex\Rar_Extractor.cpp">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="fex\Zip7_Extractor.cpp"> <ClCompile Include="fex\Zip_Extractor.cpp">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="fex\Zip_Extractor.cpp"> <ClCompile Include="fex\Zip7_Extractor.cpp">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="fex\Zlib_Inflater.cpp"> <ClCompile Include="fex\Zlib_Inflater.cpp">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="7z_C\7zAlloc.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zBuf.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zCrc.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zExtract.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zHeader.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zIn.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zItem.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zStream.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Bcj2.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Bra86.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\LzmaDec.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\CpuArch.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zCrcOpt.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Lzma2Dec.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\Bra.c">
<Filter>7z</Filter>
</ClCompile>
<ClCompile Include="7z_C\7zDecode.c">
<Filter>7z</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="7z_C\7zAlloc.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zBuf.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zCrc.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zDecode.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zExtract.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zHeader.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zIn.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zItem.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Bcj2.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Bra.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\CpuArch.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\LzmaDec.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Types.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="fex\Binary_Extractor.h"> <ClInclude Include="fex\Binary_Extractor.h">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClInclude> </ClInclude>
@ -158,30 +131,66 @@
<ClInclude Include="fex\Rar_Extractor.h"> <ClInclude Include="fex\Rar_Extractor.h">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="fex\Zip7_Extractor.h"> <ClInclude Include="fex\Zip_Extractor.h">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="fex\Zip_Extractor.h"> <ClInclude Include="fex\Zip7_Extractor.h">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="fex\Zlib_Inflater.h"> <ClInclude Include="fex\Zlib_Inflater.h">
<Filter>fex</Filter> <Filter>fex</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="7z_C\7zAlloc.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zBuf.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zCrc.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zExtract.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zHeader.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zIn.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\7zItem.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Bcj2.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Bra.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\CpuArch.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\LzmaDec.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Types.h">
<Filter>7z</Filter>
</ClInclude>
<ClInclude Include="7z_C\Lzma2Dec.h">
<Filter>7z</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="changes.txt" />
<None Include="fex.txt" />
<None Include="internals.txt" />
<None Include="license.txt" />
<None Include="readme.txt" />
<None Include="7z_C\7zC.txt"> <None Include="7z_C\7zC.txt">
<Filter>7z</Filter> <Filter>7z</Filter>
</None> </None>
<None Include="7z_C\lzma.txt"> <None Include="7z_C\lzma.txt">
<Filter>7z</Filter> <Filter>7z</Filter>
</None> </None>
<None Include="7z_C\readme.txt">
<Filter>7z</Filter>
</None>
<None Include="changes.txt" />
<None Include="fex.txt" />
<None Include="internals.txt" />
<None Include="license.txt" />
<None Include="readme.txt" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -230,12 +230,178 @@ blargg_err_t Callback_File_Reader::seek_v( int )
return blargg_ok; return blargg_ok;
} }
static const BOOST::uint8_t mask_tab[6]={0x80,0xE0,0xF0,0xF8,0xFC,0xFE};
// BLARGG_UTF8_PATHS static const BOOST::uint8_t val_tab[6]={0,0xC0,0xE0,0xF0,0xF8,0xFC};
#if BLARGG_UTF8_PATHS size_t utf8_char_len_from_header( char p_c )
{
BOOST::uint8_t c = (BOOST::uint8_t)p_c;
// Thanks to byuu for the idea for BLARGG_UTF8_PATHS and the implementations size_t cnt = 0;
for(;;)
{
if ( ( p_c & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= 6 ) return 0;
}
return cnt + 1;
}
size_t utf8_decode_char( const char *p_utf8, unsigned & wide, size_t mmax )
{
const BOOST::uint8_t * utf8 = ( const BOOST::uint8_t* )p_utf8;
if ( mmax == 0 )
{
wide = 0;
return 0;
}
if ( utf8[0] < 0x80 )
{
wide = utf8[0];
return utf8[0]>0 ? 1 : 0;
}
if ( mmax > 6 ) mmax = 6;
wide = 0;
unsigned res=0;
unsigned n;
unsigned cnt=0;
for(;;)
{
if ( ( *utf8 & mask_tab[cnt] ) == val_tab[cnt] ) break;
if ( ++cnt >= mmax ) return 0;
}
cnt++;
if ( cnt==2 && !( *utf8 & 0x1E ) ) return 0;
if ( cnt == 1 )
res = *utf8;
else
res = ( 0xFF >> ( cnt + 1 ) ) & *utf8;
for ( n = 1; n < cnt; n++ )
{
if ( ( utf8[n] & 0xC0 ) != 0x80 )
return 0;
if ( !res && n == 2 && !( ( utf8[n] & 0x7F ) >> ( 7 - cnt ) ) )
return 0;
res = ( res << 6 ) | ( utf8[n] & 0x3F );
}
wide = res;
return cnt;
}
size_t utf8_encode_char( unsigned wide, char * target )
{
size_t count;
if ( wide < 0x80 )
count = 1;
else if ( wide < 0x800 )
count = 2;
else if ( wide < 0x10000 )
count = 3;
else if ( wide < 0x200000 )
count = 4;
else if ( wide < 0x4000000 )
count = 5;
else if ( wide <= 0x7FFFFFFF )
count = 6;
else
return 0;
if ( target == 0 )
return count;
switch ( count )
{
case 6:
target[5] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x4000000;
case 5:
target[4] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x200000;
case 4:
target[3] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x10000;
case 3:
target[2] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0x800;
case 2:
target[1] = 0x80 | ( wide & 0x3F );
wide = wide >> 6;
wide |= 0xC0;
case 1:
target[0] = wide;
}
return count;
}
size_t utf16_encode_char( unsigned cur_wchar, wchar_t * out )
{
if ( cur_wchar < 0x10000 )
{
if ( out ) *out = (wchar_t) cur_wchar; return 1;
}
else if ( cur_wchar < ( 1 << 20 ) )
{
unsigned c = cur_wchar - 0x10000;
//MSDN:
//The first (high) surrogate is a 16-bit code value in the range U+D800 to U+DBFF. The second (low) surrogate is a 16-bit code value in the range U+DC00 to U+DFFF. Using surrogates, Unicode can support over one million characters. For more details about surrogates, refer to The Unicode Standard, version 2.0.
if ( out )
{
out[0] = ( wchar_t )( 0xD800 | ( 0x3FF & ( c >> 10 ) ) );
out[1] = ( wchar_t )( 0xDC00 | ( 0x3FF & c ) ) ;
}
return 2;
}
else
{
if ( out ) *out = '?'; return 1;
}
}
size_t utf16_decode_char( const wchar_t * p_source, unsigned * p_out, size_t p_source_length )
{
if ( p_source_length == 0 ) return 0;
else if ( p_source_length == 1 )
{
*p_out = p_source[0];
return 1;
}
else
{
size_t retval = 0;
unsigned decoded = p_source[0];
if ( decoded != 0 )
{
retval = 1;
if ( ( decoded & 0xFC00 ) == 0xD800 )
{
unsigned low = p_source[1];
if ( ( low & 0xFC00 ) == 0xDC00 )
{
decoded = 0x10000 + ( ( ( decoded & 0x3FF ) << 10 ) | ( low & 0x3FF ) );
retval = 2;
}
}
}
*p_out = decoded;
return retval;
}
}
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows. // Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
char* blargg_to_utf8( const wchar_t* wpath ) char* blargg_to_utf8( const wchar_t* wpath )
@ -243,15 +409,38 @@ char* blargg_to_utf8( const wchar_t* wpath )
if ( wpath == NULL ) if ( wpath == NULL )
return NULL; return NULL;
int needed = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, NULL, 0, NULL, NULL ); size_t needed = 0;
size_t mmax = wcslen( wpath );
if ( mmax <= 0 )
return NULL;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf8_encode_char( wide, 0 );
}
if ( needed <= 0 ) if ( needed <= 0 )
return NULL; return NULL;
char* path = (char*) malloc( needed ); char* path = (char*) calloc( needed + 1, 1 );
if ( path == NULL ) if ( path == NULL )
return NULL; return NULL;
int actual = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, path, needed, NULL, NULL ); ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf16_decode_char( wpath + ptr, &wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf8_encode_char( wide, path + actual );
}
if ( actual == 0 ) if ( actual == 0 )
{ {
free( path ); free( path );
@ -268,15 +457,37 @@ wchar_t* blargg_to_wide( const char* path )
if ( path == NULL ) if ( path == NULL )
return NULL; return NULL;
int needed = MultiByteToWideChar( CP_UTF8, 0, path, -1, NULL, 0 ); size_t mmax = strlen( path );
if ( mmax <= 0 )
return NULL;
size_t needed = 0;
size_t ptr = 0;
while ( ptr < mmax )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
needed += utf16_encode_char( wide, 0 );
}
if ( needed <= 0 ) if ( needed <= 0 )
return NULL; return NULL;
wchar_t* wpath = (wchar_t*) malloc( needed * sizeof *wpath ); wchar_t* wpath = (wchar_t*) calloc( needed + 1, sizeof *wpath );
if ( wpath == NULL ) if ( wpath == NULL )
return NULL; return NULL;
int actual = MultiByteToWideChar( CP_UTF8, 0, path, -1, wpath, needed ); ptr = 0;
size_t actual = 0;
while ( ptr < mmax && actual < needed )
{
unsigned wide = 0;
size_t char_len = utf8_decode_char( path + ptr, wide, mmax - ptr );
if ( !char_len ) break;
ptr += char_len;
actual += utf16_encode_char( wide, wpath + actual );
}
if ( actual == 0 ) if ( actual == 0 )
{ {
free( wpath ); free( wpath );
@ -287,6 +498,8 @@ wchar_t* blargg_to_wide( const char* path )
return wpath; return wpath;
} }
#ifdef _WIN32
static FILE* blargg_fopen( const char path [], const char mode [] ) static FILE* blargg_fopen( const char path [], const char mode [] )
{ {
FILE* file = NULL; FILE* file = NULL;

View File

@ -2,9 +2,13 @@
#include "Zip7_Extractor.h" #include "Zip7_Extractor.h"
#include "7z_C/7zExtract.h" extern "C" {
#include "7z_C/7z.h"
#include "7z_C/7zAlloc.h" #include "7z_C/7zAlloc.h"
#include "7z_C/7zCrc.h" #include "7z_C/7zCrc.h"
}
#include <time.h>
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you /* Copyright (C) 2005-2009 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser can redistribute it and/or modify it under the terms of the GNU Lesser
@ -66,7 +70,7 @@ extern "C"
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
assert( mode != SZ_SEEK_CUR ); // never used // assert( mode != SZ_SEEK_CUR ); // never used
if ( mode == SZ_SEEK_END ) if ( mode == SZ_SEEK_END )
{ {
@ -75,7 +79,7 @@ extern "C"
return SZ_OK; return SZ_OK;
} }
assert( mode == SZ_SEEK_SET ); // assert( mode == SZ_SEEK_SET );
blargg_err_t err = impl->in->seek( *pos ); blargg_err_t err = impl->in->seek( *pos );
if ( err ) if ( err )
{ {
@ -204,14 +208,39 @@ blargg_err_t Zip7_Extractor::next_v()
CSzFileItem const& item = impl->db.db.Files [index]; CSzFileItem const& item = impl->db.db.Files [index];
if ( !item.IsDir ) if ( !item.IsDir )
{ {
// TODO: Support date. unsigned long date = 0;
// NTFS representation, stored as 64-bit value. if ( item.MTimeDefined )
// Divide by 10000000 (ten million) to get seconds {
//item.MTime.Low + (.High << 32) const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
// How to convert to DOS style? /* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
struct tm tm;
set_name( item.Name ); UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
set_info( item.Size, 0, (item.FileCRCDefined ? item.FileCRC : 0) ); time /= 1000000;
time_t _time = time;
localtime_s( &tm, &_time );
date = ( tm.tm_sec >> 1 ) & 0x1F |
(( tm.tm_min & 0x3F ) << 5 ) |
(( tm.tm_hour & 0x1F ) << 11 ) |
(( tm.tm_mday & 0x1F ) << 16 ) |
(( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) |
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
}
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
name16.resize( name_length );
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
char * temp = blargg_to_utf8( name16.begin() );
if ( !temp ) temp = "";
size_t utf8_length = strlen( temp );
name8.resize( utf8_length + 1 );
memcpy( name8.begin(), temp, utf8_length + 1 );
free( temp );
set_name( name8.begin(), name16.begin() );
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
break; break;
} }
} }
@ -242,7 +271,7 @@ blargg_err_t Zip7_Extractor::data_v( void const** out )
impl->in_err = NULL; impl->in_err = NULL;
size_t offset = 0; size_t offset = 0;
size_t count = 0; size_t count = 0;
RETURN_ERR( zip7_err( SzAr_Extract( &impl->db, &impl->look.s, index, RETURN_ERR( zip7_err( SzArEx_Extract( &impl->db, &impl->look.s, index,
&impl->block_index, &impl->buf, &impl->buf_size, &impl->block_index, &impl->buf, &impl->buf_size,
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) ); &offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
assert( count == (size_t) size() ); assert( count == (size_t) size() );

View File

@ -27,6 +27,8 @@ protected:
private: private:
Zip7_Extractor_Impl* impl; Zip7_Extractor_Impl* impl;
int index; int index;
blargg_vector<char> name8;
blargg_vector<wchar_t> name16;
blargg_err_t zip7_err( int err ); blargg_err_t zip7_err( int err );
}; };

View File

@ -192,11 +192,6 @@ struct blargg_callback
void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; } void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
}; };
#ifndef _WIN32
// Not supported on any other platforms
#undef BLARGG_UTF8_PATHS
#endif
BLARGG_DEPRECATED( typedef signed int blargg_long; ) BLARGG_DEPRECATED( typedef signed int blargg_long; )
BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; ) BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
#if BLARGG_LEGACY #if BLARGG_LEGACY

View File

@ -235,7 +235,6 @@ BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
//// Wide paths //// Wide paths
#if BLARGG_UTF8_PATHS
char* fex_wide_to_path( const wchar_t* wide ) char* fex_wide_to_path( const wchar_t* wide )
{ {
return blargg_to_utf8( wide ); return blargg_to_utf8( wide );
@ -245,7 +244,6 @@ void fex_free_path( char* path )
{ {
free( path ); free( path );
} }
#endif
//// Errors //// Errors

View File

@ -40,14 +40,12 @@ returns "", since it can open any file. */
const char* fex_type_extension( fex_type_t ); const char* fex_type_extension( fex_type_t );
/**** Wide-character file paths (Windows only) ****/ /**** Wide-character file paths ****/
/** Converts wide-character path to form suitable for use with fex functions. /** Converts wide-character path to form suitable for use with fex functions. */
Only supported when BLARGG_UTF8_PATHS is defined and building on Windows. */
char* fex_wide_to_path( const wchar_t* wide ); char* fex_wide_to_path( const wchar_t* wide );
/** Frees converted path. OK to pass NULL. Only supported when BLARGG_UTF8_PATHS /** Frees converted path. OK to pass NULL. */
is defined and building on Windows */
void fex_free_path( char* ); void fex_free_path( char* );