ALL: Apply standard SVN properties to recently added files. Motly to avoid file with mixed line ending.
git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@1049 a31d4220-a93d-0410-bf67-fe4944624d44
This commit is contained in:
parent
1f861b2ad4
commit
03f20b8cbf
406
fex/7z_C/7z.h
406
fex/7z_C/7z.h
|
@ -1,203 +1,203 @@
|
||||||
/* 7z.h -- 7z interface
|
/* 7z.h -- 7z interface
|
||||||
2010-03-11 : Igor Pavlov : Public domain */
|
2010-03-11 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_H
|
#ifndef __7Z_H
|
||||||
#define __7Z_H
|
#define __7Z_H
|
||||||
|
|
||||||
#include "7zBuf.h"
|
#include "7zBuf.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
#define k7zStartHeaderSize 0x20
|
#define k7zStartHeaderSize 0x20
|
||||||
#define k7zSignatureSize 6
|
#define k7zSignatureSize 6
|
||||||
extern Byte k7zSignature[k7zSignatureSize];
|
extern Byte k7zSignature[k7zSignatureSize];
|
||||||
#define k7zMajorVersion 0
|
#define k7zMajorVersion 0
|
||||||
|
|
||||||
enum EIdEnum
|
enum EIdEnum
|
||||||
{
|
{
|
||||||
k7zIdEnd,
|
k7zIdEnd,
|
||||||
k7zIdHeader,
|
k7zIdHeader,
|
||||||
k7zIdArchiveProperties,
|
k7zIdArchiveProperties,
|
||||||
k7zIdAdditionalStreamsInfo,
|
k7zIdAdditionalStreamsInfo,
|
||||||
k7zIdMainStreamsInfo,
|
k7zIdMainStreamsInfo,
|
||||||
k7zIdFilesInfo,
|
k7zIdFilesInfo,
|
||||||
k7zIdPackInfo,
|
k7zIdPackInfo,
|
||||||
k7zIdUnpackInfo,
|
k7zIdUnpackInfo,
|
||||||
k7zIdSubStreamsInfo,
|
k7zIdSubStreamsInfo,
|
||||||
k7zIdSize,
|
k7zIdSize,
|
||||||
k7zIdCRC,
|
k7zIdCRC,
|
||||||
k7zIdFolder,
|
k7zIdFolder,
|
||||||
k7zIdCodersUnpackSize,
|
k7zIdCodersUnpackSize,
|
||||||
k7zIdNumUnpackStream,
|
k7zIdNumUnpackStream,
|
||||||
k7zIdEmptyStream,
|
k7zIdEmptyStream,
|
||||||
k7zIdEmptyFile,
|
k7zIdEmptyFile,
|
||||||
k7zIdAnti,
|
k7zIdAnti,
|
||||||
k7zIdName,
|
k7zIdName,
|
||||||
k7zIdCTime,
|
k7zIdCTime,
|
||||||
k7zIdATime,
|
k7zIdATime,
|
||||||
k7zIdMTime,
|
k7zIdMTime,
|
||||||
k7zIdWinAttributes,
|
k7zIdWinAttributes,
|
||||||
k7zIdComment,
|
k7zIdComment,
|
||||||
k7zIdEncodedHeader,
|
k7zIdEncodedHeader,
|
||||||
k7zIdStartPos,
|
k7zIdStartPos,
|
||||||
k7zIdDummy
|
k7zIdDummy
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 NumInStreams;
|
UInt32 NumInStreams;
|
||||||
UInt32 NumOutStreams;
|
UInt32 NumOutStreams;
|
||||||
UInt64 MethodID;
|
UInt64 MethodID;
|
||||||
CBuf Props;
|
CBuf Props;
|
||||||
} CSzCoderInfo;
|
} CSzCoderInfo;
|
||||||
|
|
||||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 InIndex;
|
UInt32 InIndex;
|
||||||
UInt32 OutIndex;
|
UInt32 OutIndex;
|
||||||
} CSzBindPair;
|
} CSzBindPair;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CSzCoderInfo *Coders;
|
CSzCoderInfo *Coders;
|
||||||
CSzBindPair *BindPairs;
|
CSzBindPair *BindPairs;
|
||||||
UInt32 *PackStreams;
|
UInt32 *PackStreams;
|
||||||
UInt64 *UnpackSizes;
|
UInt64 *UnpackSizes;
|
||||||
UInt32 NumCoders;
|
UInt32 NumCoders;
|
||||||
UInt32 NumBindPairs;
|
UInt32 NumBindPairs;
|
||||||
UInt32 NumPackStreams;
|
UInt32 NumPackStreams;
|
||||||
int UnpackCRCDefined;
|
int UnpackCRCDefined;
|
||||||
UInt32 UnpackCRC;
|
UInt32 UnpackCRC;
|
||||||
|
|
||||||
UInt32 NumUnpackStreams;
|
UInt32 NumUnpackStreams;
|
||||||
} CSzFolder;
|
} CSzFolder;
|
||||||
|
|
||||||
void SzFolder_Init(CSzFolder *p);
|
void SzFolder_Init(CSzFolder *p);
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
||||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||||
|
|
||||||
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
||||||
ILookInStream *stream, UInt64 startPos,
|
ILookInStream *stream, UInt64 startPos,
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 Low;
|
UInt32 Low;
|
||||||
UInt32 High;
|
UInt32 High;
|
||||||
} CNtfsFileTime;
|
} CNtfsFileTime;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CNtfsFileTime MTime;
|
CNtfsFileTime MTime;
|
||||||
UInt64 Size;
|
UInt64 Size;
|
||||||
UInt32 Crc;
|
UInt32 Crc;
|
||||||
UInt32 Attrib;
|
UInt32 Attrib;
|
||||||
Byte HasStream;
|
Byte HasStream;
|
||||||
Byte IsDir;
|
Byte IsDir;
|
||||||
Byte IsAnti;
|
Byte IsAnti;
|
||||||
Byte CrcDefined;
|
Byte CrcDefined;
|
||||||
Byte MTimeDefined;
|
Byte MTimeDefined;
|
||||||
Byte AttribDefined;
|
Byte AttribDefined;
|
||||||
} CSzFileItem;
|
} CSzFileItem;
|
||||||
|
|
||||||
void SzFile_Init(CSzFileItem *p);
|
void SzFile_Init(CSzFileItem *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt64 *PackSizes;
|
UInt64 *PackSizes;
|
||||||
Byte *PackCRCsDefined;
|
Byte *PackCRCsDefined;
|
||||||
UInt32 *PackCRCs;
|
UInt32 *PackCRCs;
|
||||||
CSzFolder *Folders;
|
CSzFolder *Folders;
|
||||||
CSzFileItem *Files;
|
CSzFileItem *Files;
|
||||||
UInt32 NumPackStreams;
|
UInt32 NumPackStreams;
|
||||||
UInt32 NumFolders;
|
UInt32 NumFolders;
|
||||||
UInt32 NumFiles;
|
UInt32 NumFiles;
|
||||||
} CSzAr;
|
} CSzAr;
|
||||||
|
|
||||||
void SzAr_Init(CSzAr *p);
|
void SzAr_Init(CSzAr *p);
|
||||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzExtract extracts file from archive
|
SzExtract extracts file from archive
|
||||||
|
|
||||||
*outBuffer must be 0 before first call for each new archive.
|
*outBuffer must be 0 before first call for each new archive.
|
||||||
|
|
||||||
Extracting cache:
|
Extracting cache:
|
||||||
If you need to decompress more than one file, you can send
|
If you need to decompress more than one file, you can send
|
||||||
these values from previous call:
|
these values from previous call:
|
||||||
*blockIndex,
|
*blockIndex,
|
||||||
*outBuffer,
|
*outBuffer,
|
||||||
*outBufferSize
|
*outBufferSize
|
||||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||||
it will increase decompression speed.
|
it will increase decompression speed.
|
||||||
|
|
||||||
If you use external function, you can declare these 3 cache variables
|
If you use external function, you can declare these 3 cache variables
|
||||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||||
|
|
||||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CSzAr db;
|
CSzAr db;
|
||||||
|
|
||||||
UInt64 startPosAfterHeader;
|
UInt64 startPosAfterHeader;
|
||||||
UInt64 dataPos;
|
UInt64 dataPos;
|
||||||
|
|
||||||
UInt32 *FolderStartPackStreamIndex;
|
UInt32 *FolderStartPackStreamIndex;
|
||||||
UInt64 *PackStreamStartPositions;
|
UInt64 *PackStreamStartPositions;
|
||||||
UInt32 *FolderStartFileIndex;
|
UInt32 *FolderStartFileIndex;
|
||||||
UInt32 *FileIndexToFolderIndexMap;
|
UInt32 *FileIndexToFolderIndexMap;
|
||||||
|
|
||||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||||
CBuf FileNames; /* UTF-16-LE */
|
CBuf FileNames; /* UTF-16-LE */
|
||||||
} CSzArEx;
|
} CSzArEx;
|
||||||
|
|
||||||
void SzArEx_Init(CSzArEx *p);
|
void SzArEx_Init(CSzArEx *p);
|
||||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if dest == NULL, the return value specifies the required size of the buffer,
|
if dest == NULL, the return value specifies the required size of the buffer,
|
||||||
in 16-bit characters, including the null-terminating character.
|
in 16-bit characters, including the null-terminating character.
|
||||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||||
are written to the dest, including the null-terminating character. */
|
are written to the dest, including the null-terminating character. */
|
||||||
|
|
||||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||||
|
|
||||||
SRes SzArEx_Extract(
|
SRes SzArEx_Extract(
|
||||||
const CSzArEx *db,
|
const CSzArEx *db,
|
||||||
ILookInStream *inStream,
|
ILookInStream *inStream,
|
||||||
UInt32 fileIndex, /* index of file */
|
UInt32 fileIndex, /* index of file */
|
||||||
UInt32 *blockIndex, /* index of solid block */
|
UInt32 *blockIndex, /* index of solid block */
|
||||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||||
size_t *outBufferSize, /* buffer size for output buffer */
|
size_t *outBufferSize, /* buffer size for output buffer */
|
||||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||||
ISzAlloc *allocMain,
|
ISzAlloc *allocMain,
|
||||||
ISzAlloc *allocTemp);
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzArEx_Open Errors:
|
SzArEx_Open Errors:
|
||||||
SZ_ERROR_NO_ARCHIVE
|
SZ_ERROR_NO_ARCHIVE
|
||||||
SZ_ERROR_ARCHIVE
|
SZ_ERROR_ARCHIVE
|
||||||
SZ_ERROR_UNSUPPORTED
|
SZ_ERROR_UNSUPPORTED
|
||||||
SZ_ERROR_MEM
|
SZ_ERROR_MEM
|
||||||
SZ_ERROR_CRC
|
SZ_ERROR_CRC
|
||||||
SZ_ERROR_INPUT_EOF
|
SZ_ERROR_INPUT_EOF
|
||||||
SZ_ERROR_FAIL
|
SZ_ERROR_FAIL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,76 +1,76 @@
|
||||||
/* 7zAlloc.c -- Allocation functions
|
/* 7zAlloc.c -- Allocation functions
|
||||||
2010-10-29 : Igor Pavlov : Public domain */
|
2010-10-29 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "7zAlloc.h"
|
#include "7zAlloc.h"
|
||||||
|
|
||||||
/* #define _SZ_ALLOC_DEBUG */
|
/* #define _SZ_ALLOC_DEBUG */
|
||||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||||
|
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
int g_allocCount = 0;
|
int g_allocCount = 0;
|
||||||
int g_allocCountTemp = 0;
|
int g_allocCountTemp = 0;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void *SzAlloc(void *p, size_t size)
|
void *SzAlloc(void *p, size_t size)
|
||||||
{
|
{
|
||||||
p = p;
|
p = p;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
||||||
g_allocCount++;
|
g_allocCount++;
|
||||||
#endif
|
#endif
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFree(void *p, void *address)
|
void SzFree(void *p, void *address)
|
||||||
{
|
{
|
||||||
p = p;
|
p = p;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
if (address != 0)
|
if (address != 0)
|
||||||
{
|
{
|
||||||
g_allocCount--;
|
g_allocCount--;
|
||||||
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *SzAllocTemp(void *p, size_t size)
|
void *SzAllocTemp(void *p, size_t size)
|
||||||
{
|
{
|
||||||
p = p;
|
p = p;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
||||||
g_allocCountTemp++;
|
g_allocCountTemp++;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFreeTemp(void *p, void *address)
|
void SzFreeTemp(void *p, void *address)
|
||||||
{
|
{
|
||||||
p = p;
|
p = p;
|
||||||
#ifdef _SZ_ALLOC_DEBUG
|
#ifdef _SZ_ALLOC_DEBUG
|
||||||
if (address != 0)
|
if (address != 0)
|
||||||
{
|
{
|
||||||
g_allocCountTemp--;
|
g_allocCountTemp--;
|
||||||
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
HeapFree(GetProcessHeap(), 0, address);
|
HeapFree(GetProcessHeap(), 0, address);
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
free(address);
|
free(address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
/* 7zAlloc.h -- Allocation functions
|
/* 7zAlloc.h -- Allocation functions
|
||||||
2010-10-29 : 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 <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void *SzAlloc(void *p, size_t size);
|
void *SzAlloc(void *p, size_t size);
|
||||||
void SzFree(void *p, void *address);
|
void SzFree(void *p, void *address);
|
||||||
|
|
||||||
void *SzAllocTemp(void *p, size_t size);
|
void *SzAllocTemp(void *p, size_t size);
|
||||||
void SzFreeTemp(void *p, void *address);
|
void SzFreeTemp(void *p, void *address);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,36 +1,36 @@
|
||||||
/* 7zBuf.c -- Byte Buffer
|
/* 7zBuf.c -- Byte Buffer
|
||||||
2008-03-28
|
2008-03-28
|
||||||
Igor Pavlov
|
Igor Pavlov
|
||||||
Public domain */
|
Public domain */
|
||||||
|
|
||||||
#include "7zBuf.h"
|
#include "7zBuf.h"
|
||||||
|
|
||||||
void Buf_Init(CBuf *p)
|
void Buf_Init(CBuf *p)
|
||||||
{
|
{
|
||||||
p->data = 0;
|
p->data = 0;
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
p->data = 0;
|
p->data = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
p->data = (Byte *)alloc->Alloc(alloc, size);
|
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||||
if (p->data != 0)
|
if (p->data != 0)
|
||||||
{
|
{
|
||||||
p->size = size;
|
p->size = size;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
alloc->Free(alloc, p->data);
|
alloc->Free(alloc, p->data);
|
||||||
p->data = 0;
|
p->data = 0;
|
||||||
p->size = 0;
|
p->size = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,39 @@
|
||||||
/* 7zBuf.h -- Byte Buffer
|
/* 7zBuf.h -- Byte Buffer
|
||||||
2009-02-07 : 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte *data;
|
Byte *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
} CBuf;
|
} CBuf;
|
||||||
|
|
||||||
void Buf_Init(CBuf *p);
|
void Buf_Init(CBuf *p);
|
||||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte *data;
|
Byte *data;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
} CDynBuf;
|
} CDynBuf;
|
||||||
|
|
||||||
void DynBuf_Construct(CDynBuf *p);
|
void DynBuf_Construct(CDynBuf *p);
|
||||||
void DynBuf_SeekToBeg(CDynBuf *p);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
388
fex/7z_C/7zC.txt
388
fex/7z_C/7zC.txt
|
@ -1,194 +1,194 @@
|
||||||
7z ANSI-C Decoder 4.62
|
7z ANSI-C Decoder 4.62
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
7z ANSI-C provides 7z/LZMA decoding.
|
7z ANSI-C provides 7z/LZMA decoding.
|
||||||
7z ANSI-C version is simplified version ported from C++ code.
|
7z ANSI-C version is simplified version ported from C++ code.
|
||||||
|
|
||||||
LZMA is default and general compression method of 7z format
|
LZMA is default and general compression method of 7z format
|
||||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
||||||
compression ratio and very fast decompression.
|
compression ratio and very fast decompression.
|
||||||
|
|
||||||
|
|
||||||
LICENSE
|
LICENSE
|
||||||
-------
|
-------
|
||||||
|
|
||||||
7z ANSI-C Decoder is part of the LZMA SDK.
|
7z ANSI-C Decoder is part of the LZMA SDK.
|
||||||
LZMA SDK is written and placed in the public domain by Igor Pavlov.
|
LZMA SDK is written and placed in the public domain by Igor Pavlov.
|
||||||
|
|
||||||
Files
|
Files
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
7zDecode.* - Low level 7z decoding
|
7zDecode.* - Low level 7z decoding
|
||||||
7zExtract.* - High level 7z decoding
|
7zExtract.* - High level 7z decoding
|
||||||
7zHeader.* - .7z format constants
|
7zHeader.* - .7z format constants
|
||||||
7zIn.* - .7z archive opening
|
7zIn.* - .7z archive opening
|
||||||
7zItem.* - .7z structures
|
7zItem.* - .7z structures
|
||||||
7zMain.c - Test application
|
7zMain.c - Test application
|
||||||
|
|
||||||
|
|
||||||
How To Use
|
How To Use
|
||||||
----------
|
----------
|
||||||
|
|
||||||
You must download 7-Zip program from www.7-zip.org.
|
You must download 7-Zip program from www.7-zip.org.
|
||||||
|
|
||||||
You can create .7z archive with 7z.exe or 7za.exe:
|
You can create .7z archive with 7z.exe or 7za.exe:
|
||||||
|
|
||||||
7za.exe a archive.7z *.htm -r -mx -m0fb=255
|
7za.exe a archive.7z *.htm -r -mx -m0fb=255
|
||||||
|
|
||||||
If you have big number of files in archive, and you need fast extracting,
|
If you have big number of files in archive, and you need fast extracting,
|
||||||
you can use partly-solid archives:
|
you can use partly-solid archives:
|
||||||
|
|
||||||
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
|
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
|
||||||
|
|
||||||
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
|
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
|
||||||
512KB for extracting one file from such archive.
|
512KB for extracting one file from such archive.
|
||||||
|
|
||||||
|
|
||||||
Limitations of current version of 7z ANSI-C Decoder
|
Limitations of current version of 7z ANSI-C Decoder
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
|
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
|
||||||
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
|
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
|
||||||
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
|
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
|
||||||
|
|
||||||
These limitations will be fixed in future versions.
|
These limitations will be fixed in future versions.
|
||||||
|
|
||||||
|
|
||||||
Using 7z ANSI-C Decoder Test application:
|
Using 7z ANSI-C Decoder Test application:
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
Usage: 7zDec <command> <archive_name>
|
Usage: 7zDec <command> <archive_name>
|
||||||
|
|
||||||
<Command>:
|
<Command>:
|
||||||
e: Extract files from archive
|
e: Extract files from archive
|
||||||
l: List contents of archive
|
l: List contents of archive
|
||||||
t: Test integrity of archive
|
t: Test integrity of archive
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
7zDec l archive.7z
|
7zDec l archive.7z
|
||||||
|
|
||||||
lists contents of archive.7z
|
lists contents of archive.7z
|
||||||
|
|
||||||
7zDec e archive.7z
|
7zDec e archive.7z
|
||||||
|
|
||||||
extracts files from archive.7z to current folder.
|
extracts files from archive.7z to current folder.
|
||||||
|
|
||||||
|
|
||||||
How to use .7z Decoder
|
How to use .7z Decoder
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Memory allocation
|
Memory allocation
|
||||||
~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
7z Decoder uses two memory pools:
|
7z Decoder uses two memory pools:
|
||||||
1) Temporary pool
|
1) Temporary pool
|
||||||
2) Main pool
|
2) Main pool
|
||||||
Such scheme can allow you to avoid fragmentation of allocated blocks.
|
Such scheme can allow you to avoid fragmentation of allocated blocks.
|
||||||
|
|
||||||
|
|
||||||
Steps for using 7z decoder
|
Steps for using 7z decoder
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
Use code at 7zMain.c as example.
|
Use code at 7zMain.c as example.
|
||||||
|
|
||||||
1) Declare variables:
|
1) Declare variables:
|
||||||
inStream /* implements ILookInStream interface */
|
inStream /* implements ILookInStream interface */
|
||||||
CSzArEx db; /* 7z archive database structure */
|
CSzArEx db; /* 7z archive database structure */
|
||||||
ISzAlloc allocImp; /* memory functions for main pool */
|
ISzAlloc allocImp; /* memory functions for main pool */
|
||||||
ISzAlloc allocTempImp; /* memory functions for temporary pool */
|
ISzAlloc allocTempImp; /* memory functions for temporary pool */
|
||||||
|
|
||||||
2) call CrcGenerateTable(); function to initialize CRC structures.
|
2) call CrcGenerateTable(); function to initialize CRC structures.
|
||||||
|
|
||||||
3) call SzArEx_Init(&db); function to initialize db structures.
|
3) call SzArEx_Init(&db); function to initialize db structures.
|
||||||
|
|
||||||
4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive
|
4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive
|
||||||
|
|
||||||
This function opens archive "inStream" and reads headers to "db".
|
This function opens archive "inStream" and reads headers to "db".
|
||||||
All items in "db" will be allocated with "allocMain" functions.
|
All items in "db" will be allocated with "allocMain" functions.
|
||||||
SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.
|
SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.
|
||||||
|
|
||||||
5) List items or Extract items
|
5) List items or Extract items
|
||||||
|
|
||||||
Listing code:
|
Listing code:
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < db.db.NumFiles; i++)
|
for (i = 0; i < db.db.NumFiles; i++)
|
||||||
{
|
{
|
||||||
CFileItem *f = db.db.Files + i;
|
CFileItem *f = db.db.Files + i;
|
||||||
printf("%10d %s\n", (int)f->Size, f->Name);
|
printf("%10d %s\n", (int)f->Size, f->Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Extracting code:
|
Extracting code:
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
SZ_RESULT SzAr_Extract(
|
SZ_RESULT SzAr_Extract(
|
||||||
CArchiveDatabaseEx *db,
|
CArchiveDatabaseEx *db,
|
||||||
ILookInStream *inStream,
|
ILookInStream *inStream,
|
||||||
UInt32 fileIndex, /* index of file */
|
UInt32 fileIndex, /* index of file */
|
||||||
UInt32 *blockIndex, /* index of solid block */
|
UInt32 *blockIndex, /* index of solid block */
|
||||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||||
size_t *outBufferSize, /* buffer size for output buffer */
|
size_t *outBufferSize, /* buffer size for output buffer */
|
||||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||||
ISzAlloc *allocMain,
|
ISzAlloc *allocMain,
|
||||||
ISzAlloc *allocTemp);
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
If you need to decompress more than one file, you can send these values from previous call:
|
If you need to decompress more than one file, you can send these values from previous call:
|
||||||
blockIndex,
|
blockIndex,
|
||||||
outBuffer,
|
outBuffer,
|
||||||
outBufferSize,
|
outBufferSize,
|
||||||
You can consider "outBuffer" as cache of solid block. If your archive is solid,
|
You can consider "outBuffer" as cache of solid block. If your archive is solid,
|
||||||
it will increase decompression speed.
|
it will increase decompression speed.
|
||||||
|
|
||||||
After decompressing you must free "outBuffer":
|
After decompressing you must free "outBuffer":
|
||||||
allocImp.Free(outBuffer);
|
allocImp.Free(outBuffer);
|
||||||
|
|
||||||
6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".
|
6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Memory requirements for .7z decoding
|
Memory requirements for .7z decoding
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
Memory usage for Archive opening:
|
Memory usage for Archive opening:
|
||||||
- Temporary pool:
|
- Temporary pool:
|
||||||
- Memory for uncompressed .7z headers
|
- Memory for uncompressed .7z headers
|
||||||
- some other temporary blocks
|
- some other temporary blocks
|
||||||
- Main pool:
|
- Main pool:
|
||||||
- Memory for database:
|
- Memory for database:
|
||||||
Estimated size of one file structures in solid archive:
|
Estimated size of one file structures in solid archive:
|
||||||
- Size (4 or 8 Bytes)
|
- Size (4 or 8 Bytes)
|
||||||
- CRC32 (4 bytes)
|
- CRC32 (4 bytes)
|
||||||
- LastWriteTime (8 bytes)
|
- LastWriteTime (8 bytes)
|
||||||
- Some file information (4 bytes)
|
- Some file information (4 bytes)
|
||||||
- File Name (variable length) + pointer + allocation structures
|
- File Name (variable length) + pointer + allocation structures
|
||||||
|
|
||||||
Memory usage for archive Decompressing:
|
Memory usage for archive Decompressing:
|
||||||
- Temporary pool:
|
- Temporary pool:
|
||||||
- Memory for LZMA decompressing structures
|
- Memory for LZMA decompressing structures
|
||||||
- Main pool:
|
- Main pool:
|
||||||
- Memory for decompressed solid block
|
- Memory for decompressed solid block
|
||||||
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
|
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
|
||||||
temprorary buffers can be about 15% of solid block size.
|
temprorary buffers can be about 15% of solid block size.
|
||||||
|
|
||||||
|
|
||||||
7z Decoder doesn't allocate memory for compressed blocks.
|
7z Decoder doesn't allocate memory for compressed blocks.
|
||||||
Instead of this, you must allocate buffer with desired
|
Instead of this, you must allocate buffer with desired
|
||||||
size before calling 7z Decoder. Use 7zMain.c as example.
|
size before calling 7z Decoder. Use 7zMain.c as example.
|
||||||
|
|
||||||
|
|
||||||
Defines
|
Defines
|
||||||
-------
|
-------
|
||||||
|
|
||||||
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
|
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
http://www.7-zip.org
|
http://www.7-zip.org
|
||||||
http://www.7-zip.org/sdk.html
|
http://www.7-zip.org/sdk.html
|
||||||
http://www.7-zip.org/support.html
|
http://www.7-zip.org/support.html
|
||||||
|
|
148
fex/7z_C/7zCrc.c
148
fex/7z_C/7zCrc.c
|
@ -1,74 +1,74 @@
|
||||||
/* 7zCrc.c -- CRC32 calculation
|
/* 7zCrc.c -- CRC32 calculation
|
||||||
2009-11-23 : Igor Pavlov : Public domain */
|
2009-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "7zCrc.h"
|
#include "7zCrc.h"
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#define kCrcPoly 0xEDB88320
|
#define kCrcPoly 0xEDB88320
|
||||||
|
|
||||||
#ifdef MY_CPU_LE
|
#ifdef MY_CPU_LE
|
||||||
#define CRC_NUM_TABLES 8
|
#define CRC_NUM_TABLES 8
|
||||||
#else
|
#else
|
||||||
#define CRC_NUM_TABLES 1
|
#define CRC_NUM_TABLES 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
|
||||||
static CRC_FUNC g_CrcUpdate;
|
static CRC_FUNC g_CrcUpdate;
|
||||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||||
|
|
||||||
#if CRC_NUM_TABLES == 1
|
#if CRC_NUM_TABLES == 1
|
||||||
|
|
||||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
#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)
|
static UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
{
|
{
|
||||||
const Byte *p = (const Byte *)data;
|
const Byte *p = (const Byte *)data;
|
||||||
for (; size > 0; size--, p++)
|
for (; size > 0; size--, p++)
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
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);
|
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||||
{
|
{
|
||||||
return g_CrcUpdate(v, data, size, g_CrcTable);
|
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||||
{
|
{
|
||||||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MY_FAST_CALL CrcGenerateTable()
|
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;
|
||||||
unsigned 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
|
#if CRC_NUM_TABLES == 1
|
||||||
g_CrcUpdate = CrcUpdateT1;
|
g_CrcUpdate = CrcUpdateT1;
|
||||||
#else
|
#else
|
||||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||||
{
|
{
|
||||||
UInt32 r = g_CrcTable[i - 256];
|
UInt32 r = g_CrcTable[i - 256];
|
||||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||||
}
|
}
|
||||||
g_CrcUpdate = CrcUpdateT4;
|
g_CrcUpdate = CrcUpdateT4;
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
if (!CPU_Is_InOrder())
|
if (!CPU_Is_InOrder())
|
||||||
g_CrcUpdate = CrcUpdateT8;
|
g_CrcUpdate = CrcUpdateT8;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
/* 7zCrc.h -- CRC32 calculation
|
/* 7zCrc.h -- CRC32 calculation
|
||||||
2009-11-21 : Igor Pavlov : Public domain */
|
2009-11-21 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_CRC_H
|
#ifndef __7Z_CRC_H
|
||||||
#define __7Z_CRC_H
|
#define __7Z_CRC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
extern UInt32 g_CrcTable[];
|
extern UInt32 g_CrcTable[];
|
||||||
|
|
||||||
/* Call CrcGenerateTable one time before other CRC functions */
|
/* 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) ^ CRC_INIT_VAL)
|
#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);
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
|
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
|
||||||
2009-11-23 : Igor Pavlov : Public domain */
|
2009-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#ifdef MY_CPU_LE
|
#ifdef MY_CPU_LE
|
||||||
|
|
||||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
#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)
|
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||||
{
|
{
|
||||||
const Byte *p = (const Byte *)data;
|
const Byte *p = (const Byte *)data;
|
||||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
for (; size >= 4; size -= 4, p += 4)
|
for (; size >= 4; size -= 4, p += 4)
|
||||||
{
|
{
|
||||||
v ^= *(const UInt32 *)p;
|
v ^= *(const UInt32 *)p;
|
||||||
v =
|
v =
|
||||||
table[0x300 + (v & 0xFF)] ^
|
table[0x300 + (v & 0xFF)] ^
|
||||||
table[0x200 + ((v >> 8) & 0xFF)] ^
|
table[0x200 + ((v >> 8) & 0xFF)] ^
|
||||||
table[0x100 + ((v >> 16) & 0xFF)] ^
|
table[0x100 + ((v >> 16) & 0xFF)] ^
|
||||||
table[0x000 + ((v >> 24))];
|
table[0x000 + ((v >> 24))];
|
||||||
}
|
}
|
||||||
for (; size > 0; size--, p++)
|
for (; size > 0; size--, p++)
|
||||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 MY_FAST_CALL CrcUpdateT8(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)
|
||||||
{
|
{
|
||||||
return CrcUpdateT4(v, data, size, table);
|
return CrcUpdateT4(v, data, size, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,470 +1,470 @@
|
||||||
/* 7zDec.c -- Decoding from 7z folder
|
/* 7zDec.c -- Decoding from 7z folder
|
||||||
2010-11-02 : Igor Pavlov : Public domain */
|
2010-11-02 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* #define _7ZIP_PPMD_SUPPPORT */
|
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||||
|
|
||||||
#include "7z.h"
|
#include "7z.h"
|
||||||
|
|
||||||
#include "Bcj2.h"
|
#include "Bcj2.h"
|
||||||
#include "Bra.h"
|
#include "Bra.h"
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
#include "LzmaDec.h"
|
#include "LzmaDec.h"
|
||||||
#include "Lzma2Dec.h"
|
#include "Lzma2Dec.h"
|
||||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
#include "Ppmd7.h"
|
#include "Ppmd7.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define k_Copy 0
|
#define k_Copy 0
|
||||||
#define k_LZMA2 0x21
|
#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_PPC 0x03030205
|
||||||
#define k_ARM 0x03030501
|
#define k_ARM 0x03030501
|
||||||
#define k_ARMT 0x03030701
|
#define k_ARMT 0x03030701
|
||||||
#define k_SPARC 0x03030805
|
#define k_SPARC 0x03030805
|
||||||
#define k_BCJ2 0x0303011B
|
#define k_BCJ2 0x0303011B
|
||||||
|
|
||||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
|
|
||||||
#define k_PPMD 0x30401
|
#define k_PPMD 0x30401
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
IByteIn p;
|
IByteIn p;
|
||||||
const Byte *cur;
|
const Byte *cur;
|
||||||
const Byte *end;
|
const Byte *end;
|
||||||
const Byte *begin;
|
const Byte *begin;
|
||||||
UInt64 processed;
|
UInt64 processed;
|
||||||
Bool extra;
|
Bool extra;
|
||||||
SRes res;
|
SRes res;
|
||||||
ILookInStream *inStream;
|
ILookInStream *inStream;
|
||||||
} CByteInToLook;
|
} CByteInToLook;
|
||||||
|
|
||||||
static Byte ReadByte(void *pp)
|
static Byte ReadByte(void *pp)
|
||||||
{
|
{
|
||||||
CByteInToLook *p = (CByteInToLook *)pp;
|
CByteInToLook *p = (CByteInToLook *)pp;
|
||||||
if (p->cur != p->end)
|
if (p->cur != p->end)
|
||||||
return *p->cur++;
|
return *p->cur++;
|
||||||
if (p->res == SZ_OK)
|
if (p->res == SZ_OK)
|
||||||
{
|
{
|
||||||
size_t size = p->cur - p->begin;
|
size_t size = p->cur - p->begin;
|
||||||
p->processed += size;
|
p->processed += size;
|
||||||
p->res = p->inStream->Skip(p->inStream, size);
|
p->res = p->inStream->Skip(p->inStream, size);
|
||||||
size = (1 << 25);
|
size = (1 << 25);
|
||||||
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
|
p->res = p->inStream->Look(p->inStream, (const void **)&p->begin, &size);
|
||||||
p->cur = p->begin;
|
p->cur = p->begin;
|
||||||
p->end = p->begin + size;
|
p->end = p->begin + size;
|
||||||
if (size != 0)
|
if (size != 0)
|
||||||
return *p->cur++;;
|
return *p->cur++;;
|
||||||
}
|
}
|
||||||
p->extra = True;
|
p->extra = True;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
static SRes SzDecodePpmd(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
{
|
{
|
||||||
CPpmd7 ppmd;
|
CPpmd7 ppmd;
|
||||||
CByteInToLook s;
|
CByteInToLook s;
|
||||||
SRes res = SZ_OK;
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
s.p.Read = ReadByte;
|
s.p.Read = ReadByte;
|
||||||
s.inStream = inStream;
|
s.inStream = inStream;
|
||||||
s.begin = s.end = s.cur = NULL;
|
s.begin = s.end = s.cur = NULL;
|
||||||
s.extra = False;
|
s.extra = False;
|
||||||
s.res = SZ_OK;
|
s.res = SZ_OK;
|
||||||
s.processed = 0;
|
s.processed = 0;
|
||||||
|
|
||||||
if (coder->Props.size != 5)
|
if (coder->Props.size != 5)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned order = coder->Props.data[0];
|
unsigned order = coder->Props.data[0];
|
||||||
UInt32 memSize = GetUi32(coder->Props.data + 1);
|
UInt32 memSize = GetUi32(coder->Props.data + 1);
|
||||||
if (order < PPMD7_MIN_ORDER ||
|
if (order < PPMD7_MIN_ORDER ||
|
||||||
order > PPMD7_MAX_ORDER ||
|
order > PPMD7_MAX_ORDER ||
|
||||||
memSize < PPMD7_MIN_MEM_SIZE ||
|
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||||
memSize > PPMD7_MAX_MEM_SIZE)
|
memSize > PPMD7_MAX_MEM_SIZE)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
Ppmd7_Construct(&ppmd);
|
Ppmd7_Construct(&ppmd);
|
||||||
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
Ppmd7_Init(&ppmd, order);
|
Ppmd7_Init(&ppmd, order);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
CPpmd7z_RangeDec rc;
|
CPpmd7z_RangeDec rc;
|
||||||
Ppmd7z_RangeDec_CreateVTable(&rc);
|
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||||
rc.Stream = &s.p;
|
rc.Stream = &s.p;
|
||||||
if (!Ppmd7z_RangeDec_Init(&rc))
|
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||||
res = SZ_ERROR_DATA;
|
res = SZ_ERROR_DATA;
|
||||||
else if (s.extra)
|
else if (s.extra)
|
||||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SizeT i;
|
SizeT i;
|
||||||
for (i = 0; i < outSize; i++)
|
for (i = 0; i < outSize; i++)
|
||||||
{
|
{
|
||||||
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
|
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.p);
|
||||||
if (s.extra || sym < 0)
|
if (s.extra || sym < 0)
|
||||||
break;
|
break;
|
||||||
outBuffer[i] = (Byte)sym;
|
outBuffer[i] = (Byte)sym;
|
||||||
}
|
}
|
||||||
if (i != outSize)
|
if (i != outSize)
|
||||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||||
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||||
res = SZ_ERROR_DATA;
|
res = SZ_ERROR_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ppmd7_Free(&ppmd, allocMain);
|
Ppmd7_Free(&ppmd, allocMain);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#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)
|
||||||
{
|
{
|
||||||
CLzmaDec state;
|
CLzmaDec state;
|
||||||
SRes res = SZ_OK;
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
LzmaDec_Construct(&state);
|
LzmaDec_Construct(&state);
|
||||||
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
||||||
state.dic = outBuffer;
|
state.dic = outBuffer;
|
||||||
state.dicBufSize = outSize;
|
state.dicBufSize = outSize;
|
||||||
LzmaDec_Init(&state);
|
LzmaDec_Init(&state);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *inBuf = NULL;
|
Byte *inBuf = NULL;
|
||||||
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, (const void **)&inBuf, &lookahead);
|
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
{
|
{
|
||||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||||
ELzmaStatus status;
|
ELzmaStatus status;
|
||||||
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||||
lookahead -= inProcessed;
|
lookahead -= inProcessed;
|
||||||
inSize -= inProcessed;
|
inSize -= inProcessed;
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||||
{
|
{
|
||||||
if (state.dicBufSize != outSize || lookahead != 0 ||
|
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||||
res = SZ_ERROR_DATA;
|
res = SZ_ERROR_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res = inStream->Skip((void *)inStream, inProcessed);
|
res = inStream->Skip((void *)inStream, inProcessed);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LzmaDec_FreeProbs(&state, allocMain);
|
LzmaDec_FreeProbs(&state, allocMain);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
static SRes SzDecodeLzma2(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||||
{
|
{
|
||||||
CLzma2Dec state;
|
CLzma2Dec state;
|
||||||
SRes res = SZ_OK;
|
SRes res = SZ_OK;
|
||||||
|
|
||||||
Lzma2Dec_Construct(&state);
|
Lzma2Dec_Construct(&state);
|
||||||
if (coder->Props.size != 1)
|
if (coder->Props.size != 1)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
|
RINOK(Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain));
|
||||||
state.decoder.dic = outBuffer;
|
state.decoder.dic = outBuffer;
|
||||||
state.decoder.dicBufSize = outSize;
|
state.decoder.dicBufSize = outSize;
|
||||||
Lzma2Dec_Init(&state);
|
Lzma2Dec_Init(&state);
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *inBuf = NULL;
|
Byte *inBuf = NULL;
|
||||||
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, (const void **)&inBuf, &lookahead);
|
res = inStream->Look((void *)inStream, (const void **)&inBuf, &lookahead);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
{
|
{
|
||||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||||
ELzmaStatus status;
|
ELzmaStatus status;
|
||||||
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
res = Lzma2Dec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||||
lookahead -= inProcessed;
|
lookahead -= inProcessed;
|
||||||
inSize -= inProcessed;
|
inSize -= inProcessed;
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
if (state.decoder.dicPos == state.decoder.dicBufSize || (inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||||
{
|
{
|
||||||
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||||
res = SZ_ERROR_DATA;
|
res = SZ_ERROR_DATA;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
res = inStream->Skip((void *)inStream, inProcessed);
|
res = inStream->Skip((void *)inStream, inProcessed);
|
||||||
if (res != SZ_OK)
|
if (res != SZ_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||||
return res;
|
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)
|
||||||
{
|
{
|
||||||
void *inBuf;
|
void *inBuf;
|
||||||
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, (const 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);
|
||||||
outBuffer += curSize;
|
outBuffer += curSize;
|
||||||
inSize -= curSize;
|
inSize -= curSize;
|
||||||
RINOK(inStream->Skip((void *)inStream, curSize));
|
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||||
}
|
}
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool IS_MAIN_METHOD(UInt32 m)
|
static Bool IS_MAIN_METHOD(UInt32 m)
|
||||||
{
|
{
|
||||||
switch(m)
|
switch(m)
|
||||||
{
|
{
|
||||||
case k_Copy:
|
case k_Copy:
|
||||||
case k_LZMA:
|
case k_LZMA:
|
||||||
case k_LZMA2:
|
case k_LZMA2:
|
||||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
case k_PPMD:
|
case k_PPMD:
|
||||||
#endif
|
#endif
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
return False;
|
return False;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
static Bool IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
c->NumInStreams == 1 &&
|
c->NumInStreams == 1 &&
|
||||||
c->NumOutStreams == 1 &&
|
c->NumOutStreams == 1 &&
|
||||||
c->MethodID <= (UInt32)0xFFFFFFFF &&
|
c->MethodID <= (UInt32)0xFFFFFFFF &&
|
||||||
IS_MAIN_METHOD((UInt32)c->MethodID);
|
IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
||||||
|
|
||||||
static SRes CheckSupportedFolder(const CSzFolder *f)
|
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_SUPPORTED_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)
|
||||||
{
|
{
|
||||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
if (f->NumCoders == 2)
|
if (f->NumCoders == 2)
|
||||||
{
|
{
|
||||||
CSzCoderInfo *c = &f->Coders[1];
|
CSzCoderInfo *c = &f->Coders[1];
|
||||||
if (c->MethodID > (UInt32)0xFFFFFFFF ||
|
if (c->MethodID > (UInt32)0xFFFFFFFF ||
|
||||||
c->NumInStreams != 1 ||
|
c->NumInStreams != 1 ||
|
||||||
c->NumOutStreams != 1 ||
|
c->NumOutStreams != 1 ||
|
||||||
f->NumPackStreams != 1 ||
|
f->NumPackStreams != 1 ||
|
||||||
f->PackStreams[0] != 0 ||
|
f->PackStreams[0] != 0 ||
|
||||||
f->NumBindPairs != 1 ||
|
f->NumBindPairs != 1 ||
|
||||||
f->BindPairs[0].InIndex != 1 ||
|
f->BindPairs[0].InIndex != 1 ||
|
||||||
f->BindPairs[0].OutIndex != 0)
|
f->BindPairs[0].OutIndex != 0)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
switch ((UInt32)c->MethodID)
|
switch ((UInt32)c->MethodID)
|
||||||
{
|
{
|
||||||
case k_BCJ:
|
case k_BCJ:
|
||||||
case k_ARM:
|
case k_ARM:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
if (f->NumCoders == 4)
|
if (f->NumCoders == 4)
|
||||||
{
|
{
|
||||||
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
|
if (!IS_SUPPORTED_CODER(&f->Coders[1]) ||
|
||||||
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
|
!IS_SUPPORTED_CODER(&f->Coders[2]) ||
|
||||||
!IS_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 ||
|
||||||
f->PackStreams[1] != 6 ||
|
f->PackStreams[1] != 6 ||
|
||||||
f->PackStreams[2] != 1 ||
|
f->PackStreams[2] != 1 ||
|
||||||
f->PackStreams[3] != 0 ||
|
f->PackStreams[3] != 0 ||
|
||||||
f->NumBindPairs != 3 ||
|
f->NumBindPairs != 3 ||
|
||||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UInt64 GetSum(const UInt64 *values, UInt32 index)
|
static UInt64 GetSum(const UInt64 *values, UInt32 index)
|
||||||
{
|
{
|
||||||
UInt64 sum = 0;
|
UInt64 sum = 0;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < index; i++)
|
for (i = 0; i < index; i++)
|
||||||
sum += values[i];
|
sum += values[i];
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||||
|
|
||||||
static SRes SzFolder_Decode2(const CSzFolder *folder, const UInt64 *packSizes,
|
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[])
|
||||||
{
|
{
|
||||||
UInt32 ci;
|
UInt32 ci;
|
||||||
SizeT tempSizes[3] = { 0, 0, 0};
|
SizeT tempSizes[3] = { 0, 0, 0};
|
||||||
SizeT tempSize3 = 0;
|
SizeT tempSize3 = 0;
|
||||||
Byte *tempBuf3 = 0;
|
Byte *tempBuf3 = 0;
|
||||||
|
|
||||||
RINOK(CheckSupportedFolder(folder));
|
RINOK(CheckSupportedFolder(folder));
|
||||||
|
|
||||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||||
{
|
{
|
||||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||||
|
|
||||||
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||||
{
|
{
|
||||||
UInt32 si = 0;
|
UInt32 si = 0;
|
||||||
UInt64 offset;
|
UInt64 offset;
|
||||||
UInt64 inSize;
|
UInt64 inSize;
|
||||||
Byte *outBufCur = outBuffer;
|
Byte *outBufCur = outBuffer;
|
||||||
SizeT outSizeCur = outSize;
|
SizeT outSizeCur = outSize;
|
||||||
if (folder->NumCoders == 4)
|
if (folder->NumCoders == 4)
|
||||||
{
|
{
|
||||||
UInt32 indices[] = { 3, 2, 0 };
|
UInt32 indices[] = { 3, 2, 0 };
|
||||||
UInt64 unpackSize = folder->UnpackSizes[ci];
|
UInt64 unpackSize = folder->UnpackSizes[ci];
|
||||||
si = indices[ci];
|
si = indices[ci];
|
||||||
if (ci < 2)
|
if (ci < 2)
|
||||||
{
|
{
|
||||||
Byte *temp;
|
Byte *temp;
|
||||||
outSizeCur = (SizeT)unpackSize;
|
outSizeCur = (SizeT)unpackSize;
|
||||||
if (outSizeCur != unpackSize)
|
if (outSizeCur != unpackSize)
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||||
if (temp == 0 && outSizeCur != 0)
|
if (temp == 0 && outSizeCur != 0)
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
outBufCur = tempBuf[1 - ci] = temp;
|
outBufCur = tempBuf[1 - ci] = temp;
|
||||||
tempSizes[1 - ci] = outSizeCur;
|
tempSizes[1 - ci] = outSizeCur;
|
||||||
}
|
}
|
||||||
else if (ci == 2)
|
else if (ci == 2)
|
||||||
{
|
{
|
||||||
if (unpackSize > outSize) /* check it */
|
if (unpackSize > outSize) /* check it */
|
||||||
return SZ_ERROR_PARAM;
|
return SZ_ERROR_PARAM;
|
||||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
offset = GetSum(packSizes, si);
|
offset = GetSum(packSizes, si);
|
||||||
inSize = packSizes[si];
|
inSize = packSizes[si];
|
||||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||||
|
|
||||||
if (coder->MethodID == k_Copy)
|
if (coder->MethodID == k_Copy)
|
||||||
{
|
{
|
||||||
if (inSize != outSizeCur) /* check it */
|
if (inSize != outSizeCur) /* check it */
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||||
}
|
}
|
||||||
else if (coder->MethodID == k_LZMA)
|
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_LZMA2)
|
||||||
{
|
{
|
||||||
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
RINOK(SzDecodeLzma2(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||||
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
RINOK(SzDecodePpmd(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||||
#else
|
#else
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (coder->MethodID == k_BCJ2)
|
else if (coder->MethodID == k_BCJ2)
|
||||||
{
|
{
|
||||||
UInt64 offset = GetSum(packSizes, 1);
|
UInt64 offset = GetSum(packSizes, 1);
|
||||||
UInt64 s3Size = packSizes[1];
|
UInt64 s3Size = packSizes[1];
|
||||||
SRes res;
|
SRes res;
|
||||||
if (ci != 3)
|
if (ci != 3)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||||
tempSizes[2] = (SizeT)s3Size;
|
tempSizes[2] = (SizeT)s3Size;
|
||||||
if (tempSizes[2] != s3Size)
|
if (tempSizes[2] != s3Size)
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||||
RINOK(res)
|
RINOK(res)
|
||||||
|
|
||||||
res = Bcj2_Decode(
|
res = Bcj2_Decode(
|
||||||
tempBuf3, tempSize3,
|
tempBuf3, tempSize3,
|
||||||
tempBuf[0], tempSizes[0],
|
tempBuf[0], tempSizes[0],
|
||||||
tempBuf[1], tempSizes[1],
|
tempBuf[1], tempSizes[1],
|
||||||
tempBuf[2], tempSizes[2],
|
tempBuf[2], tempSizes[2],
|
||||||
outBuffer, outSize);
|
outBuffer, outSize);
|
||||||
RINOK(res)
|
RINOK(res)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (ci != 1)
|
if (ci != 1)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
switch(coder->MethodID)
|
switch(coder->MethodID)
|
||||||
{
|
{
|
||||||
case k_BCJ:
|
case k_BCJ:
|
||||||
{
|
{
|
||||||
UInt32 state;
|
UInt32 state;
|
||||||
x86_Convert_Init(state);
|
x86_Convert_Init(state);
|
||||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CASE_BRA_CONV(ARM)
|
CASE_BRA_CONV(ARM)
|
||||||
default:
|
default:
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes SzFolder_Decode(const CSzFolder *folder, const UInt64 *packSizes,
|
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 = SzFolder_Decode2(folder, packSizes, 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]);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/* 7zDecode.h -- Decoding from 7z folder
|
/* 7zDecode.h -- Decoding from 7z folder
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2008-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_DECODE_H
|
#ifndef __7Z_DECODE_H
|
||||||
#define __7Z_DECODE_H
|
#define __7Z_DECODE_H
|
||||||
|
|
||||||
#include "7zItem.h"
|
#include "7zItem.h"
|
||||||
|
|
||||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||||
ILookInStream *stream, UInt64 startPos,
|
ILookInStream *stream, UInt64 startPos,
|
||||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,93 +1,93 @@
|
||||||
/* 7zExtract.c -- Extracting from 7z archive
|
/* 7zExtract.c -- Extracting from 7z archive
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2008-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "7zCrc.h"
|
#include "7zCrc.h"
|
||||||
#include "7zDecode.h"
|
#include "7zDecode.h"
|
||||||
#include "7zExtract.h"
|
#include "7zExtract.h"
|
||||||
|
|
||||||
SRes SzAr_Extract(
|
SRes SzAr_Extract(
|
||||||
const CSzArEx *p,
|
const CSzArEx *p,
|
||||||
ILookInStream *inStream,
|
ILookInStream *inStream,
|
||||||
UInt32 fileIndex,
|
UInt32 fileIndex,
|
||||||
UInt32 *blockIndex,
|
UInt32 *blockIndex,
|
||||||
Byte **outBuffer,
|
Byte **outBuffer,
|
||||||
size_t *outBufferSize,
|
size_t *outBufferSize,
|
||||||
size_t *offset,
|
size_t *offset,
|
||||||
size_t *outSizeProcessed,
|
size_t *outSizeProcessed,
|
||||||
ISzAlloc *allocMain,
|
ISzAlloc *allocMain,
|
||||||
ISzAlloc *allocTemp)
|
ISzAlloc *allocTemp)
|
||||||
{
|
{
|
||||||
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
|
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
|
||||||
SRes res = SZ_OK;
|
SRes res = SZ_OK;
|
||||||
*offset = 0;
|
*offset = 0;
|
||||||
*outSizeProcessed = 0;
|
*outSizeProcessed = 0;
|
||||||
if (folderIndex == (UInt32)-1)
|
if (folderIndex == (UInt32)-1)
|
||||||
{
|
{
|
||||||
IAlloc_Free(allocMain, *outBuffer);
|
IAlloc_Free(allocMain, *outBuffer);
|
||||||
*blockIndex = folderIndex;
|
*blockIndex = folderIndex;
|
||||||
*outBuffer = 0;
|
*outBuffer = 0;
|
||||||
*outBufferSize = 0;
|
*outBufferSize = 0;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
||||||
{
|
{
|
||||||
CSzFolder *folder = p->db.Folders + folderIndex;
|
CSzFolder *folder = p->db.Folders + folderIndex;
|
||||||
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
|
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
|
||||||
size_t unpackSize = (size_t)unpackSizeSpec;
|
size_t unpackSize = (size_t)unpackSizeSpec;
|
||||||
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
|
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
|
||||||
|
|
||||||
if (unpackSize != unpackSizeSpec)
|
if (unpackSize != unpackSizeSpec)
|
||||||
return SZ_ERROR_MEM;
|
return SZ_ERROR_MEM;
|
||||||
*blockIndex = folderIndex;
|
*blockIndex = folderIndex;
|
||||||
IAlloc_Free(allocMain, *outBuffer);
|
IAlloc_Free(allocMain, *outBuffer);
|
||||||
*outBuffer = 0;
|
*outBuffer = 0;
|
||||||
|
|
||||||
RINOK(LookInStream_SeekTo(inStream, startOffset));
|
RINOK(LookInStream_SeekTo(inStream, startOffset));
|
||||||
|
|
||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
{
|
{
|
||||||
*outBufferSize = unpackSize;
|
*outBufferSize = unpackSize;
|
||||||
if (unpackSize != 0)
|
if (unpackSize != 0)
|
||||||
{
|
{
|
||||||
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
|
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
|
||||||
if (*outBuffer == 0)
|
if (*outBuffer == 0)
|
||||||
res = SZ_ERROR_MEM;
|
res = SZ_ERROR_MEM;
|
||||||
}
|
}
|
||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
{
|
{
|
||||||
res = SzDecode(p->db.PackSizes +
|
res = SzDecode(p->db.PackSizes +
|
||||||
p->FolderStartPackStreamIndex[folderIndex], folder,
|
p->FolderStartPackStreamIndex[folderIndex], folder,
|
||||||
inStream, startOffset,
|
inStream, startOffset,
|
||||||
*outBuffer, unpackSize, allocTemp);
|
*outBuffer, unpackSize, allocTemp);
|
||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
{
|
{
|
||||||
if (folder->UnpackCRCDefined)
|
if (folder->UnpackCRCDefined)
|
||||||
{
|
{
|
||||||
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
|
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
|
||||||
res = SZ_ERROR_CRC;
|
res = SZ_ERROR_CRC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (res == SZ_OK)
|
if (res == SZ_OK)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
CSzFileItem *fileItem = p->db.Files + fileIndex;
|
CSzFileItem *fileItem = p->db.Files + fileIndex;
|
||||||
*offset = 0;
|
*offset = 0;
|
||||||
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
||||||
*offset += (UInt32)p->db.Files[i].Size;
|
*offset += (UInt32)p->db.Files[i].Size;
|
||||||
*outSizeProcessed = (size_t)fileItem->Size;
|
*outSizeProcessed = (size_t)fileItem->Size;
|
||||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
if (*offset + *outSizeProcessed > *outBufferSize)
|
||||||
return SZ_ERROR_FAIL;
|
return SZ_ERROR_FAIL;
|
||||||
{
|
{
|
||||||
if (fileItem->FileCRCDefined)
|
if (fileItem->FileCRCDefined)
|
||||||
{
|
{
|
||||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
||||||
res = SZ_ERROR_CRC;
|
res = SZ_ERROR_CRC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,49 +1,49 @@
|
||||||
/* 7zExtract.h -- Extracting from 7z archive
|
/* 7zExtract.h -- Extracting from 7z archive
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2008-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_EXTRACT_H
|
#ifndef __7Z_EXTRACT_H
|
||||||
#define __7Z_EXTRACT_H
|
#define __7Z_EXTRACT_H
|
||||||
|
|
||||||
#include "7zIn.h"
|
#include "7zIn.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SzExtract extracts file from archive
|
SzExtract extracts file from archive
|
||||||
|
|
||||||
*outBuffer must be 0 before first call for each new archive.
|
*outBuffer must be 0 before first call for each new archive.
|
||||||
|
|
||||||
Extracting cache:
|
Extracting cache:
|
||||||
If you need to decompress more than one file, you can send
|
If you need to decompress more than one file, you can send
|
||||||
these values from previous call:
|
these values from previous call:
|
||||||
*blockIndex,
|
*blockIndex,
|
||||||
*outBuffer,
|
*outBuffer,
|
||||||
*outBufferSize
|
*outBufferSize
|
||||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||||
it will increase decompression speed.
|
it will increase decompression speed.
|
||||||
|
|
||||||
If you use external function, you can declare these 3 cache variables
|
If you use external function, you can declare these 3 cache variables
|
||||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||||
|
|
||||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes SzAr_Extract(
|
SRes SzAr_Extract(
|
||||||
const CSzArEx *db,
|
const CSzArEx *db,
|
||||||
ILookInStream *inStream,
|
ILookInStream *inStream,
|
||||||
UInt32 fileIndex, /* index of file */
|
UInt32 fileIndex, /* index of file */
|
||||||
UInt32 *blockIndex, /* index of solid block */
|
UInt32 *blockIndex, /* index of solid block */
|
||||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||||
size_t *outBufferSize, /* buffer size for output buffer */
|
size_t *outBufferSize, /* buffer size for output buffer */
|
||||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||||
ISzAlloc *allocMain,
|
ISzAlloc *allocMain,
|
||||||
ISzAlloc *allocTemp);
|
ISzAlloc *allocTemp);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* 7zHeader.c -- 7z Headers
|
/* 7zHeader.c -- 7z Headers
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "7zHeader.h"
|
#include "7zHeader.h"
|
||||||
|
|
||||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
||||||
|
|
|
@ -1,57 +1,57 @@
|
||||||
/* 7zHeader.h -- 7z Headers
|
/* 7zHeader.h -- 7z Headers
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_HEADER_H
|
#ifndef __7Z_HEADER_H
|
||||||
#define __7Z_HEADER_H
|
#define __7Z_HEADER_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#define k7zSignatureSize 6
|
#define k7zSignatureSize 6
|
||||||
extern Byte k7zSignature[k7zSignatureSize];
|
extern Byte k7zSignature[k7zSignatureSize];
|
||||||
|
|
||||||
#define k7zMajorVersion 0
|
#define k7zMajorVersion 0
|
||||||
|
|
||||||
#define k7zStartHeaderSize 0x20
|
#define k7zStartHeaderSize 0x20
|
||||||
|
|
||||||
enum EIdEnum
|
enum EIdEnum
|
||||||
{
|
{
|
||||||
k7zIdEnd,
|
k7zIdEnd,
|
||||||
|
|
||||||
k7zIdHeader,
|
k7zIdHeader,
|
||||||
|
|
||||||
k7zIdArchiveProperties,
|
k7zIdArchiveProperties,
|
||||||
|
|
||||||
k7zIdAdditionalStreamsInfo,
|
k7zIdAdditionalStreamsInfo,
|
||||||
k7zIdMainStreamsInfo,
|
k7zIdMainStreamsInfo,
|
||||||
k7zIdFilesInfo,
|
k7zIdFilesInfo,
|
||||||
|
|
||||||
k7zIdPackInfo,
|
k7zIdPackInfo,
|
||||||
k7zIdUnpackInfo,
|
k7zIdUnpackInfo,
|
||||||
k7zIdSubStreamsInfo,
|
k7zIdSubStreamsInfo,
|
||||||
|
|
||||||
k7zIdSize,
|
k7zIdSize,
|
||||||
k7zIdCRC,
|
k7zIdCRC,
|
||||||
|
|
||||||
k7zIdFolder,
|
k7zIdFolder,
|
||||||
|
|
||||||
k7zIdCodersUnpackSize,
|
k7zIdCodersUnpackSize,
|
||||||
k7zIdNumUnpackStream,
|
k7zIdNumUnpackStream,
|
||||||
|
|
||||||
k7zIdEmptyStream,
|
k7zIdEmptyStream,
|
||||||
k7zIdEmptyFile,
|
k7zIdEmptyFile,
|
||||||
k7zIdAnti,
|
k7zIdAnti,
|
||||||
|
|
||||||
k7zIdName,
|
k7zIdName,
|
||||||
k7zIdCTime,
|
k7zIdCTime,
|
||||||
k7zIdATime,
|
k7zIdATime,
|
||||||
k7zIdMTime,
|
k7zIdMTime,
|
||||||
k7zIdWinAttributes,
|
k7zIdWinAttributes,
|
||||||
k7zIdComment,
|
k7zIdComment,
|
||||||
|
|
||||||
k7zIdEncodedHeader,
|
k7zIdEncodedHeader,
|
||||||
|
|
||||||
k7zIdStartPos,
|
k7zIdStartPos,
|
||||||
k7zIdDummy
|
k7zIdDummy
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
2804
fex/7z_C/7zIn.c
2804
fex/7z_C/7zIn.c
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +1,49 @@
|
||||||
/* 7zIn.h -- 7z Input functions
|
/* 7zIn.h -- 7z Input functions
|
||||||
2008-11-23 : Igor Pavlov : Public domain */
|
2008-11-23 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_IN_H
|
#ifndef __7Z_IN_H
|
||||||
#define __7Z_IN_H
|
#define __7Z_IN_H
|
||||||
|
|
||||||
#include "7zHeader.h"
|
#include "7zHeader.h"
|
||||||
#include "7zItem.h"
|
#include "7zItem.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CSzAr db;
|
CSzAr db;
|
||||||
|
|
||||||
UInt64 startPosAfterHeader;
|
UInt64 startPosAfterHeader;
|
||||||
UInt64 dataPos;
|
UInt64 dataPos;
|
||||||
|
|
||||||
UInt32 *FolderStartPackStreamIndex;
|
UInt32 *FolderStartPackStreamIndex;
|
||||||
UInt64 *PackStreamStartPositions;
|
UInt64 *PackStreamStartPositions;
|
||||||
UInt32 *FolderStartFileIndex;
|
UInt32 *FolderStartFileIndex;
|
||||||
UInt32 *FileIndexToFolderIndexMap;
|
UInt32 *FileIndexToFolderIndexMap;
|
||||||
} CSzArEx;
|
} CSzArEx;
|
||||||
|
|
||||||
void SzArEx_Init(CSzArEx *p);
|
void SzArEx_Init(CSzArEx *p);
|
||||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Errors:
|
Errors:
|
||||||
SZ_ERROR_NO_ARCHIVE
|
SZ_ERROR_NO_ARCHIVE
|
||||||
SZ_ERROR_ARCHIVE
|
SZ_ERROR_ARCHIVE
|
||||||
SZ_ERROR_UNSUPPORTED
|
SZ_ERROR_UNSUPPORTED
|
||||||
SZ_ERROR_MEM
|
SZ_ERROR_MEM
|
||||||
SZ_ERROR_CRC
|
SZ_ERROR_CRC
|
||||||
SZ_ERROR_INPUT_EOF
|
SZ_ERROR_INPUT_EOF
|
||||||
SZ_ERROR_FAIL
|
SZ_ERROR_FAIL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,129 +1,129 @@
|
||||||
/* 7zItem.c -- 7z Items
|
/* 7zItem.c -- 7z Items
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "7zItem.h"
|
#include "7zItem.h"
|
||||||
|
|
||||||
void SzCoderInfo_Init(CSzCoderInfo *p)
|
void SzCoderInfo_Init(CSzCoderInfo *p)
|
||||||
{
|
{
|
||||||
Buf_Init(&p->Props);
|
Buf_Init(&p->Props);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
|
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
Buf_Free(&p->Props, alloc);
|
Buf_Free(&p->Props, alloc);
|
||||||
SzCoderInfo_Init(p);
|
SzCoderInfo_Init(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFolder_Init(CSzFolder *p)
|
void SzFolder_Init(CSzFolder *p)
|
||||||
{
|
{
|
||||||
p->Coders = 0;
|
p->Coders = 0;
|
||||||
p->BindPairs = 0;
|
p->BindPairs = 0;
|
||||||
p->PackStreams = 0;
|
p->PackStreams = 0;
|
||||||
p->UnpackSizes = 0;
|
p->UnpackSizes = 0;
|
||||||
p->NumCoders = 0;
|
p->NumCoders = 0;
|
||||||
p->NumBindPairs = 0;
|
p->NumBindPairs = 0;
|
||||||
p->NumPackStreams = 0;
|
p->NumPackStreams = 0;
|
||||||
p->UnpackCRCDefined = 0;
|
p->UnpackCRCDefined = 0;
|
||||||
p->UnpackCRC = 0;
|
p->UnpackCRC = 0;
|
||||||
p->NumUnpackStreams = 0;
|
p->NumUnpackStreams = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
|
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
if (p->Coders)
|
if (p->Coders)
|
||||||
for (i = 0; i < p->NumCoders; i++)
|
for (i = 0; i < p->NumCoders; i++)
|
||||||
SzCoderInfo_Free(&p->Coders[i], alloc);
|
SzCoderInfo_Free(&p->Coders[i], alloc);
|
||||||
IAlloc_Free(alloc, p->Coders);
|
IAlloc_Free(alloc, p->Coders);
|
||||||
IAlloc_Free(alloc, p->BindPairs);
|
IAlloc_Free(alloc, p->BindPairs);
|
||||||
IAlloc_Free(alloc, p->PackStreams);
|
IAlloc_Free(alloc, p->PackStreams);
|
||||||
IAlloc_Free(alloc, p->UnpackSizes);
|
IAlloc_Free(alloc, p->UnpackSizes);
|
||||||
SzFolder_Init(p);
|
SzFolder_Init(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
|
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
|
||||||
{
|
{
|
||||||
UInt32 result = 0;
|
UInt32 result = 0;
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < p->NumCoders; i++)
|
for (i = 0; i < p->NumCoders; i++)
|
||||||
result += p->Coders[i].NumOutStreams;
|
result += p->Coders[i].NumOutStreams;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
|
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < p->NumBindPairs; i++)
|
for (i = 0; i < p->NumBindPairs; i++)
|
||||||
if (p->BindPairs[i].InIndex == inStreamIndex)
|
if (p->BindPairs[i].InIndex == inStreamIndex)
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
|
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
for (i = 0; i < p->NumBindPairs; i++)
|
for (i = 0; i < p->NumBindPairs; i++)
|
||||||
if (p->BindPairs[i].OutIndex == outStreamIndex)
|
if (p->BindPairs[i].OutIndex == outStreamIndex)
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
|
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
|
||||||
{
|
{
|
||||||
int i = (int)SzFolder_GetNumOutStreams(p);
|
int i = (int)SzFolder_GetNumOutStreams(p);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
return 0;
|
return 0;
|
||||||
for (i--; i >= 0; i--)
|
for (i--; i >= 0; i--)
|
||||||
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
|
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
|
||||||
return p->UnpackSizes[i];
|
return p->UnpackSizes[i];
|
||||||
/* throw 1; */
|
/* throw 1; */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzFile_Init(CSzFileItem *p)
|
void SzFile_Init(CSzFileItem *p)
|
||||||
{
|
{
|
||||||
p->HasStream = 1;
|
p->HasStream = 1;
|
||||||
p->IsDir = 0;
|
p->IsDir = 0;
|
||||||
p->IsAnti = 0;
|
p->IsAnti = 0;
|
||||||
p->FileCRCDefined = 0;
|
p->FileCRCDefined = 0;
|
||||||
p->MTimeDefined = 0;
|
p->MTimeDefined = 0;
|
||||||
p->Name = 0;
|
p->Name = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
|
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
IAlloc_Free(alloc, p->Name);
|
IAlloc_Free(alloc, p->Name);
|
||||||
SzFile_Init(p);
|
SzFile_Init(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzAr_Init(CSzAr *p)
|
void SzAr_Init(CSzAr *p)
|
||||||
{
|
{
|
||||||
p->PackSizes = 0;
|
p->PackSizes = 0;
|
||||||
p->PackCRCsDefined = 0;
|
p->PackCRCsDefined = 0;
|
||||||
p->PackCRCs = 0;
|
p->PackCRCs = 0;
|
||||||
p->Folders = 0;
|
p->Folders = 0;
|
||||||
p->Files = 0;
|
p->Files = 0;
|
||||||
p->NumPackStreams = 0;
|
p->NumPackStreams = 0;
|
||||||
p->NumFolders = 0;
|
p->NumFolders = 0;
|
||||||
p->NumFiles = 0;
|
p->NumFiles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
|
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
if (p->Folders)
|
if (p->Folders)
|
||||||
for (i = 0; i < p->NumFolders; i++)
|
for (i = 0; i < p->NumFolders; i++)
|
||||||
SzFolder_Free(&p->Folders[i], alloc);
|
SzFolder_Free(&p->Folders[i], alloc);
|
||||||
if (p->Files)
|
if (p->Files)
|
||||||
for (i = 0; i < p->NumFiles; i++)
|
for (i = 0; i < p->NumFiles; i++)
|
||||||
SzFile_Free(&p->Files[i], alloc);
|
SzFile_Free(&p->Files[i], alloc);
|
||||||
IAlloc_Free(alloc, p->PackSizes);
|
IAlloc_Free(alloc, p->PackSizes);
|
||||||
IAlloc_Free(alloc, p->PackCRCsDefined);
|
IAlloc_Free(alloc, p->PackCRCsDefined);
|
||||||
IAlloc_Free(alloc, p->PackCRCs);
|
IAlloc_Free(alloc, p->PackCRCs);
|
||||||
IAlloc_Free(alloc, p->Folders);
|
IAlloc_Free(alloc, p->Folders);
|
||||||
IAlloc_Free(alloc, p->Files);
|
IAlloc_Free(alloc, p->Files);
|
||||||
SzAr_Init(p);
|
SzAr_Init(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,83 +1,83 @@
|
||||||
/* 7zItem.h -- 7z Items
|
/* 7zItem.h -- 7z Items
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __7Z_ITEM_H
|
#ifndef __7Z_ITEM_H
|
||||||
#define __7Z_ITEM_H
|
#define __7Z_ITEM_H
|
||||||
|
|
||||||
#include "7zBuf.h"
|
#include "7zBuf.h"
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 NumInStreams;
|
UInt32 NumInStreams;
|
||||||
UInt32 NumOutStreams;
|
UInt32 NumOutStreams;
|
||||||
UInt64 MethodID;
|
UInt64 MethodID;
|
||||||
CBuf Props;
|
CBuf Props;
|
||||||
} CSzCoderInfo;
|
} CSzCoderInfo;
|
||||||
|
|
||||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 InIndex;
|
UInt32 InIndex;
|
||||||
UInt32 OutIndex;
|
UInt32 OutIndex;
|
||||||
} CBindPair;
|
} CBindPair;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CSzCoderInfo *Coders;
|
CSzCoderInfo *Coders;
|
||||||
CBindPair *BindPairs;
|
CBindPair *BindPairs;
|
||||||
UInt32 *PackStreams;
|
UInt32 *PackStreams;
|
||||||
UInt64 *UnpackSizes;
|
UInt64 *UnpackSizes;
|
||||||
UInt32 NumCoders;
|
UInt32 NumCoders;
|
||||||
UInt32 NumBindPairs;
|
UInt32 NumBindPairs;
|
||||||
UInt32 NumPackStreams;
|
UInt32 NumPackStreams;
|
||||||
int UnpackCRCDefined;
|
int UnpackCRCDefined;
|
||||||
UInt32 UnpackCRC;
|
UInt32 UnpackCRC;
|
||||||
|
|
||||||
UInt32 NumUnpackStreams;
|
UInt32 NumUnpackStreams;
|
||||||
} CSzFolder;
|
} CSzFolder;
|
||||||
|
|
||||||
void SzFolder_Init(CSzFolder *p);
|
void SzFolder_Init(CSzFolder *p);
|
||||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
||||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 Low;
|
UInt32 Low;
|
||||||
UInt32 High;
|
UInt32 High;
|
||||||
} CNtfsFileTime;
|
} CNtfsFileTime;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CNtfsFileTime MTime;
|
CNtfsFileTime MTime;
|
||||||
UInt64 Size;
|
UInt64 Size;
|
||||||
char *Name;
|
char *Name;
|
||||||
UInt32 FileCRC;
|
UInt32 FileCRC;
|
||||||
|
|
||||||
Byte HasStream;
|
Byte HasStream;
|
||||||
Byte IsDir;
|
Byte IsDir;
|
||||||
Byte IsAnti;
|
Byte IsAnti;
|
||||||
Byte FileCRCDefined;
|
Byte FileCRCDefined;
|
||||||
Byte MTimeDefined;
|
Byte MTimeDefined;
|
||||||
} CSzFileItem;
|
} CSzFileItem;
|
||||||
|
|
||||||
void SzFile_Init(CSzFileItem *p);
|
void SzFile_Init(CSzFileItem *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt64 *PackSizes;
|
UInt64 *PackSizes;
|
||||||
Byte *PackCRCsDefined;
|
Byte *PackCRCsDefined;
|
||||||
UInt32 *PackCRCs;
|
UInt32 *PackCRCs;
|
||||||
CSzFolder *Folders;
|
CSzFolder *Folders;
|
||||||
CSzFileItem *Files;
|
CSzFileItem *Files;
|
||||||
UInt32 NumPackStreams;
|
UInt32 NumPackStreams;
|
||||||
UInt32 NumFolders;
|
UInt32 NumFolders;
|
||||||
UInt32 NumFiles;
|
UInt32 NumFiles;
|
||||||
} CSzAr;
|
} CSzAr;
|
||||||
|
|
||||||
void SzAr_Init(CSzAr *p);
|
void SzAr_Init(CSzAr *p);
|
||||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,169 +1,169 @@
|
||||||
/* 7zStream.c -- 7z Stream functions
|
/* 7zStream.c -- 7z Stream functions
|
||||||
2010-03-11 : Igor Pavlov : Public domain */
|
2010-03-11 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
size_t processed = size;
|
size_t processed = size;
|
||||||
RINOK(stream->Read(stream, buf, &processed));
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
if (processed == 0)
|
if (processed == 0)
|
||||||
return errorType;
|
return errorType;
|
||||||
buf = (void *)((Byte *)buf + processed);
|
buf = (void *)((Byte *)buf + processed);
|
||||||
size -= processed;
|
size -= processed;
|
||||||
}
|
}
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||||
{
|
{
|
||||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||||
{
|
{
|
||||||
size_t processed = 1;
|
size_t processed = 1;
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||||
{
|
{
|
||||||
Int64 t = offset;
|
Int64 t = offset;
|
||||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
const 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||||
{
|
{
|
||||||
while (size != 0)
|
while (size != 0)
|
||||||
{
|
{
|
||||||
size_t processed = size;
|
size_t processed = size;
|
||||||
RINOK(stream->Read(stream, buf, &processed));
|
RINOK(stream->Read(stream, buf, &processed));
|
||||||
if (processed == 0)
|
if (processed == 0)
|
||||||
return errorType;
|
return errorType;
|
||||||
buf = (void *)((Byte *)buf + processed);
|
buf = (void *)((Byte *)buf + processed);
|
||||||
size -= processed;
|
size -= processed;
|
||||||
}
|
}
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
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, const 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;
|
||||||
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)
|
||||||
{
|
{
|
||||||
p->pos = 0;
|
p->pos = 0;
|
||||||
size2 = LookToRead_BUF_SIZE;
|
size2 = LookToRead_BUF_SIZE;
|
||||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||||
p->size = size2;
|
p->size = size2;
|
||||||
}
|
}
|
||||||
if (size2 < *size)
|
if (size2 < *size)
|
||||||
*size = size2;
|
*size = size2;
|
||||||
*buf = p->buf + p->pos;
|
*buf = p->buf + p->pos;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LookToRead_Look_Exact(void *pp, const 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;
|
||||||
size_t size2 = p->size - p->pos;
|
size_t size2 = p->size - p->pos;
|
||||||
if (size2 == 0 && *size > 0)
|
if (size2 == 0 && *size > 0)
|
||||||
{
|
{
|
||||||
p->pos = 0;
|
p->pos = 0;
|
||||||
if (*size > LookToRead_BUF_SIZE)
|
if (*size > LookToRead_BUF_SIZE)
|
||||||
*size = LookToRead_BUF_SIZE;
|
*size = LookToRead_BUF_SIZE;
|
||||||
res = p->realStream->Read(p->realStream, p->buf, size);
|
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||||
size2 = p->size = *size;
|
size2 = p->size = *size;
|
||||||
}
|
}
|
||||||
if (size2 < *size)
|
if (size2 < *size)
|
||||||
*size = size2;
|
*size = size2;
|
||||||
*buf = p->buf + p->pos;
|
*buf = p->buf + p->pos;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||||
{
|
{
|
||||||
CLookToRead *p = (CLookToRead *)pp;
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
p->pos += offset;
|
p->pos += offset;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
CLookToRead *p = (CLookToRead *)pp;
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
size_t rem = p->size - p->pos;
|
size_t rem = p->size - p->pos;
|
||||||
if (rem == 0)
|
if (rem == 0)
|
||||||
return p->realStream->Read(p->realStream, buf, size);
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
if (rem > *size)
|
if (rem > *size)
|
||||||
rem = *size;
|
rem = *size;
|
||||||
memcpy(buf, p->buf + p->pos, rem);
|
memcpy(buf, p->buf + p->pos, rem);
|
||||||
p->pos += rem;
|
p->pos += rem;
|
||||||
*size = rem;
|
*size = rem;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||||
{
|
{
|
||||||
CLookToRead *p = (CLookToRead *)pp;
|
CLookToRead *p = (CLookToRead *)pp;
|
||||||
p->pos = p->size = 0;
|
p->pos = p->size = 0;
|
||||||
return p->realStream->Seek(p->realStream, pos, origin);
|
return p->realStream->Seek(p->realStream, pos, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||||
{
|
{
|
||||||
p->s.Look = lookahead ?
|
p->s.Look = lookahead ?
|
||||||
LookToRead_Look_Lookahead :
|
LookToRead_Look_Lookahead :
|
||||||
LookToRead_Look_Exact;
|
LookToRead_Look_Exact;
|
||||||
p->s.Skip = LookToRead_Skip;
|
p->s.Skip = LookToRead_Skip;
|
||||||
p->s.Read = LookToRead_Read;
|
p->s.Read = LookToRead_Read;
|
||||||
p->s.Seek = LookToRead_Seek;
|
p->s.Seek = LookToRead_Seek;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LookToRead_Init(CLookToRead *p)
|
void LookToRead_Init(CLookToRead *p)
|
||||||
{
|
{
|
||||||
p->pos = p->size = 0;
|
p->pos = p->size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
return LookInStream_LookRead(p->realStream, buf, size);
|
return LookInStream_LookRead(p->realStream, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecToLook_CreateVTable(CSecToLook *p)
|
void SecToLook_CreateVTable(CSecToLook *p)
|
||||||
{
|
{
|
||||||
p->s.Read = SecToLook_Read;
|
p->s.Read = SecToLook_Read;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||||
{
|
{
|
||||||
CSecToRead *p = (CSecToRead *)pp;
|
CSecToRead *p = (CSecToRead *)pp;
|
||||||
return p->realStream->Read(p->realStream, buf, size);
|
return p->realStream->Read(p->realStream, buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecToRead_CreateVTable(CSecToRead *p)
|
void SecToRead_CreateVTable(CSecToRead *p)
|
||||||
{
|
{
|
||||||
p->s.Read = SecToRead_Read;
|
p->s.Read = SecToRead_Read;
|
||||||
}
|
}
|
||||||
|
|
264
fex/7z_C/Bcj2.c
264
fex/7z_C/Bcj2.c
|
@ -1,132 +1,132 @@
|
||||||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Bcj2.h"
|
#include "Bcj2.h"
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
#ifdef _LZMA_PROB32
|
||||||
#define CProb UInt32
|
#define CProb UInt32
|
||||||
#else
|
#else
|
||||||
#define CProb UInt16
|
#define CProb UInt16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||||
|
|
||||||
#define kNumTopBits 24
|
#define kNumTopBits 24
|
||||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||||
|
|
||||||
#define kNumBitModelTotalBits 11
|
#define kNumBitModelTotalBits 11
|
||||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||||
#define kNumMoveBits 5
|
#define kNumMoveBits 5
|
||||||
|
|
||||||
#define RC_READ_BYTE (*buffer++)
|
#define RC_READ_BYTE (*buffer++)
|
||||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||||
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
||||||
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
||||||
|
|
||||||
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
||||||
|
|
||||||
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||||
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
||||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
||||||
|
|
||||||
int Bcj2_Decode(
|
int Bcj2_Decode(
|
||||||
const Byte *buf0, SizeT size0,
|
const Byte *buf0, SizeT size0,
|
||||||
const Byte *buf1, SizeT size1,
|
const Byte *buf1, SizeT size1,
|
||||||
const Byte *buf2, SizeT size2,
|
const Byte *buf2, SizeT size2,
|
||||||
const Byte *buf3, SizeT size3,
|
const Byte *buf3, SizeT size3,
|
||||||
Byte *outBuf, SizeT outSize)
|
Byte *outBuf, SizeT outSize)
|
||||||
{
|
{
|
||||||
CProb p[256 + 2];
|
CProb p[256 + 2];
|
||||||
SizeT inPos = 0, outPos = 0;
|
SizeT inPos = 0, outPos = 0;
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
if (outSize == 0)
|
if (outSize == 0)
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte b;
|
Byte b;
|
||||||
CProb *prob;
|
CProb *prob;
|
||||||
UInt32 bound;
|
UInt32 bound;
|
||||||
UInt32 ttt;
|
UInt32 ttt;
|
||||||
|
|
||||||
SizeT limit = size0 - inPos;
|
SizeT limit = size0 - inPos;
|
||||||
if (outSize - outPos < limit)
|
if (outSize - outPos < limit)
|
||||||
limit = outSize - outPos;
|
limit = outSize - outPos;
|
||||||
while (limit != 0)
|
while (limit != 0)
|
||||||
{
|
{
|
||||||
Byte b = buf0[inPos];
|
Byte b = buf0[inPos];
|
||||||
outBuf[outPos++] = b;
|
outBuf[outPos++] = b;
|
||||||
if (IsJ(prevByte, b))
|
if (IsJ(prevByte, b))
|
||||||
break;
|
break;
|
||||||
inPos++;
|
inPos++;
|
||||||
prevByte = b;
|
prevByte = b;
|
||||||
limit--;
|
limit--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (limit == 0 || outPos == outSize)
|
if (limit == 0 || outPos == outSize)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
b = buf0[inPos++];
|
b = buf0[inPos++];
|
||||||
|
|
||||||
if (b == 0xE8)
|
if (b == 0xE8)
|
||||||
prob = p + prevByte;
|
prob = p + prevByte;
|
||||||
else if (b == 0xE9)
|
else if (b == 0xE9)
|
||||||
prob = p + 256;
|
prob = p + 256;
|
||||||
else
|
else
|
||||||
prob = p + 257;
|
prob = p + 257;
|
||||||
|
|
||||||
IF_BIT_0(prob)
|
IF_BIT_0(prob)
|
||||||
{
|
{
|
||||||
UPDATE_0(prob)
|
UPDATE_0(prob)
|
||||||
prevByte = b;
|
prevByte = b;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
const Byte *v;
|
const Byte *v;
|
||||||
UPDATE_1(prob)
|
UPDATE_1(prob)
|
||||||
if (b == 0xE8)
|
if (b == 0xE8)
|
||||||
{
|
{
|
||||||
v = buf1;
|
v = buf1;
|
||||||
if (size1 < 4)
|
if (size1 < 4)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
buf1 += 4;
|
buf1 += 4;
|
||||||
size1 -= 4;
|
size1 -= 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v = buf2;
|
v = buf2;
|
||||||
if (size2 < 4)
|
if (size2 < 4)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
buf2 += 4;
|
buf2 += 4;
|
||||||
size2 -= 4;
|
size2 -= 4;
|
||||||
}
|
}
|
||||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
||||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
||||||
outBuf[outPos++] = (Byte)dest;
|
outBuf[outPos++] = (Byte)dest;
|
||||||
if (outPos == outSize)
|
if (outPos == outSize)
|
||||||
break;
|
break;
|
||||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||||
if (outPos == outSize)
|
if (outPos == outSize)
|
||||||
break;
|
break;
|
||||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||||
if (outPos == outSize)
|
if (outPos == outSize)
|
||||||
break;
|
break;
|
||||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||||
2009-02-07 : 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Conditions:
|
Conditions:
|
||||||
outSize <= FullOutputSize,
|
outSize <= FullOutputSize,
|
||||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||||
|
|
||||||
If buf0 overlaps outBuf, there are two required conditions:
|
If buf0 overlaps outBuf, there are two required conditions:
|
||||||
1) (buf0 >= outBuf)
|
1) (buf0 >= outBuf)
|
||||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int Bcj2_Decode(
|
int Bcj2_Decode(
|
||||||
const Byte *buf0, SizeT size0,
|
const Byte *buf0, SizeT size0,
|
||||||
const Byte *buf1, SizeT size1,
|
const Byte *buf1, SizeT size1,
|
||||||
const Byte *buf2, SizeT size2,
|
const Byte *buf2, SizeT size2,
|
||||||
const Byte *buf3, SizeT size3,
|
const Byte *buf3, SizeT size3,
|
||||||
Byte *outBuf, SizeT outSize);
|
Byte *outBuf, SizeT outSize);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
266
fex/7z_C/Bra.c
266
fex/7z_C/Bra.c
|
@ -1,133 +1,133 @@
|
||||||
/* Bra.c -- Converters for RISC code
|
/* Bra.c -- Converters for RISC code
|
||||||
2010-04-16 : Igor Pavlov : Public domain */
|
2010-04-16 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Bra.h"
|
#include "Bra.h"
|
||||||
|
|
||||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
{
|
{
|
||||||
SizeT i;
|
SizeT i;
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return 0;
|
return 0;
|
||||||
size -= 4;
|
size -= 4;
|
||||||
ip += 8;
|
ip += 8;
|
||||||
for (i = 0; i <= size; i += 4)
|
for (i = 0; i <= size; i += 4)
|
||||||
{
|
{
|
||||||
if (data[i + 3] == 0xEB)
|
if (data[i + 3] == 0xEB)
|
||||||
{
|
{
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
|
UInt32 src = ((UInt32)data[i + 2] << 16) | ((UInt32)data[i + 1] << 8) | (data[i + 0]);
|
||||||
src <<= 2;
|
src <<= 2;
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = ip + (UInt32)i + src;
|
dest = ip + (UInt32)i + src;
|
||||||
else
|
else
|
||||||
dest = src - (ip + (UInt32)i);
|
dest = src - (ip + (UInt32)i);
|
||||||
dest >>= 2;
|
dest >>= 2;
|
||||||
data[i + 2] = (Byte)(dest >> 16);
|
data[i + 2] = (Byte)(dest >> 16);
|
||||||
data[i + 1] = (Byte)(dest >> 8);
|
data[i + 1] = (Byte)(dest >> 8);
|
||||||
data[i + 0] = (Byte)dest;
|
data[i + 0] = (Byte)dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
{
|
{
|
||||||
SizeT i;
|
SizeT i;
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return 0;
|
return 0;
|
||||||
size -= 4;
|
size -= 4;
|
||||||
ip += 4;
|
ip += 4;
|
||||||
for (i = 0; i <= size; i += 2)
|
for (i = 0; i <= size; i += 2)
|
||||||
{
|
{
|
||||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||||
(data[i + 3] & 0xF8) == 0xF8)
|
(data[i + 3] & 0xF8) == 0xF8)
|
||||||
{
|
{
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
UInt32 src =
|
UInt32 src =
|
||||||
(((UInt32)data[i + 1] & 0x7) << 19) |
|
(((UInt32)data[i + 1] & 0x7) << 19) |
|
||||||
((UInt32)data[i + 0] << 11) |
|
((UInt32)data[i + 0] << 11) |
|
||||||
(((UInt32)data[i + 3] & 0x7) << 8) |
|
(((UInt32)data[i + 3] & 0x7) << 8) |
|
||||||
(data[i + 2]);
|
(data[i + 2]);
|
||||||
|
|
||||||
src <<= 1;
|
src <<= 1;
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = ip + (UInt32)i + src;
|
dest = ip + (UInt32)i + src;
|
||||||
else
|
else
|
||||||
dest = src - (ip + (UInt32)i);
|
dest = src - (ip + (UInt32)i);
|
||||||
dest >>= 1;
|
dest >>= 1;
|
||||||
|
|
||||||
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
data[i + 1] = (Byte)(0xF0 | ((dest >> 19) & 0x7));
|
||||||
data[i + 0] = (Byte)(dest >> 11);
|
data[i + 0] = (Byte)(dest >> 11);
|
||||||
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
data[i + 3] = (Byte)(0xF8 | ((dest >> 8) & 0x7));
|
||||||
data[i + 2] = (Byte)dest;
|
data[i + 2] = (Byte)dest;
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
{
|
{
|
||||||
SizeT i;
|
SizeT i;
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return 0;
|
return 0;
|
||||||
size -= 4;
|
size -= 4;
|
||||||
for (i = 0; i <= size; i += 4)
|
for (i = 0; i <= size; i += 4)
|
||||||
{
|
{
|
||||||
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||||
{
|
{
|
||||||
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
|
UInt32 src = ((UInt32)(data[i + 0] & 3) << 24) |
|
||||||
((UInt32)data[i + 1] << 16) |
|
((UInt32)data[i + 1] << 16) |
|
||||||
((UInt32)data[i + 2] << 8) |
|
((UInt32)data[i + 2] << 8) |
|
||||||
((UInt32)data[i + 3] & (~3));
|
((UInt32)data[i + 3] & (~3));
|
||||||
|
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = ip + (UInt32)i + src;
|
dest = ip + (UInt32)i + src;
|
||||||
else
|
else
|
||||||
dest = src - (ip + (UInt32)i);
|
dest = src - (ip + (UInt32)i);
|
||||||
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
data[i + 0] = (Byte)(0x48 | ((dest >> 24) & 0x3));
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
data[i + 3] &= 0x3;
|
data[i + 3] &= 0x3;
|
||||||
data[i + 3] |= dest;
|
data[i + 3] |= dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||||
{
|
{
|
||||||
UInt32 i;
|
UInt32 i;
|
||||||
if (size < 4)
|
if (size < 4)
|
||||||
return 0;
|
return 0;
|
||||||
size -= 4;
|
size -= 4;
|
||||||
for (i = 0; i <= size; i += 4)
|
for (i = 0; i <= size; i += 4)
|
||||||
{
|
{
|
||||||
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
||||||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
||||||
{
|
{
|
||||||
UInt32 src =
|
UInt32 src =
|
||||||
((UInt32)data[i + 0] << 24) |
|
((UInt32)data[i + 0] << 24) |
|
||||||
((UInt32)data[i + 1] << 16) |
|
((UInt32)data[i + 1] << 16) |
|
||||||
((UInt32)data[i + 2] << 8) |
|
((UInt32)data[i + 2] << 8) |
|
||||||
((UInt32)data[i + 3]);
|
((UInt32)data[i + 3]);
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
|
|
||||||
src <<= 2;
|
src <<= 2;
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = ip + i + src;
|
dest = ip + i + src;
|
||||||
else
|
else
|
||||||
dest = src - (ip + i);
|
dest = src - (ip + i);
|
||||||
dest >>= 2;
|
dest >>= 2;
|
||||||
|
|
||||||
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
||||||
|
|
||||||
data[i + 0] = (Byte)(dest >> 24);
|
data[i + 0] = (Byte)(dest >> 24);
|
||||||
data[i + 1] = (Byte)(dest >> 16);
|
data[i + 1] = (Byte)(dest >> 16);
|
||||||
data[i + 2] = (Byte)(dest >> 8);
|
data[i + 2] = (Byte)(dest >> 8);
|
||||||
data[i + 3] = (Byte)dest;
|
data[i + 3] = (Byte)dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
136
fex/7z_C/Bra.h
136
fex/7z_C/Bra.h
|
@ -1,68 +1,68 @@
|
||||||
/* Bra.h -- Branch converters for executables
|
/* Bra.h -- Branch converters for executables
|
||||||
2009-02-07 : 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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.
|
||||||
|
|
||||||
In:
|
In:
|
||||||
data - data buffer
|
data - data buffer
|
||||||
size - size of data
|
size - size of data
|
||||||
ip - current virtual Instruction Pinter (IP) value
|
ip - current virtual Instruction Pinter (IP) value
|
||||||
state - state variable for x86 converter
|
state - state variable for x86 converter
|
||||||
encoding - 0 (for decoding), 1 (for encoding)
|
encoding - 0 (for decoding), 1 (for encoding)
|
||||||
|
|
||||||
Out:
|
Out:
|
||||||
state - state variable for x86 converter
|
state - state variable for x86 converter
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The number of processed bytes. If you call these functions with multiple calls,
|
The number of processed bytes. If you call these functions with multiple calls,
|
||||||
you must start next call with first byte after block of processed bytes.
|
you must start next call with first byte after block of processed bytes.
|
||||||
|
|
||||||
Type Endian Alignment LookAhead
|
Type Endian Alignment LookAhead
|
||||||
|
|
||||||
x86 little 1 4
|
x86 little 1 4
|
||||||
ARMT little 2 2
|
ARMT little 2 2
|
||||||
ARM little 4 0
|
ARM little 4 0
|
||||||
PPC big 4 0
|
PPC big 4 0
|
||||||
SPARC big 4 0
|
SPARC big 4 0
|
||||||
IA64 little 16 0
|
IA64 little 16 0
|
||||||
|
|
||||||
size must be >= Alignment + LookAhead, if it's not last block.
|
size must be >= Alignment + LookAhead, if it's not last block.
|
||||||
If (size < Alignment + LookAhead), converter returns 0.
|
If (size < Alignment + LookAhead), converter returns 0.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
UInt32 ip = 0;
|
UInt32 ip = 0;
|
||||||
for ()
|
for ()
|
||||||
{
|
{
|
||||||
; size must be >= Alignment + LookAhead, if it's not last block
|
; size must be >= Alignment + LookAhead, if it's not last block
|
||||||
SizeT processed = Convert(data, size, ip, 1);
|
SizeT processed = Convert(data, size, ip, 1);
|
||||||
data += processed;
|
data += processed;
|
||||||
size -= processed;
|
size -= processed;
|
||||||
ip += processed;
|
ip += processed;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define x86_Convert_Init(state) { state = 0; }
|
#define x86_Convert_Init(state) { state = 0; }
|
||||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
170
fex/7z_C/Bra86.c
170
fex/7z_C/Bra86.c
|
@ -1,85 +1,85 @@
|
||||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||||
2008-10-04 : Igor Pavlov : Public domain */
|
2008-10-04 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "Bra.h"
|
#include "Bra.h"
|
||||||
|
|
||||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
||||||
|
|
||||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||||
|
|
||||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||||
{
|
{
|
||||||
SizeT bufferPos = 0, prevPosT;
|
SizeT bufferPos = 0, prevPosT;
|
||||||
UInt32 prevMask = *state & 0x7;
|
UInt32 prevMask = *state & 0x7;
|
||||||
if (size < 5)
|
if (size < 5)
|
||||||
return 0;
|
return 0;
|
||||||
ip += 5;
|
ip += 5;
|
||||||
prevPosT = (SizeT)0 - 1;
|
prevPosT = (SizeT)0 - 1;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte *p = data + bufferPos;
|
Byte *p = data + bufferPos;
|
||||||
Byte *limit = data + size - 4;
|
Byte *limit = data + size - 4;
|
||||||
for (; p < limit; p++)
|
for (; p < limit; p++)
|
||||||
if ((*p & 0xFE) == 0xE8)
|
if ((*p & 0xFE) == 0xE8)
|
||||||
break;
|
break;
|
||||||
bufferPos = (SizeT)(p - data);
|
bufferPos = (SizeT)(p - data);
|
||||||
if (p >= limit)
|
if (p >= limit)
|
||||||
break;
|
break;
|
||||||
prevPosT = bufferPos - prevPosT;
|
prevPosT = bufferPos - prevPosT;
|
||||||
if (prevPosT > 3)
|
if (prevPosT > 3)
|
||||||
prevMask = 0;
|
prevMask = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||||
if (prevMask != 0)
|
if (prevMask != 0)
|
||||||
{
|
{
|
||||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||||
{
|
{
|
||||||
prevPosT = bufferPos;
|
prevPosT = bufferPos;
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||||
bufferPos++;
|
bufferPos++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevPosT = bufferPos;
|
prevPosT = bufferPos;
|
||||||
|
|
||||||
if (Test86MSByte(p[4]))
|
if (Test86MSByte(p[4]))
|
||||||
{
|
{
|
||||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||||
UInt32 dest;
|
UInt32 dest;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
Byte b;
|
Byte b;
|
||||||
int index;
|
int index;
|
||||||
if (encoding)
|
if (encoding)
|
||||||
dest = (ip + (UInt32)bufferPos) + src;
|
dest = (ip + (UInt32)bufferPos) + src;
|
||||||
else
|
else
|
||||||
dest = src - (ip + (UInt32)bufferPos);
|
dest = src - (ip + (UInt32)bufferPos);
|
||||||
if (prevMask == 0)
|
if (prevMask == 0)
|
||||||
break;
|
break;
|
||||||
index = kMaskToBitNumber[prevMask] * 8;
|
index = kMaskToBitNumber[prevMask] * 8;
|
||||||
b = (Byte)(dest >> (24 - index));
|
b = (Byte)(dest >> (24 - index));
|
||||||
if (!Test86MSByte(b))
|
if (!Test86MSByte(b))
|
||||||
break;
|
break;
|
||||||
src = dest ^ ((1 << (32 - index)) - 1);
|
src = dest ^ ((1 << (32 - index)) - 1);
|
||||||
}
|
}
|
||||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||||
p[3] = (Byte)(dest >> 16);
|
p[3] = (Byte)(dest >> 16);
|
||||||
p[2] = (Byte)(dest >> 8);
|
p[2] = (Byte)(dest >> 8);
|
||||||
p[1] = (Byte)dest;
|
p[1] = (Byte)dest;
|
||||||
bufferPos += 5;
|
bufferPos += 5;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||||
bufferPos++;
|
bufferPos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prevPosT = bufferPos - prevPosT;
|
prevPosT = bufferPos - prevPosT;
|
||||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||||
return bufferPos;
|
return bufferPos;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,173 +1,173 @@
|
||||||
/* CpuArch.c -- CPU specific code
|
/* CpuArch.c -- CPU specific code
|
||||||
2010-10-26: Igor Pavlov : Public domain */
|
2010-10-26: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#include "CpuArch.h"
|
#include "CpuArch.h"
|
||||||
|
|
||||||
#ifdef MY_CPU_X86_OR_AMD64
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
||||||
#define USE_ASM
|
#define USE_ASM
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
||||||
static UInt32 CheckFlag(UInt32 flag)
|
static UInt32 CheckFlag(UInt32 flag)
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
__asm pushfd;
|
__asm pushfd;
|
||||||
__asm pop EAX;
|
__asm pop EAX;
|
||||||
__asm mov EDX, EAX;
|
__asm mov EDX, EAX;
|
||||||
__asm xor EAX, flag;
|
__asm xor EAX, flag;
|
||||||
__asm push EAX;
|
__asm push EAX;
|
||||||
__asm popfd;
|
__asm popfd;
|
||||||
__asm pushfd;
|
__asm pushfd;
|
||||||
__asm pop EAX;
|
__asm pop EAX;
|
||||||
__asm xor EAX, EDX;
|
__asm xor EAX, EDX;
|
||||||
__asm push EDX;
|
__asm push EDX;
|
||||||
__asm popfd;
|
__asm popfd;
|
||||||
__asm and flag, EAX;
|
__asm and flag, EAX;
|
||||||
#else
|
#else
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"pushf\n\t"
|
"pushf\n\t"
|
||||||
"pop %%EAX\n\t"
|
"pop %%EAX\n\t"
|
||||||
"movl %%EAX,%%EDX\n\t"
|
"movl %%EAX,%%EDX\n\t"
|
||||||
"xorl %0,%%EAX\n\t"
|
"xorl %0,%%EAX\n\t"
|
||||||
"push %%EAX\n\t"
|
"push %%EAX\n\t"
|
||||||
"popf\n\t"
|
"popf\n\t"
|
||||||
"pushf\n\t"
|
"pushf\n\t"
|
||||||
"pop %%EAX\n\t"
|
"pop %%EAX\n\t"
|
||||||
"xorl %%EDX,%%EAX\n\t"
|
"xorl %%EDX,%%EAX\n\t"
|
||||||
"push %%EDX\n\t"
|
"push %%EDX\n\t"
|
||||||
"popf\n\t"
|
"popf\n\t"
|
||||||
"andl %%EAX, %0\n\t":
|
"andl %%EAX, %0\n\t":
|
||||||
"=c" (flag) : "c" (flag));
|
"=c" (flag) : "c" (flag));
|
||||||
#endif
|
#endif
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
||||||
#else
|
#else
|
||||||
#define CHECK_CPUID_IS_SUPPORTED
|
#define CHECK_CPUID_IS_SUPPORTED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
static void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||||
{
|
{
|
||||||
#ifdef USE_ASM
|
#ifdef USE_ASM
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
UInt32 a2, b2, c2, d2;
|
UInt32 a2, b2, c2, d2;
|
||||||
__asm xor EBX, EBX;
|
__asm xor EBX, EBX;
|
||||||
__asm xor ECX, ECX;
|
__asm xor ECX, ECX;
|
||||||
__asm xor EDX, EDX;
|
__asm xor EDX, EDX;
|
||||||
__asm mov EAX, function;
|
__asm mov EAX, function;
|
||||||
__asm cpuid;
|
__asm cpuid;
|
||||||
__asm mov a2, EAX;
|
__asm mov a2, EAX;
|
||||||
__asm mov b2, EBX;
|
__asm mov b2, EBX;
|
||||||
__asm mov c2, ECX;
|
__asm mov c2, ECX;
|
||||||
__asm mov d2, EDX;
|
__asm mov d2, EDX;
|
||||||
|
|
||||||
*a = a2;
|
*a = a2;
|
||||||
*b = b2;
|
*b = b2;
|
||||||
*c = c2;
|
*c = c2;
|
||||||
*d = d2;
|
*d = d2;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Mac cross-compile compiler:
|
// Mac cross-compile compiler:
|
||||||
// can't find register in class 'BREG' while reloading 'asm'
|
// can't find register in class 'BREG' while reloading 'asm'
|
||||||
// so use class 'r' and register var binding
|
// so use class 'r' and register var binding
|
||||||
register _b asm("%bx");
|
register _b asm("%bx");
|
||||||
__asm__ __volatile__ (
|
__asm__ __volatile__ (
|
||||||
"cpuid"
|
"cpuid"
|
||||||
: "=a" (*a) ,
|
: "=a" (*a) ,
|
||||||
"=r" (_b) ,
|
"=r" (_b) ,
|
||||||
"=c" (*c) ,
|
"=c" (*c) ,
|
||||||
"=d" (*d)
|
"=d" (*d)
|
||||||
: "0" (function)) ;
|
: "0" (function)) ;
|
||||||
*b = _b;
|
*b = _b;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int CPUInfo[4];
|
int CPUInfo[4];
|
||||||
__cpuid(CPUInfo, function);
|
__cpuid(CPUInfo, function);
|
||||||
*a = CPUInfo[0];
|
*a = CPUInfo[0];
|
||||||
*b = CPUInfo[1];
|
*b = CPUInfo[1];
|
||||||
*c = CPUInfo[2];
|
*c = CPUInfo[2];
|
||||||
*d = CPUInfo[3];
|
*d = CPUInfo[3];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
|
Bool x86cpuid_CheckAndRead(Cx86cpuid *p)
|
||||||
{
|
{
|
||||||
CHECK_CPUID_IS_SUPPORTED
|
CHECK_CPUID_IS_SUPPORTED
|
||||||
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
||||||
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UInt32 kVendors[][3] =
|
static UInt32 kVendors[][3] =
|
||||||
{
|
{
|
||||||
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
||||||
{ 0x68747541, 0x69746E65, 0x444D4163},
|
{ 0x68747541, 0x69746E65, 0x444D4163},
|
||||||
{ 0x746E6543, 0x48727561, 0x736C7561}
|
{ 0x746E6543, 0x48727561, 0x736C7561}
|
||||||
};
|
};
|
||||||
|
|
||||||
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
||||||
{
|
{
|
||||||
const UInt32 *v = kVendors[i];
|
const UInt32 *v = kVendors[i];
|
||||||
if (v[0] == p->vendor[0] &&
|
if (v[0] == p->vendor[0] &&
|
||||||
v[1] == p->vendor[1] &&
|
v[1] == p->vendor[1] &&
|
||||||
v[2] == p->vendor[2])
|
v[2] == p->vendor[2])
|
||||||
return (int)i;
|
return (int)i;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool CPU_Is_InOrder()
|
Bool CPU_Is_InOrder()
|
||||||
{
|
{
|
||||||
Cx86cpuid p;
|
Cx86cpuid p;
|
||||||
int firm;
|
int firm;
|
||||||
UInt32 family, model;
|
UInt32 family, model;
|
||||||
if (!x86cpuid_CheckAndRead(&p))
|
if (!x86cpuid_CheckAndRead(&p))
|
||||||
return True;
|
return True;
|
||||||
family = x86cpuid_GetFamily(&p);
|
family = x86cpuid_GetFamily(&p);
|
||||||
model = x86cpuid_GetModel(&p);
|
model = x86cpuid_GetModel(&p);
|
||||||
firm = x86cpuid_GetFirm(&p);
|
firm = x86cpuid_GetFirm(&p);
|
||||||
switch (firm)
|
switch (firm)
|
||||||
{
|
{
|
||||||
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && model == 0x100C));
|
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_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
||||||
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
||||||
}
|
}
|
||||||
return True;
|
return True;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||||
static Bool CPU_Sys_Is_SSE_Supported()
|
static Bool CPU_Sys_Is_SSE_Supported()
|
||||||
{
|
{
|
||||||
OSVERSIONINFO vi;
|
OSVERSIONINFO vi;
|
||||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||||
if (!GetVersionEx(&vi))
|
if (!GetVersionEx(&vi))
|
||||||
return False;
|
return False;
|
||||||
return (vi.dwMajorVersion >= 5);
|
return (vi.dwMajorVersion >= 5);
|
||||||
}
|
}
|
||||||
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
||||||
#else
|
#else
|
||||||
#define CHECK_SYS_SSE_SUPPORT
|
#define CHECK_SYS_SSE_SUPPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Bool CPU_Is_Aes_Supported()
|
Bool CPU_Is_Aes_Supported()
|
||||||
{
|
{
|
||||||
Cx86cpuid p;
|
Cx86cpuid p;
|
||||||
CHECK_SYS_SSE_SUPPORT
|
CHECK_SYS_SSE_SUPPORT
|
||||||
if (!x86cpuid_CheckAndRead(&p))
|
if (!x86cpuid_CheckAndRead(&p))
|
||||||
return False;
|
return False;
|
||||||
return (p.c >> 25) & 1;
|
return (p.c >> 25) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,155 +1,155 @@
|
||||||
/* CpuArch.h -- CPU specific code
|
/* CpuArch.h -- CPU specific code
|
||||||
2010-10-26: Igor Pavlov : Public domain */
|
2010-10-26: Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __CPU_ARCH_H
|
#ifndef __CPU_ARCH_H
|
||||||
#define __CPU_ARCH_H
|
#define __CPU_ARCH_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
/*
|
/*
|
||||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
MY_CPU_LE means that 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).
|
If MY_CPU_LE is not defined, we don't know about that property of platform (it can be LITTLE ENDIAN).
|
||||||
|
|
||||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||||
If MY_CPU_LE_UNALIGN is not defined, we don't know 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_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||||
#define MY_CPU_AMD64
|
#define MY_CPU_AMD64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||||
#define MY_CPU_64BIT
|
#define MY_CPU_64BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_M_IX86) || defined(__i386__)
|
#if defined(_M_IX86) || defined(__i386__)
|
||||||
#define MY_CPU_X86
|
#define MY_CPU_X86
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||||
#define MY_CPU_X86_OR_AMD64
|
#define MY_CPU_X86_OR_AMD64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||||
#define MY_CPU_32BIT
|
#define MY_CPU_32BIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_M_ARM)
|
#if defined(_WIN32) && defined(_M_ARM)
|
||||||
#define MY_CPU_ARM_LE
|
#define MY_CPU_ARM_LE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_WIN32) && defined(_M_IA64)
|
#if defined(_WIN32) && defined(_M_IA64)
|
||||||
#define MY_CPU_IA64_LE
|
#define MY_CPU_IA64_LE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_X86_OR_AMD64)
|
#if defined(MY_CPU_X86_OR_AMD64)
|
||||||
#define MY_CPU_LE_UNALIGN
|
#define MY_CPU_LE_UNALIGN
|
||||||
#endif
|
#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__)
|
#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
|
#define MY_CPU_LE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__BIG_ENDIAN__)
|
#if defined(__BIG_ENDIAN__)
|
||||||
#define MY_CPU_BE
|
#define MY_CPU_BE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||||
Stop_Compiling_Bad_Endian
|
Stop_Compiling_Bad_Endian
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MY_CPU_LE_UNALIGN
|
#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 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);
|
#define SetUi64(p, d) *(UInt64 *)(p) = (d);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||||
|
|
||||||
#define GetUi32(p) ( \
|
#define GetUi32(p) ( \
|
||||||
((const Byte *)(p))[0] | \
|
((const Byte *)(p))[0] | \
|
||||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||||
((UInt32)((const Byte *)(p))[3] << 24))
|
((UInt32)((const Byte *)(p))[3] << 24))
|
||||||
|
|
||||||
#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); \
|
#define SetUi16(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); }
|
||||||
|
|
||||||
#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); \
|
#define SetUi64(p, d) { UInt64 _x64_ = (d); \
|
||||||
SetUi32(p, (UInt32)_x64_); \
|
SetUi32(p, (UInt32)_x64_); \
|
||||||
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
|
SetUi32(((Byte *)(p)) + 4, (UInt32)(_x64_ >> 32)); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(MY_CPU_LE_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)
|
||||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define GetBe32(p) ( \
|
#define GetBe32(p) ( \
|
||||||
((UInt32)((const Byte *)(p))[0] << 24) | \
|
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||||
((UInt32)((const Byte *)(p))[1] << 16) | \
|
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||||
((UInt32)((const Byte *)(p))[2] << 8) | \
|
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||||
((const Byte *)(p))[3] )
|
((const Byte *)(p))[3] )
|
||||||
|
|
||||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#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
|
#ifdef MY_CPU_X86_OR_AMD64
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UInt32 maxFunc;
|
UInt32 maxFunc;
|
||||||
UInt32 vendor[3];
|
UInt32 vendor[3];
|
||||||
UInt32 ver;
|
UInt32 ver;
|
||||||
UInt32 b;
|
UInt32 b;
|
||||||
UInt32 c;
|
UInt32 c;
|
||||||
UInt32 d;
|
UInt32 d;
|
||||||
} Cx86cpuid;
|
} Cx86cpuid;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
CPU_FIRM_INTEL,
|
CPU_FIRM_INTEL,
|
||||||
CPU_FIRM_AMD,
|
CPU_FIRM_AMD,
|
||||||
CPU_FIRM_VIA
|
CPU_FIRM_VIA
|
||||||
};
|
};
|
||||||
|
|
||||||
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
|
Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||||
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||||
|
|
||||||
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
#define x86cpuid_GetFamily(p) (((p)->ver >> 8) & 0xFF00F)
|
||||||
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
#define x86cpuid_GetModel(p) (((p)->ver >> 4) & 0xF00F)
|
||||||
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
#define x86cpuid_GetStepping(p) ((p)->ver & 0xF)
|
||||||
|
|
||||||
Bool CPU_Is_InOrder();
|
Bool CPU_Is_InOrder();
|
||||||
Bool CPU_Is_Aes_Supported();
|
Bool CPU_Is_Aes_Supported();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,371 +1,371 @@
|
||||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||||
2009-05-03 : Igor Pavlov : Public domain */
|
2009-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
/* #define SHOW_DEBUG_INFO */
|
/* #define SHOW_DEBUG_INFO */
|
||||||
|
|
||||||
#ifdef SHOW_DEBUG_INFO
|
#ifdef SHOW_DEBUG_INFO
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "Lzma2Dec.h"
|
#include "Lzma2Dec.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
00000000 - EOS
|
00000000 - EOS
|
||||||
00000001 U U - Uncompressed Reset Dic
|
00000001 U U - Uncompressed Reset Dic
|
||||||
00000010 U U - Uncompressed No Reset
|
00000010 U U - Uncompressed No Reset
|
||||||
100uuuuu U U P P - LZMA no reset
|
100uuuuu U U P P - LZMA no reset
|
||||||
101uuuuu U U P P - LZMA reset state
|
101uuuuu U U P P - LZMA reset state
|
||||||
110uuuuu U U P P S - LZMA reset state + new prop
|
110uuuuu U U P P S - LZMA reset state + new prop
|
||||||
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||||
|
|
||||||
u, U - Unpack Size
|
u, U - Unpack Size
|
||||||
P - Pack Size
|
P - Pack Size
|
||||||
S - Props
|
S - Props
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||||
#define LZMA2_CONTROL_EOF 0
|
#define LZMA2_CONTROL_EOF 0
|
||||||
|
|
||||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 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_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||||
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||||
|
|
||||||
#define LZMA2_LCLP_MAX 4
|
#define LZMA2_LCLP_MAX 4
|
||||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||||
|
|
||||||
#ifdef SHOW_DEBUG_INFO
|
#ifdef SHOW_DEBUG_INFO
|
||||||
#define PRF(x) x
|
#define PRF(x) x
|
||||||
#else
|
#else
|
||||||
#define PRF(x)
|
#define PRF(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
LZMA2_STATE_CONTROL,
|
LZMA2_STATE_CONTROL,
|
||||||
LZMA2_STATE_UNPACK0,
|
LZMA2_STATE_UNPACK0,
|
||||||
LZMA2_STATE_UNPACK1,
|
LZMA2_STATE_UNPACK1,
|
||||||
LZMA2_STATE_PACK0,
|
LZMA2_STATE_PACK0,
|
||||||
LZMA2_STATE_PACK1,
|
LZMA2_STATE_PACK1,
|
||||||
LZMA2_STATE_PROP,
|
LZMA2_STATE_PROP,
|
||||||
LZMA2_STATE_DATA,
|
LZMA2_STATE_DATA,
|
||||||
LZMA2_STATE_DATA_CONT,
|
LZMA2_STATE_DATA_CONT,
|
||||||
LZMA2_STATE_FINISHED,
|
LZMA2_STATE_FINISHED,
|
||||||
LZMA2_STATE_ERROR
|
LZMA2_STATE_ERROR
|
||||||
} ELzma2State;
|
} ELzma2State;
|
||||||
|
|
||||||
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||||
{
|
{
|
||||||
UInt32 dicSize;
|
UInt32 dicSize;
|
||||||
if (prop > 40)
|
if (prop > 40)
|
||||||
return SZ_ERROR_UNSUPPORTED;
|
return SZ_ERROR_UNSUPPORTED;
|
||||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||||
props[0] = (Byte)LZMA2_LCLP_MAX;
|
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||||
props[1] = (Byte)(dicSize);
|
props[1] = (Byte)(dicSize);
|
||||||
props[2] = (Byte)(dicSize >> 8);
|
props[2] = (Byte)(dicSize >> 8);
|
||||||
props[3] = (Byte)(dicSize >> 16);
|
props[3] = (Byte)(dicSize >> 16);
|
||||||
props[4] = (Byte)(dicSize >> 24);
|
props[4] = (Byte)(dicSize >> 24);
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
Byte props[LZMA_PROPS_SIZE];
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
Byte props[LZMA_PROPS_SIZE];
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Lzma2Dec_Init(CLzma2Dec *p)
|
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||||
{
|
{
|
||||||
p->state = LZMA2_STATE_CONTROL;
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
p->needInitDic = True;
|
p->needInitDic = True;
|
||||||
p->needInitState = True;
|
p->needInitState = True;
|
||||||
p->needInitProp = True;
|
p->needInitProp = True;
|
||||||
LzmaDec_Init(&p->decoder);
|
LzmaDec_Init(&p->decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||||
{
|
{
|
||||||
switch(p->state)
|
switch(p->state)
|
||||||
{
|
{
|
||||||
case LZMA2_STATE_CONTROL:
|
case LZMA2_STATE_CONTROL:
|
||||||
p->control = b;
|
p->control = b;
|
||||||
PRF(printf("\n %4X ", p->decoder.dicPos));
|
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||||
PRF(printf(" %2X", b));
|
PRF(printf(" %2X", b));
|
||||||
if (p->control == 0)
|
if (p->control == 0)
|
||||||
return LZMA2_STATE_FINISHED;
|
return LZMA2_STATE_FINISHED;
|
||||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
{
|
{
|
||||||
if ((p->control & 0x7F) > 2)
|
if ((p->control & 0x7F) > 2)
|
||||||
return LZMA2_STATE_ERROR;
|
return LZMA2_STATE_ERROR;
|
||||||
p->unpackSize = 0;
|
p->unpackSize = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
p->unpackSize = (UInt32)(p->control & 0x1F) << 16;
|
||||||
return LZMA2_STATE_UNPACK0;
|
return LZMA2_STATE_UNPACK0;
|
||||||
|
|
||||||
case LZMA2_STATE_UNPACK0:
|
case LZMA2_STATE_UNPACK0:
|
||||||
p->unpackSize |= (UInt32)b << 8;
|
p->unpackSize |= (UInt32)b << 8;
|
||||||
return LZMA2_STATE_UNPACK1;
|
return LZMA2_STATE_UNPACK1;
|
||||||
|
|
||||||
case LZMA2_STATE_UNPACK1:
|
case LZMA2_STATE_UNPACK1:
|
||||||
p->unpackSize |= (UInt32)b;
|
p->unpackSize |= (UInt32)b;
|
||||||
p->unpackSize++;
|
p->unpackSize++;
|
||||||
PRF(printf(" %8d", p->unpackSize));
|
PRF(printf(" %8d", p->unpackSize));
|
||||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||||
|
|
||||||
case LZMA2_STATE_PACK0:
|
case LZMA2_STATE_PACK0:
|
||||||
p->packSize = (UInt32)b << 8;
|
p->packSize = (UInt32)b << 8;
|
||||||
return LZMA2_STATE_PACK1;
|
return LZMA2_STATE_PACK1;
|
||||||
|
|
||||||
case LZMA2_STATE_PACK1:
|
case LZMA2_STATE_PACK1:
|
||||||
p->packSize |= (UInt32)b;
|
p->packSize |= (UInt32)b;
|
||||||
p->packSize++;
|
p->packSize++;
|
||||||
PRF(printf(" %8d", p->packSize));
|
PRF(printf(" %8d", p->packSize));
|
||||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||||
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||||
|
|
||||||
case LZMA2_STATE_PROP:
|
case LZMA2_STATE_PROP:
|
||||||
{
|
{
|
||||||
int lc, lp;
|
int lc, lp;
|
||||||
if (b >= (9 * 5 * 5))
|
if (b >= (9 * 5 * 5))
|
||||||
return LZMA2_STATE_ERROR;
|
return LZMA2_STATE_ERROR;
|
||||||
lc = b % 9;
|
lc = b % 9;
|
||||||
b /= 9;
|
b /= 9;
|
||||||
p->decoder.prop.pb = b / 5;
|
p->decoder.prop.pb = b / 5;
|
||||||
lp = b % 5;
|
lp = b % 5;
|
||||||
if (lc + lp > LZMA2_LCLP_MAX)
|
if (lc + lp > LZMA2_LCLP_MAX)
|
||||||
return LZMA2_STATE_ERROR;
|
return LZMA2_STATE_ERROR;
|
||||||
p->decoder.prop.lc = lc;
|
p->decoder.prop.lc = lc;
|
||||||
p->decoder.prop.lp = lp;
|
p->decoder.prop.lp = lp;
|
||||||
p->needInitProp = False;
|
p->needInitProp = False;
|
||||||
return LZMA2_STATE_DATA;
|
return LZMA2_STATE_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LZMA2_STATE_ERROR;
|
return LZMA2_STATE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||||
{
|
{
|
||||||
memcpy(p->dic + p->dicPos, src, size);
|
memcpy(p->dic + p->dicPos, src, size);
|
||||||
p->dicPos += size;
|
p->dicPos += size;
|
||||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||||
p->checkDicSize = p->prop.dicSize;
|
p->checkDicSize = p->prop.dicSize;
|
||||||
p->processedPos += (UInt32)size;
|
p->processedPos += (UInt32)size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
|
||||||
{
|
{
|
||||||
p->needFlush = 1;
|
p->needFlush = 1;
|
||||||
p->remainLen = 0;
|
p->remainLen = 0;
|
||||||
p->tempBufSize = 0;
|
p->tempBufSize = 0;
|
||||||
|
|
||||||
if (initDic)
|
if (initDic)
|
||||||
{
|
{
|
||||||
p->processedPos = 0;
|
p->processedPos = 0;
|
||||||
p->checkDicSize = 0;
|
p->checkDicSize = 0;
|
||||||
p->needInitState = 1;
|
p->needInitState = 1;
|
||||||
}
|
}
|
||||||
if (initState)
|
if (initState)
|
||||||
p->needInitState = 1;
|
p->needInitState = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||||
{
|
{
|
||||||
SizeT inSize = *srcLen;
|
SizeT inSize = *srcLen;
|
||||||
*srcLen = 0;
|
*srcLen = 0;
|
||||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
|
|
||||||
while (p->state != LZMA2_STATE_FINISHED)
|
while (p->state != LZMA2_STATE_FINISHED)
|
||||||
{
|
{
|
||||||
SizeT dicPos = p->decoder.dicPos;
|
SizeT dicPos = p->decoder.dicPos;
|
||||||
if (p->state == LZMA2_STATE_ERROR)
|
if (p->state == LZMA2_STATE_ERROR)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||||
{
|
{
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||||
{
|
{
|
||||||
if (*srcLen == inSize)
|
if (*srcLen == inSize)
|
||||||
{
|
{
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
(*srcLen)++;
|
(*srcLen)++;
|
||||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
SizeT destSizeCur = dicLimit - dicPos;
|
SizeT destSizeCur = dicLimit - dicPos;
|
||||||
SizeT srcSizeCur = inSize - *srcLen;
|
SizeT srcSizeCur = inSize - *srcLen;
|
||||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||||
|
|
||||||
if (p->unpackSize <= destSizeCur)
|
if (p->unpackSize <= destSizeCur)
|
||||||
{
|
{
|
||||||
destSizeCur = (SizeT)p->unpackSize;
|
destSizeCur = (SizeT)p->unpackSize;
|
||||||
curFinishMode = LZMA_FINISH_END;
|
curFinishMode = LZMA_FINISH_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||||
{
|
{
|
||||||
if (*srcLen == inSize)
|
if (*srcLen == inSize)
|
||||||
{
|
{
|
||||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p->state == LZMA2_STATE_DATA)
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
{
|
{
|
||||||
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
Bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||||
if (initDic)
|
if (initDic)
|
||||||
p->needInitProp = p->needInitState = True;
|
p->needInitProp = p->needInitState = True;
|
||||||
else if (p->needInitDic)
|
else if (p->needInitDic)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
p->needInitDic = False;
|
p->needInitDic = False;
|
||||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (srcSizeCur > destSizeCur)
|
if (srcSizeCur > destSizeCur)
|
||||||
srcSizeCur = destSizeCur;
|
srcSizeCur = destSizeCur;
|
||||||
|
|
||||||
if (srcSizeCur == 0)
|
if (srcSizeCur == 0)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||||
|
|
||||||
src += srcSizeCur;
|
src += srcSizeCur;
|
||||||
*srcLen += srcSizeCur;
|
*srcLen += srcSizeCur;
|
||||||
p->unpackSize -= (UInt32)srcSizeCur;
|
p->unpackSize -= (UInt32)srcSizeCur;
|
||||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SizeT outSizeProcessed;
|
SizeT outSizeProcessed;
|
||||||
SRes res;
|
SRes res;
|
||||||
|
|
||||||
if (p->state == LZMA2_STATE_DATA)
|
if (p->state == LZMA2_STATE_DATA)
|
||||||
{
|
{
|
||||||
int mode = LZMA2_GET_LZMA_MODE(p);
|
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||||
Bool initDic = (mode == 3);
|
Bool initDic = (mode == 3);
|
||||||
Bool initState = (mode > 0);
|
Bool initState = (mode > 0);
|
||||||
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
|
|
||||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||||
p->needInitDic = False;
|
p->needInitDic = False;
|
||||||
p->needInitState = False;
|
p->needInitState = False;
|
||||||
p->state = LZMA2_STATE_DATA_CONT;
|
p->state = LZMA2_STATE_DATA_CONT;
|
||||||
}
|
}
|
||||||
if (srcSizeCur > p->packSize)
|
if (srcSizeCur > p->packSize)
|
||||||
srcSizeCur = (SizeT)p->packSize;
|
srcSizeCur = (SizeT)p->packSize;
|
||||||
|
|
||||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
|
|
||||||
src += srcSizeCur;
|
src += srcSizeCur;
|
||||||
*srcLen += srcSizeCur;
|
*srcLen += srcSizeCur;
|
||||||
p->packSize -= (UInt32)srcSizeCur;
|
p->packSize -= (UInt32)srcSizeCur;
|
||||||
|
|
||||||
outSizeProcessed = p->decoder.dicPos - dicPos;
|
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||||
p->unpackSize -= (UInt32)outSizeProcessed;
|
p->unpackSize -= (UInt32)outSizeProcessed;
|
||||||
|
|
||||||
RINOK(res);
|
RINOK(res);
|
||||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||||
{
|
{
|
||||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||||
p->unpackSize != 0 || p->packSize != 0)
|
p->unpackSize != 0 || p->packSize != 0)
|
||||||
return SZ_ERROR_DATA;
|
return SZ_ERROR_DATA;
|
||||||
p->state = LZMA2_STATE_CONTROL;
|
p->state = LZMA2_STATE_CONTROL;
|
||||||
}
|
}
|
||||||
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||||
*status = LZMA_STATUS_NOT_FINISHED;
|
*status = LZMA_STATUS_NOT_FINISHED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, 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)
|
||||||
{
|
{
|
||||||
SizeT outSize = *destLen, inSize = *srcLen;
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
*srcLen = *destLen = 0;
|
*srcLen = *destLen = 0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
|
SizeT srcSizeCur = inSize, outSizeCur, dicPos;
|
||||||
ELzmaFinishMode curFinishMode;
|
ELzmaFinishMode curFinishMode;
|
||||||
SRes res;
|
SRes res;
|
||||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||||
p->decoder.dicPos = 0;
|
p->decoder.dicPos = 0;
|
||||||
dicPos = p->decoder.dicPos;
|
dicPos = p->decoder.dicPos;
|
||||||
if (outSize > p->decoder.dicBufSize - dicPos)
|
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||||
{
|
{
|
||||||
outSizeCur = p->decoder.dicBufSize;
|
outSizeCur = p->decoder.dicBufSize;
|
||||||
curFinishMode = LZMA_FINISH_ANY;
|
curFinishMode = LZMA_FINISH_ANY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
outSizeCur = dicPos + outSize;
|
outSizeCur = dicPos + outSize;
|
||||||
curFinishMode = finishMode;
|
curFinishMode = finishMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||||
src += srcSizeCur;
|
src += srcSizeCur;
|
||||||
inSize -= srcSizeCur;
|
inSize -= srcSizeCur;
|
||||||
*srcLen += srcSizeCur;
|
*srcLen += srcSizeCur;
|
||||||
outSizeCur = p->decoder.dicPos - dicPos;
|
outSizeCur = p->decoder.dicPos - dicPos;
|
||||||
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||||
dest += outSizeCur;
|
dest += outSizeCur;
|
||||||
outSize -= outSizeCur;
|
outSize -= outSizeCur;
|
||||||
*destLen += outSizeCur;
|
*destLen += outSizeCur;
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
return res;
|
return res;
|
||||||
if (outSizeCur == 0 || outSize == 0)
|
if (outSizeCur == 0 || outSize == 0)
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
||||||
{
|
{
|
||||||
CLzma2Dec decoder;
|
CLzma2Dec decoder;
|
||||||
SRes res;
|
SRes res;
|
||||||
SizeT outSize = *destLen, inSize = *srcLen;
|
SizeT outSize = *destLen, inSize = *srcLen;
|
||||||
Byte props[LZMA_PROPS_SIZE];
|
Byte props[LZMA_PROPS_SIZE];
|
||||||
|
|
||||||
Lzma2Dec_Construct(&decoder);
|
Lzma2Dec_Construct(&decoder);
|
||||||
|
|
||||||
*destLen = *srcLen = 0;
|
*destLen = *srcLen = 0;
|
||||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||||
decoder.decoder.dic = dest;
|
decoder.decoder.dic = dest;
|
||||||
decoder.decoder.dicBufSize = outSize;
|
decoder.decoder.dicBufSize = outSize;
|
||||||
|
|
||||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||||
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
|
RINOK(LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc));
|
||||||
|
|
||||||
*srcLen = inSize;
|
*srcLen = inSize;
|
||||||
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
|
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
|
||||||
*destLen = decoder.decoder.dicPos;
|
*destLen = decoder.decoder.dicPos;
|
||||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||||
res = SZ_ERROR_INPUT_EOF;
|
res = SZ_ERROR_INPUT_EOF;
|
||||||
|
|
||||||
LzmaDec_FreeProbs(&decoder.decoder, alloc);
|
LzmaDec_FreeProbs(&decoder.decoder, alloc);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,84 +1,84 @@
|
||||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||||
2009-05-03 : Igor Pavlov : Public domain */
|
2009-05-03 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMA2_DEC_H
|
#ifndef __LZMA2_DEC_H
|
||||||
#define __LZMA2_DEC_H
|
#define __LZMA2_DEC_H
|
||||||
|
|
||||||
#include "LzmaDec.h"
|
#include "LzmaDec.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ---------- State Interface ---------- */
|
/* ---------- State Interface ---------- */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CLzmaDec decoder;
|
CLzmaDec decoder;
|
||||||
UInt32 packSize;
|
UInt32 packSize;
|
||||||
UInt32 unpackSize;
|
UInt32 unpackSize;
|
||||||
int state;
|
int state;
|
||||||
Byte control;
|
Byte control;
|
||||||
Bool needInitDic;
|
Bool needInitDic;
|
||||||
Bool needInitState;
|
Bool needInitState;
|
||||||
Bool needInitProp;
|
Bool needInitProp;
|
||||||
} CLzma2Dec;
|
} CLzma2Dec;
|
||||||
|
|
||||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||||
|
|
||||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAlloc *alloc);
|
||||||
void Lzma2Dec_Init(CLzma2Dec *p);
|
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
finishMode:
|
finishMode:
|
||||||
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||||
LZMA_FINISH_ANY - use smallest number of input bytes
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
LZMA_FINISH_END - read EndOfStream marker after decoding
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
status:
|
status:
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
LZMA_STATUS_NOT_FINISHED
|
LZMA_STATUS_NOT_FINISHED
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- One Call Interface ---------- */
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
finishMode:
|
finishMode:
|
||||||
It has meaning only if the decoding reaches output limit (*destLen).
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
LZMA_FINISH_ANY - use smallest number of input bytes
|
LZMA_FINISH_ANY - use smallest number of input bytes
|
||||||
LZMA_FINISH_END - read EndOfStream marker after decoding
|
LZMA_FINISH_END - read EndOfStream marker after decoding
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
status:
|
status:
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
LZMA_STATUS_NOT_FINISHED
|
LZMA_STATUS_NOT_FINISHED
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
2000
fex/7z_C/LzmaDec.c
2000
fex/7z_C/LzmaDec.c
File diff suppressed because it is too large
Load Diff
|
@ -1,231 +1,231 @@
|
||||||
/* LzmaDec.h -- LZMA Decoder
|
/* LzmaDec.h -- LZMA Decoder
|
||||||
2009-02-07 : Igor Pavlov : Public domain */
|
2009-02-07 : Igor Pavlov : Public domain */
|
||||||
|
|
||||||
#ifndef __LZMA_DEC_H
|
#ifndef __LZMA_DEC_H
|
||||||
#define __LZMA_DEC_H
|
#define __LZMA_DEC_H
|
||||||
|
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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 */
|
||||||
|
|
||||||
#ifdef _LZMA_PROB32
|
#ifdef _LZMA_PROB32
|
||||||
#define CLzmaProb UInt32
|
#define CLzmaProb UInt32
|
||||||
#else
|
#else
|
||||||
#define CLzmaProb UInt16
|
#define CLzmaProb UInt16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Properties ---------- */
|
/* ---------- LZMA Properties ---------- */
|
||||||
|
|
||||||
#define LZMA_PROPS_SIZE 5
|
#define LZMA_PROPS_SIZE 5
|
||||||
|
|
||||||
typedef struct _CLzmaProps
|
typedef struct _CLzmaProps
|
||||||
{
|
{
|
||||||
unsigned lc, lp, pb;
|
unsigned lc, lp, pb;
|
||||||
UInt32 dicSize;
|
UInt32 dicSize;
|
||||||
} CLzmaProps;
|
} CLzmaProps;
|
||||||
|
|
||||||
/* LzmaProps_Decode - decodes properties
|
/* LzmaProps_Decode - decodes properties
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- LZMA Decoder state ---------- */
|
/* ---------- LZMA Decoder state ---------- */
|
||||||
|
|
||||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||||
|
|
||||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
CLzmaProps prop;
|
CLzmaProps prop;
|
||||||
CLzmaProb *probs;
|
CLzmaProb *probs;
|
||||||
Byte *dic;
|
Byte *dic;
|
||||||
const Byte *buf;
|
const Byte *buf;
|
||||||
UInt32 range, code;
|
UInt32 range, code;
|
||||||
SizeT dicPos;
|
SizeT dicPos;
|
||||||
SizeT dicBufSize;
|
SizeT dicBufSize;
|
||||||
UInt32 processedPos;
|
UInt32 processedPos;
|
||||||
UInt32 checkDicSize;
|
UInt32 checkDicSize;
|
||||||
unsigned state;
|
unsigned state;
|
||||||
UInt32 reps[4];
|
UInt32 reps[4];
|
||||||
unsigned remainLen;
|
unsigned remainLen;
|
||||||
int needFlush;
|
int needFlush;
|
||||||
int needInitState;
|
int needInitState;
|
||||||
UInt32 numProbs;
|
UInt32 numProbs;
|
||||||
unsigned tempBufSize;
|
unsigned tempBufSize;
|
||||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||||
} CLzmaDec;
|
} CLzmaDec;
|
||||||
|
|
||||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||||
|
|
||||||
void LzmaDec_Init(CLzmaDec *p);
|
void LzmaDec_Init(CLzmaDec *p);
|
||||||
|
|
||||||
/* There are two types of LZMA streams:
|
/* There are two types of LZMA streams:
|
||||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
LZMA_FINISH_ANY, /* finish at any point */
|
LZMA_FINISH_ANY, /* finish at any point */
|
||||||
LZMA_FINISH_END /* block must be finished at the end */
|
LZMA_FINISH_END /* block must be finished at the end */
|
||||||
} ELzmaFinishMode;
|
} ELzmaFinishMode;
|
||||||
|
|
||||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||||
|
|
||||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||||
|
|
||||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||||
and output value of destLen will be less than output buffer size limit.
|
and output value of destLen will be less than output buffer size limit.
|
||||||
You can check status result also.
|
You can check status result also.
|
||||||
|
|
||||||
You can use multiple checks to test data integrity after full decompression:
|
You can use multiple checks to test data integrity after full decompression:
|
||||||
1) Check Result and "status" variable.
|
1) Check Result and "status" variable.
|
||||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||||
You must use correct finish mode in that case. */
|
You must use correct finish mode in that case. */
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||||
} ELzmaStatus;
|
} ELzmaStatus;
|
||||||
|
|
||||||
/* ELzmaStatus is used only as output value for function call */
|
/* ELzmaStatus is used only as output value for function call */
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Interfaces ---------- */
|
/* ---------- Interfaces ---------- */
|
||||||
|
|
||||||
/* There are 3 levels of interfaces:
|
/* There are 3 levels of interfaces:
|
||||||
1) Dictionary Interface
|
1) Dictionary Interface
|
||||||
2) Buffer Interface
|
2) Buffer Interface
|
||||||
3) One Call Interface
|
3) One Call Interface
|
||||||
You can select any of these interfaces, but don't mix functions from different
|
You can select any of these interfaces, but don't mix functions from different
|
||||||
groups for same object. */
|
groups for same object. */
|
||||||
|
|
||||||
|
|
||||||
/* There are two variants to allocate state for Dictionary Interface:
|
/* There are two variants to allocate state for Dictionary Interface:
|
||||||
1) LzmaDec_Allocate / LzmaDec_Free
|
1) LzmaDec_Allocate / LzmaDec_Free
|
||||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||||
You can use variant 2, if you set dictionary buffer manually.
|
You can use variant 2, if you set dictionary buffer manually.
|
||||||
For Buffer Interface you must always use variant 1.
|
For Buffer Interface you must always use variant 1.
|
||||||
|
|
||||||
LzmaDec_Allocate* can return:
|
LzmaDec_Allocate* can return:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
||||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||||
|
|
||||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||||
|
|
||||||
/* ---------- Dictionary Interface ---------- */
|
/* ---------- Dictionary Interface ---------- */
|
||||||
|
|
||||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||||
dictionary to some other external buffer.
|
dictionary to some other external buffer.
|
||||||
You must work with CLzmaDec variables directly in this interface.
|
You must work with CLzmaDec variables directly in this interface.
|
||||||
|
|
||||||
STEPS:
|
STEPS:
|
||||||
LzmaDec_Constr()
|
LzmaDec_Constr()
|
||||||
LzmaDec_Allocate()
|
LzmaDec_Allocate()
|
||||||
for (each new stream)
|
for (each new stream)
|
||||||
{
|
{
|
||||||
LzmaDec_Init()
|
LzmaDec_Init()
|
||||||
while (it needs more decompression)
|
while (it needs more decompression)
|
||||||
{
|
{
|
||||||
LzmaDec_DecodeToDic()
|
LzmaDec_DecodeToDic()
|
||||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LzmaDec_Free()
|
LzmaDec_Free()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* LzmaDec_DecodeToDic
|
/* LzmaDec_DecodeToDic
|
||||||
|
|
||||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||||
|
|
||||||
finishMode:
|
finishMode:
|
||||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
status:
|
status:
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
LZMA_STATUS_NOT_FINISHED
|
LZMA_STATUS_NOT_FINISHED
|
||||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Buffer Interface ---------- */
|
/* ---------- Buffer Interface ---------- */
|
||||||
|
|
||||||
/* It's zlib-like interface.
|
/* It's zlib-like interface.
|
||||||
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
||||||
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
||||||
to work with CLzmaDec variables manually.
|
to work with CLzmaDec variables manually.
|
||||||
|
|
||||||
finishMode:
|
finishMode:
|
||||||
It has meaning only if the decoding reaches output limit (*destLen).
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- One Call Interface ---------- */
|
/* ---------- One Call Interface ---------- */
|
||||||
|
|
||||||
/* LzmaDecode
|
/* LzmaDecode
|
||||||
|
|
||||||
finishMode:
|
finishMode:
|
||||||
It has meaning only if the decoding reaches output limit (*destLen).
|
It has meaning only if the decoding reaches output limit (*destLen).
|
||||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
SZ_OK
|
SZ_OK
|
||||||
status:
|
status:
|
||||||
LZMA_STATUS_FINISHED_WITH_MARK
|
LZMA_STATUS_FINISHED_WITH_MARK
|
||||||
LZMA_STATUS_NOT_FINISHED
|
LZMA_STATUS_NOT_FINISHED
|
||||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||||
SZ_ERROR_DATA - Data error
|
SZ_ERROR_DATA - Data error
|
||||||
SZ_ERROR_MEM - Memory allocation error
|
SZ_ERROR_MEM - Memory allocation error
|
||||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
508
fex/7z_C/Types.h
508
fex/7z_C/Types.h
|
@ -1,254 +1,254 @@
|
||||||
/* Types.h -- Basic types
|
/* Types.h -- Basic types
|
||||||
2010-10-09 : 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 _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EXTERN_C_BEGIN
|
#ifndef EXTERN_C_BEGIN
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
#define EXTERN_C_BEGIN extern "C" {
|
#define EXTERN_C_BEGIN extern "C" {
|
||||||
#define EXTERN_C_END }
|
#define EXTERN_C_END }
|
||||||
#else
|
#else
|
||||||
#define EXTERN_C_BEGIN
|
#define EXTERN_C_BEGIN
|
||||||
#define EXTERN_C_END
|
#define EXTERN_C_END
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN_C_BEGIN
|
EXTERN_C_BEGIN
|
||||||
|
|
||||||
#define SZ_OK 0
|
#define SZ_OK 0
|
||||||
|
|
||||||
#define SZ_ERROR_DATA 1
|
#define SZ_ERROR_DATA 1
|
||||||
#define SZ_ERROR_MEM 2
|
#define SZ_ERROR_MEM 2
|
||||||
#define SZ_ERROR_CRC 3
|
#define SZ_ERROR_CRC 3
|
||||||
#define SZ_ERROR_UNSUPPORTED 4
|
#define SZ_ERROR_UNSUPPORTED 4
|
||||||
#define SZ_ERROR_PARAM 5
|
#define SZ_ERROR_PARAM 5
|
||||||
#define SZ_ERROR_INPUT_EOF 6
|
#define SZ_ERROR_INPUT_EOF 6
|
||||||
#define SZ_ERROR_OUTPUT_EOF 7
|
#define SZ_ERROR_OUTPUT_EOF 7
|
||||||
#define SZ_ERROR_READ 8
|
#define SZ_ERROR_READ 8
|
||||||
#define SZ_ERROR_WRITE 9
|
#define SZ_ERROR_WRITE 9
|
||||||
#define SZ_ERROR_PROGRESS 10
|
#define SZ_ERROR_PROGRESS 10
|
||||||
#define SZ_ERROR_FAIL 11
|
#define SZ_ERROR_FAIL 11
|
||||||
#define SZ_ERROR_THREAD 12
|
#define SZ_ERROR_THREAD 12
|
||||||
|
|
||||||
#define SZ_ERROR_ARCHIVE 16
|
#define SZ_ERROR_ARCHIVE 16
|
||||||
#define SZ_ERROR_NO_ARCHIVE 17
|
#define SZ_ERROR_NO_ARCHIVE 17
|
||||||
|
|
||||||
typedef int SRes;
|
typedef int SRes;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
typedef DWORD WRes;
|
typedef DWORD WRes;
|
||||||
#else
|
#else
|
||||||
typedef int WRes;
|
typedef int WRes;
|
||||||
#endif
|
#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
|
||||||
|
|
||||||
typedef unsigned char Byte;
|
typedef unsigned char Byte;
|
||||||
typedef short Int16;
|
typedef short Int16;
|
||||||
typedef unsigned short UInt16;
|
typedef unsigned short UInt16;
|
||||||
|
|
||||||
#ifdef _LZMA_UINT32_IS_ULONG
|
#ifdef _LZMA_UINT32_IS_ULONG
|
||||||
typedef long Int32;
|
typedef long Int32;
|
||||||
typedef unsigned long UInt32;
|
typedef unsigned long UInt32;
|
||||||
#else
|
#else
|
||||||
typedef int Int32;
|
typedef int Int32;
|
||||||
typedef unsigned int UInt32;
|
typedef unsigned int UInt32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _SZ_NO_INT_64
|
#ifdef _SZ_NO_INT_64
|
||||||
|
|
||||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||||
NOTES: Some code will work incorrectly in that case! */
|
NOTES: Some code will work incorrectly in that case! */
|
||||||
|
|
||||||
typedef long Int64;
|
typedef long Int64;
|
||||||
typedef unsigned long UInt64;
|
typedef unsigned long UInt64;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#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
|
#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
|
#define UINT64_CONST(n) n ## ULL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||||
typedef UInt32 SizeT;
|
typedef UInt32 SizeT;
|
||||||
#else
|
#else
|
||||||
typedef size_t SizeT;
|
typedef size_t SizeT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef int Bool;
|
typedef int Bool;
|
||||||
#define True 1
|
#define True 1
|
||||||
#define False 0
|
#define False 0
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define MY_STD_CALL __stdcall
|
#define MY_STD_CALL __stdcall
|
||||||
#else
|
#else
|
||||||
#define MY_STD_CALL
|
#define MY_STD_CALL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
#if _MSC_VER >= 1300
|
#if _MSC_VER >= 1300
|
||||||
#define MY_NO_INLINE __declspec(noinline)
|
#define MY_NO_INLINE __declspec(noinline)
|
||||||
#else
|
#else
|
||||||
#define MY_NO_INLINE
|
#define MY_NO_INLINE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MY_CDECL __cdecl
|
#define MY_CDECL __cdecl
|
||||||
#define MY_FAST_CALL __fastcall
|
#define MY_FAST_CALL __fastcall
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define MY_CDECL
|
#define MY_CDECL
|
||||||
#define MY_FAST_CALL
|
#define MY_FAST_CALL
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* The following interfaces use first parameter as pointer to structure */
|
/* The following interfaces use first parameter as pointer to structure */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||||
} IByteIn;
|
} IByteIn;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void (*Write)(void *p, Byte b);
|
void (*Write)(void *p, Byte b);
|
||||||
} IByteOut;
|
} IByteOut;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
SRes (*Read)(void *p, 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 allowed */
|
(output(*size) < input(*size)) is allowed */
|
||||||
} ISeqInStream;
|
} ISeqInStream;
|
||||||
|
|
||||||
/* it can return SZ_ERROR_INPUT_EOF */
|
/* it can return SZ_ERROR_INPUT_EOF */
|
||||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||||
/* Returns: result - the number of actually written bytes.
|
/* Returns: result - the number of actually written bytes.
|
||||||
(result < size) means error */
|
(result < size) means error */
|
||||||
} ISeqOutStream;
|
} ISeqOutStream;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SZ_SEEK_SET = 0,
|
SZ_SEEK_SET = 0,
|
||||||
SZ_SEEK_CUR = 1,
|
SZ_SEEK_CUR = 1,
|
||||||
SZ_SEEK_END = 2
|
SZ_SEEK_END = 2
|
||||||
} ESzSeek;
|
} ESzSeek;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
} ISeekInStream;
|
} ISeekInStream;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRes (*Look)(void *p, const 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 */
|
||||||
SRes (*Skip)(void *p, size_t offset);
|
SRes (*Skip)(void *p, size_t offset);
|
||||||
/* offset must be <= output(*size) of Look */
|
/* offset must be <= output(*size) of Look */
|
||||||
|
|
||||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||||
} ILookInStream;
|
} ILookInStream;
|
||||||
|
|
||||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
||||||
|
|
||||||
/* reads via ILookInStream::Read */
|
/* reads via ILookInStream::Read */
|
||||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||||
|
|
||||||
#define LookToRead_BUF_SIZE (1 << 14)
|
#define LookToRead_BUF_SIZE (1 << 14)
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ILookInStream s;
|
ILookInStream s;
|
||||||
ISeekInStream *realStream;
|
ISeekInStream *realStream;
|
||||||
size_t pos;
|
size_t pos;
|
||||||
size_t size;
|
size_t size;
|
||||||
Byte buf[LookToRead_BUF_SIZE];
|
Byte buf[LookToRead_BUF_SIZE];
|
||||||
} CLookToRead;
|
} CLookToRead;
|
||||||
|
|
||||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||||
void LookToRead_Init(CLookToRead *p);
|
void LookToRead_Init(CLookToRead *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ISeqInStream s;
|
ISeqInStream s;
|
||||||
ILookInStream *realStream;
|
ILookInStream *realStream;
|
||||||
} CSecToLook;
|
} CSecToLook;
|
||||||
|
|
||||||
void SecToLook_CreateVTable(CSecToLook *p);
|
void SecToLook_CreateVTable(CSecToLook *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
ISeqInStream s;
|
ISeqInStream s;
|
||||||
ILookInStream *realStream;
|
ILookInStream *realStream;
|
||||||
} CSecToRead;
|
} CSecToRead;
|
||||||
|
|
||||||
void SecToRead_CreateVTable(CSecToRead *p);
|
void SecToRead_CreateVTable(CSecToRead *p);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||||
/* Returns: result. (result != SZ_OK) means break.
|
/* Returns: result. (result != SZ_OK) means break.
|
||||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||||
} ICompressProgress;
|
} ICompressProgress;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
void *(*Alloc)(void *p, size_t size);
|
void *(*Alloc)(void *p, size_t size);
|
||||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||||
} ISzAlloc;
|
} ISzAlloc;
|
||||||
|
|
||||||
#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 _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
#define CHAR_PATH_SEPARATOR '\\'
|
#define CHAR_PATH_SEPARATOR '\\'
|
||||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||||
#define STRING_PATH_SEPARATOR "\\"
|
#define STRING_PATH_SEPARATOR "\\"
|
||||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define CHAR_PATH_SEPARATOR '/'
|
#define CHAR_PATH_SEPARATOR '/'
|
||||||
#define WCHAR_PATH_SEPARATOR L'/'
|
#define WCHAR_PATH_SEPARATOR L'/'
|
||||||
#define STRING_PATH_SEPARATOR "/"
|
#define STRING_PATH_SEPARATOR "/"
|
||||||
#define WSTRING_PATH_SEPARATOR L"/"
|
#define WSTRING_PATH_SEPARATOR L"/"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EXTERN_C_END
|
EXTERN_C_END
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
1188
fex/7z_C/lzma.txt
1188
fex/7z_C/lzma.txt
File diff suppressed because it is too large
Load Diff
142
fex/changes.txt
142
fex/changes.txt
|
@ -1,71 +1,71 @@
|
||||||
File_Extractor Change Log
|
File_Extractor Change Log
|
||||||
-------------------------
|
-------------------------
|
||||||
- Change that might break code.
|
- Change that might break code.
|
||||||
+ Improvement that is unlikely to break any code.
|
+ Improvement that is unlikely to break any code.
|
||||||
* Other changes.
|
* Other changes.
|
||||||
|
|
||||||
|
|
||||||
File_Extractor 1.0.0 (2009-10-12)
|
File_Extractor 1.0.0 (2009-10-12)
|
||||||
--------------------
|
--------------------
|
||||||
- Added fex_stat() which MUST be called before getting current file
|
- Added fex_stat() which MUST be called before getting current file
|
||||||
information beyond name, like fex_size().
|
information beyond name, like fex_size().
|
||||||
|
|
||||||
- Changed fex_*() functions to always report error via return value,
|
- Changed fex_*() functions to always report error via return value,
|
||||||
rather than sometimes via a parameter. This will break user code that
|
rather than sometimes via a parameter. This will break user code that
|
||||||
uses fex_data(), fex_open(), fex_open_type(), and fex_identify_file().
|
uses fex_data(), fex_open(), fex_open_type(), and fex_identify_file().
|
||||||
See demos for usage.
|
See demos for usage.
|
||||||
|
|
||||||
- Deprecated C++ interface. Use fex.h and nothing else to access library
|
- Deprecated C++ interface. Use fex.h and nothing else to access library
|
||||||
from user code.
|
from user code.
|
||||||
|
|
||||||
- Removed archive types (fex_zip_type, etc.) from interface. Use
|
- Removed archive types (fex_zip_type, etc.) from interface. Use
|
||||||
fex_identify_extension() to get particular type.
|
fex_identify_extension() to get particular type.
|
||||||
|
|
||||||
- Removed fex_mini.c, unzip.h, and unrarlib.h for now, as maintaining
|
- Removed fex_mini.c, unzip.h, and unrarlib.h for now, as maintaining
|
||||||
them was too taxing. If others express desire for them, I can re-add
|
them was too taxing. If others express desire for them, I can re-add
|
||||||
them.
|
them.
|
||||||
|
|
||||||
- Removed fex_scan_only() and fex_read_once(), as they don't improve
|
- Removed fex_scan_only() and fex_read_once(), as they don't improve
|
||||||
performance anymore. Use fex_read() in place of fex_read_once().
|
performance anymore. Use fex_read() in place of fex_read_once().
|
||||||
|
|
||||||
- Removed fex_remain(). Use fex_size()-fex_tell() to find number of
|
- Removed fex_remain(). Use fex_size()-fex_tell() to find number of
|
||||||
bytes remaining.
|
bytes remaining.
|
||||||
|
|
||||||
- Removed fex_set_user_data() and related functions, as they didn't seem
|
- Removed fex_set_user_data() and related functions, as they didn't seem
|
||||||
useful to anyone.
|
useful to anyone.
|
||||||
|
|
||||||
- Removed fex_type_t structure from interface and added accessors
|
- Removed fex_type_t structure from interface and added accessors
|
||||||
instead (fex_type_name(), fex_type_extension()).
|
instead (fex_type_name(), fex_type_extension()).
|
||||||
|
|
||||||
+ Improved archive file type determination to reject other archive types
|
+ Improved archive file type determination to reject other archive types
|
||||||
not handled by the library, rather than opening them as binary files.
|
not handled by the library, rather than opening them as binary files.
|
||||||
|
|
||||||
+ Added Doxygen compatibility to fex.h.
|
+ Added Doxygen compatibility to fex.h.
|
||||||
|
|
||||||
+ Added fex_crc32() to quickly get CRC-32 of current file from archive
|
+ Added fex_crc32() to quickly get CRC-32 of current file from archive
|
||||||
header, without having to read entire file to calculate it.
|
header, without having to read entire file to calculate it.
|
||||||
|
|
||||||
+ Added fex_err_code() to get numeric error code, along with other
|
+ Added fex_err_code() to get numeric error code, along with other
|
||||||
helpful error-related functions. Also added more documentation on how to
|
helpful error-related functions. Also added more documentation on how to
|
||||||
handle library errors in user code.
|
handle library errors in user code.
|
||||||
|
|
||||||
+ Added fex_init() for use in multi-threaded programs.
|
+ Added fex_init() for use in multi-threaded programs.
|
||||||
|
|
||||||
+ Added fex_seek_arc() to seek to particular file in archive.
|
+ Added fex_seek_arc() to seek to particular file in archive.
|
||||||
|
|
||||||
+ Added fex_wname() to get Unicode name of current file.
|
+ Added fex_wname() to get Unicode name of current file.
|
||||||
|
|
||||||
+ Added support for building as DLL.
|
+ Added support for building as DLL.
|
||||||
|
|
||||||
+ Added support for wide-character file paths on Windows, enabled with
|
+ Added support for wide-character file paths on Windows, enabled with
|
||||||
BLARGG_UTF8_PATHS (thanks to byuu for the idea). This is necessary to
|
BLARGG_UTF8_PATHS (thanks to byuu for the idea). This is necessary to
|
||||||
support file paths on non-English Windows systems.
|
support file paths on non-English Windows systems.
|
||||||
|
|
||||||
+ Started using unit testing during development.
|
+ Started using unit testing during development.
|
||||||
|
|
||||||
+ Updated to 7-zip 4.65, unrar_core 3.8.5.
|
+ Updated to 7-zip 4.65, unrar_core 3.8.5.
|
||||||
|
|
||||||
|
|
||||||
File_Extractor 0.4.3 (2008-12-08)
|
File_Extractor 0.4.3 (2008-12-08)
|
||||||
--------------------
|
--------------------
|
||||||
* Limited release
|
* Limited release
|
||||||
|
|
660
fex/fex.txt
660
fex/fex.txt
|
@ -1,330 +1,330 @@
|
||||||
File_Extractor 1.0.0
|
File_Extractor 1.0.0
|
||||||
--------------------
|
--------------------
|
||||||
Author : Shay Green <gblargg@gmail.com>
|
Author : Shay Green <gblargg@gmail.com>
|
||||||
Website : http://code.google.com/p/file-extractor/
|
Website : http://code.google.com/p/file-extractor/
|
||||||
License : GNU LGPL 2.1 or later for all except unrar
|
License : GNU LGPL 2.1 or later for all except unrar
|
||||||
Language: C interface, C++ implementation
|
Language: C interface, C++ implementation
|
||||||
|
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
--------
|
--------
|
||||||
* Overview
|
* Overview
|
||||||
* Limitations
|
* Limitations
|
||||||
* Extracting file data
|
* Extracting file data
|
||||||
* Archive file type handling
|
* Archive file type handling
|
||||||
* Using in multiple threads
|
* Using in multiple threads
|
||||||
* Error handling
|
* Error handling
|
||||||
* Solving problems
|
* Solving problems
|
||||||
* Thanks
|
* Thanks
|
||||||
|
|
||||||
|
|
||||||
Overview
|
Overview
|
||||||
--------
|
--------
|
||||||
File_Exactor (fex) allows you to write one version of file-opening code
|
File_Exactor (fex) allows you to write one version of file-opening code
|
||||||
that handles normal files and archives of files. It presents each as a
|
that handles normal files and archives of files. It presents each as a
|
||||||
series of files that you can scan and optionally extract; a single file
|
series of files that you can scan and optionally extract; a single file
|
||||||
is made to act like an archive of just one file, so your code doesn't
|
is made to act like an archive of just one file, so your code doesn't
|
||||||
need to do anything special to handle it.
|
need to do anything special to handle it.
|
||||||
|
|
||||||
Basic steps for scanning and extracting from an archive:
|
Basic steps for scanning and extracting from an archive:
|
||||||
|
|
||||||
* Open an archive or normal file using fex_open().
|
* Open an archive or normal file using fex_open().
|
||||||
* Scanning/extraction loop:
|
* Scanning/extraction loop:
|
||||||
- Exit loop if fex_done() returns true.
|
- Exit loop if fex_done() returns true.
|
||||||
- Get current file's name with fex_name().
|
- Get current file's name with fex_name().
|
||||||
- If more file information is needed, call fex_stat() first.
|
- If more file information is needed, call fex_stat() first.
|
||||||
- If extracting, use fex_data() or fex_read().
|
- If extracting, use fex_data() or fex_read().
|
||||||
- Go to next file in archive with fex_next().
|
- Go to next file in archive with fex_next().
|
||||||
* Close archive and free memory with fex_close().
|
* Close archive and free memory with fex_close().
|
||||||
|
|
||||||
You can stop scanning an archive at any point, for example once you've
|
You can stop scanning an archive at any point, for example once you've
|
||||||
found the file you're looking for. If you need to go back to the first
|
found the file you're looking for. If you need to go back to the first
|
||||||
file, call fex_rewind() at any time. Be sure to check error codes
|
file, call fex_rewind() at any time. Be sure to check error codes
|
||||||
returned by most functions.
|
returned by most functions.
|
||||||
|
|
||||||
|
|
||||||
Limitations
|
Limitations
|
||||||
-----------
|
-----------
|
||||||
All archives:
|
All archives:
|
||||||
* A file's checksum is verified only after ALL its data is extracted.
|
* A file's checksum is verified only after ALL its data is extracted.
|
||||||
* Encryption, segmentation, files larger than 2GB, and other extra
|
* Encryption, segmentation, files larger than 2GB, and other extra
|
||||||
features are not supported.
|
features are not supported.
|
||||||
|
|
||||||
GZ archives:
|
GZ archives:
|
||||||
* Only gzip archives of a single file are supported. If it has multiple
|
* Only gzip archives of a single file are supported. If it has multiple
|
||||||
files, the reported size will be wrong. Multi-file gzip archives are
|
files, the reported size will be wrong. Multi-file gzip archives are
|
||||||
very rare.
|
very rare.
|
||||||
|
|
||||||
ZIP archives:
|
ZIP archives:
|
||||||
* Supports files compressed using either deflation or store
|
* Supports files compressed using either deflation or store
|
||||||
(uncompressed). Other compression schemes like BZip2 and Deflate64 are
|
(uncompressed). Other compression schemes like BZip2 and Deflate64 are
|
||||||
not supported.
|
not supported.
|
||||||
* Archive must have a valid directory structure at the end.
|
* Archive must have a valid directory structure at the end.
|
||||||
|
|
||||||
RAR archives:
|
RAR archives:
|
||||||
* Support for really old 1.x archives might not work. If you have some
|
* Support for really old 1.x archives might not work. If you have some
|
||||||
of these old archives, send them to me so I can test them.
|
of these old archives, send them to me so I can test them.
|
||||||
|
|
||||||
7-zip:
|
7-zip:
|
||||||
* Solid archives can currently use lots of memory when open.
|
* Solid archives can currently use lots of memory when open.
|
||||||
|
|
||||||
|
|
||||||
Extracting file data
|
Extracting file data
|
||||||
--------------------
|
--------------------
|
||||||
A file's data can be extracted with one or more calls to fex_read(), as
|
A file's data can be extracted with one or more calls to fex_read(), as
|
||||||
you would read from a normal file. Use fex_tell() to find out how much
|
you would read from a normal file. Use fex_tell() to find out how much
|
||||||
has already been read. Use this if you need the data read into your own
|
has already been read. Use this if you need the data read into your own
|
||||||
structure in memory.
|
structure in memory.
|
||||||
|
|
||||||
File data can also be extracted to memory by the library with
|
File data can also be extracted to memory by the library with
|
||||||
fex_data(). The pointer returned is valid only until you go to another
|
fex_data(). The pointer returned is valid only until you go to another
|
||||||
file or close the archive, so this is only useful if you need to examine
|
file or close the archive, so this is only useful if you need to examine
|
||||||
or process the data immediately and not keep it around for later.
|
or process the data immediately and not keep it around for later.
|
||||||
Archive extractors naturally keep a copy of the extracted data in memory
|
Archive extractors naturally keep a copy of the extracted data in memory
|
||||||
already for solid archive types (currently 7-zip and RAR), so this
|
already for solid archive types (currently 7-zip and RAR), so this
|
||||||
function is optimized to avoid making a second copy of it in those
|
function is optimized to avoid making a second copy of it in those
|
||||||
cases.
|
cases.
|
||||||
|
|
||||||
Use fex_size() to find the size of the extracted data. Remember that
|
Use fex_size() to find the size of the extracted data. Remember that
|
||||||
fex_stat() or fex_data() must be called BEFORE calling fex_size().
|
fex_stat() or fex_data() must be called BEFORE calling fex_size().
|
||||||
|
|
||||||
|
|
||||||
Archive file type handling
|
Archive file type handling
|
||||||
--------------------------
|
--------------------------
|
||||||
By default, fex uses the filename extension and header to determine
|
By default, fex uses the filename extension and header to determine
|
||||||
archive type. If the filename extension is unrecognized or it lacks an
|
archive type. If the filename extension is unrecognized or it lacks an
|
||||||
extension, fex examines the first few bytes of the file. If still
|
extension, fex examines the first few bytes of the file. If still
|
||||||
unrecognized, fex opens it as binary. Fex also checks for common archive
|
unrecognized, fex opens it as binary. Fex also checks for common archive
|
||||||
types that it doesn't support, so that it can reject as unsupported them
|
types that it doesn't support, so that it can reject as unsupported them
|
||||||
rather than unhelpfully opening them as binary.
|
rather than unhelpfully opening them as binary.
|
||||||
|
|
||||||
Your file format might itself be an archive, for example your files end
|
Your file format might itself be an archive, for example your files end
|
||||||
in ".rsn" yet are normal RAR archives, or they end in ".vgz" and are
|
in ".rsn" yet are normal RAR archives, or they end in ".vgz" and are
|
||||||
gzipped. This is why fex checks the headers of files with unknown
|
gzipped. This is why fex checks the headers of files with unknown
|
||||||
filename extensions, rather than treating them as binary or rejecting
|
filename extensions, rather than treating them as binary or rejecting
|
||||||
them.
|
them.
|
||||||
|
|
||||||
Type identification can be customized by using the various
|
Type identification can be customized by using the various
|
||||||
identification functions and fex_open_type(). For example, you could
|
identification functions and fex_open_type(). For example, you could
|
||||||
avoid the header check:
|
avoid the header check:
|
||||||
|
|
||||||
fex_t* fex;
|
fex_t* fex;
|
||||||
fex_type_t type = fex_identify_extension( path );
|
fex_type_t type = fex_identify_extension( path );
|
||||||
if ( type == NULL )
|
if ( type == NULL )
|
||||||
error( "Unsupported archive type" );
|
error( "Unsupported archive type" );
|
||||||
|
|
||||||
error( fex_open_type( &fex, path, type ) );
|
error( fex_open_type( &fex, path, type ) );
|
||||||
|
|
||||||
Note that you'll only get a NULL type for known archive type that fex
|
Note that you'll only get a NULL type for known archive type that fex
|
||||||
doesn't handle; you won't get it for your own files, for example
|
doesn't handle; you won't get it for your own files, for example
|
||||||
fex_identify_extension("myfile.foo") won't return NULL (unless for some
|
fex_identify_extension("myfile.foo") won't return NULL (unless for some
|
||||||
reason you've disabled binary file support).
|
reason you've disabled binary file support).
|
||||||
|
|
||||||
Use fex_type_list() to get a list of the types fex supports, for example
|
Use fex_type_list() to get a list of the types fex supports, for example
|
||||||
to tell the user what archive types your program supports:
|
to tell the user what archive types your program supports:
|
||||||
|
|
||||||
const fex_type_t* t;
|
const fex_type_t* t;
|
||||||
for ( t = fex_type_list(); *t; t++ )
|
for ( t = fex_type_list(); *t; t++ )
|
||||||
printf( "%s\n", fex_type_name( *t ) );
|
printf( "%s\n", fex_type_name( *t ) );
|
||||||
|
|
||||||
To get the fex_type_t for a particular archive type, use
|
To get the fex_type_t for a particular archive type, use
|
||||||
fex_identify_extension():
|
fex_identify_extension():
|
||||||
|
|
||||||
fex_type_t zip_type = fex_identify_extension( ".zip" );
|
fex_type_t zip_type = fex_identify_extension( ".zip" );
|
||||||
if ( zip_type == NULL )
|
if ( zip_type == NULL )
|
||||||
error( "ZIP isn't supported" );
|
error( "ZIP isn't supported" );
|
||||||
|
|
||||||
Be sure to check the result as shown, rather than assuming the library
|
Be sure to check the result as shown, rather than assuming the library
|
||||||
supports a particular archive type. Use an extension of "" to get the
|
supports a particular archive type. Use an extension of "" to get the
|
||||||
type for binary files:
|
type for binary files:
|
||||||
|
|
||||||
fex_type_t bin_type = fex_identify_extension( "" );
|
fex_type_t bin_type = fex_identify_extension( "" );
|
||||||
if ( bin_type == NULL )
|
if ( bin_type == NULL )
|
||||||
error( "Binary files aren't supported?!?" );
|
error( "Binary files aren't supported?!?" );
|
||||||
|
|
||||||
|
|
||||||
Using in multiple threads
|
Using in multiple threads
|
||||||
-------------------------
|
-------------------------
|
||||||
Fex supports multi-threaded programs. If only one thread at a time is
|
Fex supports multi-threaded programs. If only one thread at a time is
|
||||||
using the library, nothing special needs to be done. If more than one
|
using the library, nothing special needs to be done. If more than one
|
||||||
thread is using the library, the following must be done:
|
thread is using the library, the following must be done:
|
||||||
|
|
||||||
* Call fex_init() from the main thread and ensure it completes before
|
* Call fex_init() from the main thread and ensure it completes before
|
||||||
any other threads use any fex functions. This initializes shared data
|
any other threads use any fex functions. This initializes shared data
|
||||||
tables used by the extractors.
|
tables used by the extractors.
|
||||||
|
|
||||||
* For each archive opened, only access it from one thread at a time.
|
* For each archive opened, only access it from one thread at a time.
|
||||||
Different archives can be accessed from different threads without any
|
Different archives can be accessed from different threads without any
|
||||||
synchronization, since fex uses no global variables. If the same archive
|
synchronization, since fex uses no global variables. If the same archive
|
||||||
must be accessed from multiple threads, all calls to any fex functions
|
must be accessed from multiple threads, all calls to any fex functions
|
||||||
must be in critical section(s).
|
must be in critical section(s).
|
||||||
|
|
||||||
|
|
||||||
Unicode file paths on Windows
|
Unicode file paths on Windows
|
||||||
-----------------------------
|
-----------------------------
|
||||||
If using Windows and your program supports Unicode file paths, enable
|
If using Windows and your program supports Unicode file paths, enable
|
||||||
BLARGG_UTF8_PATHS in blargg_config.h, and convert your wide-character
|
BLARGG_UTF8_PATHS in blargg_config.h, and convert your wide-character
|
||||||
paths to UTF-8 before passing them to fex.h functions:
|
paths to UTF-8 before passing them to fex.h functions:
|
||||||
|
|
||||||
/* Wide-character path that could have come from system */
|
/* Wide-character path that could have come from system */
|
||||||
wchar_t wide_path [] = L"demo.zip";
|
wchar_t wide_path [] = L"demo.zip";
|
||||||
|
|
||||||
/* Convert from wide path and check for error */
|
/* Convert from wide path and check for error */
|
||||||
char* path = fex_wide_to_path( wide_path );
|
char* path = fex_wide_to_path( wide_path );
|
||||||
if ( path == NULL )
|
if ( path == NULL )
|
||||||
error( "Out of memory" );
|
error( "Out of memory" );
|
||||||
|
|
||||||
/* Use converted path for fex call */
|
/* Use converted path for fex call */
|
||||||
error( fex_open( &fex, path ) );
|
error( fex_open( &fex, path ) );
|
||||||
|
|
||||||
/* Free memory used by path */
|
/* Free memory used by path */
|
||||||
fex_free_path( path );
|
fex_free_path( path );
|
||||||
|
|
||||||
The converted path can be used with any of the fex functions that take
|
The converted path can be used with any of the fex functions that take
|
||||||
paths, for example fex_identify_extension() or fex_has_extension().
|
paths, for example fex_identify_extension() or fex_has_extension().
|
||||||
|
|
||||||
|
|
||||||
Error handling
|
Error handling
|
||||||
--------------
|
--------------
|
||||||
Most functions that can fail return fex_err_t, a pointer type. On
|
Most functions that can fail return fex_err_t, a pointer type. On
|
||||||
failure they return a pointer to an error object, and on success they
|
failure they return a pointer to an error object, and on success they
|
||||||
return NULL. Use fex_err_code() to get a conventional error code, or
|
return NULL. Use fex_err_code() to get a conventional error code, or
|
||||||
fex_err_str() to get a string suitable for reporting to the user.
|
fex_err_str() to get a string suitable for reporting to the user.
|
||||||
|
|
||||||
There are two basic approches that your code can use to handle library
|
There are two basic approches that your code can use to handle library
|
||||||
errors. It can return errors, or report them and exit the function via
|
errors. It can return errors, or report them and exit the function via
|
||||||
some other means.
|
some other means.
|
||||||
|
|
||||||
Your code can return errors as the library does, using fex_err_t:
|
Your code can return errors as the library does, using fex_err_t:
|
||||||
|
|
||||||
#define RETURN_ERR( expr ) \
|
#define RETURN_ERR( expr ) \
|
||||||
do {\
|
do {\
|
||||||
fex_err_t err = (expr);\
|
fex_err_t err = (expr);\
|
||||||
if ( err != NULL )\
|
if ( err != NULL )\
|
||||||
return err;\
|
return err;\
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
fex_err_t my_func()
|
fex_err_t my_func()
|
||||||
{
|
{
|
||||||
RETURN_ERR( fex_foo() );
|
RETURN_ERR( fex_foo() );
|
||||||
RETURN_ERR( fex_bar() );
|
RETURN_ERR( fex_bar() );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
If you have your own error codes, you can convert fex's errors to them:
|
If you have your own error codes, you can convert fex's errors to them:
|
||||||
|
|
||||||
// error codes that differ from library's
|
// error codes that differ from library's
|
||||||
enum {
|
enum {
|
||||||
my_ok = 0,
|
my_ok = 0,
|
||||||
my_generic_error = 123,
|
my_generic_error = 123,
|
||||||
my_out_of_memory = 456,
|
my_out_of_memory = 456,
|
||||||
my_file_not_found = 789
|
my_file_not_found = 789
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
|
|
||||||
int convert_error( fex_err_t err )
|
int convert_error( fex_err_t err )
|
||||||
{
|
{
|
||||||
switch ( fex_err_code( err ) )
|
switch ( fex_err_code( err ) )
|
||||||
{
|
{
|
||||||
case fex_ok: return my_ok;
|
case fex_ok: return my_ok;
|
||||||
case fex_err_generic: return my_generic_error;
|
case fex_err_generic: return my_generic_error;
|
||||||
case fex_err_memory: return my_out_of_memory;
|
case fex_err_memory: return my_out_of_memory;
|
||||||
case fex_err_file_missing: return my_file_not_found;
|
case fex_err_file_missing: return my_file_not_found;
|
||||||
// ...
|
// ...
|
||||||
default: return my_generic_error;
|
default: return my_generic_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RETURN_ERR( expr ) \
|
#define RETURN_ERR( expr ) \
|
||||||
do {\
|
do {\
|
||||||
fex_err_t err = (expr);\
|
fex_err_t err = (expr);\
|
||||||
if ( err != NULL )\
|
if ( err != NULL )\
|
||||||
return convert_error( err );\
|
return convert_error( err );\
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
int my_func()
|
int my_func()
|
||||||
{
|
{
|
||||||
RETURN_ERR( fex_foo() );
|
RETURN_ERR( fex_foo() );
|
||||||
RETURN_ERR( fex_bar() );
|
RETURN_ERR( fex_bar() );
|
||||||
return my_ok;
|
return my_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
The other approach is to pass all errors to an error handler function
|
The other approach is to pass all errors to an error handler function
|
||||||
that never returns if passed a non-success error value:
|
that never returns if passed a non-success error value:
|
||||||
|
|
||||||
// never returns if err != NULL
|
// never returns if err != NULL
|
||||||
void handle_error( fex_err_t err );
|
void handle_error( fex_err_t err );
|
||||||
|
|
||||||
void my_func()
|
void my_func()
|
||||||
{
|
{
|
||||||
handle_error( fex_foo() );
|
handle_error( fex_foo() );
|
||||||
handle_error( fex_bar() );
|
handle_error( fex_bar() );
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_error() could print the error and exit the program:
|
handle_error() could print the error and exit the program:
|
||||||
|
|
||||||
void handle_error( fex_err_t err )
|
void handle_error( fex_err_t err )
|
||||||
{
|
{
|
||||||
if ( err != NULL )
|
if ( err != NULL )
|
||||||
{
|
{
|
||||||
const char* str = fex_err_str( err );
|
const char* str = fex_err_str( err );
|
||||||
printf( "Error: %s\n", str );
|
printf( "Error: %s\n", str );
|
||||||
exit( EXIT_FAILURE );
|
exit( EXIT_FAILURE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_error() could also throw a C++ exception (or equivalently in C,
|
handle_error() could also throw a C++ exception (or equivalently in C,
|
||||||
longmp() back to a setjmp() done inside caller()):
|
longmp() back to a setjmp() done inside caller()):
|
||||||
|
|
||||||
void handle_error( fex_err_t err )
|
void handle_error( fex_err_t err )
|
||||||
{
|
{
|
||||||
switch ( fex_err_code( err ) )
|
switch ( fex_err_code( err ) )
|
||||||
{
|
{
|
||||||
case fex_ok: return;
|
case fex_ok: return;
|
||||||
case fex_err_memory: throw std::bad_alloc();
|
case fex_err_memory: throw std::bad_alloc();
|
||||||
// ...
|
// ...
|
||||||
case fex_err_generic:
|
case fex_err_generic:
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error( fex_err_str( err ) );
|
throw std::runtime_error( fex_err_str( err ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void caller()
|
void caller()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
my_func();
|
my_func();
|
||||||
}
|
}
|
||||||
catch ( const std::exception& e )
|
catch ( const std::exception& e )
|
||||||
{
|
{
|
||||||
printf( "Error: %s\n", e.what() );
|
printf( "Error: %s\n", e.what() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Solving problems
|
Solving problems
|
||||||
----------------
|
----------------
|
||||||
If you're having problems, try the following:
|
If you're having problems, try the following:
|
||||||
|
|
||||||
* Enable debugging support in your environment. This enables assertions
|
* Enable debugging support in your environment. This enables assertions
|
||||||
and other run-time checks. In particular, be sure NDEBUG isn't defined.
|
and other run-time checks. In particular, be sure NDEBUG isn't defined.
|
||||||
|
|
||||||
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
|
* Turn the compiler's optimizer is off. Sometimes an optimizer generates
|
||||||
bad code.
|
bad code.
|
||||||
|
|
||||||
* If multiple threads are being used, ensure that only one at a time is
|
* If multiple threads are being used, ensure that only one at a time is
|
||||||
accessing a given set of objects from the library. This library is not
|
accessing a given set of objects from the library. This library is not
|
||||||
in general thread-safe, though independent objects can be used in
|
in general thread-safe, though independent objects can be used in
|
||||||
separate threads.
|
separate threads.
|
||||||
|
|
||||||
* If all else fails, see if the demo works.
|
* If all else fails, see if the demo works.
|
||||||
|
|
||||||
|
|
||||||
Thanks
|
Thanks
|
||||||
------
|
------
|
||||||
Thanks to Richard Bannister, Kode54, byuu, Cless, and DJRobX for testing
|
Thanks to Richard Bannister, Kode54, byuu, Cless, and DJRobX for testing
|
||||||
and giving feedback for the library. Thanks to the authors of zlib,
|
and giving feedback for the library. Thanks to the authors of zlib,
|
||||||
unrar, and 7-zip.
|
unrar, and 7-zip.
|
||||||
|
|
||||||
--
|
--
|
||||||
Shay Green <gblargg@gmail.com>
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
|
@ -1,77 +1,77 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Binary_Extractor.h"
|
#include "Binary_Extractor.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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
// TODO: could close file once data has been read into memory
|
// TODO: could close file once data has been read into memory
|
||||||
|
|
||||||
static File_Extractor* new_binary()
|
static File_Extractor* new_binary()
|
||||||
{
|
{
|
||||||
return BLARGG_NEW Binary_Extractor;
|
return BLARGG_NEW Binary_Extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_type_t_ const fex_bin_type [1] = {{
|
fex_type_t_ const fex_bin_type [1] = {{
|
||||||
"",
|
"",
|
||||||
&new_binary,
|
&new_binary,
|
||||||
"file",
|
"file",
|
||||||
NULL
|
NULL
|
||||||
}};
|
}};
|
||||||
|
|
||||||
Binary_Extractor::Binary_Extractor() :
|
Binary_Extractor::Binary_Extractor() :
|
||||||
File_Extractor( fex_bin_type )
|
File_Extractor( fex_bin_type )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Binary_Extractor::~Binary_Extractor()
|
Binary_Extractor::~Binary_Extractor()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::open_path_v()
|
blargg_err_t Binary_Extractor::open_path_v()
|
||||||
{
|
{
|
||||||
set_name( arc_path() );
|
set_name( arc_path() );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::open_v()
|
blargg_err_t Binary_Extractor::open_v()
|
||||||
{
|
{
|
||||||
set_name( arc_path() );
|
set_name( arc_path() );
|
||||||
set_info( arc().remain(), 0, 0 );
|
set_info( arc().remain(), 0, 0 );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Binary_Extractor::close_v()
|
void Binary_Extractor::close_v()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::next_v()
|
blargg_err_t Binary_Extractor::next_v()
|
||||||
{
|
{
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::rewind_v()
|
blargg_err_t Binary_Extractor::rewind_v()
|
||||||
{
|
{
|
||||||
return open_path_v();
|
return open_path_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::stat_v()
|
blargg_err_t Binary_Extractor::stat_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( open_arc_file() );
|
RETURN_ERR( open_arc_file() );
|
||||||
RETURN_ERR( arc().seek( 0 ) );
|
RETURN_ERR( arc().seek( 0 ) );
|
||||||
return open_v();
|
return open_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Binary_Extractor::extract_v( void* p, int n )
|
blargg_err_t Binary_Extractor::extract_v( void* p, int n )
|
||||||
{
|
{
|
||||||
return arc().read( p, n );
|
return arc().read( p, n );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
// Presents a single file as an "archive" of just that file.
|
// Presents a single file as an "archive" of just that file.
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BINARY_EXTRACTOR_H
|
#ifndef BINARY_EXTRACTOR_H
|
||||||
#define BINARY_EXTRACTOR_H
|
#define BINARY_EXTRACTOR_H
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
|
|
||||||
class Binary_Extractor : public File_Extractor {
|
class Binary_Extractor : public File_Extractor {
|
||||||
public:
|
public:
|
||||||
Binary_Extractor();
|
Binary_Extractor();
|
||||||
virtual ~Binary_Extractor();
|
virtual ~Binary_Extractor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t open_path_v();
|
virtual blargg_err_t open_path_v();
|
||||||
virtual blargg_err_t open_v();
|
virtual blargg_err_t open_v();
|
||||||
virtual void close_v();
|
virtual void close_v();
|
||||||
|
|
||||||
virtual blargg_err_t next_v();
|
virtual blargg_err_t next_v();
|
||||||
virtual blargg_err_t rewind_v();
|
virtual blargg_err_t rewind_v();
|
||||||
|
|
||||||
virtual blargg_err_t stat_v();
|
virtual blargg_err_t stat_v();
|
||||||
virtual blargg_err_t extract_v( void*, int );
|
virtual blargg_err_t extract_v( void*, int );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,264 +1,264 @@
|
||||||
// Lightweight interface for reading data from byte stream
|
// Lightweight interface for reading data from byte stream
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef DATA_READER_H
|
#ifndef DATA_READER_H
|
||||||
#define DATA_READER_H
|
#define DATA_READER_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
/* Some functions accept a long instead of int for convenience where caller has
|
/* Some functions accept a long instead of int for convenience where caller has
|
||||||
a long due to some other interface, and would otherwise have to get a warning,
|
a long due to some other interface, and would otherwise have to get a warning,
|
||||||
or cast it (and verify that it wasn't outside the range of an int).
|
or cast it (and verify that it wasn't outside the range of an int).
|
||||||
|
|
||||||
To really support huge (>2GB) files, long isn't a solution, since there's no
|
To really support huge (>2GB) files, long isn't a solution, since there's no
|
||||||
guarantee it's more than 32 bits. We'd need to use long long (if available), or
|
guarantee it's more than 32 bits. We'd need to use long long (if available), or
|
||||||
something compiler-specific, and change all places file sizes or offsets are
|
something compiler-specific, and change all places file sizes or offsets are
|
||||||
used. */
|
used. */
|
||||||
|
|
||||||
// Supports reading and finding out how many bytes are remaining
|
// Supports reading and finding out how many bytes are remaining
|
||||||
class Data_Reader {
|
class Data_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more
|
// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more
|
||||||
// tham remain() bytes doesn't result in error, just *n being set to remain().
|
// tham remain() bytes doesn't result in error, just *n being set to remain().
|
||||||
blargg_err_t read_avail( void* p, int* n );
|
blargg_err_t read_avail( void* p, int* n );
|
||||||
blargg_err_t read_avail( void* p, long* n );
|
blargg_err_t read_avail( void* p, long* n );
|
||||||
|
|
||||||
// Reads exactly n bytes, or returns error if they couldn't ALL be read.
|
// Reads exactly n bytes, or returns error if they couldn't ALL be read.
|
||||||
// Reading past end of file results in blargg_err_file_eof.
|
// Reading past end of file results in blargg_err_file_eof.
|
||||||
blargg_err_t read( void* p, int n );
|
blargg_err_t read( void* p, int n );
|
||||||
|
|
||||||
// Number of bytes remaining until end of file
|
// Number of bytes remaining until end of file
|
||||||
int remain() const { return remain_; }
|
int remain() const { return remain_; }
|
||||||
|
|
||||||
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
|
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
|
||||||
blargg_err_t skip( int n );
|
blargg_err_t skip( int n );
|
||||||
|
|
||||||
virtual ~Data_Reader() { }
|
virtual ~Data_Reader() { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Data_Reader( const Data_Reader& );
|
Data_Reader( const Data_Reader& );
|
||||||
Data_Reader& operator = ( const Data_Reader& );
|
Data_Reader& operator = ( const Data_Reader& );
|
||||||
|
|
||||||
// Derived interface
|
// Derived interface
|
||||||
protected:
|
protected:
|
||||||
Data_Reader() : remain_( 0 ) { }
|
Data_Reader() : remain_( 0 ) { }
|
||||||
|
|
||||||
// Sets remain
|
// Sets remain
|
||||||
void set_remain( int n ) { assert( n >= 0 ); remain_ = n; }
|
void set_remain( int n ) { assert( n >= 0 ); remain_ = n; }
|
||||||
|
|
||||||
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
|
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
|
||||||
// AFTER this call succeeds, not before. set_remain() should NOT be called from this.
|
// AFTER this call succeeds, not before. set_remain() should NOT be called from this.
|
||||||
virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
||||||
|
|
||||||
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
|
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
|
||||||
// and discards it. Value of remain() is updated AFTER this call succeeds, not
|
// and discards it. Value of remain() is updated AFTER this call succeeds, not
|
||||||
// before. set_remain() should NOT be called from this.
|
// before. set_remain() should NOT be called from this.
|
||||||
virtual blargg_err_t skip_v( int n );
|
virtual blargg_err_t skip_v( int n );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
BLARGG_DISABLE_NOTHROW
|
BLARGG_DISABLE_NOTHROW
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int remain_;
|
int remain_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Supports seeking in addition to Data_Reader operations
|
// Supports seeking in addition to Data_Reader operations
|
||||||
class File_Reader : public Data_Reader {
|
class File_Reader : public Data_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Size of file
|
// Size of file
|
||||||
int size() const { return size_; }
|
int size() const { return size_; }
|
||||||
|
|
||||||
// Current position in file
|
// Current position in file
|
||||||
int tell() const { return size_ - remain(); }
|
int tell() const { return size_ - remain(); }
|
||||||
|
|
||||||
// Goes to new position
|
// Goes to new position
|
||||||
blargg_err_t seek( int );
|
blargg_err_t seek( int );
|
||||||
|
|
||||||
// Derived interface
|
// Derived interface
|
||||||
protected:
|
protected:
|
||||||
// Sets size and resets position
|
// Sets size and resets position
|
||||||
void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); }
|
void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); }
|
||||||
void set_size( long n ) { set_size( STATIC_CAST(int, n) ); }
|
void set_size( long n ) { set_size( STATIC_CAST(int, n) ); }
|
||||||
|
|
||||||
// Sets reported position
|
// Sets reported position
|
||||||
void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }
|
void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }
|
||||||
|
|
||||||
// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated
|
// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated
|
||||||
// AFTER this call succeeds, not before. set_* functions should NOT be called from this.
|
// AFTER this call succeeds, not before. set_* functions should NOT be called from this.
|
||||||
virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
File_Reader() : size_( 0 ) { }
|
File_Reader() : size_( 0 ) { }
|
||||||
|
|
||||||
virtual blargg_err_t skip_v( int );
|
virtual blargg_err_t skip_v( int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int size_;
|
int size_;
|
||||||
|
|
||||||
void set_remain(); // avoid accidental use of set_remain
|
void set_remain(); // avoid accidental use of set_remain
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Reads from file on disk
|
// Reads from file on disk
|
||||||
class Std_File_Reader : public File_Reader {
|
class Std_File_Reader : public File_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Opens file
|
// Opens file
|
||||||
blargg_err_t open( const char path [] );
|
blargg_err_t open( const char path [] );
|
||||||
|
|
||||||
// Closes file if one was open
|
// Closes file if one was open
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
// Switches to unbuffered mode. Useful if buffering is already being
|
// Switches to unbuffered mode. Useful if buffering is already being
|
||||||
// done at a higher level.
|
// done at a higher level.
|
||||||
void make_unbuffered();
|
void make_unbuffered();
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
Std_File_Reader();
|
Std_File_Reader();
|
||||||
virtual ~Std_File_Reader();
|
virtual ~Std_File_Reader();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
virtual blargg_err_t seek_v( int );
|
virtual blargg_err_t seek_v( int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* file_;
|
void* file_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Treats range of memory as a file
|
// Treats range of memory as a file
|
||||||
class Mem_File_Reader : public File_Reader {
|
class Mem_File_Reader : public File_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Mem_File_Reader( const void* begin, long size );
|
Mem_File_Reader( const void* begin, long size );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
virtual blargg_err_t seek_v( int );
|
virtual blargg_err_t seek_v( int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* const begin;
|
const char* const begin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Allows only count bytes to be read from reader passed
|
// Allows only count bytes to be read from reader passed
|
||||||
class Subset_Reader : public Data_Reader {
|
class Subset_Reader : public Data_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Subset_Reader( Data_Reader*, int count );
|
Subset_Reader( Data_Reader*, int count );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Data_Reader* const in;
|
Data_Reader* const in;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Joins already-read header and remaining data into original file.
|
// Joins already-read header and remaining data into original file.
|
||||||
// Meant for cases where you've already read header and don't want
|
// Meant for cases where you've already read header and don't want
|
||||||
// to seek and re-read data (for efficiency).
|
// to seek and re-read data (for efficiency).
|
||||||
class Remaining_Reader : public Data_Reader {
|
class Remaining_Reader : public Data_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Remaining_Reader( void const* header, int header_size, Data_Reader* );
|
Remaining_Reader( void const* header, int header_size, Data_Reader* );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Data_Reader* const in;
|
Data_Reader* const in;
|
||||||
void const* header;
|
void const* header;
|
||||||
int header_remain;
|
int header_remain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Invokes callback function to read data
|
// Invokes callback function to read data
|
||||||
extern "C" { // necessary to be usable from C
|
extern "C" { // necessary to be usable from C
|
||||||
typedef const char* (*callback_reader_func_t)(
|
typedef const char* (*callback_reader_func_t)(
|
||||||
void* user_data, // Same value passed to constructor
|
void* user_data, // Same value passed to constructor
|
||||||
void* out, // Buffer to place data into
|
void* out, // Buffer to place data into
|
||||||
int count // Number of bytes to read
|
int count // Number of bytes to read
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
class Callback_Reader : public Data_Reader {
|
class Callback_Reader : public Data_Reader {
|
||||||
public:
|
public:
|
||||||
typedef callback_reader_func_t callback_t;
|
typedef callback_reader_func_t callback_t;
|
||||||
Callback_Reader( callback_t, long size, void* user_data );
|
Callback_Reader( callback_t, long size, void* user_data );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
callback_t const callback;
|
callback_t const callback;
|
||||||
void* const user_data;
|
void* const user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Invokes callback function to read data
|
// Invokes callback function to read data
|
||||||
extern "C" { // necessary to be usable from C
|
extern "C" { // necessary to be usable from C
|
||||||
typedef const char* (*callback_file_reader_func_t)(
|
typedef const char* (*callback_file_reader_func_t)(
|
||||||
void* user_data, // Same value passed to constructor
|
void* user_data, // Same value passed to constructor
|
||||||
void* out, // Buffer to place data into
|
void* out, // Buffer to place data into
|
||||||
int count, // Number of bytes to read
|
int count, // Number of bytes to read
|
||||||
int pos // Position in file to read from
|
int pos // Position in file to read from
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
class Callback_File_Reader : public File_Reader {
|
class Callback_File_Reader : public File_Reader {
|
||||||
public:
|
public:
|
||||||
typedef callback_file_reader_func_t callback_t;
|
typedef callback_file_reader_func_t callback_t;
|
||||||
Callback_File_Reader( callback_t, long size, void* user_data );
|
Callback_File_Reader( callback_t, long size, void* user_data );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
virtual blargg_err_t seek_v( int );
|
virtual blargg_err_t seek_v( int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
callback_t const callback;
|
callback_t const callback;
|
||||||
void* const user_data;
|
void* const user_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB_H
|
#ifdef HAVE_ZLIB_H
|
||||||
|
|
||||||
// Reads file compressed with gzip (or uncompressed)
|
// Reads file compressed with gzip (or uncompressed)
|
||||||
class Gzip_File_Reader : public File_Reader {
|
class Gzip_File_Reader : public File_Reader {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Opens possibly gzipped file
|
// Opens possibly gzipped file
|
||||||
blargg_err_t open( const char path [] );
|
blargg_err_t open( const char path [] );
|
||||||
|
|
||||||
// Closes file if one was open
|
// Closes file if one was open
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
Gzip_File_Reader();
|
Gzip_File_Reader();
|
||||||
~Gzip_File_Reader();
|
~Gzip_File_Reader();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
virtual blargg_err_t seek_v( int );
|
virtual blargg_err_t seek_v( int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// void* so "zlib.h" doesn't have to be included here
|
// void* so "zlib.h" doesn't have to be included here
|
||||||
void* file_;
|
void* file_;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char* blargg_to_utf8( const wchar_t* );
|
char* blargg_to_utf8( const wchar_t* );
|
||||||
wchar_t* blargg_to_wide( const char* );
|
wchar_t* blargg_to_wide( const char* );
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,341 +1,341 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
File_Extractor::fex_t( fex_type_t t ) :
|
File_Extractor::fex_t( fex_type_t t ) :
|
||||||
type_( t )
|
type_( t )
|
||||||
{
|
{
|
||||||
own_file_ = NULL;
|
own_file_ = NULL;
|
||||||
|
|
||||||
close_();
|
close_();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open
|
// Open
|
||||||
|
|
||||||
blargg_err_t File_Extractor::set_path( const char* path )
|
blargg_err_t File_Extractor::set_path( const char* path )
|
||||||
{
|
{
|
||||||
if ( !path )
|
if ( !path )
|
||||||
path = "";
|
path = "";
|
||||||
|
|
||||||
RETURN_ERR( path_.resize( strlen( path ) + 1 ) );
|
RETURN_ERR( path_.resize( strlen( path ) + 1 ) );
|
||||||
memcpy( path_.begin(), path, path_.size() );
|
memcpy( path_.begin(), path, path_.size() );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::open( const char path [] )
|
blargg_err_t File_Extractor::open( const char path [] )
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
RETURN_ERR( set_path( path ) );
|
RETURN_ERR( set_path( path ) );
|
||||||
|
|
||||||
blargg_err_t err = open_path_v();
|
blargg_err_t err = open_path_v();
|
||||||
if ( err )
|
if ( err )
|
||||||
close();
|
close();
|
||||||
else
|
else
|
||||||
opened_ = true;
|
opened_ = true;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::open_path_v()
|
blargg_err_t File_Extractor::open_path_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( open_arc_file() );
|
RETURN_ERR( open_arc_file() );
|
||||||
|
|
||||||
return open_v();
|
return open_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
static void make_unbuffered( Std_File_Reader* r )
|
static void make_unbuffered( Std_File_Reader* r )
|
||||||
{
|
{
|
||||||
r->make_unbuffered();
|
r->make_unbuffered();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
static void make_unbuffered( void* )
|
static void make_unbuffered( void* )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
blargg_err_t File_Extractor::open_arc_file( bool unbuffered )
|
blargg_err_t File_Extractor::open_arc_file( bool unbuffered )
|
||||||
{
|
{
|
||||||
if ( reader_ )
|
if ( reader_ )
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
|
|
||||||
FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER;
|
FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER;
|
||||||
CHECK_ALLOC( in );
|
CHECK_ALLOC( in );
|
||||||
|
|
||||||
blargg_err_t err = in->open( arc_path() );
|
blargg_err_t err = in->open( arc_path() );
|
||||||
if ( err )
|
if ( err )
|
||||||
{
|
{
|
||||||
delete in;
|
delete in;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
reader_ = in;
|
reader_ = in;
|
||||||
own_file();
|
own_file();
|
||||||
if ( unbuffered )
|
if ( unbuffered )
|
||||||
make_unbuffered( in );
|
make_unbuffered( in );
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::open( File_Reader* input, const char* path )
|
blargg_err_t File_Extractor::open( File_Reader* input, const char* path )
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
RETURN_ERR( set_path( path ) );
|
RETURN_ERR( set_path( path ) );
|
||||||
|
|
||||||
RETURN_ERR( input->seek( 0 ) );
|
RETURN_ERR( input->seek( 0 ) );
|
||||||
|
|
||||||
reader_ = input;
|
reader_ = input;
|
||||||
blargg_err_t err = open_v();
|
blargg_err_t err = open_v();
|
||||||
if ( err )
|
if ( err )
|
||||||
close();
|
close();
|
||||||
else
|
else
|
||||||
opened_ = true;
|
opened_ = true;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close
|
// Close
|
||||||
|
|
||||||
void File_Extractor::close()
|
void File_Extractor::close()
|
||||||
{
|
{
|
||||||
close_v();
|
close_v();
|
||||||
close_();
|
close_();
|
||||||
}
|
}
|
||||||
|
|
||||||
void File_Extractor::close_()
|
void File_Extractor::close_()
|
||||||
{
|
{
|
||||||
delete own_file_;
|
delete own_file_;
|
||||||
own_file_ = NULL;
|
own_file_ = NULL;
|
||||||
|
|
||||||
tell_ = 0;
|
tell_ = 0;
|
||||||
reader_ = NULL;
|
reader_ = NULL;
|
||||||
opened_ = false;
|
opened_ = false;
|
||||||
|
|
||||||
path_.clear();
|
path_.clear();
|
||||||
clear_file();
|
clear_file();
|
||||||
}
|
}
|
||||||
|
|
||||||
File_Extractor::~fex_t()
|
File_Extractor::~fex_t()
|
||||||
{
|
{
|
||||||
check( !opened() ); // fails if derived destructor didn't call close()
|
check( !opened() ); // fails if derived destructor didn't call close()
|
||||||
|
|
||||||
delete own_file_;
|
delete own_file_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scanning
|
// Scanning
|
||||||
|
|
||||||
void File_Extractor::clear_file()
|
void File_Extractor::clear_file()
|
||||||
{
|
{
|
||||||
name_ = NULL;
|
name_ = NULL;
|
||||||
wname_ = NULL;
|
wname_ = NULL;
|
||||||
done_ = true;
|
done_ = true;
|
||||||
stat_called = false;
|
stat_called = false;
|
||||||
data_ptr_ = NULL;
|
data_ptr_ = NULL;
|
||||||
|
|
||||||
set_info( 0 );
|
set_info( 0 );
|
||||||
own_data_.clear();
|
own_data_.clear();
|
||||||
clear_file_v();
|
clear_file_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname )
|
void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname )
|
||||||
{
|
{
|
||||||
name_ = new_name;
|
name_ = new_name;
|
||||||
wname_ = new_wname;
|
wname_ = new_wname;
|
||||||
done_ = false;
|
done_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void File_Extractor::set_info( int new_size, unsigned date, unsigned crc )
|
void File_Extractor::set_info( int new_size, unsigned date, unsigned crc )
|
||||||
{
|
{
|
||||||
size_ = new_size;
|
size_ = new_size;
|
||||||
date_ = (date != 0xFFFFFFFF ? date : 0);
|
date_ = (date != 0xFFFFFFFF ? date : 0);
|
||||||
crc32_ = crc;
|
crc32_ = crc;
|
||||||
set_remain( new_size );
|
set_remain( new_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::next_()
|
blargg_err_t File_Extractor::next_()
|
||||||
{
|
{
|
||||||
tell_++;
|
tell_++;
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
blargg_err_t err = next_v();
|
blargg_err_t err = next_v();
|
||||||
if ( err )
|
if ( err )
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::next()
|
blargg_err_t File_Extractor::next()
|
||||||
{
|
{
|
||||||
assert( !done() );
|
assert( !done() );
|
||||||
return next_();
|
return next_();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::rewind()
|
blargg_err_t File_Extractor::rewind()
|
||||||
{
|
{
|
||||||
assert( opened() );
|
assert( opened() );
|
||||||
|
|
||||||
tell_ = 0;
|
tell_ = 0;
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
blargg_err_t err = rewind_v();
|
blargg_err_t err = rewind_v();
|
||||||
if ( err )
|
if ( err )
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::stat()
|
blargg_err_t File_Extractor::stat()
|
||||||
{
|
{
|
||||||
assert( !done() );
|
assert( !done() );
|
||||||
|
|
||||||
if ( !stat_called )
|
if ( !stat_called )
|
||||||
{
|
{
|
||||||
RETURN_ERR( stat_v() );
|
RETURN_ERR( stat_v() );
|
||||||
stat_called = true;
|
stat_called = true;
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell/seek
|
// Tell/seek
|
||||||
|
|
||||||
int const pos_offset = 1;
|
int const pos_offset = 1;
|
||||||
|
|
||||||
fex_pos_t File_Extractor::tell_arc() const
|
fex_pos_t File_Extractor::tell_arc() const
|
||||||
{
|
{
|
||||||
assert( opened() );
|
assert( opened() );
|
||||||
|
|
||||||
fex_pos_t pos = tell_arc_v();
|
fex_pos_t pos = tell_arc_v();
|
||||||
assert( pos >= 0 );
|
assert( pos >= 0 );
|
||||||
|
|
||||||
return pos + pos_offset;
|
return pos + pos_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::seek_arc( fex_pos_t pos )
|
blargg_err_t File_Extractor::seek_arc( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
assert( opened() );
|
assert( opened() );
|
||||||
assert( pos != 0 );
|
assert( pos != 0 );
|
||||||
|
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
blargg_err_t err = seek_arc_v( pos - pos_offset );
|
blargg_err_t err = seek_arc_v( pos - pos_offset );
|
||||||
if ( err )
|
if ( err )
|
||||||
clear_file();
|
clear_file();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_pos_t File_Extractor::tell_arc_v() const
|
fex_pos_t File_Extractor::tell_arc_v() const
|
||||||
{
|
{
|
||||||
return tell_;
|
return tell_;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos )
|
blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
// >= because seeking to current file should always reset read pointer etc.
|
// >= because seeking to current file should always reset read pointer etc.
|
||||||
if ( tell_ >= pos )
|
if ( tell_ >= pos )
|
||||||
RETURN_ERR( rewind() );
|
RETURN_ERR( rewind() );
|
||||||
|
|
||||||
while ( tell_ < pos )
|
while ( tell_ < pos )
|
||||||
{
|
{
|
||||||
RETURN_ERR( next_() );
|
RETURN_ERR( next_() );
|
||||||
|
|
||||||
if ( done() )
|
if ( done() )
|
||||||
{
|
{
|
||||||
assert( false );
|
assert( false );
|
||||||
return blargg_err_caller;
|
return blargg_err_caller;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( tell_ == pos );
|
assert( tell_ == pos );
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extraction
|
// Extraction
|
||||||
|
|
||||||
blargg_err_t File_Extractor::rewind_file()
|
blargg_err_t File_Extractor::rewind_file()
|
||||||
{
|
{
|
||||||
RETURN_ERR( stat() );
|
RETURN_ERR( stat() );
|
||||||
|
|
||||||
if ( tell() > 0 )
|
if ( tell() > 0 )
|
||||||
{
|
{
|
||||||
if ( data_ptr_ )
|
if ( data_ptr_ )
|
||||||
{
|
{
|
||||||
set_remain( size() );
|
set_remain( size() );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RETURN_ERR( seek_arc( tell_arc() ) );
|
RETURN_ERR( seek_arc( tell_arc() ) );
|
||||||
RETURN_ERR( stat() );
|
RETURN_ERR( stat() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::data( const void** data_out )
|
blargg_err_t File_Extractor::data( const void** data_out )
|
||||||
{
|
{
|
||||||
assert( !done() );
|
assert( !done() );
|
||||||
|
|
||||||
*data_out = NULL;
|
*data_out = NULL;
|
||||||
if ( !data_ptr_ )
|
if ( !data_ptr_ )
|
||||||
{
|
{
|
||||||
int old_tell = tell();
|
int old_tell = tell();
|
||||||
|
|
||||||
RETURN_ERR( rewind_file() );
|
RETURN_ERR( rewind_file() );
|
||||||
|
|
||||||
void const* ptr;
|
void const* ptr;
|
||||||
RETURN_ERR( data_v( &ptr ) );
|
RETURN_ERR( data_v( &ptr ) );
|
||||||
data_ptr_ = ptr;
|
data_ptr_ = ptr;
|
||||||
|
|
||||||
// Now that data is in memory, we can seek by simply setting remain
|
// Now that data is in memory, we can seek by simply setting remain
|
||||||
set_remain( size() - old_tell );
|
set_remain( size() - old_tell );
|
||||||
}
|
}
|
||||||
|
|
||||||
*data_out = data_ptr_;
|
*data_out = data_ptr_;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::data_v( void const** out )
|
blargg_err_t File_Extractor::data_v( void const** out )
|
||||||
{
|
{
|
||||||
RETURN_ERR( own_data_.resize( size() ) );
|
RETURN_ERR( own_data_.resize( size() ) );
|
||||||
*out = own_data_.begin();
|
*out = own_data_.begin();
|
||||||
|
|
||||||
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
|
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
|
||||||
if ( err )
|
if ( err )
|
||||||
own_data_.clear();
|
own_data_.clear();
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::extract_v( void* out, int count )
|
blargg_err_t File_Extractor::extract_v( void* out, int count )
|
||||||
{
|
{
|
||||||
void const* p;
|
void const* p;
|
||||||
RETURN_ERR( data( &p ) );
|
RETURN_ERR( data( &p ) );
|
||||||
memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count );
|
memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count );
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t File_Extractor::read_v( void* out, int count )
|
blargg_err_t File_Extractor::read_v( void* out, int count )
|
||||||
{
|
{
|
||||||
if ( data_ptr_ )
|
if ( data_ptr_ )
|
||||||
return File_Extractor::extract_v( out, count );
|
return File_Extractor::extract_v( out, count );
|
||||||
|
|
||||||
return extract_v( out, count );
|
return extract_v( out, count );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,191 +1,191 @@
|
||||||
// Compressed file archive interface
|
// Compressed file archive interface
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef FILE_EXTRACTOR_H
|
#ifndef FILE_EXTRACTOR_H
|
||||||
#define FILE_EXTRACTOR_H
|
#define FILE_EXTRACTOR_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#include "Data_Reader.h"
|
#include "Data_Reader.h"
|
||||||
#include "fex.h"
|
#include "fex.h"
|
||||||
|
|
||||||
struct fex_t : private Data_Reader {
|
struct fex_t : private Data_Reader {
|
||||||
public:
|
public:
|
||||||
virtual ~fex_t();
|
virtual ~fex_t();
|
||||||
|
|
||||||
// Open/close
|
// Open/close
|
||||||
|
|
||||||
// Opens archive from custom data source. Keeps pointer until close().
|
// Opens archive from custom data source. Keeps pointer until close().
|
||||||
blargg_err_t open( File_Reader* input, const char* path = NULL );
|
blargg_err_t open( File_Reader* input, const char* path = NULL );
|
||||||
|
|
||||||
// Takes ownership of File_Reader* passed to open(), so that close()
|
// Takes ownership of File_Reader* passed to open(), so that close()
|
||||||
// will delete it.
|
// will delete it.
|
||||||
void own_file() { own_file_ = reader_; }
|
void own_file() { own_file_ = reader_; }
|
||||||
|
|
||||||
// See fex.h
|
// See fex.h
|
||||||
blargg_err_t open( const char path [] );
|
blargg_err_t open( const char path [] );
|
||||||
fex_type_t type() const { return type_; }
|
fex_type_t type() const { return type_; }
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
// Scanning
|
// Scanning
|
||||||
|
|
||||||
// See fex.h
|
// See fex.h
|
||||||
bool done() const { return done_; }
|
bool done() const { return done_; }
|
||||||
blargg_err_t next();
|
blargg_err_t next();
|
||||||
blargg_err_t rewind();
|
blargg_err_t rewind();
|
||||||
fex_pos_t tell_arc() const;
|
fex_pos_t tell_arc() const;
|
||||||
blargg_err_t seek_arc( fex_pos_t );
|
blargg_err_t seek_arc( fex_pos_t );
|
||||||
|
|
||||||
// Info
|
// Info
|
||||||
|
|
||||||
// See fex.h
|
// See fex.h
|
||||||
const char* name() const { return name_; }
|
const char* name() const { return name_; }
|
||||||
const wchar_t* wname() const { return wname_; }
|
const wchar_t* wname() const { return wname_; }
|
||||||
blargg_err_t stat();
|
blargg_err_t stat();
|
||||||
int size() const { assert( stat_called ); return size_; }
|
int size() const { assert( stat_called ); return size_; }
|
||||||
unsigned int dos_date() const { return date_; }
|
unsigned int dos_date() const { return date_; }
|
||||||
unsigned int crc32() const { return crc32_; }
|
unsigned int crc32() const { return crc32_; }
|
||||||
|
|
||||||
// Extraction
|
// Extraction
|
||||||
|
|
||||||
// Data_Reader to current file's data, so standard Data_Reader interface can
|
// Data_Reader to current file's data, so standard Data_Reader interface can
|
||||||
// be used, rather than having to treat archives specially. stat() must have
|
// be used, rather than having to treat archives specially. stat() must have
|
||||||
// been called.
|
// been called.
|
||||||
Data_Reader& reader() { assert( stat_called ); return *this; }
|
Data_Reader& reader() { assert( stat_called ); return *this; }
|
||||||
|
|
||||||
// See fex.h
|
// See fex.h
|
||||||
blargg_err_t data( const void** data_out );
|
blargg_err_t data( const void** data_out );
|
||||||
int tell() const { return size_ - remain(); }
|
int tell() const { return size_ - remain(); }
|
||||||
|
|
||||||
// Derived interface
|
// Derived interface
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Sets type of object
|
// Sets type of object
|
||||||
fex_t( fex_type_t );
|
fex_t( fex_type_t );
|
||||||
|
|
||||||
// Path to archive file, or "" if none supplied
|
// Path to archive file, or "" if none supplied
|
||||||
const char* arc_path() const { return path_.begin(); }
|
const char* arc_path() const { return path_.begin(); }
|
||||||
|
|
||||||
// Opens archive file if it's not already. If unbuffered is true, opens file
|
// Opens archive file if it's not already. If unbuffered is true, opens file
|
||||||
// without any buffering.
|
// without any buffering.
|
||||||
blargg_err_t open_arc_file( bool unbuffered = false );
|
blargg_err_t open_arc_file( bool unbuffered = false );
|
||||||
|
|
||||||
// Archive file
|
// Archive file
|
||||||
File_Reader& arc() const { return *reader_; }
|
File_Reader& arc() const { return *reader_; }
|
||||||
|
|
||||||
// Sets current file name
|
// Sets current file name
|
||||||
void set_name( const char name [], const wchar_t* wname = NULL );
|
void set_name( const char name [], const wchar_t* wname = NULL );
|
||||||
|
|
||||||
// Sets current file information
|
// Sets current file information
|
||||||
void set_info( int size, unsigned date = 0, unsigned crc = 0 );
|
void set_info( int size, unsigned date = 0, unsigned crc = 0 );
|
||||||
|
|
||||||
// User overrides
|
// User overrides
|
||||||
|
|
||||||
// Overrides must do indicated task. Non-pure functions have reasonable default
|
// Overrides must do indicated task. Non-pure functions have reasonable default
|
||||||
// implementation. Overrides should avoid calling public functions like
|
// implementation. Overrides should avoid calling public functions like
|
||||||
// next() and rewind().
|
// next() and rewind().
|
||||||
|
|
||||||
// Open archive using file_path(). OK to delay actual file opening until later.
|
// Open archive using file_path(). OK to delay actual file opening until later.
|
||||||
// Default just calls open_arc_file(), then open_v().
|
// Default just calls open_arc_file(), then open_v().
|
||||||
virtual blargg_err_t open_path_v();
|
virtual blargg_err_t open_path_v();
|
||||||
|
|
||||||
// Open archive using file() for source data. If unsupported, return error.
|
// Open archive using file() for source data. If unsupported, return error.
|
||||||
virtual blargg_err_t open_v() BLARGG_PURE( ; )
|
virtual blargg_err_t open_v() BLARGG_PURE( ; )
|
||||||
|
|
||||||
// Go to next file in archive and call set_name() and optionally set_info()
|
// Go to next file in archive and call set_name() and optionally set_info()
|
||||||
virtual blargg_err_t next_v() BLARGG_PURE( ; )
|
virtual blargg_err_t next_v() BLARGG_PURE( ; )
|
||||||
|
|
||||||
// Go back to first file in archive
|
// Go back to first file in archive
|
||||||
virtual blargg_err_t rewind_v() BLARGG_PURE( ; )
|
virtual blargg_err_t rewind_v() BLARGG_PURE( ; )
|
||||||
|
|
||||||
// Close archive. Called even if open_path_v() or open_v() return unsuccessfully.
|
// Close archive. Called even if open_path_v() or open_v() return unsuccessfully.
|
||||||
virtual void close_v() BLARGG_PURE( ; )
|
virtual void close_v() BLARGG_PURE( ; )
|
||||||
|
|
||||||
// Clear any fields related to current file
|
// Clear any fields related to current file
|
||||||
virtual void clear_file_v() { }
|
virtual void clear_file_v() { }
|
||||||
|
|
||||||
// Call set_info() if not already called by next_v()
|
// Call set_info() if not already called by next_v()
|
||||||
virtual blargg_err_t stat_v() { return blargg_ok; }
|
virtual blargg_err_t stat_v() { return blargg_ok; }
|
||||||
|
|
||||||
// Return value that allows later return to this file. Result must be >= 0.
|
// Return value that allows later return to this file. Result must be >= 0.
|
||||||
virtual fex_pos_t tell_arc_v() const;
|
virtual fex_pos_t tell_arc_v() const;
|
||||||
|
|
||||||
// Return to previously saved position
|
// Return to previously saved position
|
||||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||||
|
|
||||||
// One or both of the following must be overridden
|
// One or both of the following must be overridden
|
||||||
|
|
||||||
// Provide pointer to data for current file in archive
|
// Provide pointer to data for current file in archive
|
||||||
virtual blargg_err_t data_v( const void** out );
|
virtual blargg_err_t data_v( const void** out );
|
||||||
|
|
||||||
// Extract next n bytes
|
// Extract next n bytes
|
||||||
virtual blargg_err_t extract_v( void* out, int n );
|
virtual blargg_err_t extract_v( void* out, int n );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
BLARGG_DISABLE_NOTHROW
|
BLARGG_DISABLE_NOTHROW
|
||||||
|
|
||||||
private:
|
private:
|
||||||
fex_type_t const type_;
|
fex_type_t const type_;
|
||||||
|
|
||||||
// Archive file
|
// Archive file
|
||||||
blargg_vector<char> path_;
|
blargg_vector<char> path_;
|
||||||
File_Reader* reader_;
|
File_Reader* reader_;
|
||||||
File_Reader* own_file_;
|
File_Reader* own_file_;
|
||||||
bool opened_;
|
bool opened_;
|
||||||
|
|
||||||
// Position in archive
|
// Position in archive
|
||||||
fex_pos_t tell_; // only used by default implementation of tell/seek
|
fex_pos_t tell_; // only used by default implementation of tell/seek
|
||||||
bool done_;
|
bool done_;
|
||||||
|
|
||||||
// Info for current file in archive
|
// Info for current file in archive
|
||||||
const char* name_;
|
const char* name_;
|
||||||
const wchar_t* wname_;
|
const wchar_t* wname_;
|
||||||
unsigned date_;
|
unsigned date_;
|
||||||
unsigned crc32_;
|
unsigned crc32_;
|
||||||
int size_;
|
int size_;
|
||||||
bool stat_called;
|
bool stat_called;
|
||||||
|
|
||||||
// Current file contents
|
// Current file contents
|
||||||
void const* data_ptr_; // NULL if not read into memory
|
void const* data_ptr_; // NULL if not read into memory
|
||||||
blargg_vector<char> own_data_;
|
blargg_vector<char> own_data_;
|
||||||
|
|
||||||
bool opened() const { return opened_; }
|
bool opened() const { return opened_; }
|
||||||
void clear_file();
|
void clear_file();
|
||||||
void close_();
|
void close_();
|
||||||
blargg_err_t set_path( const char* path );
|
blargg_err_t set_path( const char* path );
|
||||||
blargg_err_t rewind_file();
|
blargg_err_t rewind_file();
|
||||||
blargg_err_t next_();
|
blargg_err_t next_();
|
||||||
|
|
||||||
// Data_Reader overrides
|
// Data_Reader overrides
|
||||||
// TODO: override skip_v?
|
// TODO: override skip_v?
|
||||||
virtual blargg_err_t read_v( void* out, int n );
|
virtual blargg_err_t read_v( void* out, int n );
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fex_type_t_
|
struct fex_type_t_
|
||||||
{
|
{
|
||||||
const char* extension;
|
const char* extension;
|
||||||
File_Extractor* (*new_fex)();
|
File_Extractor* (*new_fex)();
|
||||||
const char* name;
|
const char* name;
|
||||||
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
|
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const fex_type_t_
|
extern const fex_type_t_
|
||||||
fex_7z_type [1],
|
fex_7z_type [1],
|
||||||
fex_gz_type [1],
|
fex_gz_type [1],
|
||||||
fex_rar_type [1],
|
fex_rar_type [1],
|
||||||
fex_zip_type [1],
|
fex_zip_type [1],
|
||||||
fex_bin_type [1];
|
fex_bin_type [1];
|
||||||
|
|
||||||
inline blargg_err_t File_Extractor::open_v() { return blargg_ok; }
|
inline blargg_err_t File_Extractor::open_v() { return blargg_ok; }
|
||||||
inline blargg_err_t File_Extractor::next_v() { return blargg_ok; }
|
inline blargg_err_t File_Extractor::next_v() { return blargg_ok; }
|
||||||
inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; }
|
inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; }
|
||||||
inline void File_Extractor::close_v() { }
|
inline void File_Extractor::close_v() { }
|
||||||
|
|
||||||
// Default to Std_File_Reader for archive access
|
// Default to Std_File_Reader for archive access
|
||||||
#ifndef FEX_FILE_READER
|
#ifndef FEX_FILE_READER
|
||||||
#define FEX_FILE_READER Std_File_Reader
|
#define FEX_FILE_READER Std_File_Reader
|
||||||
#elif defined (FEX_FILE_READER_INCLUDE)
|
#elif defined (FEX_FILE_READER_INCLUDE)
|
||||||
#include FEX_FILE_READER_INCLUDE
|
#include FEX_FILE_READER_INCLUDE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,98 +1,98 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Gzip_Extractor.h"
|
#include "Gzip_Extractor.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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
// TODO: could close file once data has been read into memory
|
// TODO: could close file once data has been read into memory
|
||||||
|
|
||||||
static blargg_err_t init_gzip_file()
|
static blargg_err_t init_gzip_file()
|
||||||
{
|
{
|
||||||
get_crc_table(); // initialize zlib's CRC-32 tables
|
get_crc_table(); // initialize zlib's CRC-32 tables
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Extractor* new_gzip()
|
static File_Extractor* new_gzip()
|
||||||
{
|
{
|
||||||
return BLARGG_NEW Gzip_Extractor;
|
return BLARGG_NEW Gzip_Extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_type_t_ const fex_gz_type [1] = {{
|
fex_type_t_ const fex_gz_type [1] = {{
|
||||||
".gz",
|
".gz",
|
||||||
&new_gzip,
|
&new_gzip,
|
||||||
"gzipped file",
|
"gzipped file",
|
||||||
&init_gzip_file
|
&init_gzip_file
|
||||||
}};
|
}};
|
||||||
|
|
||||||
Gzip_Extractor::Gzip_Extractor() :
|
Gzip_Extractor::Gzip_Extractor() :
|
||||||
File_Extractor( fex_gz_type )
|
File_Extractor( fex_gz_type )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
Gzip_Extractor::~Gzip_Extractor()
|
Gzip_Extractor::~Gzip_Extractor()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::open_path_v()
|
blargg_err_t Gzip_Extractor::open_path_v()
|
||||||
{
|
{
|
||||||
// skip opening file
|
// skip opening file
|
||||||
return open_v();
|
return open_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::stat_v()
|
blargg_err_t Gzip_Extractor::stat_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( open_arc_file( true ) );
|
RETURN_ERR( open_arc_file( true ) );
|
||||||
if ( !gr.opened() || gr.tell() != 0 )
|
if ( !gr.opened() || gr.tell() != 0 )
|
||||||
RETURN_ERR( gr.open( &arc() ) );
|
RETURN_ERR( gr.open( &arc() ) );
|
||||||
|
|
||||||
set_info( gr.remain(), 0, gr.crc32() );
|
set_info( gr.remain(), 0, gr.crc32() );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::open_v()
|
blargg_err_t Gzip_Extractor::open_v()
|
||||||
{
|
{
|
||||||
// Remove .gz suffix
|
// Remove .gz suffix
|
||||||
size_t len = strlen( arc_path() );
|
size_t len = strlen( arc_path() );
|
||||||
if ( fex_has_extension( arc_path(), ".gz" ) )
|
if ( fex_has_extension( arc_path(), ".gz" ) )
|
||||||
len -= 3;
|
len -= 3;
|
||||||
|
|
||||||
RETURN_ERR( name.resize( len + 1 ) );
|
RETURN_ERR( name.resize( len + 1 ) );
|
||||||
memcpy( name.begin(), arc_path(), name.size() );
|
memcpy( name.begin(), arc_path(), name.size() );
|
||||||
name [name.size() - 1] = '\0';
|
name [name.size() - 1] = '\0';
|
||||||
|
|
||||||
set_name( name.begin() );
|
set_name( name.begin() );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gzip_Extractor::close_v()
|
void Gzip_Extractor::close_v()
|
||||||
{
|
{
|
||||||
name.clear();
|
name.clear();
|
||||||
gr.close();
|
gr.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::next_v()
|
blargg_err_t Gzip_Extractor::next_v()
|
||||||
{
|
{
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::rewind_v()
|
blargg_err_t Gzip_Extractor::rewind_v()
|
||||||
{
|
{
|
||||||
set_name( name.begin() );
|
set_name( name.begin() );
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
|
blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
|
||||||
{
|
{
|
||||||
return gr.read( p, n );
|
return gr.read( p, n );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
// Presents a gzipped file as an "archive" of just that file.
|
// Presents a gzipped file as an "archive" of just that file.
|
||||||
// Also handles non-gzipped files.
|
// Also handles non-gzipped files.
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef GZIP_EXTRACTOR_H
|
#ifndef GZIP_EXTRACTOR_H
|
||||||
#define GZIP_EXTRACTOR_H
|
#define GZIP_EXTRACTOR_H
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
#include "Gzip_Reader.h"
|
#include "Gzip_Reader.h"
|
||||||
|
|
||||||
class Gzip_Extractor : public File_Extractor {
|
class Gzip_Extractor : public File_Extractor {
|
||||||
public:
|
public:
|
||||||
Gzip_Extractor();
|
Gzip_Extractor();
|
||||||
virtual ~Gzip_Extractor();
|
virtual ~Gzip_Extractor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t open_path_v();
|
virtual blargg_err_t open_path_v();
|
||||||
virtual blargg_err_t open_v();
|
virtual blargg_err_t open_v();
|
||||||
virtual void close_v();
|
virtual void close_v();
|
||||||
|
|
||||||
virtual blargg_err_t next_v();
|
virtual blargg_err_t next_v();
|
||||||
virtual blargg_err_t rewind_v();
|
virtual blargg_err_t rewind_v();
|
||||||
|
|
||||||
virtual blargg_err_t stat_v();
|
virtual blargg_err_t stat_v();
|
||||||
virtual blargg_err_t extract_v( void*, int );
|
virtual blargg_err_t extract_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Gzip_Reader gr;
|
Gzip_Reader gr;
|
||||||
blargg_vector<char> name;
|
blargg_vector<char> name;
|
||||||
|
|
||||||
void set_info_();
|
void set_info_();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,85 +1,85 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Gzip_Reader.h"
|
#include "Gzip_Reader.h"
|
||||||
|
|
||||||
#include "blargg_endian.h"
|
#include "blargg_endian.h"
|
||||||
|
|
||||||
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
|
/* Copyright (C) 2006-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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
Gzip_Reader::Gzip_Reader()
|
Gzip_Reader::Gzip_Reader()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Gzip_Reader::~Gzip_Reader()
|
Gzip_Reader::~Gzip_Reader()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
|
static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
|
||||||
{
|
{
|
||||||
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
|
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Reader::calc_size()
|
blargg_err_t Gzip_Reader::calc_size()
|
||||||
{
|
{
|
||||||
size_ = in->size();
|
size_ = in->size();
|
||||||
crc32_ = 0;
|
crc32_ = 0;
|
||||||
if ( inflater.deflated() )
|
if ( inflater.deflated() )
|
||||||
{
|
{
|
||||||
byte trailer [8];
|
byte trailer [8];
|
||||||
int old_pos = in->tell();
|
int old_pos = in->tell();
|
||||||
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
|
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
|
||||||
RETURN_ERR( in->read( trailer, sizeof trailer ) );
|
RETURN_ERR( in->read( trailer, sizeof trailer ) );
|
||||||
RETURN_ERR( in->seek( old_pos ) );
|
RETURN_ERR( in->seek( old_pos ) );
|
||||||
crc32_ = get_le32( trailer + 0 );
|
crc32_ = get_le32( trailer + 0 );
|
||||||
|
|
||||||
unsigned n = get_le32( trailer + 4 );
|
unsigned n = get_le32( trailer + 4 );
|
||||||
if ( n > INT_MAX )
|
if ( n > INT_MAX )
|
||||||
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
|
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
|
||||||
|
|
||||||
size_ = n;
|
size_ = n;
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Reader::open( File_Reader* new_in )
|
blargg_err_t Gzip_Reader::open( File_Reader* new_in )
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
|
|
||||||
in = new_in;
|
in = new_in;
|
||||||
RETURN_ERR( in->seek( 0 ) );
|
RETURN_ERR( in->seek( 0 ) );
|
||||||
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
|
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
|
||||||
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
||||||
RETURN_ERR( calc_size() );
|
RETURN_ERR( calc_size() );
|
||||||
set_remain( size_ );
|
set_remain( size_ );
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gzip_Reader::close()
|
void Gzip_Reader::close()
|
||||||
{
|
{
|
||||||
in = NULL;
|
in = NULL;
|
||||||
inflater.end();
|
inflater.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Gzip_Reader::read_v( void* out, int count )
|
blargg_err_t Gzip_Reader::read_v( void* out, int count )
|
||||||
{
|
{
|
||||||
assert( in );
|
assert( in );
|
||||||
int actual = count;
|
int actual = count;
|
||||||
RETURN_ERR( inflater.read( out, &actual ) );
|
RETURN_ERR( inflater.read( out, &actual ) );
|
||||||
|
|
||||||
if ( actual != count )
|
if ( actual != count )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +1,46 @@
|
||||||
// Transparently decompresses gzip files, as well as uncompressed
|
// Transparently decompresses gzip files, as well as uncompressed
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef GZIP_READER_H
|
#ifndef GZIP_READER_H
|
||||||
#define GZIP_READER_H
|
#define GZIP_READER_H
|
||||||
|
|
||||||
#include "Data_Reader.h"
|
#include "Data_Reader.h"
|
||||||
#include "Zlib_Inflater.h"
|
#include "Zlib_Inflater.h"
|
||||||
|
|
||||||
class Gzip_Reader : public Data_Reader {
|
class Gzip_Reader : public Data_Reader {
|
||||||
public:
|
public:
|
||||||
// Keeps pointer to reader until close(). If
|
// Keeps pointer to reader until close(). If
|
||||||
blargg_err_t open( File_Reader* );
|
blargg_err_t open( File_Reader* );
|
||||||
|
|
||||||
// True if file is open
|
// True if file is open
|
||||||
bool opened() const { return in != NULL; }
|
bool opened() const { return in != NULL; }
|
||||||
|
|
||||||
// Frees memory
|
// Frees memory
|
||||||
void close();
|
void close();
|
||||||
|
|
||||||
// True if file is compressed
|
// True if file is compressed
|
||||||
bool deflated() const { return inflater.deflated(); }
|
bool deflated() const { return inflater.deflated(); }
|
||||||
|
|
||||||
// CRC-32 of data, of 0 if unavailable
|
// CRC-32 of data, of 0 if unavailable
|
||||||
unsigned int crc32() const { return crc32_; }
|
unsigned int crc32() const { return crc32_; }
|
||||||
|
|
||||||
// Number of bytes read since opening
|
// Number of bytes read since opening
|
||||||
int tell() const { return size_ - remain(); }
|
int tell() const { return size_ - remain(); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Gzip_Reader();
|
Gzip_Reader();
|
||||||
virtual ~Gzip_Reader();
|
virtual ~Gzip_Reader();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t read_v( void*, int );
|
virtual blargg_err_t read_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File_Reader* in;
|
File_Reader* in;
|
||||||
unsigned crc32_;
|
unsigned crc32_;
|
||||||
int size_;
|
int size_;
|
||||||
Zlib_Inflater inflater;
|
Zlib_Inflater inflater;
|
||||||
|
|
||||||
blargg_err_t calc_size();
|
blargg_err_t calc_size();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,197 +1,197 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
#if FEX_ENABLE_RAR
|
#if FEX_ENABLE_RAR
|
||||||
|
|
||||||
#include "Rar_Extractor.h"
|
#include "Rar_Extractor.h"
|
||||||
|
|
||||||
/* Copyright (C) 2009 Shay Green. This module is free software; you
|
/* Copyright (C) 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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
static blargg_err_t init_rar()
|
static blargg_err_t init_rar()
|
||||||
{
|
{
|
||||||
unrar_init();
|
unrar_init();
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Extractor* new_rar()
|
static File_Extractor* new_rar()
|
||||||
{
|
{
|
||||||
return BLARGG_NEW Rar_Extractor;
|
return BLARGG_NEW Rar_Extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_type_t_ const fex_rar_type [1] = {{
|
fex_type_t_ const fex_rar_type [1] = {{
|
||||||
".rar",
|
".rar",
|
||||||
&new_rar,
|
&new_rar,
|
||||||
"RAR archive",
|
"RAR archive",
|
||||||
&init_rar
|
&init_rar
|
||||||
}};
|
}};
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::convert_err( unrar_err_t err )
|
blargg_err_t Rar_Extractor::convert_err( unrar_err_t err )
|
||||||
{
|
{
|
||||||
blargg_err_t reader_err = reader.err;
|
blargg_err_t reader_err = reader.err;
|
||||||
reader.err = blargg_ok;
|
reader.err = blargg_ok;
|
||||||
if ( reader_err )
|
if ( reader_err )
|
||||||
check( err == unrar_next_err );
|
check( err == unrar_next_err );
|
||||||
|
|
||||||
switch ( err )
|
switch ( err )
|
||||||
{
|
{
|
||||||
case unrar_ok: return blargg_ok;
|
case unrar_ok: return blargg_ok;
|
||||||
case unrar_err_memory: return blargg_err_memory;
|
case unrar_err_memory: return blargg_err_memory;
|
||||||
case unrar_err_open: return blargg_err_file_read;
|
case unrar_err_open: return blargg_err_file_read;
|
||||||
case unrar_err_not_arc: return blargg_err_file_type;
|
case unrar_err_not_arc: return blargg_err_file_type;
|
||||||
case unrar_err_corrupt: return blargg_err_file_corrupt;
|
case unrar_err_corrupt: return blargg_err_file_corrupt;
|
||||||
case unrar_err_io: return blargg_err_file_io;
|
case unrar_err_io: return blargg_err_file_io;
|
||||||
case unrar_err_arc_eof: return blargg_err_internal;
|
case unrar_err_arc_eof: return blargg_err_internal;
|
||||||
case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" );
|
case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" );
|
||||||
case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" );
|
case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" );
|
||||||
case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" );
|
case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" );
|
||||||
case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" );
|
case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" );
|
||||||
case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" );
|
case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" );
|
||||||
case unrar_next_err: break;
|
case unrar_next_err: break;
|
||||||
default:
|
default:
|
||||||
check( false ); // unhandled RAR error
|
check( false ); // unhandled RAR error
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( reader_err )
|
if ( reader_err )
|
||||||
return reader_err;
|
return reader_err;
|
||||||
|
|
||||||
check( false );
|
check( false );
|
||||||
return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" );
|
return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err )
|
static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err )
|
||||||
{
|
{
|
||||||
if ( !err )
|
if ( !err )
|
||||||
return unrar_ok;
|
return unrar_ok;
|
||||||
|
|
||||||
h->err = err;
|
h->err = err;
|
||||||
return unrar_next_err;
|
return unrar_next_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
|
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
|
||||||
{
|
{
|
||||||
// TODO: 64-bit file support
|
// TODO: 64-bit file support
|
||||||
|
|
||||||
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
|
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
|
||||||
if ( h->pos != pos )
|
if ( h->pos != pos )
|
||||||
{
|
{
|
||||||
blargg_err_t err = h->in->seek( pos );
|
blargg_err_t err = h->in->seek( pos );
|
||||||
if ( err )
|
if ( err )
|
||||||
return handle_err( h, err );
|
return handle_err( h, err );
|
||||||
|
|
||||||
h->pos = pos;
|
h->pos = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t err = h->in->read_avail( out, count );
|
blargg_err_t err = h->in->read_avail( out, count );
|
||||||
if ( err )
|
if ( err )
|
||||||
return handle_err( h, err );
|
return handle_err( h, err );
|
||||||
|
|
||||||
h->pos += *count;
|
h->pos += *count;
|
||||||
|
|
||||||
return unrar_ok;
|
return unrar_ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rar_Extractor::Rar_Extractor() :
|
Rar_Extractor::Rar_Extractor() :
|
||||||
File_Extractor( fex_rar_type )
|
File_Extractor( fex_rar_type )
|
||||||
{
|
{
|
||||||
unrar = NULL;
|
unrar = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Rar_Extractor::~Rar_Extractor()
|
Rar_Extractor::~Rar_Extractor()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::open_v()
|
blargg_err_t Rar_Extractor::open_v()
|
||||||
{
|
{
|
||||||
reader.pos = 0;
|
reader.pos = 0;
|
||||||
reader.in = &arc();
|
reader.in = &arc();
|
||||||
reader.err = blargg_ok;
|
reader.err = blargg_ok;
|
||||||
|
|
||||||
RETURN_ERR( arc().seek( 0 ) );
|
RETURN_ERR( arc().seek( 0 ) );
|
||||||
RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) );
|
RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) );
|
||||||
return skip_unextractables();
|
return skip_unextractables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rar_Extractor::close_v()
|
void Rar_Extractor::close_v()
|
||||||
{
|
{
|
||||||
unrar_close( unrar );
|
unrar_close( unrar );
|
||||||
|
|
||||||
unrar = NULL;
|
unrar = NULL;
|
||||||
reader.in = NULL;
|
reader.in = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::skip_unextractables()
|
blargg_err_t Rar_Extractor::skip_unextractables()
|
||||||
{
|
{
|
||||||
while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) )
|
while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) )
|
||||||
RETURN_ERR( next_raw() );
|
RETURN_ERR( next_raw() );
|
||||||
|
|
||||||
if ( !unrar_done( unrar ) )
|
if ( !unrar_done( unrar ) )
|
||||||
{
|
{
|
||||||
unrar_info_t const* info = unrar_info( unrar );
|
unrar_info_t const* info = unrar_info( unrar );
|
||||||
|
|
||||||
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
|
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
|
||||||
set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
|
set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::next_raw()
|
blargg_err_t Rar_Extractor::next_raw()
|
||||||
{
|
{
|
||||||
return convert_err( unrar_next( unrar ) );
|
return convert_err( unrar_next( unrar ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::next_v()
|
blargg_err_t Rar_Extractor::next_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( next_raw() );
|
RETURN_ERR( next_raw() );
|
||||||
return skip_unextractables();
|
return skip_unextractables();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::rewind_v()
|
blargg_err_t Rar_Extractor::rewind_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( convert_err( unrar_rewind( unrar ) ) );
|
RETURN_ERR( convert_err( unrar_rewind( unrar ) ) );
|
||||||
return skip_unextractables();
|
return skip_unextractables();
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_pos_t Rar_Extractor::tell_arc_v() const
|
fex_pos_t Rar_Extractor::tell_arc_v() const
|
||||||
{
|
{
|
||||||
return unrar_tell( unrar );
|
return unrar_tell( unrar );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos )
|
blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) );
|
RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) );
|
||||||
return skip_unextractables();
|
return skip_unextractables();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::data_v( void const** out )
|
blargg_err_t Rar_Extractor::data_v( void const** out )
|
||||||
{
|
{
|
||||||
return convert_err( unrar_extract_mem( unrar, out ) );
|
return convert_err( unrar_extract_mem( unrar, out ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Rar_Extractor::extract_v( void* out, int count )
|
blargg_err_t Rar_Extractor::extract_v( void* out, int count )
|
||||||
{
|
{
|
||||||
// We can read entire file directly into user buffer
|
// We can read entire file directly into user buffer
|
||||||
if ( count == size() )
|
if ( count == size() )
|
||||||
return convert_err( unrar_extract( unrar, out, count ) );
|
return convert_err( unrar_extract( unrar, out, count ) );
|
||||||
|
|
||||||
// This will call data_v() and copy from that buffer for us
|
// This will call data_v() and copy from that buffer for us
|
||||||
return File_Extractor::extract_v( out, count );
|
return File_Extractor::extract_v( out, count );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,43 +1,43 @@
|
||||||
// RAR archive extractor
|
// RAR archive extractor
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef RAR_EXTRACTOR_H
|
#ifndef RAR_EXTRACTOR_H
|
||||||
#define RAR_EXTRACTOR_H
|
#define RAR_EXTRACTOR_H
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
#include "unrar/unrar.h"
|
#include "unrar/unrar.h"
|
||||||
|
|
||||||
class Rar_Extractor : public File_Extractor {
|
class Rar_Extractor : public File_Extractor {
|
||||||
public:
|
public:
|
||||||
Rar_Extractor();
|
Rar_Extractor();
|
||||||
virtual ~Rar_Extractor();
|
virtual ~Rar_Extractor();
|
||||||
|
|
||||||
struct read_callback_t
|
struct read_callback_t
|
||||||
{
|
{
|
||||||
const char* err;
|
const char* err;
|
||||||
int pos;
|
int pos;
|
||||||
File_Reader* in;
|
File_Reader* in;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t open_v();
|
virtual blargg_err_t open_v();
|
||||||
virtual void close_v();
|
virtual void close_v();
|
||||||
|
|
||||||
virtual blargg_err_t next_v();
|
virtual blargg_err_t next_v();
|
||||||
virtual blargg_err_t rewind_v();
|
virtual blargg_err_t rewind_v();
|
||||||
virtual fex_pos_t tell_arc_v() const;
|
virtual fex_pos_t tell_arc_v() const;
|
||||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||||
|
|
||||||
virtual blargg_err_t data_v( void const** );
|
virtual blargg_err_t data_v( void const** );
|
||||||
virtual blargg_err_t extract_v( void*, int );
|
virtual blargg_err_t extract_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unrar_t* unrar;
|
unrar_t* unrar;
|
||||||
read_callback_t reader;
|
read_callback_t reader;
|
||||||
|
|
||||||
blargg_err_t convert_err( unrar_err_t );
|
blargg_err_t convert_err( unrar_err_t );
|
||||||
blargg_err_t skip_unextractables();
|
blargg_err_t skip_unextractables();
|
||||||
blargg_err_t next_raw();
|
blargg_err_t next_raw();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,354 +1,354 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Zip7_Extractor.h"
|
#include "Zip7_Extractor.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "7z_C/7z.h"
|
#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>
|
#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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
static ISzAlloc zip7_alloc = { SzAlloc, SzFree };
|
static ISzAlloc zip7_alloc = { SzAlloc, SzFree };
|
||||||
static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
|
static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
|
||||||
|
|
||||||
struct Zip7_Extractor_Impl :
|
struct Zip7_Extractor_Impl :
|
||||||
ISeekInStream
|
ISeekInStream
|
||||||
{
|
{
|
||||||
CLookToRead look;
|
CLookToRead look;
|
||||||
CSzArEx db;
|
CSzArEx db;
|
||||||
|
|
||||||
// SzExtract state
|
// SzExtract state
|
||||||
UInt32 block_index;
|
UInt32 block_index;
|
||||||
Byte* buf;
|
Byte* buf;
|
||||||
size_t buf_size;
|
size_t buf_size;
|
||||||
|
|
||||||
File_Reader* in;
|
File_Reader* in;
|
||||||
const char* in_err;
|
const char* in_err;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
|
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
|
||||||
// back to ISeekInStream* FIRST, then cast to our Impl structure
|
// back to ISeekInStream* FIRST, then cast to our Impl structure
|
||||||
|
|
||||||
static SRes zip7_read_( void* vstream, void* out, size_t* size )
|
static SRes zip7_read_( void* vstream, void* out, size_t* size )
|
||||||
{
|
{
|
||||||
assert( out && size );
|
assert( out && size );
|
||||||
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);
|
||||||
|
|
||||||
long lsize = *size;
|
long lsize = *size;
|
||||||
blargg_err_t err = impl->in->read_avail( out, &lsize );
|
blargg_err_t err = impl->in->read_avail( out, &lsize );
|
||||||
if ( err )
|
if ( err )
|
||||||
{
|
{
|
||||||
*size = 0;
|
*size = 0;
|
||||||
impl->in_err = err;
|
impl->in_err = err;
|
||||||
return SZ_ERROR_READ;
|
return SZ_ERROR_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
*size = lsize;
|
*size = lsize;
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
|
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
|
||||||
{
|
{
|
||||||
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 )
|
||||||
{
|
{
|
||||||
assert( *pos == 0 ); // only used to find file length
|
assert( *pos == 0 ); // only used to find file length
|
||||||
*pos = impl->in->size();
|
*pos = impl->in->size();
|
||||||
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 )
|
||||||
{
|
{
|
||||||
// don't set in_err in this case, since it might be benign
|
// don't set in_err in this case, since it might be benign
|
||||||
if ( err == blargg_err_file_eof )
|
if ( err == blargg_err_file_eof )
|
||||||
return SZ_ERROR_INPUT_EOF;
|
return SZ_ERROR_INPUT_EOF;
|
||||||
|
|
||||||
impl->in_err = err;
|
impl->in_err = err;
|
||||||
return SZ_ERROR_READ;
|
return SZ_ERROR_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
return SZ_OK;
|
return SZ_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::zip7_err( int err )
|
blargg_err_t Zip7_Extractor::zip7_err( int err )
|
||||||
{
|
{
|
||||||
// TODO: ignore in_err in some cases? unsure about which error to use
|
// TODO: ignore in_err in some cases? unsure about which error to use
|
||||||
blargg_err_t in_err = impl->in_err;
|
blargg_err_t in_err = impl->in_err;
|
||||||
impl->in_err = NULL;
|
impl->in_err = NULL;
|
||||||
if ( in_err )
|
if ( in_err )
|
||||||
{
|
{
|
||||||
check( err != SZ_OK );
|
check( err != SZ_OK );
|
||||||
return in_err;
|
return in_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch ( err )
|
switch ( err )
|
||||||
{
|
{
|
||||||
case SZ_OK: return blargg_ok;
|
case SZ_OK: return blargg_ok;
|
||||||
case SZ_ERROR_MEM: return blargg_err_memory;
|
case SZ_ERROR_MEM: return blargg_err_memory;
|
||||||
case SZ_ERROR_READ: return blargg_err_file_io;
|
case SZ_ERROR_READ: return blargg_err_file_io;
|
||||||
case SZ_ERROR_CRC:
|
case SZ_ERROR_CRC:
|
||||||
case SZ_ERROR_DATA:
|
case SZ_ERROR_DATA:
|
||||||
case SZ_ERROR_INPUT_EOF:
|
case SZ_ERROR_INPUT_EOF:
|
||||||
case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt;
|
case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt;
|
||||||
case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature;
|
case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature;
|
||||||
case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type;
|
case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_err_generic;
|
return blargg_err_generic;
|
||||||
}
|
}
|
||||||
|
|
||||||
static blargg_err_t init_7z()
|
static blargg_err_t init_7z()
|
||||||
{
|
{
|
||||||
static bool inited;
|
static bool inited;
|
||||||
if ( !inited )
|
if ( !inited )
|
||||||
{
|
{
|
||||||
inited = true;
|
inited = true;
|
||||||
CrcGenerateTable();
|
CrcGenerateTable();
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Extractor* new_7z()
|
static File_Extractor* new_7z()
|
||||||
{
|
{
|
||||||
return BLARGG_NEW Zip7_Extractor;
|
return BLARGG_NEW Zip7_Extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_type_t_ const fex_7z_type [1] = {{
|
fex_type_t_ const fex_7z_type [1] = {{
|
||||||
".7z",
|
".7z",
|
||||||
&new_7z,
|
&new_7z,
|
||||||
"7-zip archive",
|
"7-zip archive",
|
||||||
&init_7z
|
&init_7z
|
||||||
}};
|
}};
|
||||||
|
|
||||||
Zip7_Extractor::Zip7_Extractor() :
|
Zip7_Extractor::Zip7_Extractor() :
|
||||||
File_Extractor( fex_7z_type )
|
File_Extractor( fex_7z_type )
|
||||||
{
|
{
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Zip7_Extractor::~Zip7_Extractor()
|
Zip7_Extractor::~Zip7_Extractor()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::open_v()
|
blargg_err_t Zip7_Extractor::open_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( init_7z() );
|
RETURN_ERR( init_7z() );
|
||||||
|
|
||||||
if ( !impl )
|
if ( !impl )
|
||||||
{
|
{
|
||||||
impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl );
|
impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl );
|
||||||
CHECK_ALLOC( impl );
|
CHECK_ALLOC( impl );
|
||||||
}
|
}
|
||||||
|
|
||||||
impl->in = &arc();
|
impl->in = &arc();
|
||||||
impl->block_index = (UInt32) -1;
|
impl->block_index = (UInt32) -1;
|
||||||
impl->buf = NULL;
|
impl->buf = NULL;
|
||||||
impl->buf_size = 0;
|
impl->buf_size = 0;
|
||||||
|
|
||||||
LookToRead_CreateVTable( &impl->look, false );
|
LookToRead_CreateVTable( &impl->look, false );
|
||||||
impl->ISeekInStream::Read = zip7_read_;
|
impl->ISeekInStream::Read = zip7_read_;
|
||||||
impl->ISeekInStream::Seek = zip7_seek_;
|
impl->ISeekInStream::Seek = zip7_seek_;
|
||||||
impl->look.realStream = impl;
|
impl->look.realStream = impl;
|
||||||
LookToRead_Init( &impl->look );
|
LookToRead_Init( &impl->look );
|
||||||
|
|
||||||
SzArEx_Init( &impl->db );
|
SzArEx_Init( &impl->db );
|
||||||
|
|
||||||
impl->in_err = NULL;
|
impl->in_err = NULL;
|
||||||
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
|
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
|
||||||
&zip7_alloc, &zip7_alloc_temp ) ) );
|
&zip7_alloc, &zip7_alloc_temp ) ) );
|
||||||
|
|
||||||
return seek_arc_v( 0 );
|
return seek_arc_v( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zip7_Extractor::close_v()
|
void Zip7_Extractor::close_v()
|
||||||
{
|
{
|
||||||
if ( impl )
|
if ( impl )
|
||||||
{
|
{
|
||||||
if ( impl->in )
|
if ( impl->in )
|
||||||
{
|
{
|
||||||
impl->in = NULL;
|
impl->in = NULL;
|
||||||
SzArEx_Free( &impl->db, &zip7_alloc );
|
SzArEx_Free( &impl->db, &zip7_alloc );
|
||||||
}
|
}
|
||||||
IAlloc_Free( &zip7_alloc, impl->buf );
|
IAlloc_Free( &zip7_alloc, impl->buf );
|
||||||
free( impl );
|
free( impl );
|
||||||
impl = NULL;
|
impl = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method was taken from ogre-7z (thanks), and is thus LGPL
|
// This method was taken from ogre-7z (thanks), and is thus LGPL
|
||||||
bool Zip7_Extractor::utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen )
|
bool Zip7_Extractor::utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen )
|
||||||
{
|
{
|
||||||
static const unsigned char sUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
static const unsigned char sUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||||
|
|
||||||
size_t destPos = 0, srcPos = 0;
|
size_t destPos = 0, srcPos = 0;
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
unsigned int numAdds;
|
unsigned int numAdds;
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
if( srcPos == srcLen )
|
if( srcPos == srcLen )
|
||||||
{
|
{
|
||||||
*destLen = destPos;
|
*destLen = destPos;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = src[srcPos++];
|
value = src[srcPos++];
|
||||||
if( value < 0x80 )
|
if( value < 0x80 )
|
||||||
{
|
{
|
||||||
if( dest )
|
if( dest )
|
||||||
{
|
{
|
||||||
dest[destPos] = (char)value;
|
dest[destPos] = (char)value;
|
||||||
}
|
}
|
||||||
destPos++;
|
destPos++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( value >= 0xD800 && value < 0xE000 )
|
if( value >= 0xD800 && value < 0xE000 )
|
||||||
{
|
{
|
||||||
unsigned long c2;
|
unsigned long c2;
|
||||||
if( value >= 0xDC00 || srcPos == srcLen )
|
if( value >= 0xDC00 || srcPos == srcLen )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
c2 = src[srcPos++];
|
c2 = src[srcPos++];
|
||||||
if( c2 < 0xDC00 || c2 >= 0xE000 )
|
if( c2 < 0xDC00 || c2 >= 0xE000 )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
value = (((value - 0xD800) << 10) | (c2 - 0xDC00)) + 0x10000;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( numAdds = 1; numAdds < 5; numAdds++ )
|
for( numAdds = 1; numAdds < 5; numAdds++ )
|
||||||
{
|
{
|
||||||
if( value < (((UInt32)1) << (numAdds * 5 + 6)) )
|
if( value < (((UInt32)1) << (numAdds * 5 + 6)) )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( dest )
|
if( dest )
|
||||||
{
|
{
|
||||||
dest[destPos] = (char)(sUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
|
dest[destPos] = (char)(sUtf8Limits[numAdds - 1] + (value >> (6 * numAdds)));
|
||||||
}
|
}
|
||||||
|
|
||||||
destPos++;
|
destPos++;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
numAdds--;
|
numAdds--;
|
||||||
if( dest )
|
if( dest )
|
||||||
{
|
{
|
||||||
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
|
dest[destPos] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F));
|
||||||
}
|
}
|
||||||
destPos++;
|
destPos++;
|
||||||
}
|
}
|
||||||
while( numAdds != 0 );
|
while( numAdds != 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
*destLen = destPos;
|
*destLen = destPos;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::next_v()
|
blargg_err_t Zip7_Extractor::next_v()
|
||||||
{
|
{
|
||||||
while ( ++index < (int) impl->db.db.NumFiles )
|
while ( ++index < (int) impl->db.db.NumFiles )
|
||||||
{
|
{
|
||||||
CSzFileItem const& item = impl->db.db.Files [index];
|
CSzFileItem const& item = impl->db.db.Files [index];
|
||||||
if ( !item.IsDir )
|
if ( !item.IsDir )
|
||||||
{
|
{
|
||||||
unsigned long date = 0;
|
unsigned long date = 0;
|
||||||
if ( item.MTimeDefined )
|
if ( item.MTimeDefined )
|
||||||
{
|
{
|
||||||
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
|
const UInt64 epoch = ((UInt64)0x019db1de << 32) + 0xd53e8000;
|
||||||
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
|
/* 0x019db1ded53e8000ULL: 1970-01-01 00:00:00 (UTC) */
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
|
|
||||||
UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
|
UInt64 time = ((UInt64)item.MTime.High << 32) + item.MTime.Low - epoch;
|
||||||
time /= 1000000;
|
time /= 1000000;
|
||||||
|
|
||||||
time_t _time = time;
|
time_t _time = time;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
tm = *localtime( &_time );
|
tm = *localtime( &_time );
|
||||||
#else
|
#else
|
||||||
localtime_r( &_time, &tm );
|
localtime_r( &_time, &tm );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
date = (( tm.tm_sec >> 1 ) & 0x1F) |
|
date = (( tm.tm_sec >> 1 ) & 0x1F) |
|
||||||
(( tm.tm_min & 0x3F ) << 5 ) |
|
(( tm.tm_min & 0x3F ) << 5 ) |
|
||||||
(( tm.tm_hour & 0x1F ) << 11 ) |
|
(( tm.tm_hour & 0x1F ) << 11 ) |
|
||||||
(( tm.tm_mday & 0x1F ) << 16 ) |
|
(( tm.tm_mday & 0x1F ) << 16 ) |
|
||||||
(( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) |
|
(( ( tm.tm_mon + 1 ) & 0x0F ) << 21 ) |
|
||||||
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
|
(( ( tm.tm_year - 80 ) & 0x7F ) << 25 );
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
|
size_t name_length = SzArEx_GetFileNameUtf16( &impl->db, index, 0 );
|
||||||
size_t utf8_length = 0;
|
size_t utf8_length = 0;
|
||||||
name16.resize( name_length );
|
name16.resize( name_length );
|
||||||
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
|
SzArEx_GetFileNameUtf16( &impl->db, index, ( UInt16 * ) name16.begin() );
|
||||||
unsigned char temp[1024];
|
unsigned char temp[1024];
|
||||||
utf16ToUtf8( temp, &utf8_length, (const short*)name16.begin(), name_length - 1 );
|
utf16ToUtf8( temp, &utf8_length, (const short*)name16.begin(), name_length - 1 );
|
||||||
temp[utf8_length] = '\0';
|
temp[utf8_length] = '\0';
|
||||||
|
|
||||||
name8.resize( utf8_length + 1 );
|
name8.resize( utf8_length + 1 );
|
||||||
memcpy( name8.begin(), temp, utf8_length + 1 );
|
memcpy( name8.begin(), temp, utf8_length + 1 );
|
||||||
set_name( name8.begin(), name16.begin() );
|
set_name( name8.begin(), name16.begin() );
|
||||||
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
|
set_info( item.Size, 0, (item.CrcDefined ? item.Crc : 0) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::rewind_v()
|
blargg_err_t Zip7_Extractor::rewind_v()
|
||||||
{
|
{
|
||||||
return seek_arc_v( 0 );
|
return seek_arc_v( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_pos_t Zip7_Extractor::tell_arc_v() const
|
fex_pos_t Zip7_Extractor::tell_arc_v() const
|
||||||
{
|
{
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
|
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
|
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
|
||||||
|
|
||||||
index = pos - 1;
|
index = pos - 1;
|
||||||
return next_v();
|
return next_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip7_Extractor::data_v( void const** out )
|
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( SzArEx_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() );
|
||||||
|
|
||||||
*out = impl->buf + offset;
|
*out = impl->buf + offset;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
// 7-zip archive extractor
|
// 7-zip archive extractor
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef ZIP7_EXTRACTOR_H
|
#ifndef ZIP7_EXTRACTOR_H
|
||||||
#define ZIP7_EXTRACTOR_H
|
#define ZIP7_EXTRACTOR_H
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
|
|
||||||
struct Zip7_Extractor_Impl;
|
struct Zip7_Extractor_Impl;
|
||||||
|
|
||||||
class Zip7_Extractor : public File_Extractor {
|
class Zip7_Extractor : public File_Extractor {
|
||||||
public:
|
public:
|
||||||
Zip7_Extractor();
|
Zip7_Extractor();
|
||||||
virtual ~Zip7_Extractor();
|
virtual ~Zip7_Extractor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t open_v();
|
virtual blargg_err_t open_v();
|
||||||
virtual void close_v();
|
virtual void close_v();
|
||||||
|
|
||||||
virtual blargg_err_t next_v();
|
virtual blargg_err_t next_v();
|
||||||
virtual blargg_err_t rewind_v();
|
virtual blargg_err_t rewind_v();
|
||||||
virtual fex_pos_t tell_arc_v() const;
|
virtual fex_pos_t tell_arc_v() const;
|
||||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||||
|
|
||||||
virtual blargg_err_t data_v( void const** out );
|
virtual blargg_err_t data_v( void const** out );
|
||||||
|
|
||||||
bool utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen );
|
bool utf16ToUtf8( unsigned char* dest, size_t* destLen, const short* src, size_t srcLen );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Zip7_Extractor_Impl* impl;
|
Zip7_Extractor_Impl* impl;
|
||||||
int index;
|
int index;
|
||||||
blargg_vector<char> name8;
|
blargg_vector<char> name8;
|
||||||
blargg_vector<wchar_t> name16;
|
blargg_vector<wchar_t> name16;
|
||||||
|
|
||||||
blargg_err_t zip7_err( int err );
|
blargg_err_t zip7_err( int err );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,390 +1,390 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Zip_Extractor.h"
|
#include "Zip_Extractor.h"
|
||||||
|
|
||||||
#include "blargg_endian.h"
|
#include "blargg_endian.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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
/* To avoid copying filename string from catalog, I terminate it by modifying
|
/* To avoid copying filename string from catalog, I terminate it by modifying
|
||||||
catalog data. This potentially requires moving the first byte of the type
|
catalog data. This potentially requires moving the first byte of the type
|
||||||
of the next entry elsewhere; I move it to the first byte of made_by. Kind
|
of the next entry elsewhere; I move it to the first byte of made_by. Kind
|
||||||
of hacky, but I'd rather not have to allocate memory for a copy of it. */
|
of hacky, but I'd rather not have to allocate memory for a copy of it. */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
/* Reads this much from end of file when first opening. Only this much is
|
/* Reads this much from end of file when first opening. Only this much is
|
||||||
searched for the end catalog entry. If whole catalog is within this data,
|
searched for the end catalog entry. If whole catalog is within this data,
|
||||||
nothing more needs to be read on open. */
|
nothing more needs to be read on open. */
|
||||||
int const end_read_size = 8 * 1024;
|
int const end_read_size = 8 * 1024;
|
||||||
|
|
||||||
/* Reads are are made using file offset that's a multiple of this,
|
/* Reads are are made using file offset that's a multiple of this,
|
||||||
increasing performance. */
|
increasing performance. */
|
||||||
int const disk_block_size = 4 * 1024;
|
int const disk_block_size = 4 * 1024;
|
||||||
|
|
||||||
// Read buffer used for extracting file data
|
// Read buffer used for extracting file data
|
||||||
int const read_buf_size = 16 * 1024;
|
int const read_buf_size = 16 * 1024;
|
||||||
|
|
||||||
struct header_t
|
struct header_t
|
||||||
{
|
{
|
||||||
char type [4];
|
char type [4];
|
||||||
byte vers [2];
|
byte vers [2];
|
||||||
byte flags [2];
|
byte flags [2];
|
||||||
byte method [2];
|
byte method [2];
|
||||||
byte date [4];
|
byte date [4];
|
||||||
byte crc [4];
|
byte crc [4];
|
||||||
byte raw_size [4];
|
byte raw_size [4];
|
||||||
byte size [4];
|
byte size [4];
|
||||||
byte filename_len [2];
|
byte filename_len [2];
|
||||||
byte extra_len [2];
|
byte extra_len [2];
|
||||||
char filename [2]; // [filename_len]
|
char filename [2]; // [filename_len]
|
||||||
//char extra [extra_len];
|
//char extra [extra_len];
|
||||||
};
|
};
|
||||||
int const header_size = 30;
|
int const header_size = 30;
|
||||||
|
|
||||||
struct entry_t
|
struct entry_t
|
||||||
{
|
{
|
||||||
char type [4];
|
char type [4];
|
||||||
byte made_by [2];
|
byte made_by [2];
|
||||||
byte vers [2];
|
byte vers [2];
|
||||||
byte flags [2];
|
byte flags [2];
|
||||||
byte method [2];
|
byte method [2];
|
||||||
byte date [4];
|
byte date [4];
|
||||||
byte crc [4];
|
byte crc [4];
|
||||||
byte raw_size [4];
|
byte raw_size [4];
|
||||||
byte size [4];
|
byte size [4];
|
||||||
byte filename_len [2];
|
byte filename_len [2];
|
||||||
byte extra_len [2];
|
byte extra_len [2];
|
||||||
byte comment_len [2];
|
byte comment_len [2];
|
||||||
byte disk [2];
|
byte disk [2];
|
||||||
byte int_attrib [2];
|
byte int_attrib [2];
|
||||||
byte ext_attrib [4];
|
byte ext_attrib [4];
|
||||||
byte file_offset [4];
|
byte file_offset [4];
|
||||||
char filename [2]; // [filename_len]
|
char filename [2]; // [filename_len]
|
||||||
//char extra [extra_len];
|
//char extra [extra_len];
|
||||||
//char comment [comment_len];
|
//char comment [comment_len];
|
||||||
};
|
};
|
||||||
int const entry_size = 46;
|
int const entry_size = 46;
|
||||||
|
|
||||||
struct end_entry_t
|
struct end_entry_t
|
||||||
{
|
{
|
||||||
char type [4];
|
char type [4];
|
||||||
byte disk [2];
|
byte disk [2];
|
||||||
byte first_disk [2];
|
byte first_disk [2];
|
||||||
byte disk_entry_count [2];
|
byte disk_entry_count [2];
|
||||||
byte entry_count [2];
|
byte entry_count [2];
|
||||||
byte dir_size [4];
|
byte dir_size [4];
|
||||||
byte dir_offset [4];
|
byte dir_offset [4];
|
||||||
byte comment_len [2];
|
byte comment_len [2];
|
||||||
char comment [2]; // [comment_len]
|
char comment [2]; // [comment_len]
|
||||||
};
|
};
|
||||||
int const end_entry_size = 22;
|
int const end_entry_size = 22;
|
||||||
|
|
||||||
static blargg_err_t init_zip()
|
static blargg_err_t init_zip()
|
||||||
{
|
{
|
||||||
get_crc_table(); // initialize zlib's CRC-32 tables
|
get_crc_table(); // initialize zlib's CRC-32 tables
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static File_Extractor* new_zip()
|
static File_Extractor* new_zip()
|
||||||
{
|
{
|
||||||
return BLARGG_NEW Zip_Extractor;
|
return BLARGG_NEW Zip_Extractor;
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_type_t_ const fex_zip_type [1] = {{
|
fex_type_t_ const fex_zip_type [1] = {{
|
||||||
".zip",
|
".zip",
|
||||||
&new_zip,
|
&new_zip,
|
||||||
"ZIP archive",
|
"ZIP archive",
|
||||||
&init_zip
|
&init_zip
|
||||||
}};
|
}};
|
||||||
|
|
||||||
Zip_Extractor::Zip_Extractor() :
|
Zip_Extractor::Zip_Extractor() :
|
||||||
File_Extractor( fex_zip_type )
|
File_Extractor( fex_zip_type )
|
||||||
{
|
{
|
||||||
Zip_Extractor::clear_file_v();
|
Zip_Extractor::clear_file_v();
|
||||||
|
|
||||||
// If these fail, structures had extra padding inserted by compiler
|
// If these fail, structures had extra padding inserted by compiler
|
||||||
assert( offsetof (header_t,filename) == header_size );
|
assert( offsetof (header_t,filename) == header_size );
|
||||||
assert( offsetof (entry_t,filename) == entry_size );
|
assert( offsetof (entry_t,filename) == entry_size );
|
||||||
assert( offsetof (end_entry_t,comment) == end_entry_size );
|
assert( offsetof (end_entry_t,comment) == end_entry_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
Zip_Extractor::~Zip_Extractor()
|
Zip_Extractor::~Zip_Extractor()
|
||||||
{
|
{
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::open_path_v()
|
blargg_err_t Zip_Extractor::open_path_v()
|
||||||
{
|
{
|
||||||
RETURN_ERR( open_arc_file( true ) );
|
RETURN_ERR( open_arc_file( true ) );
|
||||||
return File_Extractor::open_path_v();
|
return File_Extractor::open_path_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void Zip_Extractor::reorder_entry_header( int offset )
|
void Zip_Extractor::reorder_entry_header( int offset )
|
||||||
{
|
{
|
||||||
catalog [offset + 0] = 0;
|
catalog [offset + 0] = 0;
|
||||||
catalog [offset + 4] = 'P';
|
catalog [offset + 4] = 'P';
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::open_v()
|
blargg_err_t Zip_Extractor::open_v()
|
||||||
{
|
{
|
||||||
if ( arc().size() < end_entry_size )
|
if ( arc().size() < end_entry_size )
|
||||||
return blargg_err_file_type;
|
return blargg_err_file_type;
|
||||||
|
|
||||||
// Read final end_read_size bytes of file
|
// Read final end_read_size bytes of file
|
||||||
int file_pos = max( 0, arc().size() - end_read_size );
|
int file_pos = max( 0, arc().size() - end_read_size );
|
||||||
file_pos -= file_pos % disk_block_size;
|
file_pos -= file_pos % disk_block_size;
|
||||||
RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
|
RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
|
||||||
RETURN_ERR( arc().seek( file_pos ) );
|
RETURN_ERR( arc().seek( file_pos ) );
|
||||||
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
||||||
|
|
||||||
// Find end-of-catalog entry
|
// Find end-of-catalog entry
|
||||||
int end_pos = catalog.size() - end_entry_size;
|
int end_pos = catalog.size() - end_entry_size;
|
||||||
while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
|
while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
|
||||||
end_pos--;
|
end_pos--;
|
||||||
if ( end_pos < 0 )
|
if ( end_pos < 0 )
|
||||||
return blargg_err_file_type;
|
return blargg_err_file_type;
|
||||||
end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
|
end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
|
||||||
end_pos += file_pos;
|
end_pos += file_pos;
|
||||||
|
|
||||||
// some idiotic zip compressors add data to end of zip without setting comment len
|
// some idiotic zip compressors add data to end of zip without setting comment len
|
||||||
// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) );
|
// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) );
|
||||||
|
|
||||||
// Find file offset of beginning of catalog
|
// Find file offset of beginning of catalog
|
||||||
catalog_begin = get_le32( end_entry.dir_offset );
|
catalog_begin = get_le32( end_entry.dir_offset );
|
||||||
int catalog_size = end_pos - catalog_begin;
|
int catalog_size = end_pos - catalog_begin;
|
||||||
if ( catalog_size < 0 )
|
if ( catalog_size < 0 )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
catalog_size += end_entry_size;
|
catalog_size += end_entry_size;
|
||||||
|
|
||||||
// See if catalog is entirely contained in bytes already read
|
// See if catalog is entirely contained in bytes already read
|
||||||
int begin_offset = catalog_begin - file_pos;
|
int begin_offset = catalog_begin - file_pos;
|
||||||
if ( begin_offset >= 0 )
|
if ( begin_offset >= 0 )
|
||||||
memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
|
memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
|
||||||
|
|
||||||
RETURN_ERR( catalog.resize( catalog_size ) );
|
RETURN_ERR( catalog.resize( catalog_size ) );
|
||||||
if ( begin_offset < 0 )
|
if ( begin_offset < 0 )
|
||||||
{
|
{
|
||||||
// Catalog begins before bytes read, so it needs to be read
|
// Catalog begins before bytes read, so it needs to be read
|
||||||
RETURN_ERR( arc().seek( catalog_begin ) );
|
RETURN_ERR( arc().seek( catalog_begin ) );
|
||||||
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// First entry in catalog should be a file or end of archive
|
// First entry in catalog should be a file or end of archive
|
||||||
if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) )
|
if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) )
|
||||||
return blargg_err_file_type;
|
return blargg_err_file_type;
|
||||||
|
|
||||||
reorder_entry_header( 0 );
|
reorder_entry_header( 0 );
|
||||||
return rewind_v();
|
return rewind_v();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zip_Extractor::close_v()
|
void Zip_Extractor::close_v()
|
||||||
{
|
{
|
||||||
catalog.clear();
|
catalog.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scanning
|
// Scanning
|
||||||
|
|
||||||
inline
|
inline
|
||||||
static bool is_normal_file( entry_t const& e, unsigned len )
|
static bool is_normal_file( entry_t const& e, unsigned len )
|
||||||
{
|
{
|
||||||
int last_char = (len ? e.filename [len - 1] : '/');
|
int last_char = (len ? e.filename [len - 1] : '/');
|
||||||
bool is_dir = (last_char == '/' || last_char == '\\');
|
bool is_dir = (last_char == '/' || last_char == '\\');
|
||||||
if ( is_dir && get_le32( e.size ) == 0 )
|
if ( is_dir && get_le32( e.size ) == 0 )
|
||||||
return false;
|
return false;
|
||||||
check( !is_dir );
|
check( !is_dir );
|
||||||
|
|
||||||
// Mac OS X puts meta-information in separate files with normal extensions,
|
// Mac OS X puts meta-information in separate files with normal extensions,
|
||||||
// so they must be filtered out or caller will mistake them for normal files.
|
// so they must be filtered out or caller will mistake them for normal files.
|
||||||
if ( e.made_by[1] == 3 )
|
if ( e.made_by[1] == 3 )
|
||||||
{
|
{
|
||||||
const char* dir = strrchr( e.filename, '/' );
|
const char* dir = strrchr( e.filename, '/' );
|
||||||
if ( dir )
|
if ( dir )
|
||||||
dir++;
|
dir++;
|
||||||
else
|
else
|
||||||
dir = e.filename;
|
dir = e.filename;
|
||||||
|
|
||||||
if ( *dir == '.' )
|
if ( *dir == '.' )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if ( !strcmp( dir, "Icon\x0D" ) )
|
if ( !strcmp( dir, "Icon\x0D" ) )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::update_info( bool advance_first )
|
blargg_err_t Zip_Extractor::update_info( bool advance_first )
|
||||||
{
|
{
|
||||||
while ( 1 )
|
while ( 1 )
|
||||||
{
|
{
|
||||||
entry_t& e = (entry_t&) catalog [catalog_pos];
|
entry_t& e = (entry_t&) catalog [catalog_pos];
|
||||||
|
|
||||||
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
|
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
|
||||||
{
|
{
|
||||||
check( !memcmp( e.type, "\0K\5\6P", 5 ) );
|
check( !memcmp( e.type, "\0K\5\6P", 5 ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned len = get_le16( e.filename_len );
|
unsigned len = get_le16( e.filename_len );
|
||||||
int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
|
int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
|
||||||
get_le16( e.comment_len );
|
get_le16( e.comment_len );
|
||||||
if ( (unsigned) next_offset > catalog.size() - end_entry_size )
|
if ( (unsigned) next_offset > catalog.size() - end_entry_size )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
if ( catalog [next_offset] == 'P' )
|
if ( catalog [next_offset] == 'P' )
|
||||||
reorder_entry_header( next_offset );
|
reorder_entry_header( next_offset );
|
||||||
|
|
||||||
if ( !advance_first )
|
if ( !advance_first )
|
||||||
{
|
{
|
||||||
e.filename [len] = 0; // terminate name
|
e.filename [len] = 0; // terminate name
|
||||||
|
|
||||||
if ( is_normal_file( e, len ) )
|
if ( is_normal_file( e, len ) )
|
||||||
{
|
{
|
||||||
set_name( e.filename );
|
set_name( e.filename );
|
||||||
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
|
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catalog_pos = next_offset;
|
catalog_pos = next_offset;
|
||||||
advance_first = false;
|
advance_first = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::next_v()
|
blargg_err_t Zip_Extractor::next_v()
|
||||||
{
|
{
|
||||||
return update_info( true );
|
return update_info( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::rewind_v()
|
blargg_err_t Zip_Extractor::rewind_v()
|
||||||
{
|
{
|
||||||
return seek_arc_v( 0 );
|
return seek_arc_v( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
fex_pos_t Zip_Extractor::tell_arc_v() const
|
fex_pos_t Zip_Extractor::tell_arc_v() const
|
||||||
{
|
{
|
||||||
return catalog_pos;
|
return catalog_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos )
|
blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos )
|
||||||
{
|
{
|
||||||
assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size );
|
assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size );
|
||||||
|
|
||||||
catalog_pos = pos;
|
catalog_pos = pos;
|
||||||
return update_info( false );
|
return update_info( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reading
|
// Reading
|
||||||
|
|
||||||
void Zip_Extractor::clear_file_v()
|
void Zip_Extractor::clear_file_v()
|
||||||
{
|
{
|
||||||
buf.end();
|
buf.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
|
blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
|
||||||
{
|
{
|
||||||
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
|
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
|
||||||
|
|
||||||
if ( *count > self.raw_remain )
|
if ( *count > self.raw_remain )
|
||||||
*count = self.raw_remain;
|
*count = self.raw_remain;
|
||||||
|
|
||||||
self.raw_remain -= *count;
|
self.raw_remain -= *count;
|
||||||
|
|
||||||
return self.arc().read( out, *count );
|
return self.arc().read( out, *count );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
|
blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
|
||||||
{
|
{
|
||||||
raw_remain = arc().size() - offset;
|
raw_remain = arc().size() - offset;
|
||||||
RETURN_ERR( arc().seek( offset ) );
|
RETURN_ERR( arc().seek( offset ) );
|
||||||
return buf.begin( inflater_read, this, buf_size, initial_read );
|
return buf.begin( inflater_read, this, buf_size, initial_read );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::first_read( int count )
|
blargg_err_t Zip_Extractor::first_read( int count )
|
||||||
{
|
{
|
||||||
entry_t const& e = (entry_t&) catalog [catalog_pos];
|
entry_t const& e = (entry_t&) catalog [catalog_pos];
|
||||||
|
|
||||||
// Determine compression
|
// Determine compression
|
||||||
{
|
{
|
||||||
int method = get_le16( e.method );
|
int method = get_le16( e.method );
|
||||||
if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 )
|
if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 )
|
||||||
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" );
|
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" );
|
||||||
file_deflated = (method != 0);
|
file_deflated = (method != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int raw_size = get_le32( e.raw_size );
|
int raw_size = get_le32( e.raw_size );
|
||||||
|
|
||||||
int file_offset = get_le32( e.file_offset );
|
int file_offset = get_le32( e.file_offset );
|
||||||
int align = file_offset % disk_block_size;
|
int align = file_offset % disk_block_size;
|
||||||
{
|
{
|
||||||
// read header
|
// read header
|
||||||
int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data
|
int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data
|
||||||
buf_size -= buf_size % disk_block_size;
|
buf_size -= buf_size % disk_block_size;
|
||||||
int initial_read = buf_size;
|
int initial_read = buf_size;
|
||||||
if ( !file_deflated || count < size() )
|
if ( !file_deflated || count < size() )
|
||||||
{
|
{
|
||||||
buf_size = read_buf_size;
|
buf_size = read_buf_size;
|
||||||
initial_read = disk_block_size * 2;
|
initial_read = disk_block_size * 2;
|
||||||
}
|
}
|
||||||
// TODO: avoid re-reading if buffer already has data we want?
|
// TODO: avoid re-reading if buffer already has data we want?
|
||||||
RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) );
|
RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) );
|
||||||
}
|
}
|
||||||
header_t const& h = (header_t&) buf.data() [align];
|
header_t const& h = (header_t&) buf.data() [align];
|
||||||
if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) )
|
if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
// CRCs of header and file data
|
// CRCs of header and file data
|
||||||
correct_crc = get_le32( h.crc );
|
correct_crc = get_le32( h.crc );
|
||||||
if ( !correct_crc )
|
if ( !correct_crc )
|
||||||
correct_crc = get_le32( e.crc );
|
correct_crc = get_le32( e.crc );
|
||||||
check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match
|
check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match
|
||||||
crc = ::crc32( 0, NULL, 0 );
|
crc = ::crc32( 0, NULL, 0 );
|
||||||
|
|
||||||
// Data offset
|
// Data offset
|
||||||
int data_offset = file_offset + header_size +
|
int data_offset = file_offset + header_size +
|
||||||
get_le16( h.filename_len ) + get_le16( h.extra_len );
|
get_le16( h.filename_len ) + get_le16( h.extra_len );
|
||||||
if ( data_offset + raw_size > catalog_begin )
|
if ( data_offset + raw_size > catalog_begin )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
// Refill buffer if there's lots of extra data after header
|
// Refill buffer if there's lots of extra data after header
|
||||||
int buf_offset = data_offset - file_offset + align;
|
int buf_offset = data_offset - file_offset + align;
|
||||||
if ( buf_offset > buf.filled() )
|
if ( buf_offset > buf.filled() )
|
||||||
{
|
{
|
||||||
// TODO: this will almost never occur, making it a good place for bugs
|
// TODO: this will almost never occur, making it a good place for bugs
|
||||||
buf_offset = data_offset % disk_block_size;
|
buf_offset = data_offset % disk_block_size;
|
||||||
RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) );
|
RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_remain = raw_size - (buf.filled() - buf_offset);
|
raw_remain = raw_size - (buf.filled() - buf_offset);
|
||||||
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
|
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zip_Extractor::extract_v( void* out, int count )
|
blargg_err_t Zip_Extractor::extract_v( void* out, int count )
|
||||||
{
|
{
|
||||||
if ( tell() == 0 )
|
if ( tell() == 0 )
|
||||||
RETURN_ERR( first_read( count ) );
|
RETURN_ERR( first_read( count ) );
|
||||||
|
|
||||||
int actual = count;
|
int actual = count;
|
||||||
RETURN_ERR( buf.read( out, &actual ) );
|
RETURN_ERR( buf.read( out, &actual ) );
|
||||||
if ( actual < count )
|
if ( actual < count )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
crc = ::crc32( crc, (byte const*) out, count );
|
crc = ::crc32( crc, (byte const*) out, count );
|
||||||
if ( count == reader().remain() && crc != correct_crc )
|
if ( count == reader().remain() && crc != correct_crc )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
// ZIP archive extractor. Only supports deflation and store (no compression).
|
// ZIP archive extractor. Only supports deflation and store (no compression).
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef ZIP_EXTRACTOR_H
|
#ifndef ZIP_EXTRACTOR_H
|
||||||
#define ZIP_EXTRACTOR_H
|
#define ZIP_EXTRACTOR_H
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
#include "Zlib_Inflater.h"
|
#include "Zlib_Inflater.h"
|
||||||
|
|
||||||
class Zip_Extractor : public File_Extractor {
|
class Zip_Extractor : public File_Extractor {
|
||||||
public:
|
public:
|
||||||
Zip_Extractor();
|
Zip_Extractor();
|
||||||
virtual ~Zip_Extractor();
|
virtual ~Zip_Extractor();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual blargg_err_t open_path_v();
|
virtual blargg_err_t open_path_v();
|
||||||
virtual blargg_err_t open_v();
|
virtual blargg_err_t open_v();
|
||||||
virtual void close_v();
|
virtual void close_v();
|
||||||
|
|
||||||
virtual void clear_file_v();
|
virtual void clear_file_v();
|
||||||
virtual blargg_err_t next_v();
|
virtual blargg_err_t next_v();
|
||||||
virtual blargg_err_t rewind_v();
|
virtual blargg_err_t rewind_v();
|
||||||
virtual fex_pos_t tell_arc_v() const;
|
virtual fex_pos_t tell_arc_v() const;
|
||||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||||
|
|
||||||
virtual blargg_err_t extract_v( void*, int );
|
virtual blargg_err_t extract_v( void*, int );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
blargg_vector<char> catalog;
|
blargg_vector<char> catalog;
|
||||||
int catalog_begin; // offset of first catalog entry in file (to detect corruption)
|
int catalog_begin; // offset of first catalog entry in file (to detect corruption)
|
||||||
int catalog_pos; // position of current entry in catalog
|
int catalog_pos; // position of current entry in catalog
|
||||||
int raw_remain; // bytes remaining to be read from zip file for current file
|
int raw_remain; // bytes remaining to be read from zip file for current file
|
||||||
unsigned crc; // ongoing CRC of extracted bytes
|
unsigned crc; // ongoing CRC of extracted bytes
|
||||||
unsigned correct_crc;
|
unsigned correct_crc;
|
||||||
bool file_deflated;
|
bool file_deflated;
|
||||||
Zlib_Inflater buf;
|
Zlib_Inflater buf;
|
||||||
|
|
||||||
blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
|
blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
|
||||||
blargg_err_t update_info( bool advance_first );
|
blargg_err_t update_info( bool advance_first );
|
||||||
blargg_err_t first_read( int count );
|
blargg_err_t first_read( int count );
|
||||||
void reorder_entry_header( int offset );
|
void reorder_entry_header( int offset );
|
||||||
static blargg_err_t inflater_read( void* data, void* out, int* count );
|
static blargg_err_t inflater_read( void* data, void* out, int* count );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,257 +1,257 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "Zlib_Inflater.h"
|
#include "Zlib_Inflater.h"
|
||||||
|
|
||||||
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
|
/* Copyright (C) 2006-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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
int const block_size = 4096;
|
int const block_size = 4096;
|
||||||
|
|
||||||
static const char* get_zlib_err( int code )
|
static const char* get_zlib_err( int code )
|
||||||
{
|
{
|
||||||
assert( code != Z_OK );
|
assert( code != Z_OK );
|
||||||
switch ( code )
|
switch ( code )
|
||||||
{
|
{
|
||||||
case Z_MEM_ERROR: return blargg_err_memory;
|
case Z_MEM_ERROR: return blargg_err_memory;
|
||||||
case Z_DATA_ERROR: return blargg_err_file_corrupt;
|
case Z_DATA_ERROR: return blargg_err_file_corrupt;
|
||||||
// TODO: handle more error codes
|
// TODO: handle more error codes
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* str = zError( code );
|
const char* str = zError( code );
|
||||||
if ( !str )
|
if ( !str )
|
||||||
str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" );
|
str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" );
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zlib_Inflater::end()
|
void Zlib_Inflater::end()
|
||||||
{
|
{
|
||||||
if ( deflated_ )
|
if ( deflated_ )
|
||||||
{
|
{
|
||||||
deflated_ = false;
|
deflated_ = false;
|
||||||
if ( inflateEnd( &zbuf ) )
|
if ( inflateEnd( &zbuf ) )
|
||||||
check( false );
|
check( false );
|
||||||
}
|
}
|
||||||
buf.clear();
|
buf.clear();
|
||||||
|
|
||||||
static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
memcpy( &zbuf, &empty, sizeof zbuf );
|
memcpy( &zbuf, &empty, sizeof zbuf );
|
||||||
}
|
}
|
||||||
|
|
||||||
Zlib_Inflater::Zlib_Inflater()
|
Zlib_Inflater::Zlib_Inflater()
|
||||||
{
|
{
|
||||||
deflated_ = false;
|
deflated_ = false;
|
||||||
end(); // initialize things
|
end(); // initialize things
|
||||||
}
|
}
|
||||||
|
|
||||||
Zlib_Inflater::~Zlib_Inflater()
|
Zlib_Inflater::~Zlib_Inflater()
|
||||||
{
|
{
|
||||||
end();
|
end();
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zlib_Inflater::fill_buf( int count )
|
blargg_err_t Zlib_Inflater::fill_buf( int count )
|
||||||
{
|
{
|
||||||
byte* out = buf.end() - count;
|
byte* out = buf.end() - count;
|
||||||
RETURN_ERR( callback( user_data, out, &count ) );
|
RETURN_ERR( callback( user_data, out, &count ) );
|
||||||
zbuf.avail_in = count;
|
zbuf.avail_in = count;
|
||||||
zbuf.next_in = out;
|
zbuf.next_in = out;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
|
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
|
||||||
int new_buf_size, int initial_read )
|
int new_buf_size, int initial_read )
|
||||||
{
|
{
|
||||||
callback = new_callback;
|
callback = new_callback;
|
||||||
user_data = new_user_data;
|
user_data = new_user_data;
|
||||||
|
|
||||||
end();
|
end();
|
||||||
|
|
||||||
// TODO: decide whether using different size on alloc failure is a good idea
|
// TODO: decide whether using different size on alloc failure is a good idea
|
||||||
//RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) );
|
//RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) );
|
||||||
if ( new_buf_size && buf.resize( new_buf_size ) )
|
if ( new_buf_size && buf.resize( new_buf_size ) )
|
||||||
{
|
{
|
||||||
ACK_FAILURE();
|
ACK_FAILURE();
|
||||||
new_buf_size = 0;
|
new_buf_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !new_buf_size )
|
if ( !new_buf_size )
|
||||||
{
|
{
|
||||||
RETURN_ERR( buf.resize( 4 * block_size ) );
|
RETURN_ERR( buf.resize( 4 * block_size ) );
|
||||||
initial_read = 0;
|
initial_read = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill buffer with some data, less than normal buffer size since caller might
|
// Fill buffer with some data, less than normal buffer size since caller might
|
||||||
// just be examining beginning of file.
|
// just be examining beginning of file.
|
||||||
return fill_buf( initial_read ? initial_read : block_size );
|
return fill_buf( initial_read ? initial_read : block_size );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset )
|
blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset )
|
||||||
{
|
{
|
||||||
zbuf.next_in += data_offset;
|
zbuf.next_in += data_offset;
|
||||||
zbuf.avail_in -= data_offset;
|
zbuf.avail_in -= data_offset;
|
||||||
|
|
||||||
if ( mode == mode_auto )
|
if ( mode == mode_auto )
|
||||||
{
|
{
|
||||||
// examine buffer for gzip header
|
// examine buffer for gzip header
|
||||||
mode = mode_copy;
|
mode = mode_copy;
|
||||||
unsigned const min_gzip_size = 2 + 8 + 8;
|
unsigned const min_gzip_size = 2 + 8 + 8;
|
||||||
if ( zbuf.avail_in >= min_gzip_size &&
|
if ( zbuf.avail_in >= min_gzip_size &&
|
||||||
zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B )
|
zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B )
|
||||||
mode = mode_ungz;
|
mode = mode_ungz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( mode != mode_copy )
|
if ( mode != mode_copy )
|
||||||
{
|
{
|
||||||
int wb = MAX_WBITS + 16; // have zlib handle gzip header
|
int wb = MAX_WBITS + 16; // have zlib handle gzip header
|
||||||
if ( mode == mode_raw_deflate )
|
if ( mode == mode_raw_deflate )
|
||||||
wb = -MAX_WBITS;
|
wb = -MAX_WBITS;
|
||||||
|
|
||||||
int zerr = inflateInit2( &zbuf, wb );
|
int zerr = inflateInit2( &zbuf, wb );
|
||||||
if ( zerr )
|
if ( zerr )
|
||||||
{
|
{
|
||||||
zbuf.next_in = NULL;
|
zbuf.next_in = NULL;
|
||||||
return get_zlib_err( zerr );
|
return get_zlib_err( zerr );
|
||||||
}
|
}
|
||||||
|
|
||||||
deflated_ = true;
|
deflated_ = true;
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Reads/inflates entire stream. All input must be in buffer, and count must be total
|
// Reads/inflates entire stream. All input must be in buffer, and count must be total
|
||||||
// of all output.
|
// of all output.
|
||||||
blargg_err_t read_all( void* out, int count );
|
blargg_err_t read_all( void* out, int count );
|
||||||
|
|
||||||
|
|
||||||
// zlib automatically applies this optimization (uses inflateFast)
|
// zlib automatically applies this optimization (uses inflateFast)
|
||||||
// TODO: remove
|
// TODO: remove
|
||||||
blargg_err_t Zlib_Inflater::read_all( void* out, int count )
|
blargg_err_t Zlib_Inflater::read_all( void* out, int count )
|
||||||
{
|
{
|
||||||
if ( deflated_ )
|
if ( deflated_ )
|
||||||
{
|
{
|
||||||
zbuf.next_out = (Bytef*) out;
|
zbuf.next_out = (Bytef*) out;
|
||||||
zbuf.avail_out = count;
|
zbuf.avail_out = count;
|
||||||
|
|
||||||
int err = inflate( &zbuf, Z_FINISH );
|
int err = inflate( &zbuf, Z_FINISH );
|
||||||
|
|
||||||
if ( zbuf.avail_out || err != Z_STREAM_END )
|
if ( zbuf.avail_out || err != Z_STREAM_END )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( zbuf.avail_in < count )
|
if ( zbuf.avail_in < count )
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
|
|
||||||
memcpy( out, zbuf.next_in, count );
|
memcpy( out, zbuf.next_in, count );
|
||||||
|
|
||||||
zbuf.next_in += count;
|
zbuf.next_in += count;
|
||||||
zbuf.avail_in -= count;
|
zbuf.avail_in -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
|
blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
|
||||||
{
|
{
|
||||||
int remain = *count_io;
|
int remain = *count_io;
|
||||||
if ( remain && zbuf.next_in )
|
if ( remain && zbuf.next_in )
|
||||||
{
|
{
|
||||||
if ( deflated_ )
|
if ( deflated_ )
|
||||||
{
|
{
|
||||||
zbuf.next_out = (Bytef*) out;
|
zbuf.next_out = (Bytef*) out;
|
||||||
zbuf.avail_out = remain;
|
zbuf.avail_out = remain;
|
||||||
|
|
||||||
while ( 1 )
|
while ( 1 )
|
||||||
{
|
{
|
||||||
uInt old_avail_in = zbuf.avail_in;
|
uInt old_avail_in = zbuf.avail_in;
|
||||||
int err = inflate( &zbuf, Z_NO_FLUSH );
|
int err = inflate( &zbuf, Z_NO_FLUSH );
|
||||||
if ( err == Z_STREAM_END )
|
if ( err == Z_STREAM_END )
|
||||||
{
|
{
|
||||||
remain = zbuf.avail_out;
|
remain = zbuf.avail_out;
|
||||||
end();
|
end();
|
||||||
break; // no more data to inflate
|
break; // no more data to inflate
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( err && (err != Z_BUF_ERROR || old_avail_in) )
|
if ( err && (err != Z_BUF_ERROR || old_avail_in) )
|
||||||
return get_zlib_err( err );
|
return get_zlib_err( err );
|
||||||
|
|
||||||
if ( !zbuf.avail_out )
|
if ( !zbuf.avail_out )
|
||||||
{
|
{
|
||||||
remain = 0;
|
remain = 0;
|
||||||
break; // requested number of bytes inflated
|
break; // requested number of bytes inflated
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( zbuf.avail_in )
|
if ( zbuf.avail_in )
|
||||||
{
|
{
|
||||||
// inflate() should never leave input if there's still space for output
|
// inflate() should never leave input if there's still space for output
|
||||||
check( false );
|
check( false );
|
||||||
return blargg_err_file_corrupt;
|
return blargg_err_file_corrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
RETURN_ERR( fill_buf( buf.size() ) );
|
RETURN_ERR( fill_buf( buf.size() ) );
|
||||||
if ( !zbuf.avail_in )
|
if ( !zbuf.avail_in )
|
||||||
return blargg_err_file_corrupt; // stream didn't end but there's no more data
|
return blargg_err_file_corrupt; // stream didn't end but there's no more data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while ( 1 )
|
while ( 1 )
|
||||||
{
|
{
|
||||||
// copy buffered data
|
// copy buffered data
|
||||||
if ( zbuf.avail_in )
|
if ( zbuf.avail_in )
|
||||||
{
|
{
|
||||||
long count = zbuf.avail_in;
|
long count = zbuf.avail_in;
|
||||||
if ( count > remain )
|
if ( count > remain )
|
||||||
count = remain;
|
count = remain;
|
||||||
memcpy( out, zbuf.next_in, count );
|
memcpy( out, zbuf.next_in, count );
|
||||||
zbuf.total_out += count;
|
zbuf.total_out += count;
|
||||||
out = (char*) out + count;
|
out = (char*) out + count;
|
||||||
remain -= count;
|
remain -= count;
|
||||||
zbuf.next_in += count;
|
zbuf.next_in += count;
|
||||||
zbuf.avail_in -= count;
|
zbuf.avail_in -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !zbuf.avail_in && zbuf.next_in < buf.end() )
|
if ( !zbuf.avail_in && zbuf.next_in < buf.end() )
|
||||||
{
|
{
|
||||||
end();
|
end();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read large request directly
|
// read large request directly
|
||||||
if ( remain + zbuf.total_out % block_size >= buf.size() )
|
if ( remain + zbuf.total_out % block_size >= buf.size() )
|
||||||
{
|
{
|
||||||
int count = remain;
|
int count = remain;
|
||||||
RETURN_ERR( callback( user_data, out, &count ) );
|
RETURN_ERR( callback( user_data, out, &count ) );
|
||||||
zbuf.total_out += count;
|
zbuf.total_out += count;
|
||||||
out = (char*) out + count;
|
out = (char*) out + count;
|
||||||
remain -= count;
|
remain -= count;
|
||||||
|
|
||||||
if ( remain )
|
if ( remain )
|
||||||
{
|
{
|
||||||
end();
|
end();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !remain )
|
if ( !remain )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) );
|
RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*count_io -= remain;
|
*count_io -= remain;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,70 +1,70 @@
|
||||||
// Simplifies use of zlib for inflating data
|
// Simplifies use of zlib for inflating data
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef ZLIB_INFLATER_H
|
#ifndef ZLIB_INFLATER_H
|
||||||
#define ZLIB_INFLATER_H
|
#define ZLIB_INFLATER_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#include "Data_Reader.h"
|
#include "Data_Reader.h"
|
||||||
#include "zlib.h"
|
#include "zlib.h"
|
||||||
|
|
||||||
class Zlib_Inflater {
|
class Zlib_Inflater {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
|
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
|
||||||
// to that number, or returns error if that many can't be read.
|
// to that number, or returns error if that many can't be read.
|
||||||
typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
|
typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
|
||||||
|
|
||||||
// Begins by setting callback and filling buffer. Default buffer is 16K and
|
// Begins by setting callback and filling buffer. Default buffer is 16K and
|
||||||
// filled to 4K, or specify buf_size and initial_read for custom buffer size
|
// filled to 4K, or specify buf_size and initial_read for custom buffer size
|
||||||
// and how much to read initially.
|
// and how much to read initially.
|
||||||
blargg_err_t begin( callback_t, void* user_data,
|
blargg_err_t begin( callback_t, void* user_data,
|
||||||
int buf_size = 0, int initial_read = 0 );
|
int buf_size = 0, int initial_read = 0 );
|
||||||
|
|
||||||
// Data read into buffer by begin()
|
// Data read into buffer by begin()
|
||||||
const unsigned char* data() const { return zbuf.next_in; }
|
const unsigned char* data() const { return zbuf.next_in; }
|
||||||
int filled() const { return zbuf.avail_in; }
|
int filled() const { return zbuf.avail_in; }
|
||||||
|
|
||||||
// Begins inflation using specified mode. Using mode_auto selects between
|
// Begins inflation using specified mode. Using mode_auto selects between
|
||||||
// mode_copy and mode_ungz by examining first two bytes of buffer. Use
|
// mode_copy and mode_ungz by examining first two bytes of buffer. Use
|
||||||
// buf_offset to specify where data begins in buffer, in case there is
|
// buf_offset to specify where data begins in buffer, in case there is
|
||||||
// header data that should be skipped.
|
// header data that should be skipped.
|
||||||
enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto };
|
enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto };
|
||||||
blargg_err_t set_mode( mode_t, int buf_offset = 0 );
|
blargg_err_t set_mode( mode_t, int buf_offset = 0 );
|
||||||
|
|
||||||
// True if set_mode() has been called with mode_ungz or mode_raw_deflate
|
// True if set_mode() has been called with mode_ungz or mode_raw_deflate
|
||||||
bool deflated() const { return deflated_; }
|
bool deflated() const { return deflated_; }
|
||||||
|
|
||||||
// Reads/inflates at most *count_io bytes into *out and sets *count_io to actual
|
// Reads/inflates at most *count_io bytes into *out and sets *count_io to actual
|
||||||
// number of bytes read (less than requested if end of data was reached).
|
// number of bytes read (less than requested if end of data was reached).
|
||||||
// Buffers source data internally, even in copy mode, so input file can be
|
// Buffers source data internally, even in copy mode, so input file can be
|
||||||
// unbuffered without sacrificing performance.
|
// unbuffered without sacrificing performance.
|
||||||
blargg_err_t read( void* out, int* count_io );
|
blargg_err_t read( void* out, int* count_io );
|
||||||
|
|
||||||
// Total number of bytes read since begin()
|
// Total number of bytes read since begin()
|
||||||
int tell() const { return zbuf.total_out; }
|
int tell() const { return zbuf.total_out; }
|
||||||
|
|
||||||
// Ends inflation and frees memory
|
// Ends inflation and frees memory
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// noncopyable
|
// noncopyable
|
||||||
Zlib_Inflater( const Zlib_Inflater& );
|
Zlib_Inflater( const Zlib_Inflater& );
|
||||||
Zlib_Inflater& operator = ( const Zlib_Inflater& );
|
Zlib_Inflater& operator = ( const Zlib_Inflater& );
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
public:
|
public:
|
||||||
Zlib_Inflater();
|
Zlib_Inflater();
|
||||||
~Zlib_Inflater();
|
~Zlib_Inflater();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
z_stream_s zbuf;
|
z_stream_s zbuf;
|
||||||
blargg_vector<unsigned char> buf;
|
blargg_vector<unsigned char> buf;
|
||||||
bool deflated_;
|
bool deflated_;
|
||||||
callback_t callback;
|
callback_t callback;
|
||||||
void* user_data;
|
void* user_data;
|
||||||
|
|
||||||
blargg_err_t fill_buf( int count );
|
blargg_err_t fill_buf( int count );
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,51 +1,51 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
/* Copyright (C) 2008-2009 Shay Green. This module is free software; you
|
/* Copyright (C) 2008-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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
void blargg_vector_::init()
|
void blargg_vector_::init()
|
||||||
{
|
{
|
||||||
begin_ = NULL;
|
begin_ = NULL;
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void blargg_vector_::clear()
|
void blargg_vector_::clear()
|
||||||
{
|
{
|
||||||
void* p = begin_;
|
void* p = begin_;
|
||||||
begin_ = NULL;
|
begin_ = NULL;
|
||||||
size_ = 0;
|
size_ = 0;
|
||||||
free( p );
|
free( p );
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
|
blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
|
||||||
{
|
{
|
||||||
if ( n != size_ )
|
if ( n != size_ )
|
||||||
{
|
{
|
||||||
if ( n == 0 )
|
if ( n == 0 )
|
||||||
{
|
{
|
||||||
// Simpler to handle explicitly. Realloc will handle a size of 0,
|
// Simpler to handle explicitly. Realloc will handle a size of 0,
|
||||||
// but then we have to avoid raising an error for a NULL return.
|
// but then we have to avoid raising an error for a NULL return.
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
void* p = realloc( begin_, n * elem_size );
|
void* p = realloc( begin_, n * elem_size );
|
||||||
CHECK_ALLOC( p );
|
CHECK_ALLOC( p );
|
||||||
begin_ = p;
|
begin_ = p;
|
||||||
size_ = n;
|
size_ = n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,201 +1,201 @@
|
||||||
// Sets up common environment for Shay Green's libraries.
|
// Sets up common environment for Shay Green's libraries.
|
||||||
// To change configuration options, modify blargg_config.h, not this file.
|
// To change configuration options, modify blargg_config.h, not this file.
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BLARGG_COMMON_H
|
#ifndef BLARGG_COMMON_H
|
||||||
#define BLARGG_COMMON_H
|
#define BLARGG_COMMON_H
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
typedef const char* blargg_err_t; // 0 on success, otherwise error string
|
typedef const char* blargg_err_t; // 0 on success, otherwise error string
|
||||||
|
|
||||||
// Success; no error
|
// Success; no error
|
||||||
int const blargg_ok = 0;
|
int const blargg_ok = 0;
|
||||||
|
|
||||||
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
|
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
|
||||||
#if __GNUC__ >= 3 || _MSC_VER >= 1100
|
#if __GNUC__ >= 3 || _MSC_VER >= 1100
|
||||||
#define BLARGG_RESTRICT __restrict
|
#define BLARGG_RESTRICT __restrict
|
||||||
#else
|
#else
|
||||||
#define BLARGG_RESTRICT
|
#define BLARGG_RESTRICT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if __cplusplus >= 199711
|
#if __cplusplus >= 199711
|
||||||
#define BLARGG_MUTABLE mutable
|
#define BLARGG_MUTABLE mutable
|
||||||
#else
|
#else
|
||||||
#define BLARGG_MUTABLE
|
#define BLARGG_MUTABLE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
|
/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
|
||||||
I don't just use 'abcd' because that's implementation-dependent. */
|
I don't just use 'abcd' because that's implementation-dependent. */
|
||||||
#define BLARGG_4CHAR( a, b, c, d ) \
|
#define BLARGG_4CHAR( a, b, c, d ) \
|
||||||
((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
|
((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
|
||||||
|
|
||||||
/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
|
/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
|
||||||
Can be used at file, function, or class scope. */
|
Can be used at file, function, or class scope. */
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
|
// MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
|
||||||
#define BLARGG_STATIC_ASSERT( expr ) \
|
#define BLARGG_STATIC_ASSERT( expr ) \
|
||||||
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
|
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
|
||||||
#else
|
#else
|
||||||
// Others fail when declaring same function multiple times in class,
|
// Others fail when declaring same function multiple times in class,
|
||||||
// so differentiate them by line
|
// so differentiate them by line
|
||||||
#define BLARGG_STATIC_ASSERT( expr ) \
|
#define BLARGG_STATIC_ASSERT( expr ) \
|
||||||
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
|
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Pure virtual functions cause a vtable entry to a "called pure virtual"
|
/* Pure virtual functions cause a vtable entry to a "called pure virtual"
|
||||||
error handler, requiring linkage to the C++ runtime library. This macro is
|
error handler, requiring linkage to the C++ runtime library. This macro is
|
||||||
used in place of the "= 0", and simply expands to its argument. During
|
used in place of the "= 0", and simply expands to its argument. During
|
||||||
development, it expands to "= 0", allowing detection of missing overrides. */
|
development, it expands to "= 0", allowing detection of missing overrides. */
|
||||||
#define BLARGG_PURE( def ) def
|
#define BLARGG_PURE( def ) def
|
||||||
|
|
||||||
/* My code depends on ASCII anywhere a character or string constant is
|
/* My code depends on ASCII anywhere a character or string constant is
|
||||||
compared with data read from a file, and anywhere file data is read and
|
compared with data read from a file, and anywhere file data is read and
|
||||||
treated as a string. */
|
treated as a string. */
|
||||||
#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
|
#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
|
||||||
#error "ASCII character set required"
|
#error "ASCII character set required"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* My code depends on int being at least 32 bits. Almost everything these days
|
/* My code depends on int being at least 32 bits. Almost everything these days
|
||||||
uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
|
uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
|
||||||
to test with. The issue can't be gotten around by using a suitable blargg_int
|
to test with. The issue can't be gotten around by using a suitable blargg_int
|
||||||
everywhere either, because int is often converted to implicitly when doing
|
everywhere either, because int is often converted to implicitly when doing
|
||||||
arithmetic on smaller types. */
|
arithmetic on smaller types. */
|
||||||
#if UINT_MAX < 0xFFFFFFFF
|
#if UINT_MAX < 0xFFFFFFFF
|
||||||
#error "int must be at least 32 bits"
|
#error "int must be at least 32 bits"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// In case compiler doesn't support these properly. Used rarely.
|
// In case compiler doesn't support these properly. Used rarely.
|
||||||
#define STATIC_CAST(T,expr) static_cast<T> (expr)
|
#define STATIC_CAST(T,expr) static_cast<T> (expr)
|
||||||
#define CONST_CAST( T,expr) const_cast<T> (expr)
|
#define CONST_CAST( T,expr) const_cast<T> (expr)
|
||||||
|
|
||||||
// User configuration can override the above macros if necessary
|
// User configuration can override the above macros if necessary
|
||||||
#include "blargg_config.h"
|
#include "blargg_config.h"
|
||||||
|
|
||||||
/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
|
/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
|
||||||
future version. In GCC, we can let the compiler warn. In other compilers,
|
future version. In GCC, we can let the compiler warn. In other compilers,
|
||||||
we strip it out unless BLARGG_LEGACY is true. */
|
we strip it out unless BLARGG_LEGACY is true. */
|
||||||
#if BLARGG_LEGACY
|
#if BLARGG_LEGACY
|
||||||
// Allow old client code to work without warnings
|
// Allow old client code to work without warnings
|
||||||
#define BLARGG_DEPRECATED_TEXT( text ) text
|
#define BLARGG_DEPRECATED_TEXT( text ) text
|
||||||
#define BLARGG_DEPRECATED( text ) text
|
#define BLARGG_DEPRECATED( text ) text
|
||||||
#elif __GNUC__ >= 4
|
#elif __GNUC__ >= 4
|
||||||
// In GCC, we can mark declarations and let the compiler warn
|
// In GCC, we can mark declarations and let the compiler warn
|
||||||
#define BLARGG_DEPRECATED_TEXT( text ) text
|
#define BLARGG_DEPRECATED_TEXT( text ) text
|
||||||
#define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
|
#define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
|
||||||
#else
|
#else
|
||||||
// By default, deprecated items are removed, to avoid use in new code
|
// By default, deprecated items are removed, to avoid use in new code
|
||||||
#define BLARGG_DEPRECATED_TEXT( text )
|
#define BLARGG_DEPRECATED_TEXT( text )
|
||||||
#define BLARGG_DEPRECATED( text )
|
#define BLARGG_DEPRECATED( text )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* BOOST::int8_t, BOOST::int32_t, etc.
|
/* BOOST::int8_t, BOOST::int32_t, etc.
|
||||||
I used BOOST since I originally was going to allow use of the boost library
|
I used BOOST since I originally was going to allow use of the boost library
|
||||||
for prividing the definitions. If I'm defining them, they must be scoped or
|
for prividing the definitions. If I'm defining them, they must be scoped or
|
||||||
else they could conflict with the standard ones at global scope. Even if
|
else they could conflict with the standard ones at global scope. Even if
|
||||||
HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
|
HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
|
||||||
global scope already. */
|
global scope already. */
|
||||||
#if defined (HAVE_STDINT_H) || \
|
#if defined (HAVE_STDINT_H) || \
|
||||||
UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
|
UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#define BOOST
|
#define BOOST
|
||||||
#else
|
#else
|
||||||
struct BOOST
|
struct BOOST
|
||||||
{
|
{
|
||||||
typedef signed char int8_t;
|
typedef signed char int8_t;
|
||||||
typedef unsigned char uint8_t;
|
typedef unsigned char uint8_t;
|
||||||
typedef short int16_t;
|
typedef short int16_t;
|
||||||
typedef unsigned short uint16_t;
|
typedef unsigned short uint16_t;
|
||||||
typedef int int32_t;
|
typedef int int32_t;
|
||||||
typedef unsigned int uint32_t;
|
typedef unsigned int uint32_t;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* My code is not written with exceptions in mind, so either uses new (nothrow)
|
/* My code is not written with exceptions in mind, so either uses new (nothrow)
|
||||||
OR overrides operator new in my classes. The former is best since clients
|
OR overrides operator new in my classes. The former is best since clients
|
||||||
creating objects will get standard exceptions on failure, but that causes it
|
creating objects will get standard exceptions on failure, but that causes it
|
||||||
to require the standard C++ library. So, when the client is using the C
|
to require the standard C++ library. So, when the client is using the C
|
||||||
interface, I override operator new to use malloc. */
|
interface, I override operator new to use malloc. */
|
||||||
|
|
||||||
// BLARGG_DISABLE_NOTHROW is put inside classes
|
// BLARGG_DISABLE_NOTHROW is put inside classes
|
||||||
#ifndef BLARGG_DISABLE_NOTHROW
|
#ifndef BLARGG_DISABLE_NOTHROW
|
||||||
// throw spec mandatory in ISO C++ if NULL can be returned
|
// throw spec mandatory in ISO C++ if NULL can be returned
|
||||||
#if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
|
#if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
|
||||||
#define BLARGG_THROWS_NOTHING throw ()
|
#define BLARGG_THROWS_NOTHING throw ()
|
||||||
#else
|
#else
|
||||||
#define BLARGG_THROWS_NOTHING
|
#define BLARGG_THROWS_NOTHING
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BLARGG_DISABLE_NOTHROW \
|
#define BLARGG_DISABLE_NOTHROW \
|
||||||
void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
|
void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
|
||||||
void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
|
void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
|
||||||
|
|
||||||
#define BLARGG_NEW new
|
#define BLARGG_NEW new
|
||||||
#else
|
#else
|
||||||
// BLARGG_NEW is used in place of new in library code
|
// BLARGG_NEW is used in place of new in library code
|
||||||
#include <new>
|
#include <new>
|
||||||
#define BLARGG_NEW new (std::nothrow)
|
#define BLARGG_NEW new (std::nothrow)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class blargg_vector_ {
|
class blargg_vector_ {
|
||||||
protected:
|
protected:
|
||||||
void* begin_;
|
void* begin_;
|
||||||
size_t size_;
|
size_t size_;
|
||||||
void init();
|
void init();
|
||||||
blargg_err_t resize_( size_t n, size_t elem_size );
|
blargg_err_t resize_( size_t n, size_t elem_size );
|
||||||
public:
|
public:
|
||||||
size_t size() const { return size_; }
|
size_t size() const { return size_; }
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Very lightweight vector for POD types (no constructor/destructor)
|
// Very lightweight vector for POD types (no constructor/destructor)
|
||||||
template<class T>
|
template<class T>
|
||||||
class blargg_vector : public blargg_vector_ {
|
class blargg_vector : public blargg_vector_ {
|
||||||
union T_must_be_pod { T t; }; // fails if T is not POD
|
union T_must_be_pod { T t; }; // fails if T is not POD
|
||||||
public:
|
public:
|
||||||
blargg_vector() { init(); }
|
blargg_vector() { init(); }
|
||||||
~blargg_vector() { clear(); }
|
~blargg_vector() { clear(); }
|
||||||
|
|
||||||
blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
|
blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
|
||||||
|
|
||||||
T* begin() { return static_cast<T*> (begin_); }
|
T* begin() { return static_cast<T*> (begin_); }
|
||||||
const T* begin() const { return static_cast<T*> (begin_); }
|
const T* begin() const { return static_cast<T*> (begin_); }
|
||||||
|
|
||||||
T* end() { return static_cast<T*> (begin_) + size_; }
|
T* end() { return static_cast<T*> (begin_) + size_; }
|
||||||
const T* end() const { return static_cast<T*> (begin_) + size_; }
|
const T* end() const { return static_cast<T*> (begin_) + size_; }
|
||||||
|
|
||||||
T& operator [] ( size_t n )
|
T& operator [] ( size_t n )
|
||||||
{
|
{
|
||||||
assert( n < size_ );
|
assert( n < size_ );
|
||||||
return static_cast<T*> (begin_) [n];
|
return static_cast<T*> (begin_) [n];
|
||||||
}
|
}
|
||||||
|
|
||||||
const T& operator [] ( size_t n ) const
|
const T& operator [] ( size_t n ) const
|
||||||
{
|
{
|
||||||
assert( n < size_ );
|
assert( n < size_ );
|
||||||
return static_cast<T*> (begin_) [n];
|
return static_cast<T*> (begin_) [n];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Callback function with user data.
|
// Callback function with user data.
|
||||||
// blargg_callback<T> set_callback; // for user, this acts like...
|
// blargg_callback<T> set_callback; // for user, this acts like...
|
||||||
// void set_callback( T func, void* user_data = NULL ); // ...this
|
// void set_callback( T func, void* user_data = NULL ); // ...this
|
||||||
// To call function, do set_callback.f( .. set_callback.data ... );
|
// To call function, do set_callback.f( .. set_callback.data ... );
|
||||||
template<class T>
|
template<class T>
|
||||||
struct blargg_callback
|
struct blargg_callback
|
||||||
{
|
{
|
||||||
T f;
|
T f;
|
||||||
void* data;
|
void* data;
|
||||||
blargg_callback() { f = NULL; }
|
blargg_callback() { f = NULL; }
|
||||||
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; }
|
||||||
};
|
};
|
||||||
|
|
||||||
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
|
||||||
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
|
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
// Library configuration. Modify this file as necessary.
|
// Library configuration. Modify this file as necessary.
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BLARGG_CONFIG_H
|
#ifndef BLARGG_CONFIG_H
|
||||||
#define BLARGG_CONFIG_H
|
#define BLARGG_CONFIG_H
|
||||||
|
|
||||||
// Uncomment a #define line below to have effect described.
|
// Uncomment a #define line below to have effect described.
|
||||||
|
|
||||||
// Enable RAR archive support. Doing so adds extra licensing restrictions
|
// Enable RAR archive support. Doing so adds extra licensing restrictions
|
||||||
// to this library (see unrar/readme.txt for more information).
|
// to this library (see unrar/readme.txt for more information).
|
||||||
//#define FEX_ENABLE_RAR 1
|
//#define FEX_ENABLE_RAR 1
|
||||||
|
|
||||||
// Accept file paths encoded as UTF-8. Currently only affects Windows,
|
// Accept file paths encoded as UTF-8. Currently only affects Windows,
|
||||||
// as Unix/Linux/Mac OS X already use UTF-8 paths.
|
// as Unix/Linux/Mac OS X already use UTF-8 paths.
|
||||||
//#define BLARGG_UTF8_PATHS 1
|
//#define BLARGG_UTF8_PATHS 1
|
||||||
|
|
||||||
// Enable support for as building DLL on Windows.
|
// Enable support for as building DLL on Windows.
|
||||||
//#define BLARGG_BUILD_DLL 1
|
//#define BLARGG_BUILD_DLL 1
|
||||||
|
|
||||||
// Support only the listed archive types. Remove any you don't need.
|
// Support only the listed archive types. Remove any you don't need.
|
||||||
#define FEX_TYPE_LIST \
|
#define FEX_TYPE_LIST \
|
||||||
fex_7z_type,\
|
fex_7z_type,\
|
||||||
fex_gz_type,\
|
fex_gz_type,\
|
||||||
fex_zip_type,
|
fex_zip_type,
|
||||||
|
|
||||||
// Use standard config.h if present
|
// Use standard config.h if present
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,185 +1,185 @@
|
||||||
// CPU Byte Order Utilities
|
// CPU Byte Order Utilities
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BLARGG_ENDIAN_H
|
#ifndef BLARGG_ENDIAN_H
|
||||||
#define BLARGG_ENDIAN_H
|
#define BLARGG_ENDIAN_H
|
||||||
|
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
|
|
||||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
||||||
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
|
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
|
||||||
#define BLARGG_CPU_X86 1
|
#define BLARGG_CPU_X86 1
|
||||||
#define BLARGG_CPU_CISC 1
|
#define BLARGG_CPU_CISC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
|
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
|
||||||
defined (__POWERPC__) || defined (__powerc)
|
defined (__POWERPC__) || defined (__powerc)
|
||||||
#define BLARGG_CPU_POWERPC 1
|
#define BLARGG_CPU_POWERPC 1
|
||||||
#define BLARGG_CPU_RISC 1
|
#define BLARGG_CPU_RISC 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
||||||
// one may be #defined to 1. Only needed if something actually depends on byte order.
|
// one may be #defined to 1. Only needed if something actually depends on byte order.
|
||||||
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
|
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
// GCC handles this for us
|
// GCC handles this for us
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||||
#define BLARGG_LITTLE_ENDIAN 1
|
#define BLARGG_LITTLE_ENDIAN 1
|
||||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||||
#define BLARGG_BIG_ENDIAN 1
|
#define BLARGG_BIG_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
|
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
|
||||||
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
|
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
|
||||||
#define BLARGG_LITTLE_ENDIAN 1
|
#define BLARGG_LITTLE_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
||||||
defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
||||||
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
||||||
#define BLARGG_BIG_ENDIAN 1
|
#define BLARGG_BIG_ENDIAN 1
|
||||||
#elif !defined (__mips__)
|
#elif !defined (__mips__)
|
||||||
// No endian specified; assume little-endian, since it's most common
|
// No endian specified; assume little-endian, since it's most common
|
||||||
#define BLARGG_LITTLE_ENDIAN 1
|
#define BLARGG_LITTLE_ENDIAN 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
|
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
|
||||||
#undef BLARGG_LITTLE_ENDIAN
|
#undef BLARGG_LITTLE_ENDIAN
|
||||||
#undef BLARGG_BIG_ENDIAN
|
#undef BLARGG_BIG_ENDIAN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
inline void blargg_verify_byte_order()
|
inline void blargg_verify_byte_order()
|
||||||
{
|
{
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
#if BLARGG_BIG_ENDIAN
|
#if BLARGG_BIG_ENDIAN
|
||||||
volatile int i = 1;
|
volatile int i = 1;
|
||||||
assert( *(volatile char*) &i == 0 );
|
assert( *(volatile char*) &i == 0 );
|
||||||
#elif BLARGG_LITTLE_ENDIAN
|
#elif BLARGG_LITTLE_ENDIAN
|
||||||
volatile int i = 1;
|
volatile int i = 1;
|
||||||
assert( *(volatile char*) &i != 0 );
|
assert( *(volatile char*) &i != 0 );
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_le16( void const* p )
|
inline unsigned get_le16( void const* p )
|
||||||
{
|
{
|
||||||
return (unsigned) ((unsigned char const*) p) [1] << 8 |
|
return (unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||||
(unsigned) ((unsigned char const*) p) [0];
|
(unsigned) ((unsigned char const*) p) [0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_be16( void const* p )
|
inline unsigned get_be16( void const* p )
|
||||||
{
|
{
|
||||||
return (unsigned) ((unsigned char const*) p) [0] << 8 |
|
return (unsigned) ((unsigned char const*) p) [0] << 8 |
|
||||||
(unsigned) ((unsigned char const*) p) [1];
|
(unsigned) ((unsigned char const*) p) [1];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_le32( void const* p )
|
inline unsigned get_le32( void const* p )
|
||||||
{
|
{
|
||||||
return (unsigned) ((unsigned char const*) p) [3] << 24 |
|
return (unsigned) ((unsigned char const*) p) [3] << 24 |
|
||||||
(unsigned) ((unsigned char const*) p) [2] << 16 |
|
(unsigned) ((unsigned char const*) p) [2] << 16 |
|
||||||
(unsigned) ((unsigned char const*) p) [1] << 8 |
|
(unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||||
(unsigned) ((unsigned char const*) p) [0];
|
(unsigned) ((unsigned char const*) p) [0];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned get_be32( void const* p )
|
inline unsigned get_be32( void const* p )
|
||||||
{
|
{
|
||||||
return (unsigned) ((unsigned char const*) p) [0] << 24 |
|
return (unsigned) ((unsigned char const*) p) [0] << 24 |
|
||||||
(unsigned) ((unsigned char const*) p) [1] << 16 |
|
(unsigned) ((unsigned char const*) p) [1] << 16 |
|
||||||
(unsigned) ((unsigned char const*) p) [2] << 8 |
|
(unsigned) ((unsigned char const*) p) [2] << 8 |
|
||||||
(unsigned) ((unsigned char const*) p) [3];
|
(unsigned) ((unsigned char const*) p) [3];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_le16( void* p, unsigned n )
|
inline void set_le16( void* p, unsigned n )
|
||||||
{
|
{
|
||||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [0] = (unsigned char) n;
|
((unsigned char*) p) [0] = (unsigned char) n;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_be16( void* p, unsigned n )
|
inline void set_be16( void* p, unsigned n )
|
||||||
{
|
{
|
||||||
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
|
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [1] = (unsigned char) n;
|
((unsigned char*) p) [1] = (unsigned char) n;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_le32( void* p, unsigned n )
|
inline void set_le32( void* p, unsigned n )
|
||||||
{
|
{
|
||||||
((unsigned char*) p) [0] = (unsigned char) n;
|
((unsigned char*) p) [0] = (unsigned char) n;
|
||||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
||||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set_be32( void* p, unsigned n )
|
inline void set_be32( void* p, unsigned n )
|
||||||
{
|
{
|
||||||
((unsigned char*) p) [3] = (unsigned char) n;
|
((unsigned char*) p) [3] = (unsigned char) n;
|
||||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
||||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
||||||
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BLARGG_NONPORTABLE
|
#if BLARGG_NONPORTABLE
|
||||||
// Optimized implementation if byte order is known
|
// Optimized implementation if byte order is known
|
||||||
#if BLARGG_LITTLE_ENDIAN
|
#if BLARGG_LITTLE_ENDIAN
|
||||||
#define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
#define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
||||||
#define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
#define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
||||||
#define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
#define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||||
#define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
#define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||||
#elif BLARGG_BIG_ENDIAN
|
#elif BLARGG_BIG_ENDIAN
|
||||||
#define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
#define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
||||||
#define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
#define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
||||||
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||||
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||||
|
|
||||||
#if BLARGG_CPU_POWERPC
|
#if BLARGG_CPU_POWERPC
|
||||||
// PowerPC has special byte-reversed instructions
|
// PowerPC has special byte-reversed instructions
|
||||||
#if defined (__MWERKS__)
|
#if defined (__MWERKS__)
|
||||||
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
||||||
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
||||||
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
||||||
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
||||||
#elif defined (__GNUC__)
|
#elif defined (__GNUC__)
|
||||||
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
|
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
|
||||||
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
|
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
|
||||||
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||||
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_LE16
|
#ifndef GET_LE16
|
||||||
#define GET_LE16( addr ) get_le16( addr )
|
#define GET_LE16( addr ) get_le16( addr )
|
||||||
#define SET_LE16( addr, data ) set_le16( addr, data )
|
#define SET_LE16( addr, data ) set_le16( addr, data )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_LE32
|
#ifndef GET_LE32
|
||||||
#define GET_LE32( addr ) get_le32( addr )
|
#define GET_LE32( addr ) get_le32( addr )
|
||||||
#define SET_LE32( addr, data ) set_le32( addr, data )
|
#define SET_LE32( addr, data ) set_le32( addr, data )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_BE16
|
#ifndef GET_BE16
|
||||||
#define GET_BE16( addr ) get_be16( addr )
|
#define GET_BE16( addr ) get_be16( addr )
|
||||||
#define SET_BE16( addr, data ) set_be16( addr, data )
|
#define SET_BE16( addr, data ) set_be16( addr, data )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef GET_BE32
|
#ifndef GET_BE32
|
||||||
#define GET_BE32( addr ) get_be32( addr )
|
#define GET_BE32( addr ) get_be32( addr )
|
||||||
#define SET_BE32( addr, data ) set_be32( addr, data )
|
#define SET_BE32( addr, data ) set_be32( addr, data )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// auto-selecting versions
|
// auto-selecting versions
|
||||||
|
|
||||||
inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
|
inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
|
||||||
inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
|
inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
|
||||||
inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
|
inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
|
||||||
inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
|
inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
|
||||||
inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
|
inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
|
||||||
inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
|
inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
|
||||||
inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
|
inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
|
||||||
inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
|
inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,113 +1,113 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "blargg_errors.h"
|
#include "blargg_errors.h"
|
||||||
|
|
||||||
/* Copyright (C) 2009 Shay Green. This module is free software; you
|
/* Copyright (C) 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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
|
blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
|
||||||
blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
|
blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
|
||||||
blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
|
blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
|
||||||
blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
|
blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
|
||||||
blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
|
blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
|
||||||
|
|
||||||
blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
|
blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
|
||||||
blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
|
blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
|
||||||
blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
|
blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
|
||||||
blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
|
blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
|
||||||
blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
|
blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
|
||||||
blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
|
blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
|
||||||
|
|
||||||
blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
|
blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
|
||||||
blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
|
blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
|
||||||
blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
|
blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
|
||||||
|
|
||||||
const char* blargg_err_str( blargg_err_t err )
|
const char* blargg_err_str( blargg_err_t err )
|
||||||
{
|
{
|
||||||
if ( !err )
|
if ( !err )
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if ( *err == BLARGG_ERR_TYPE("")[0] )
|
if ( *err == BLARGG_ERR_TYPE("")[0] )
|
||||||
return err + 1;
|
return err + 1;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool blargg_is_err_type( blargg_err_t err, const char type [] )
|
bool blargg_is_err_type( blargg_err_t err, const char type [] )
|
||||||
{
|
{
|
||||||
if ( err )
|
if ( err )
|
||||||
{
|
{
|
||||||
// True if first strlen(type) characters of err match type
|
// True if first strlen(type) characters of err match type
|
||||||
char const* p = err;
|
char const* p = err;
|
||||||
while ( *type && *type == *p )
|
while ( *type && *type == *p )
|
||||||
{
|
{
|
||||||
type++;
|
type++;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !*type )
|
if ( !*type )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* blargg_err_details( blargg_err_t err )
|
const char* blargg_err_details( blargg_err_t err )
|
||||||
{
|
{
|
||||||
const char* p = err;
|
const char* p = err;
|
||||||
if ( !p )
|
if ( !p )
|
||||||
{
|
{
|
||||||
p = "";
|
p = "";
|
||||||
}
|
}
|
||||||
else if ( *p == BLARGG_ERR_TYPE("")[0] )
|
else if ( *p == BLARGG_ERR_TYPE("")[0] )
|
||||||
{
|
{
|
||||||
while ( *p && *p != ';' )
|
while ( *p && *p != ';' )
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
// Skip ; and space after it
|
// Skip ; and space after it
|
||||||
if ( *p )
|
if ( *p )
|
||||||
{
|
{
|
||||||
p++;
|
p++;
|
||||||
|
|
||||||
check( *p == ' ' );
|
check( *p == ' ' );
|
||||||
if ( *p )
|
if ( *p )
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
|
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
|
||||||
{
|
{
|
||||||
if ( !err )
|
if ( !err )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
while ( codes->str && !blargg_is_err_type( err, codes->str ) )
|
while ( codes->str && !blargg_is_err_type( err, codes->str ) )
|
||||||
codes++;
|
codes++;
|
||||||
|
|
||||||
return codes->code;
|
return codes->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
|
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
|
||||||
{
|
{
|
||||||
if ( !code )
|
if ( !code )
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
|
|
||||||
while ( codes->str && codes->code != code )
|
while ( codes->str && codes->code != code )
|
||||||
codes++;
|
codes++;
|
||||||
|
|
||||||
if ( !codes->str )
|
if ( !codes->str )
|
||||||
return blargg_err_generic;
|
return blargg_err_generic;
|
||||||
|
|
||||||
return codes->str;
|
return codes->str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,80 +1,80 @@
|
||||||
// Error strings and conversion functions
|
// Error strings and conversion functions
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BLARGG_ERRORS_H
|
#ifndef BLARGG_ERRORS_H
|
||||||
#define BLARGG_ERRORS_H
|
#define BLARGG_ERRORS_H
|
||||||
|
|
||||||
#ifndef BLARGG_COMMON_H
|
#ifndef BLARGG_COMMON_H
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef const char blargg_err_def_t [];
|
typedef const char blargg_err_def_t [];
|
||||||
|
|
||||||
// Basic errors
|
// Basic errors
|
||||||
extern blargg_err_def_t blargg_err_generic;
|
extern blargg_err_def_t blargg_err_generic;
|
||||||
extern blargg_err_def_t blargg_err_memory;
|
extern blargg_err_def_t blargg_err_memory;
|
||||||
extern blargg_err_def_t blargg_err_caller;
|
extern blargg_err_def_t blargg_err_caller;
|
||||||
extern blargg_err_def_t blargg_err_internal;
|
extern blargg_err_def_t blargg_err_internal;
|
||||||
extern blargg_err_def_t blargg_err_limitation;
|
extern blargg_err_def_t blargg_err_limitation;
|
||||||
|
|
||||||
// File low-level
|
// File low-level
|
||||||
extern blargg_err_def_t blargg_err_file_missing; // not found
|
extern blargg_err_def_t blargg_err_file_missing; // not found
|
||||||
extern blargg_err_def_t blargg_err_file_read;
|
extern blargg_err_def_t blargg_err_file_read;
|
||||||
extern blargg_err_def_t blargg_err_file_write;
|
extern blargg_err_def_t blargg_err_file_write;
|
||||||
extern blargg_err_def_t blargg_err_file_io;
|
extern blargg_err_def_t blargg_err_file_io;
|
||||||
extern blargg_err_def_t blargg_err_file_full;
|
extern blargg_err_def_t blargg_err_file_full;
|
||||||
extern blargg_err_def_t blargg_err_file_eof;
|
extern blargg_err_def_t blargg_err_file_eof;
|
||||||
|
|
||||||
// File high-level
|
// File high-level
|
||||||
extern blargg_err_def_t blargg_err_file_type; // wrong file type
|
extern blargg_err_def_t blargg_err_file_type; // wrong file type
|
||||||
extern blargg_err_def_t blargg_err_file_feature;
|
extern blargg_err_def_t blargg_err_file_feature;
|
||||||
extern blargg_err_def_t blargg_err_file_corrupt;
|
extern blargg_err_def_t blargg_err_file_corrupt;
|
||||||
|
|
||||||
// C string describing error, or "" if err == NULL
|
// C string describing error, or "" if err == NULL
|
||||||
const char* blargg_err_str( blargg_err_t err );
|
const char* blargg_err_str( blargg_err_t err );
|
||||||
|
|
||||||
// True iff error is of given type, or false if err == NULL
|
// True iff error is of given type, or false if err == NULL
|
||||||
bool blargg_is_err_type( blargg_err_t, const char type [] );
|
bool blargg_is_err_type( blargg_err_t, const char type [] );
|
||||||
|
|
||||||
// Details of error without describing main cause, or "" if err == NULL
|
// Details of error without describing main cause, or "" if err == NULL
|
||||||
const char* blargg_err_details( blargg_err_t err );
|
const char* blargg_err_details( blargg_err_t err );
|
||||||
|
|
||||||
// Converts error string to integer code using mapping table. Calls blargg_is_err_type()
|
// Converts error string to integer code using mapping table. Calls blargg_is_err_type()
|
||||||
// for each str and returns code on first match. Returns 0 if err == NULL.
|
// for each str and returns code on first match. Returns 0 if err == NULL.
|
||||||
struct blargg_err_to_code_t {
|
struct blargg_err_to_code_t {
|
||||||
const char* str;
|
const char* str;
|
||||||
int code;
|
int code;
|
||||||
};
|
};
|
||||||
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
|
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
|
||||||
|
|
||||||
// Converts error code back to string. If code == 0, returns NULL. If not in table,
|
// Converts error code back to string. If code == 0, returns NULL. If not in table,
|
||||||
// returns blargg_err_generic.
|
// returns blargg_err_generic.
|
||||||
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
|
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
|
||||||
|
|
||||||
// Generates error string literal with details of cause
|
// Generates error string literal with details of cause
|
||||||
#define BLARGG_ERR( type, str ) (type "; " str)
|
#define BLARGG_ERR( type, str ) (type "; " str)
|
||||||
|
|
||||||
// Extra space to make it clear when blargg_err_str() isn't called to get
|
// Extra space to make it clear when blargg_err_str() isn't called to get
|
||||||
// printable version of error. At some point, I might prefix error strings
|
// printable version of error. At some point, I might prefix error strings
|
||||||
// with a code, to speed conversion to a code.
|
// with a code, to speed conversion to a code.
|
||||||
#define BLARGG_ERR_TYPE( str ) " " str
|
#define BLARGG_ERR_TYPE( str ) " " str
|
||||||
|
|
||||||
// Error types to pass to BLARGG_ERR macro
|
// Error types to pass to BLARGG_ERR macro
|
||||||
#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
|
#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
|
||||||
#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
|
#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
|
||||||
#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
|
#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
|
||||||
#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
|
#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
|
||||||
#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
|
#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
|
||||||
|
|
||||||
#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
|
#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
|
||||||
#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
|
#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
|
||||||
#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
|
#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
|
||||||
#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
|
#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
|
||||||
#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
|
#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
|
||||||
#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
|
#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
|
||||||
|
|
||||||
#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
|
#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
|
||||||
#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
|
#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
|
||||||
#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
|
#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,125 +1,125 @@
|
||||||
/* Included at the beginning of library source files, AFTER all other #include
|
/* Included at the beginning of library source files, AFTER all other #include
|
||||||
lines. Sets up helpful macros and services used in my source code. Since this
|
lines. Sets up helpful macros and services used in my source code. Since this
|
||||||
is only "active" in my source code, I don't have to worry about polluting the
|
is only "active" in my source code, I don't have to worry about polluting the
|
||||||
global namespace with unprefixed names. */
|
global namespace with unprefixed names. */
|
||||||
|
|
||||||
// File_Extractor 1.0.0
|
// File_Extractor 1.0.0
|
||||||
#ifndef BLARGG_SOURCE_H
|
#ifndef BLARGG_SOURCE_H
|
||||||
#define BLARGG_SOURCE_H
|
#define BLARGG_SOURCE_H
|
||||||
|
|
||||||
#ifndef BLARGG_COMMON_H // optimization only
|
#ifndef BLARGG_COMMON_H // optimization only
|
||||||
#include "blargg_common.h"
|
#include "blargg_common.h"
|
||||||
#endif
|
#endif
|
||||||
#include "blargg_errors.h"
|
#include "blargg_errors.h"
|
||||||
|
|
||||||
#include <string.h> /* memcpy(), memset(), memmove() */
|
#include <string.h> /* memcpy(), memset(), memmove() */
|
||||||
#include <stddef.h> /* offsetof() */
|
#include <stddef.h> /* offsetof() */
|
||||||
|
|
||||||
/* The following four macros are for debugging only. Some or all might be
|
/* The following four macros are for debugging only. Some or all might be
|
||||||
defined to do nothing, depending on the circumstances. Described is what
|
defined to do nothing, depending on the circumstances. Described is what
|
||||||
happens when a particular macro is defined to do something. When defined to
|
happens when a particular macro is defined to do something. When defined to
|
||||||
do nothing, the macros do NOT evaluate their argument(s). */
|
do nothing, the macros do NOT evaluate their argument(s). */
|
||||||
|
|
||||||
/* If expr is false, prints file and line number, then aborts program. Meant
|
/* If expr is false, prints file and line number, then aborts program. Meant
|
||||||
for checking internal state and consistency. A failed assertion indicates a bug
|
for checking internal state and consistency. A failed assertion indicates a bug
|
||||||
in MY code.
|
in MY code.
|
||||||
|
|
||||||
void assert( bool expr ); */
|
void assert( bool expr ); */
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/* If expr is false, prints file and line number, then aborts program. Meant
|
/* If expr is false, prints file and line number, then aborts program. Meant
|
||||||
for checking caller-supplied parameters and operations that are outside the
|
for checking caller-supplied parameters and operations that are outside the
|
||||||
control of the module. A failed requirement probably indicates a bug in YOUR
|
control of the module. A failed requirement probably indicates a bug in YOUR
|
||||||
code.
|
code.
|
||||||
|
|
||||||
void require( bool expr ); */
|
void require( bool expr ); */
|
||||||
#undef require
|
#undef require
|
||||||
#define require( expr ) assert( expr )
|
#define require( expr ) assert( expr )
|
||||||
|
|
||||||
/* Like printf() except output goes to debugging console/file.
|
/* Like printf() except output goes to debugging console/file.
|
||||||
|
|
||||||
void dprintf( const char format [], ... ); */
|
void dprintf( const char format [], ... ); */
|
||||||
static inline void blargg_dprintf_( const char [], ... ) { }
|
static inline void blargg_dprintf_( const char [], ... ) { }
|
||||||
#undef dprintf
|
#undef dprintf
|
||||||
#define dprintf (1) ? (void) 0 : blargg_dprintf_
|
#define dprintf (1) ? (void) 0 : blargg_dprintf_
|
||||||
|
|
||||||
/* If expr is false, prints file and line number to debug console/log, then
|
/* If expr is false, prints file and line number to debug console/log, then
|
||||||
continues execution normally. Meant for flagging potential problems or things
|
continues execution normally. Meant for flagging potential problems or things
|
||||||
that should be looked into, but that aren't serious problems.
|
that should be looked into, but that aren't serious problems.
|
||||||
|
|
||||||
void check( bool expr ); */
|
void check( bool expr ); */
|
||||||
#undef check
|
#undef check
|
||||||
#define check( expr ) ((void) 0)
|
#define check( expr ) ((void) 0)
|
||||||
|
|
||||||
/* If expr yields non-NULL error string, returns it from current function,
|
/* If expr yields non-NULL error string, returns it from current function,
|
||||||
otherwise continues normally. */
|
otherwise continues normally. */
|
||||||
#undef RETURN_ERR
|
#undef RETURN_ERR
|
||||||
#define RETURN_ERR( expr ) \
|
#define RETURN_ERR( expr ) \
|
||||||
do {\
|
do {\
|
||||||
blargg_err_t blargg_return_err_ = (expr);\
|
blargg_err_t blargg_return_err_ = (expr);\
|
||||||
if ( blargg_return_err_ )\
|
if ( blargg_return_err_ )\
|
||||||
return blargg_return_err_;\
|
return blargg_return_err_;\
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
|
/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
|
||||||
#undef CHECK_ALLOC
|
#undef CHECK_ALLOC
|
||||||
#define CHECK_ALLOC( ptr ) \
|
#define CHECK_ALLOC( ptr ) \
|
||||||
do {\
|
do {\
|
||||||
if ( !(ptr) )\
|
if ( !(ptr) )\
|
||||||
return blargg_err_memory;\
|
return blargg_err_memory;\
|
||||||
} while ( 0 )
|
} while ( 0 )
|
||||||
|
|
||||||
/* The usual min/max functions for built-in types.
|
/* The usual min/max functions for built-in types.
|
||||||
|
|
||||||
template<typename T> T min( T x, T y ) { return x < y ? x : y; }
|
template<typename T> T min( T x, T y ) { return x < y ? x : y; }
|
||||||
template<typename T> T max( T x, T y ) { return x > y ? x : y; } */
|
template<typename T> T max( T x, T y ) { return x > y ? x : y; } */
|
||||||
#define BLARGG_DEF_MIN_MAX( type ) \
|
#define BLARGG_DEF_MIN_MAX( type ) \
|
||||||
static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
|
static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
|
||||||
static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
|
static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
|
||||||
|
|
||||||
BLARGG_DEF_MIN_MAX( int )
|
BLARGG_DEF_MIN_MAX( int )
|
||||||
BLARGG_DEF_MIN_MAX( unsigned )
|
BLARGG_DEF_MIN_MAX( unsigned )
|
||||||
BLARGG_DEF_MIN_MAX( long )
|
BLARGG_DEF_MIN_MAX( long )
|
||||||
BLARGG_DEF_MIN_MAX( unsigned long )
|
BLARGG_DEF_MIN_MAX( unsigned long )
|
||||||
BLARGG_DEF_MIN_MAX( float )
|
BLARGG_DEF_MIN_MAX( float )
|
||||||
BLARGG_DEF_MIN_MAX( double )
|
BLARGG_DEF_MIN_MAX( double )
|
||||||
|
|
||||||
#undef min
|
#undef min
|
||||||
#define min blargg_min
|
#define min blargg_min
|
||||||
|
|
||||||
#undef max
|
#undef max
|
||||||
#define max blargg_max
|
#define max blargg_max
|
||||||
|
|
||||||
// typedef unsigned char byte;
|
// typedef unsigned char byte;
|
||||||
typedef unsigned char blargg_byte;
|
typedef unsigned char blargg_byte;
|
||||||
#undef byte
|
#undef byte
|
||||||
#define byte blargg_byte
|
#define byte blargg_byte
|
||||||
|
|
||||||
#ifndef BLARGG_EXPORT
|
#ifndef BLARGG_EXPORT
|
||||||
#if defined (_WIN32) && BLARGG_BUILD_DLL
|
#if defined (_WIN32) && BLARGG_BUILD_DLL
|
||||||
#define BLARGG_EXPORT __declspec(dllexport)
|
#define BLARGG_EXPORT __declspec(dllexport)
|
||||||
#elif defined (__GNUC__)
|
#elif defined (__GNUC__)
|
||||||
// can always set visibility, even when not building DLL
|
// can always set visibility, even when not building DLL
|
||||||
#define BLARGG_EXPORT __attribute__ ((visibility ("default")))
|
#define BLARGG_EXPORT __attribute__ ((visibility ("default")))
|
||||||
#else
|
#else
|
||||||
#define BLARGG_EXPORT
|
#define BLARGG_EXPORT
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BLARGG_LEGACY
|
#if BLARGG_LEGACY
|
||||||
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
||||||
#define BLARGG_RETURN_ERR RETURN_ERR
|
#define BLARGG_RETURN_ERR RETURN_ERR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Called after failed operation when overall operation may still complete OK.
|
// Called after failed operation when overall operation may still complete OK.
|
||||||
// Only used by unit testing framework.
|
// Only used by unit testing framework.
|
||||||
#undef ACK_FAILURE
|
#undef ACK_FAILURE
|
||||||
#define ACK_FAILURE() ((void)0)
|
#define ACK_FAILURE() ((void)0)
|
||||||
|
|
||||||
/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc.
|
/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc.
|
||||||
and check */
|
and check */
|
||||||
#ifdef BLARGG_SOURCE_BEGIN
|
#ifdef BLARGG_SOURCE_BEGIN
|
||||||
#include BLARGG_SOURCE_BEGIN
|
#include BLARGG_SOURCE_BEGIN
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
642
fex/fex/fex.cpp
642
fex/fex/fex.cpp
|
@ -1,321 +1,321 @@
|
||||||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||||
|
|
||||||
#include "fex.h"
|
#include "fex.h"
|
||||||
|
|
||||||
#include "File_Extractor.h"
|
#include "File_Extractor.h"
|
||||||
#include "blargg_endian.h"
|
#include "blargg_endian.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.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
|
||||||
General Public License as published by the Free Software Foundation; either
|
General Public License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version. This
|
version 2.1 of the License, or (at your option) any later version. This
|
||||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||||
details. You should have received a copy of the GNU Lesser General Public
|
details. You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this module; if not, write to the Free Software Foundation,
|
License along with this module; if not, write to the Free Software Foundation,
|
||||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||||
|
|
||||||
#include "blargg_source.h"
|
#include "blargg_source.h"
|
||||||
|
|
||||||
|
|
||||||
//// Types
|
//// Types
|
||||||
|
|
||||||
BLARGG_EXPORT const fex_type_t* fex_type_list( void )
|
BLARGG_EXPORT const fex_type_t* fex_type_list( void )
|
||||||
{
|
{
|
||||||
static fex_type_t const fex_type_list_ [] =
|
static fex_type_t const fex_type_list_ [] =
|
||||||
{
|
{
|
||||||
#ifdef FEX_TYPE_LIST
|
#ifdef FEX_TYPE_LIST
|
||||||
FEX_TYPE_LIST
|
FEX_TYPE_LIST
|
||||||
#else
|
#else
|
||||||
// Modify blargg_config.h to change type list, NOT this file
|
// Modify blargg_config.h to change type list, NOT this file
|
||||||
fex_7z_type,
|
fex_7z_type,
|
||||||
fex_gz_type,
|
fex_gz_type,
|
||||||
#if FEX_ENABLE_RAR
|
#if FEX_ENABLE_RAR
|
||||||
fex_rar_type,
|
fex_rar_type,
|
||||||
#endif
|
#endif
|
||||||
fex_zip_type,
|
fex_zip_type,
|
||||||
#endif
|
#endif
|
||||||
fex_bin_type,
|
fex_bin_type,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
return fex_type_list_;
|
return fex_type_list_;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_init( void )
|
BLARGG_EXPORT fex_err_t fex_init( void )
|
||||||
{
|
{
|
||||||
static bool inited;
|
static bool inited;
|
||||||
if ( !inited )
|
if ( !inited )
|
||||||
{
|
{
|
||||||
for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t )
|
for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t )
|
||||||
{
|
{
|
||||||
if ( (*t)->init )
|
if ( (*t)->init )
|
||||||
RETURN_ERR( (*t)->init() );
|
RETURN_ERR( (*t)->init() );
|
||||||
}
|
}
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT const char* fex_identify_header( void const* header )
|
BLARGG_EXPORT const char* fex_identify_header( void const* header )
|
||||||
{
|
{
|
||||||
unsigned four = get_be32( header );
|
unsigned four = get_be32( header );
|
||||||
switch ( four )
|
switch ( four )
|
||||||
{
|
{
|
||||||
case 0x52457E5E:
|
case 0x52457E5E:
|
||||||
case 0x52617221: return ".rar";
|
case 0x52617221: return ".rar";
|
||||||
|
|
||||||
case 0x377ABCAF: return ".7z";
|
case 0x377ABCAF: return ".7z";
|
||||||
|
|
||||||
case 0x504B0304:
|
case 0x504B0304:
|
||||||
case 0x504B0506: return ".zip";
|
case 0x504B0506: return ".zip";
|
||||||
|
|
||||||
case 0x53495421: return ".sit";
|
case 0x53495421: return ".sit";
|
||||||
case 0x41724301: return ".arc";
|
case 0x41724301: return ".arc";
|
||||||
case 0x4D534346: return ".cab";
|
case 0x4D534346: return ".cab";
|
||||||
case 0x5A4F4F20: return ".zoo";
|
case 0x5A4F4F20: return ".zoo";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned three = four >> 8;
|
unsigned three = four >> 8;
|
||||||
switch ( three )
|
switch ( three )
|
||||||
{
|
{
|
||||||
case 0x425A68: return ".bz2";
|
case 0x425A68: return ".bz2";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned two = four >> 16;
|
unsigned two = four >> 16;
|
||||||
switch ( two )
|
switch ( two )
|
||||||
{
|
{
|
||||||
case 0x1F8B: return ".gz";
|
case 0x1F8B: return ".gz";
|
||||||
case 0x60EA: return ".arj";
|
case 0x60EA: return ".arj";
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned skip_first_two = four & 0xFFFF;
|
unsigned skip_first_two = four & 0xFFFF;
|
||||||
if ( skip_first_two == 0x2D6C )
|
if ( skip_first_two == 0x2D6C )
|
||||||
return ".lha";
|
return ".lha";
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fex_has_extension_( const char str [], const char suffix [], size_t str_len )
|
static int fex_has_extension_( const char str [], const char suffix [], size_t str_len )
|
||||||
{
|
{
|
||||||
size_t suffix_len = strlen( suffix );
|
size_t suffix_len = strlen( suffix );
|
||||||
if ( str_len >= suffix_len )
|
if ( str_len >= suffix_len )
|
||||||
{
|
{
|
||||||
str += str_len - suffix_len;
|
str += str_len - suffix_len;
|
||||||
while ( *str && tolower( (unsigned char) *str ) == *suffix )
|
while ( *str && tolower( (unsigned char) *str ) == *suffix )
|
||||||
{
|
{
|
||||||
str++;
|
str++;
|
||||||
suffix++;
|
suffix++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *suffix == 0;
|
return *suffix == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] )
|
BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] )
|
||||||
{
|
{
|
||||||
return fex_has_extension_( str, suffix, strlen( str ) );
|
return fex_has_extension_( str, suffix, strlen( str ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_archive_extension( const char str [] )
|
static int is_archive_extension( const char str [] )
|
||||||
{
|
{
|
||||||
static const char exts [] [6] = {
|
static const char exts [] [6] = {
|
||||||
".7z",
|
".7z",
|
||||||
".arc",
|
".arc",
|
||||||
".arj",
|
".arj",
|
||||||
".bz2",
|
".bz2",
|
||||||
".cab",
|
".cab",
|
||||||
".dmg",
|
".dmg",
|
||||||
".gz",
|
".gz",
|
||||||
".lha",
|
".lha",
|
||||||
".lz",
|
".lz",
|
||||||
".lzh",
|
".lzh",
|
||||||
".lzma",
|
".lzma",
|
||||||
".lzo",
|
".lzo",
|
||||||
".lzx",
|
".lzx",
|
||||||
".pea",
|
".pea",
|
||||||
".rar",
|
".rar",
|
||||||
".sit",
|
".sit",
|
||||||
".sitx",
|
".sitx",
|
||||||
".tgz",
|
".tgz",
|
||||||
".tlz",
|
".tlz",
|
||||||
".z",
|
".z",
|
||||||
".zip",
|
".zip",
|
||||||
".zoo",
|
".zoo",
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
|
|
||||||
size_t str_len = strlen( str );
|
size_t str_len = strlen( str );
|
||||||
const char (*ext) [6] = exts;
|
const char (*ext) [6] = exts;
|
||||||
for ( ; **ext; ext++ )
|
for ( ; **ext; ext++ )
|
||||||
{
|
{
|
||||||
if ( fex_has_extension_( str, *ext, str_len ) )
|
if ( fex_has_extension_( str, *ext, str_len ) )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] )
|
BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] )
|
||||||
{
|
{
|
||||||
size_t str_len = strlen( str );
|
size_t str_len = strlen( str );
|
||||||
for ( fex_type_t const* types = fex_type_list(); *types; types++ )
|
for ( fex_type_t const* types = fex_type_list(); *types; types++ )
|
||||||
{
|
{
|
||||||
if ( fex_has_extension_( str, (*types)->extension, str_len ) )
|
if ( fex_has_extension_( str, (*types)->extension, str_len ) )
|
||||||
{
|
{
|
||||||
// Avoid treating known archive type as binary
|
// Avoid treating known archive type as binary
|
||||||
if ( *(*types)->extension || !is_archive_extension( str ) )
|
if ( *(*types)->extension || !is_archive_extension( str ) )
|
||||||
return *types;
|
return *types;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] )
|
BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] )
|
||||||
{
|
{
|
||||||
*type_out = NULL;
|
*type_out = NULL;
|
||||||
|
|
||||||
fex_type_t type = fex_identify_extension( path );
|
fex_type_t type = fex_identify_extension( path );
|
||||||
|
|
||||||
// Unsupported extension?
|
// Unsupported extension?
|
||||||
if ( !type )
|
if ( !type )
|
||||||
return blargg_ok; // reject
|
return blargg_ok; // reject
|
||||||
|
|
||||||
// Unknown/no extension?
|
// Unknown/no extension?
|
||||||
if ( !*(type->extension) )
|
if ( !*(type->extension) )
|
||||||
{
|
{
|
||||||
// Examine header
|
// Examine header
|
||||||
FEX_FILE_READER in;
|
FEX_FILE_READER in;
|
||||||
RETURN_ERR( in.open( path ) );
|
RETURN_ERR( in.open( path ) );
|
||||||
if ( in.remain() >= fex_identify_header_size )
|
if ( in.remain() >= fex_identify_header_size )
|
||||||
{
|
{
|
||||||
char h [fex_identify_header_size];
|
char h [fex_identify_header_size];
|
||||||
RETURN_ERR( in.read( h, sizeof h ) );
|
RETURN_ERR( in.read( h, sizeof h ) );
|
||||||
|
|
||||||
type = fex_identify_extension( fex_identify_header( h ) );
|
type = fex_identify_extension( fex_identify_header( h ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*type_out = type;
|
*type_out = type;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type )
|
BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type )
|
||||||
{
|
{
|
||||||
*fe_out = NULL;
|
*fe_out = NULL;
|
||||||
|
|
||||||
if ( !type )
|
if ( !type )
|
||||||
return blargg_err_file_type;
|
return blargg_err_file_type;
|
||||||
|
|
||||||
fex_t* fe = type->new_fex();
|
fex_t* fe = type->new_fex();
|
||||||
CHECK_ALLOC( fe );
|
CHECK_ALLOC( fe );
|
||||||
|
|
||||||
fex_err_t err = fe->open( path );
|
fex_err_t err = fe->open( path );
|
||||||
if ( err )
|
if ( err )
|
||||||
{
|
{
|
||||||
delete fe;
|
delete fe;
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
*fe_out = fe;
|
*fe_out = fe;
|
||||||
return blargg_ok;
|
return blargg_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
|
BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
|
||||||
{
|
{
|
||||||
*fe_out = NULL;
|
*fe_out = NULL;
|
||||||
|
|
||||||
fex_type_t type;
|
fex_type_t type;
|
||||||
RETURN_ERR( fex_identify_file( &type, path ) );
|
RETURN_ERR( fex_identify_file( &type, path ) );
|
||||||
|
|
||||||
return fex_open_type( fe_out, path, type );
|
return fex_open_type( fe_out, path, type );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Wide paths
|
//// Wide 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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
void fex_free_path( char* path )
|
void fex_free_path( char* path )
|
||||||
{
|
{
|
||||||
free( path );
|
free( path );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Errors
|
//// Errors
|
||||||
|
|
||||||
#define ENTRY( name ) { blargg_err_##name, fex_err_##name }
|
#define ENTRY( name ) { blargg_err_##name, fex_err_##name }
|
||||||
static blargg_err_to_code_t const fex_codes [] =
|
static blargg_err_to_code_t const fex_codes [] =
|
||||||
{
|
{
|
||||||
ENTRY( generic ),
|
ENTRY( generic ),
|
||||||
ENTRY( memory ),
|
ENTRY( memory ),
|
||||||
ENTRY( caller ),
|
ENTRY( caller ),
|
||||||
ENTRY( internal ),
|
ENTRY( internal ),
|
||||||
ENTRY( limitation ),
|
ENTRY( limitation ),
|
||||||
|
|
||||||
ENTRY( file_missing ),
|
ENTRY( file_missing ),
|
||||||
ENTRY( file_read ),
|
ENTRY( file_read ),
|
||||||
ENTRY( file_io ),
|
ENTRY( file_io ),
|
||||||
ENTRY( file_eof ),
|
ENTRY( file_eof ),
|
||||||
|
|
||||||
ENTRY( file_type ),
|
ENTRY( file_type ),
|
||||||
ENTRY( file_feature ),
|
ENTRY( file_feature ),
|
||||||
ENTRY( file_corrupt ),
|
ENTRY( file_corrupt ),
|
||||||
|
|
||||||
{ 0, -1 }
|
{ 0, -1 }
|
||||||
};
|
};
|
||||||
#undef ENTRY
|
#undef ENTRY
|
||||||
|
|
||||||
static int err_code( fex_err_t err )
|
static int err_code( fex_err_t err )
|
||||||
{
|
{
|
||||||
return blargg_err_to_code( err, fex_codes );
|
return blargg_err_to_code( err, fex_codes );
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT int fex_err_code( fex_err_t err )
|
BLARGG_EXPORT int fex_err_code( fex_err_t err )
|
||||||
{
|
{
|
||||||
int code = err_code( err );
|
int code = err_code( err );
|
||||||
return (code >= 0 ? code : fex_err_generic);
|
return (code >= 0 ? code : fex_err_generic);
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_code_to_err( int code )
|
BLARGG_EXPORT fex_err_t fex_code_to_err( int code )
|
||||||
{
|
{
|
||||||
return blargg_code_to_err( code, fex_codes );
|
return blargg_code_to_err( code, fex_codes );
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT const char* fex_err_details( fex_err_t err )
|
BLARGG_EXPORT const char* fex_err_details( fex_err_t err )
|
||||||
{
|
{
|
||||||
// If we don't have error code assigned, return entire string
|
// If we don't have error code assigned, return entire string
|
||||||
return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
|
return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//// Wrappers
|
//// Wrappers
|
||||||
|
|
||||||
BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count )
|
BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count )
|
||||||
{
|
{
|
||||||
RETURN_ERR( fe->stat() );
|
RETURN_ERR( fe->stat() );
|
||||||
return fe->reader().read( out, count );
|
return fe->reader().read( out, count );
|
||||||
}
|
}
|
||||||
|
|
||||||
BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; }
|
BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; }
|
||||||
BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); }
|
BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); }
|
||||||
BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); }
|
BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); }
|
||||||
BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); }
|
BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); }
|
||||||
BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
|
BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
|
||||||
BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); }
|
BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); }
|
||||||
BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); }
|
BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); }
|
||||||
BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); }
|
BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); }
|
||||||
BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); }
|
BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); }
|
||||||
BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); }
|
BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); }
|
||||||
BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); }
|
BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); }
|
||||||
BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); }
|
BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); }
|
||||||
BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); }
|
BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); }
|
||||||
BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); }
|
BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); }
|
||||||
BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; }
|
BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; }
|
||||||
BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; }
|
BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; }
|
||||||
BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); }
|
BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); }
|
||||||
BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); }
|
BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); }
|
||||||
|
|
408
fex/fex/fex.h
408
fex/fex/fex.h
|
@ -1,204 +1,204 @@
|
||||||
/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */
|
/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */
|
||||||
|
|
||||||
/* File_Extractor 1.0.0 */
|
/* File_Extractor 1.0.0 */
|
||||||
#ifndef FEX_H
|
#ifndef FEX_H
|
||||||
#define FEX_H
|
#define FEX_H
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/** First parameter of most functions is fex_t*, or const fex_t* if nothing is
|
/** First parameter of most functions is fex_t*, or const fex_t* if nothing is
|
||||||
changed. Once one of these functions returns an error, the archive should not
|
changed. Once one of these functions returns an error, the archive should not
|
||||||
be used any further, other than to close it. One exception is
|
be used any further, other than to close it. One exception is
|
||||||
fex_error_file_eof; the archive may still be used after this. */
|
fex_error_file_eof; the archive may still be used after this. */
|
||||||
typedef struct fex_t fex_t;
|
typedef struct fex_t fex_t;
|
||||||
|
|
||||||
/** Pointer to error, or NULL if function was successful. See error functions
|
/** Pointer to error, or NULL if function was successful. See error functions
|
||||||
below. */
|
below. */
|
||||||
#ifndef fex_err_t /* (#ifndef allows better testing of library) */
|
#ifndef fex_err_t /* (#ifndef allows better testing of library) */
|
||||||
typedef const char* fex_err_t;
|
typedef const char* fex_err_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**** File types ****/
|
/**** File types ****/
|
||||||
|
|
||||||
/** Archive file type identifier. Can also hold NULL. */
|
/** Archive file type identifier. Can also hold NULL. */
|
||||||
typedef const struct fex_type_t_* fex_type_t;
|
typedef const struct fex_type_t_* fex_type_t;
|
||||||
|
|
||||||
/** Array of supported types, with NULL at end */
|
/** Array of supported types, with NULL at end */
|
||||||
const fex_type_t* fex_type_list( void );
|
const fex_type_t* fex_type_list( void );
|
||||||
|
|
||||||
/** Name of this archive type, e.g. "ZIP archive", "file" */
|
/** Name of this archive type, e.g. "ZIP archive", "file" */
|
||||||
const char* fex_type_name( fex_type_t );
|
const char* fex_type_name( fex_type_t );
|
||||||
|
|
||||||
/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type,
|
/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type,
|
||||||
returns "", since it can open any file. */
|
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 ****/
|
/**** 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. */
|
||||||
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. */
|
/** Frees converted path. OK to pass NULL. */
|
||||||
void fex_free_path( char* );
|
void fex_free_path( char* );
|
||||||
|
|
||||||
|
|
||||||
/**** Identification ****/
|
/**** Identification ****/
|
||||||
|
|
||||||
/** True if str ends in extension. If extension is "", always returns true.
|
/** True if str ends in extension. If extension is "", always returns true.
|
||||||
Converts str to lowercase before comparison, so extension should ALREADY be
|
Converts str to lowercase before comparison, so extension should ALREADY be
|
||||||
lowercase (i.e. pass ".zip", NOT ".ZIP"). */
|
lowercase (i.e. pass ".zip", NOT ".ZIP"). */
|
||||||
int fex_has_extension( const char str [], const char extension [] );
|
int fex_has_extension( const char str [], const char extension [] );
|
||||||
|
|
||||||
/** Determines type based on first fex_identify_header_size bytes of file.
|
/** Determines type based on first fex_identify_header_size bytes of file.
|
||||||
Returns usual file extension this should have (e.g. ".zip", ".gz", etc.).
|
Returns usual file extension this should have (e.g. ".zip", ".gz", etc.).
|
||||||
Returns "" if file header is not recognized. */
|
Returns "" if file header is not recognized. */
|
||||||
const char* fex_identify_header( const void* header );
|
const char* fex_identify_header( const void* header );
|
||||||
enum { fex_identify_header_size = 16 };
|
enum { fex_identify_header_size = 16 };
|
||||||
|
|
||||||
/** Determines type based on extension of a file path, or just a lone extension
|
/** Determines type based on extension of a file path, or just a lone extension
|
||||||
(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is
|
(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is
|
||||||
for an unsupported type (e.g. ".lzh"). */
|
for an unsupported type (e.g. ".lzh"). */
|
||||||
fex_type_t fex_identify_extension( const char path_or_extension [] );
|
fex_type_t fex_identify_extension( const char path_or_extension [] );
|
||||||
|
|
||||||
/** Determines type based on filename extension and/or file header. Sets *out
|
/** Determines type based on filename extension and/or file header. Sets *out
|
||||||
to determined type, or NULL if type is not supported. */
|
to determined type, or NULL if type is not supported. */
|
||||||
fex_err_t fex_identify_file( fex_type_t* out, const char path [] );
|
fex_err_t fex_identify_file( fex_type_t* out, const char path [] );
|
||||||
|
|
||||||
/** Type of an already-opened archive */
|
/** Type of an already-opened archive */
|
||||||
fex_type_t fex_type( const fex_t* );
|
fex_type_t fex_type( const fex_t* );
|
||||||
|
|
||||||
|
|
||||||
/**** Open/close ****/
|
/**** Open/close ****/
|
||||||
|
|
||||||
/** Initializes static tables used by library. Automatically called by
|
/** Initializes static tables used by library. Automatically called by
|
||||||
fex_open(). OK to call more than once. */
|
fex_open(). OK to call more than once. */
|
||||||
fex_err_t fex_init( void );
|
fex_err_t fex_init( void );
|
||||||
|
|
||||||
/** Opens archive and points *out at it. If error, sets *out to NULL. */
|
/** Opens archive and points *out at it. If error, sets *out to NULL. */
|
||||||
fex_err_t fex_open( fex_t** out, const char path [] );
|
fex_err_t fex_open( fex_t** out, const char path [] );
|
||||||
|
|
||||||
/** Opens archive of specified type and sets *out. Returns error if file is not
|
/** Opens archive of specified type and sets *out. Returns error if file is not
|
||||||
of that archive type. If error, sets *out to NULL. */
|
of that archive type. If error, sets *out to NULL. */
|
||||||
fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t );
|
fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t );
|
||||||
|
|
||||||
/** Closes archive and frees memory. OK to pass NULL. */
|
/** Closes archive and frees memory. OK to pass NULL. */
|
||||||
void fex_close( fex_t* );
|
void fex_close( fex_t* );
|
||||||
|
|
||||||
|
|
||||||
/**** Scanning ****/
|
/**** Scanning ****/
|
||||||
|
|
||||||
/** True if at end of archive. Must be called after fex_open() or fex_rewind(),
|
/** True if at end of archive. Must be called after fex_open() or fex_rewind(),
|
||||||
as an archive might contain no files. */
|
as an archive might contain no files. */
|
||||||
int fex_done( const fex_t* );
|
int fex_done( const fex_t* );
|
||||||
|
|
||||||
/** Goes to next file in archive. If there are no more files, fex_done() will
|
/** Goes to next file in archive. If there are no more files, fex_done() will
|
||||||
now return true. */
|
now return true. */
|
||||||
fex_err_t fex_next( fex_t* );
|
fex_err_t fex_next( fex_t* );
|
||||||
|
|
||||||
/** Goes back to first file in archive, as if it were just opened with
|
/** Goes back to first file in archive, as if it were just opened with
|
||||||
fex_open() */
|
fex_open() */
|
||||||
fex_err_t fex_rewind( fex_t* );
|
fex_err_t fex_rewind( fex_t* );
|
||||||
|
|
||||||
/** Saved position in archive. Can also store zero. */
|
/** Saved position in archive. Can also store zero. */
|
||||||
typedef int fex_pos_t;
|
typedef int fex_pos_t;
|
||||||
|
|
||||||
/** Position of current file in archive. Never returns zero. */
|
/** Position of current file in archive. Never returns zero. */
|
||||||
fex_pos_t fex_tell_arc( const fex_t* );
|
fex_pos_t fex_tell_arc( const fex_t* );
|
||||||
|
|
||||||
/** Returns to file at previously-saved position */
|
/** Returns to file at previously-saved position */
|
||||||
fex_err_t fex_seek_arc( fex_t*, fex_pos_t );
|
fex_err_t fex_seek_arc( fex_t*, fex_pos_t );
|
||||||
|
|
||||||
|
|
||||||
/**** Info ****/
|
/**** Info ****/
|
||||||
|
|
||||||
/** Name of current file */
|
/** Name of current file */
|
||||||
const char* fex_name( const fex_t* );
|
const char* fex_name( const fex_t* );
|
||||||
|
|
||||||
/** Wide-character name of current file, or NULL if unavailable */
|
/** Wide-character name of current file, or NULL if unavailable */
|
||||||
const wchar_t* fex_wname( const fex_t* );
|
const wchar_t* fex_wname( const fex_t* );
|
||||||
|
|
||||||
/** Makes further information available for file */
|
/** Makes further information available for file */
|
||||||
fex_err_t fex_stat( fex_t* );
|
fex_err_t fex_stat( fex_t* );
|
||||||
|
|
||||||
/** Size of current file. fex_stat() or fex_data() must have been called. */
|
/** Size of current file. fex_stat() or fex_data() must have been called. */
|
||||||
int fex_size( const fex_t* );
|
int fex_size( const fex_t* );
|
||||||
|
|
||||||
/** Modification date of current file (MS-DOS format), or 0 if unavailable.
|
/** Modification date of current file (MS-DOS format), or 0 if unavailable.
|
||||||
fex_stat() must have been called. */
|
fex_stat() must have been called. */
|
||||||
unsigned int fex_dos_date( const fex_t* );
|
unsigned int fex_dos_date( const fex_t* );
|
||||||
|
|
||||||
/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't
|
/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't
|
||||||
require calculation; simply gets it from file's header. fex_stat() must have
|
require calculation; simply gets it from file's header. fex_stat() must have
|
||||||
been called. */
|
been called. */
|
||||||
unsigned int fex_crc32( const fex_t* );
|
unsigned int fex_crc32( const fex_t* );
|
||||||
|
|
||||||
|
|
||||||
/**** Extraction ****/
|
/**** Extraction ****/
|
||||||
|
|
||||||
/** Reads n bytes from current file. Reading past end of file results in
|
/** Reads n bytes from current file. Reading past end of file results in
|
||||||
fex_err_file_eof. */
|
fex_err_file_eof. */
|
||||||
fex_err_t fex_read( fex_t*, void* out, int n );
|
fex_err_t fex_read( fex_t*, void* out, int n );
|
||||||
|
|
||||||
/** Number of bytes read from current file */
|
/** Number of bytes read from current file */
|
||||||
int fex_tell( const fex_t* );
|
int fex_tell( const fex_t* );
|
||||||
|
|
||||||
/** Points *out at current file's data in memory. Pointer is valid until
|
/** Points *out at current file's data in memory. Pointer is valid until
|
||||||
fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer
|
fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer
|
||||||
must NOT be freed(); library frees it automatically. If error, sets *out to
|
must NOT be freed(); library frees it automatically. If error, sets *out to
|
||||||
NULL. */
|
NULL. */
|
||||||
fex_err_t fex_data( fex_t*, const void** out );
|
fex_err_t fex_data( fex_t*, const void** out );
|
||||||
|
|
||||||
|
|
||||||
/**** Errors ****/
|
/**** Errors ****/
|
||||||
|
|
||||||
/** Error string associated with err. Returns "" if err is NULL. Returns err
|
/** Error string associated with err. Returns "" if err is NULL. Returns err
|
||||||
unchanged if it isn't a fex_err_t returned by library. */
|
unchanged if it isn't a fex_err_t returned by library. */
|
||||||
const char* fex_err_str( fex_err_t err );
|
const char* fex_err_str( fex_err_t err );
|
||||||
|
|
||||||
/** Details of error beyond main cause, or "" if none or err is NULL. Returns
|
/** Details of error beyond main cause, or "" if none or err is NULL. Returns
|
||||||
err unchanged if it isn't a fex_err_t returned by library. */
|
err unchanged if it isn't a fex_err_t returned by library. */
|
||||||
const char* fex_err_details( fex_err_t err );
|
const char* fex_err_details( fex_err_t err );
|
||||||
|
|
||||||
/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns
|
/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns
|
||||||
fex_err_generic if err isn't a fex_err_t returned by library. */
|
fex_err_generic if err isn't a fex_err_t returned by library. */
|
||||||
int fex_err_code( fex_err_t err );
|
int fex_err_code( fex_err_t err );
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
fex_ok = 0,/**< Successful call. Guaranteed to be zero. */
|
fex_ok = 0,/**< Successful call. Guaranteed to be zero. */
|
||||||
fex_err_generic = 0x01,/**< Error of unspecified type */
|
fex_err_generic = 0x01,/**< Error of unspecified type */
|
||||||
fex_err_memory = 0x02,/**< Out of memory */
|
fex_err_memory = 0x02,/**< Out of memory */
|
||||||
fex_err_caller = 0x03,/**< Caller called function with bad args */
|
fex_err_caller = 0x03,/**< Caller called function with bad args */
|
||||||
fex_err_internal = 0x04,/**< Internal problem, bug, etc. */
|
fex_err_internal = 0x04,/**< Internal problem, bug, etc. */
|
||||||
fex_err_limitation = 0x05,/**< Exceeded program limit */
|
fex_err_limitation = 0x05,/**< Exceeded program limit */
|
||||||
|
|
||||||
fex_err_file_missing = 0x20,/**< File not found at specified path */
|
fex_err_file_missing = 0x20,/**< File not found at specified path */
|
||||||
fex_err_file_read = 0x21,/**< Couldn't open file for reading */
|
fex_err_file_read = 0x21,/**< Couldn't open file for reading */
|
||||||
fex_err_file_io = 0x23,/**< Read/write error */
|
fex_err_file_io = 0x23,/**< Read/write error */
|
||||||
fex_err_file_eof = 0x25,/**< Tried to read past end of file */
|
fex_err_file_eof = 0x25,/**< Tried to read past end of file */
|
||||||
|
|
||||||
fex_err_file_type = 0x30,/**< File is of wrong type */
|
fex_err_file_type = 0x30,/**< File is of wrong type */
|
||||||
fex_err_file_feature = 0x32,/**< File requires unsupported feature */
|
fex_err_file_feature = 0x32,/**< File requires unsupported feature */
|
||||||
fex_err_file_corrupt = 0x33 /**< File is corrupt */
|
fex_err_file_corrupt = 0x33 /**< File is corrupt */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** fex_err_t corresponding to numeric code. Note that this might not recover
|
/** fex_err_t corresponding to numeric code. Note that this might not recover
|
||||||
the original fex_err_t before it was converted to a numeric code; in
|
the original fex_err_t before it was converted to a numeric code; in
|
||||||
particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */
|
particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */
|
||||||
fex_err_t fex_code_to_err( int code );
|
fex_err_t fex_code_to_err( int code );
|
||||||
|
|
||||||
|
|
||||||
/* Deprecated */
|
/* Deprecated */
|
||||||
typedef fex_t File_Extractor;
|
typedef fex_t File_Extractor;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,91 +1,91 @@
|
||||||
File_Extractor library internals
|
File_Extractor library internals
|
||||||
--------------------------------
|
--------------------------------
|
||||||
This describes the implementation and design.
|
This describes the implementation and design.
|
||||||
|
|
||||||
Contents
|
Contents
|
||||||
--------
|
--------
|
||||||
* Framework
|
* Framework
|
||||||
* Archive abstraction
|
* Archive abstraction
|
||||||
* 7-ZIP
|
* 7-ZIP
|
||||||
* ZIP
|
* ZIP
|
||||||
* RAR
|
* RAR
|
||||||
* GZIP
|
* GZIP
|
||||||
* Binary
|
* Binary
|
||||||
|
|
||||||
|
|
||||||
Framework
|
Framework
|
||||||
---------
|
---------
|
||||||
This library is essentially:
|
This library is essentially:
|
||||||
|
|
||||||
* Several archive readers
|
* Several archive readers
|
||||||
* Wrappers to provide common interface
|
* Wrappers to provide common interface
|
||||||
* File type detection
|
* File type detection
|
||||||
|
|
||||||
The File_Extractor base class implements the common aspects of the
|
The File_Extractor base class implements the common aspects of the
|
||||||
interface and filters out invalid calls. It also provides default
|
interface and filters out invalid calls. It also provides default
|
||||||
implementations for some operations. Each derived *_Extractor class then
|
implementations for some operations. Each derived *_Extractor class then
|
||||||
wraps the particular library.
|
wraps the particular library.
|
||||||
|
|
||||||
Then fex.h provides a stable, C-compatible wrapper over File_Extractor,
|
Then fex.h provides a stable, C-compatible wrapper over File_Extractor,
|
||||||
and does file type identification.
|
and does file type identification.
|
||||||
|
|
||||||
|
|
||||||
Archive abstraction
|
Archive abstraction
|
||||||
-------------------
|
-------------------
|
||||||
An extractor is abstracted to these fundamental operations:
|
An extractor is abstracted to these fundamental operations:
|
||||||
|
|
||||||
* Open (either from path or custom reader)
|
* Open (either from path or custom reader)
|
||||||
* Iterate over each file
|
* Iterate over each file
|
||||||
* Extract file's data (either gradually, or all at once into memory)
|
* Extract file's data (either gradually, or all at once into memory)
|
||||||
* Seek to particular file in archive
|
* Seek to particular file in archive
|
||||||
* Close
|
* Close
|
||||||
|
|
||||||
The extractor can choose whether to open a file path immediately, or
|
The extractor can choose whether to open a file path immediately, or
|
||||||
defer until the first stat() call. When extracting data, it can
|
defer until the first stat() call. When extracting data, it can
|
||||||
implement one or both of normal read and "give me a pointer to the data
|
implement one or both of normal read and "give me a pointer to the data
|
||||||
already in memory". If it only implements one, File_Extractor will
|
already in memory". If it only implements one, File_Extractor will
|
||||||
implement the other in terms of it.
|
implement the other in terms of it.
|
||||||
|
|
||||||
|
|
||||||
7-ZIP
|
7-ZIP
|
||||||
-----
|
-----
|
||||||
A fairly simple wrapper over a slightly-modified LZMA library.
|
A fairly simple wrapper over a slightly-modified LZMA library.
|
||||||
Unfortunately you probably won't be able to drop a later version of the
|
Unfortunately you probably won't be able to drop a later version of the
|
||||||
LZMA library sources in and recompile, as the interface and file
|
LZMA library sources in and recompile, as the interface and file
|
||||||
arrangement tends to change with every release. The main change I've
|
arrangement tends to change with every release. The main change I've
|
||||||
made is to declare functions extern "C" in headers, so C++ code can call
|
made is to declare functions extern "C" in headers, so C++ code can call
|
||||||
them.
|
them.
|
||||||
|
|
||||||
|
|
||||||
ZIP
|
ZIP
|
||||||
---
|
---
|
||||||
A complete implementation I wrote. Has nifty optimization that makes all
|
A complete implementation I wrote. Has nifty optimization that makes all
|
||||||
disk reads begin and end on a multiple of 4K. Also minimizes number of
|
disk reads begin and end on a multiple of 4K. Also minimizes number of
|
||||||
accesses when initially reading catalog, and extracting file data.
|
accesses when initially reading catalog, and extracting file data.
|
||||||
Correctly handles empty zip archives, unlike the popular unzip library
|
Correctly handles empty zip archives, unlike the popular unzip library
|
||||||
which reports it as a bad archive.
|
which reports it as a bad archive.
|
||||||
|
|
||||||
|
|
||||||
RAR
|
RAR
|
||||||
---
|
---
|
||||||
Wrapper over heavily-modified UnRAR extraction library based on the
|
Wrapper over heavily-modified UnRAR extraction library based on the
|
||||||
official UnRAR sources. The library is available separately with
|
official UnRAR sources. The library is available separately with
|
||||||
documentation and demos, in case you want to use it without the
|
documentation and demos, in case you want to use it without the
|
||||||
File_Extractor front-end (see unrar/changes.txt for more).
|
File_Extractor front-end (see unrar/changes.txt for more).
|
||||||
|
|
||||||
|
|
||||||
GZIP
|
GZIP
|
||||||
----
|
----
|
||||||
Uses zlib's built-in parsing. Also works with non-gzipped files, based
|
Uses zlib's built-in parsing. Also works with non-gzipped files, based
|
||||||
on absence of two-byte Gzip header. Defers opening of file until
|
on absence of two-byte Gzip header. Defers opening of file until
|
||||||
fex_stat(), speeding mere scanning of filenames. Gzip_Reader and
|
fex_stat(), speeding mere scanning of filenames. Gzip_Reader and
|
||||||
Zlib_Reader further divide the implementation into more manageable and
|
Zlib_Reader further divide the implementation into more manageable and
|
||||||
reusable components.
|
reusable components.
|
||||||
|
|
||||||
|
|
||||||
Binary
|
Binary
|
||||||
------
|
------
|
||||||
Just a minimal wrapper over C-style FILE.
|
Just a minimal wrapper over C-style FILE.
|
||||||
|
|
||||||
--
|
--
|
||||||
Shay Green <gblargg@gmail.com>
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
1008
fex/license.txt
1008
fex/license.txt
File diff suppressed because it is too large
Load Diff
118
fex/readme.txt
118
fex/readme.txt
|
@ -1,59 +1,59 @@
|
||||||
File_Extractor 1.0.0
|
File_Extractor 1.0.0
|
||||||
--------------------
|
--------------------
|
||||||
File_Extractor is a modular archive scanning and extraction library that
|
File_Extractor is a modular archive scanning and extraction library that
|
||||||
supports several popular compressed file formats. It gives a common
|
supports several popular compressed file formats. It gives a common
|
||||||
interface to the supported formats, allowing one version of user code.
|
interface to the supported formats, allowing one version of user code.
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
* Simple C interface.
|
* Simple C interface.
|
||||||
* Supports ZIP, GZIP, 7-Zip (7Z), and RAR[1] archive formats.
|
* Supports ZIP, GZIP, 7-Zip (7Z), and RAR[1] archive formats.
|
||||||
* Non-archive files act like archive of that one file, simplifying code.
|
* Non-archive files act like archive of that one file, simplifying code.
|
||||||
* Modular design allows removal of support for unneeded archive formats.
|
* Modular design allows removal of support for unneeded archive formats.
|
||||||
* Optionally supports wide-character paths on Windows.
|
* Optionally supports wide-character paths on Windows.
|
||||||
* Archive file type identification can be customized
|
* Archive file type identification can be customized
|
||||||
|
|
||||||
[1] RAR support must be enabled before use, due to its special
|
[1] RAR support must be enabled before use, due to its special
|
||||||
licensing.
|
licensing.
|
||||||
|
|
||||||
Author : Shay Green <gblargg@gmail.com>
|
Author : Shay Green <gblargg@gmail.com>
|
||||||
Website : http://code.google.com/p/file-extractor/
|
Website : http://code.google.com/p/file-extractor/
|
||||||
License : GNU LGPL 2.1 or later for all except unrar
|
License : GNU LGPL 2.1 or later for all except unrar
|
||||||
Language: C interface, C++ implementation
|
Language: C interface, C++ implementation
|
||||||
|
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
---------------
|
---------------
|
||||||
Build the demo by typing "make" at the command-line. If that doesn't
|
Build the demo by typing "make" at the command-line. If that doesn't
|
||||||
work, manually build a program from demo.c and all *.c and *.cpp files
|
work, manually build a program from demo.c and all *.c and *.cpp files
|
||||||
in fex/, 7z_C/, and zlib/. Run demo with test.zip in the same directory.
|
in fex/, 7z_C/, and zlib/. Run demo with test.zip in the same directory.
|
||||||
|
|
||||||
To enable RAR archive support, edit fex/blargg_config.h.
|
To enable RAR archive support, edit fex/blargg_config.h.
|
||||||
|
|
||||||
See fex.h for reference and fex.txt for documentation.
|
See fex.h for reference and fex.txt for documentation.
|
||||||
|
|
||||||
|
|
||||||
Files
|
Files
|
||||||
-----
|
-----
|
||||||
fex.txt Manual
|
fex.txt Manual
|
||||||
license.txt GNU LGPL 2.1 license
|
license.txt GNU LGPL 2.1 license
|
||||||
|
|
||||||
makefile Builds libfex.a and demo
|
makefile Builds libfex.a and demo
|
||||||
|
|
||||||
demo.c Basic usage
|
demo.c Basic usage
|
||||||
demo_read.c Uses fex_read() to extract data
|
demo_read.c Uses fex_read() to extract data
|
||||||
demo_rewind.c Uses fex_rewind() to re-scan archive
|
demo_rewind.c Uses fex_rewind() to re-scan archive
|
||||||
demo_seek.c Uses fex_seek_arc() to go back to files
|
demo_seek.c Uses fex_seek_arc() to go back to files
|
||||||
demo_directory.c Recursively scans directory for archives
|
demo_directory.c Recursively scans directory for archives
|
||||||
demo.zip Test archive used by demos
|
demo.zip Test archive used by demos
|
||||||
|
|
||||||
fex/
|
fex/
|
||||||
blargg_config.h Configuration (modify as needed)
|
blargg_config.h Configuration (modify as needed)
|
||||||
fex.h C interface (also usable from C++)
|
fex.h C interface (also usable from C++)
|
||||||
(all other files) Library sources
|
(all other files) Library sources
|
||||||
|
|
||||||
zlib/ Zip/Gzip (can use your system's instead)
|
zlib/ Zip/Gzip (can use your system's instead)
|
||||||
7z_C/ 7-Zip
|
7z_C/ 7-Zip
|
||||||
unrar/ RAR
|
unrar/ RAR
|
||||||
|
|
||||||
--
|
--
|
||||||
Shay Green <gblargg@gmail.com>
|
Shay Green <gblargg@gmail.com>
|
||||||
|
|
Loading…
Reference in New Issue