mirror of
https://github.com/libretro/libretro-uae.git
synced 2026-11-07 11:16:05 -10:00
libretro-common + 7zip sync
This commit is contained in:
1 parent
a411a3cb58
commit
c12d2af1bd
72 files changed
+15161
-6730
No files matched your search
@@ -282,10 +282,8 @@ else
|
||||
LDFLAGS += -s
|
||||
endif
|
||||
|
||||
# Skip 7zip for static builds
|
||||
ifneq ($(STATIC_LINKING), 1)
|
||||
CFLAGS += -DHAVE_7ZIP
|
||||
endif
|
||||
# 7zip
|
||||
CFLAGS += -DHAVE_7ZIP -D_7ZIP_ST
|
||||
|
||||
# CHD
|
||||
HAVE_CHD = 1
|
||||
|
||||
+4
-5
@@ -156,16 +156,19 @@ SOURCES_C += \
|
||||
$(DEPS_DIR)/libz/zutil.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(DEPS_DIR)/7zip/7zArcIn.c \
|
||||
$(DEPS_DIR)/7zip/7zBuf.c \
|
||||
$(DEPS_DIR)/7zip/7zCrc.c \
|
||||
$(DEPS_DIR)/7zip/7zCrcOpt.c \
|
||||
$(DEPS_DIR)/7zip/7zDec.c \
|
||||
$(DEPS_DIR)/7zip/7zFile.c \
|
||||
$(DEPS_DIR)/7zip/7zIn.c \
|
||||
$(DEPS_DIR)/7zip/7zStream.c \
|
||||
$(DEPS_DIR)/7zip/Bcj2.c \
|
||||
$(DEPS_DIR)/7zip/Bra.c \
|
||||
$(DEPS_DIR)/7zip/Bra86.c \
|
||||
$(DEPS_DIR)/7zip/BraIA64.c \
|
||||
$(DEPS_DIR)/7zip/CpuArch.c \
|
||||
$(DEPS_DIR)/7zip/Delta.c \
|
||||
$(DEPS_DIR)/7zip/Lzma2Dec.c \
|
||||
$(DEPS_DIR)/7zip/LzmaDec.c
|
||||
|
||||
@@ -201,8 +204,4 @@ ifeq ($(HAVE_CHD), 1)
|
||||
$(DEPS_DIR)/libchdr/src/libchdr_chd.c \
|
||||
$(DEPS_DIR)/libchdr/src/libchdr_flac.c \
|
||||
$(DEPS_DIR)/libchdr/src/libchdr_huffman.c
|
||||
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
SOURCES_C += $(DEPS_DIR)/7zip/LzmaDec.c
|
||||
endif
|
||||
endif
|
||||
Vendored
+128
-133
@@ -1,132 +1,157 @@
|
||||
/* 7z.h -- 7z interface
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
||||
#include "7zBuf.h"
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
#define k7zSignatureSize 6
|
||||
extern uint8_t k7zSignature[k7zSignatureSize];
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
k7zIdHeader,
|
||||
k7zIdArchiveProperties,
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnpackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
k7zIdFolder,
|
||||
k7zIdCodersUnpackSize,
|
||||
k7zIdNumUnpackStream,
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
k7zIdName,
|
||||
k7zIdCTime,
|
||||
k7zIdATime,
|
||||
k7zIdMTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
k7zIdEncodedHeader,
|
||||
k7zIdStartPos,
|
||||
k7zIdDummy
|
||||
};
|
||||
extern const Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t NumInStreams;
|
||||
uint32_t NumOutStreams;
|
||||
uint64_t MethodID;
|
||||
CBuf Props;
|
||||
const Byte *Data;
|
||||
size_t Size;
|
||||
} CSzData;
|
||||
|
||||
/* CSzCoderInfo & CSzFolder support only default methods */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t PropsOffset;
|
||||
UInt32 MethodID;
|
||||
Byte NumStreams;
|
||||
Byte PropsSize;
|
||||
} CSzCoderInfo;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CSzBond;
|
||||
|
||||
#define SZ_NUM_CODERS_IN_FOLDER_MAX 4
|
||||
#define SZ_NUM_BONDS_IN_FOLDER_MAX 3
|
||||
#define SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t InIndex;
|
||||
uint32_t OutIndex;
|
||||
} CSzBindPair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CSzBindPair *BindPairs;
|
||||
uint32_t *PackStreams;
|
||||
uint64_t *UnpackSizes;
|
||||
uint32_t NumCoders;
|
||||
uint32_t NumBindPairs;
|
||||
uint32_t NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
uint32_t UnpackCRC;
|
||||
|
||||
uint32_t NumUnpackStreams;
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBonds;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 UnpackStream;
|
||||
UInt32 PackStreams[SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX];
|
||||
CSzBond Bonds[SZ_NUM_BONDS_IN_FOLDER_MAX];
|
||||
CSzCoderInfo Coders[SZ_NUM_CODERS_IN_FOLDER_MAX];
|
||||
} CSzFolder;
|
||||
|
||||
void SzFolder_Init(CSzFolder *p);
|
||||
uint64_t SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, uint32_t inStreamIndex);
|
||||
uint32_t SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||
uint64_t SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const uint64_t *packSizes,
|
||||
ILookInStream *stream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Low;
|
||||
uint32_t High;
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CNtfsFileTime;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
uint64_t Size;
|
||||
uint32_t Crc;
|
||||
uint32_t Attrib;
|
||||
uint8_t HasStream;
|
||||
uint8_t IsDir;
|
||||
uint8_t IsAnti;
|
||||
uint8_t CrcDefined;
|
||||
uint8_t MTimeDefined;
|
||||
uint8_t AttribDefined;
|
||||
} CSzFileItem;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
UInt32 *Vals;
|
||||
} CSzBitUi32s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t *PackSizes;
|
||||
uint8_t *PackCRCsDefined;
|
||||
uint32_t *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
uint32_t NumPackStreams;
|
||||
uint32_t NumFolders;
|
||||
uint32_t NumFiles;
|
||||
Byte *Defs; /* MSB 0 bit numbering */
|
||||
/* UInt64 *Vals; */
|
||||
CNtfsFileTime *Vals;
|
||||
} CSzBitUi64s;
|
||||
|
||||
#define SzBitArray_Check(p, i) (((p)[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
#define SzBitWithVals_Check(p, i) ((p)->Defs && ((p)->Defs[(i) >> 3] & (0x80 >> ((i) & 7))) != 0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
|
||||
UInt64 *PackPositions; /* NumPackStreams + 1 */
|
||||
CSzBitUi32s FolderCRCs; /* NumFolders */
|
||||
|
||||
size_t *FoCodersOffsets; /* NumFolders + 1 */
|
||||
UInt32 *FoStartPackStreamIndex; /* NumFolders + 1 */
|
||||
UInt32 *FoToCoderUnpackSizes; /* NumFolders + 1 */
|
||||
Byte *FoToMainUnpackSizeIndex; /* NumFolders */
|
||||
UInt64 *CoderUnpackSizes; /* for all coders in all folders */
|
||||
|
||||
Byte *CodersData;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex);
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 NumFiles;
|
||||
|
||||
UInt64 *UnpackPositions; /* NumFiles + 1 */
|
||||
/* Byte *IsEmptyFiles; */
|
||||
Byte *IsDirs;
|
||||
CSzBitUi32s CRCs;
|
||||
|
||||
CSzBitUi32s Attribs;
|
||||
/* CSzBitUi32s Parents; */
|
||||
CSzBitUi64s MTime;
|
||||
CSzBitUi64s CTime;
|
||||
|
||||
UInt32 *FolderToFile; /* NumFolders + 1 */
|
||||
UInt32 *FileToFolder; /* NumFiles */
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
Byte *FileNames; /* UTF-16-LE */
|
||||
} CSzArEx;
|
||||
|
||||
#define SzArEx_IsDir(p, i) (SzBitArray_Check((p)->IsDirs, i))
|
||||
|
||||
#define SzArEx_GetFileSize(p, i) ((p)->UnpackPositions[(i) + 1] - (p)->UnpackPositions[i])
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAllocPtr alloc);
|
||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||
|
||||
/*
|
||||
if dest == NULL, the return value specifies the required size of the buffer,
|
||||
in 16-bit characters, including the null-terminating character.
|
||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
are written to the dest, including the null-terminating character. */
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
|
||||
/*
|
||||
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex);
|
||||
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
SzArEx_Extract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
@@ -138,53 +163,24 @@ void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
uint64_t startPosAfterHeader;
|
||||
uint64_t dataPos;
|
||||
|
||||
uint32_t *FolderStartPackStreamIndex;
|
||||
uint64_t *PackStreamStartPositions;
|
||||
uint32_t *FolderStartFileIndex;
|
||||
uint32_t *FileIndexToFolderIndexMap;
|
||||
|
||||
size_t *FileNameOffsets; /* in 2-byte steps */
|
||||
CBuf FileNames; /* UTF-16-LE */
|
||||
} CSzArEx;
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||
uint64_t SzArEx_GetFolderStreamPos(const CSzArEx *p, uint32_t folderIndex, uint32_t indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, uint32_t folderIndex, uint64_t *resSize);
|
||||
|
||||
/*
|
||||
if dest == NULL, the return value specifies the required size of the buffer,
|
||||
in 16-bit characters, including the null-terminating character.
|
||||
if dest != NULL, the return value specifies the number of 16-bit characters that
|
||||
are written to the dest, including the null-terminating character. */
|
||||
|
||||
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, uint16_t *dest);
|
||||
|
||||
SRes SzArEx_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
uint32_t fileIndex, /* index of file */
|
||||
uint32_t *blockIndex, /* index of solid block */
|
||||
uint8_t **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
ISzAllocPtr allocMain,
|
||||
ISzAllocPtr allocTemp);
|
||||
|
||||
|
||||
/*
|
||||
@@ -198,10 +194,9 @@ SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
|
||||
ISzAllocPtr allocMain, ISzAllocPtr allocTemp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+1771
File diff suppressed because it is too large.
Load diff
Vendored
+23
-24
@@ -1,37 +1,36 @@
|
||||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "7zBuf.h"
|
||||
|
||||
void Buf_Init(CBuf *p)
|
||||
{
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc)
|
||||
{
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (uint8_t *)alloc->Alloc(alloc, size);
|
||||
if (p->data != 0)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (Byte *)ISzAlloc_Alloc(alloc, size);
|
||||
if (p->data)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
ISzAlloc_Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
Vendored
+18
-10
@@ -1,27 +1,35 @@
|
||||
/* 7zBuf.h -- Byte Buffer
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *data;
|
||||
Byte *data;
|
||||
size_t size;
|
||||
} CBuf;
|
||||
|
||||
void Buf_Init(CBuf *p);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAllocPtr alloc);
|
||||
void Buf_Free(CBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CDynBuf;
|
||||
|
||||
void DynBuf_Construct(CDynBuf *p);
|
||||
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAllocPtr alloc);
|
||||
void DynBuf_Free(CDynBuf *p, ISzAllocPtr alloc);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+106
-54
@@ -1,76 +1,128 @@
|
||||
/* 7zCrc.c -- CRC32 calculation
|
||||
2009-11-23 : Igor Pavlov : Public domain */
|
||||
/* 7zCrc.c -- CRC32 init
|
||||
2017-06-06 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "7zCrc.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
|
||||
#ifdef MSB_FIRST
|
||||
#define CRC_NUM_TABLES 1
|
||||
#ifdef MY_CPU_LE
|
||||
#define CRC_NUM_TABLES 8
|
||||
#else
|
||||
#define CRC_NUM_TABLES 8
|
||||
#define CRC_NUM_TABLES 9
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
#endif
|
||||
|
||||
typedef uint32_t (MY_FAST_CALL *CRC_FUNC)(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
#ifndef MY_CPU_BE
|
||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
#endif
|
||||
|
||||
static CRC_FUNC g_CrcUpdate;
|
||||
uint32_t g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
typedef UInt32 (MY_FAST_CALL *CRC_FUNC)(UInt32 v, const void *data, size_t size, const UInt32 *table);
|
||||
|
||||
#if CRC_NUM_TABLES == 1
|
||||
CRC_FUNC g_CrcUpdateT4;
|
||||
CRC_FUNC g_CrcUpdateT8;
|
||||
CRC_FUNC g_CrcUpdate;
|
||||
|
||||
UInt32 g_CrcTable[256 * CRC_NUM_TABLES];
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||
}
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
static uint32_t MY_FAST_CALL CrcUpdateT1(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
const Byte *p = (const Byte *)data;
|
||||
const Byte *pEnd = p + size;
|
||||
for (; p != pEnd; p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
|
||||
#endif
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdate(uint32_t v, const void *data, size_t size)
|
||||
void MY_FAST_CALL CrcGenerateTable()
|
||||
{
|
||||
return g_CrcUpdate(v, data, size, g_CrcTable);
|
||||
}
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
for (i = 256; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
UInt32 r = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return g_CrcUpdate(CRC_INIT_VAL, data, size, g_CrcTable) ^ CRC_INIT_VAL;
|
||||
}
|
||||
#if CRC_NUM_TABLES < 4
|
||||
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
|
||||
#else
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
unsigned j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
#if CRC_NUM_TABLES == 1
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
#else
|
||||
for (; i < 256 * CRC_NUM_TABLES; i++)
|
||||
{
|
||||
uint32_t r = g_CrcTable[i - 256];
|
||||
g_CrcTable[i] = g_CrcTable[r & 0xFF] ^ (r >> 8);
|
||||
}
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#else
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#endif
|
||||
#endif
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
if (!CPU_Is_InOrder())
|
||||
#endif
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
|
||||
#else
|
||||
{
|
||||
#ifndef MY_CPU_BE
|
||||
UInt32 k = 0x01020304;
|
||||
const Byte *p = (const Byte *)&k;
|
||||
if (p[0] == 4 && p[1] == 3)
|
||||
{
|
||||
g_CrcUpdateT4 = CrcUpdateT4;
|
||||
g_CrcUpdate = CrcUpdateT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT8;
|
||||
g_CrcUpdate = CrcUpdateT8;
|
||||
#endif
|
||||
}
|
||||
else if (p[0] != 1 || p[1] != 2)
|
||||
g_CrcUpdate = CrcUpdateT1;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
for (i = 256 * CRC_NUM_TABLES - 1; i >= 256; i--)
|
||||
{
|
||||
UInt32 x = g_CrcTable[(size_t)i - 256];
|
||||
g_CrcTable[i] = CRC_UINT32_SWAP(x);
|
||||
}
|
||||
g_CrcUpdateT4 = CrcUpdateT1_BeT4;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT4;
|
||||
#if CRC_NUM_TABLES >= 8
|
||||
g_CrcUpdateT8 = CrcUpdateT1_BeT8;
|
||||
g_CrcUpdate = CrcUpdateT1_BeT8;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
Vendored
+6
-10
@@ -1,16 +1,14 @@
|
||||
/* 7zCrc.h -- CRC32 calculation
|
||||
2009-11-21 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
extern uint32_t g_CrcTable[];
|
||||
extern UInt32 g_CrcTable[];
|
||||
|
||||
/* Call CrcGenerateTable one time before other CRC functions */
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
@@ -19,11 +17,9 @@ void MY_FAST_CALL CrcGenerateTable(void);
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ CRC_INIT_VAL)
|
||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdate(uint32_t crc, const void *data, size_t size);
|
||||
uint32_t MY_FAST_CALL CrcCalc(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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+102
-25
@@ -1,38 +1,115 @@
|
||||
/* 7zCrcOpt.c -- CRC32 calculation : optimized version
|
||||
2009-11-23 : Igor Pavlov : Public domain */
|
||||
/* 7zCrcOpt.c -- CRC32 calculation
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifndef MSB_FIRST
|
||||
#ifndef MY_CPU_BE
|
||||
|
||||
#define CRC_UPDATE_BYTE_2(crc, b) (table[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table);
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT4(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
UInt32 MY_FAST_CALL CrcUpdateT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t*)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const uint32_t *)p;
|
||||
v =
|
||||
table[0x300 + (v & 0xFF)] ^
|
||||
table[0x200 + ((v >> 8) & 0xFF)] ^
|
||||
table[0x100 + ((v >> 16) & 0xFF)] ^
|
||||
table[0x000 + ((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x300)[((v ) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdateT8(uint32_t v, const void *data, size_t size, const uint32_t *table)
|
||||
UInt32 MY_FAST_CALL CrcUpdateT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
return CrcUpdateT4(v, data, size, table);
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x700)[((v ) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x400)[((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
(table + 0x300)[((d ) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x000)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_LE
|
||||
|
||||
#define CRC_UINT32_SWAP(v) ((v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | (v << 24))
|
||||
|
||||
#define CRC_UPDATE_BYTE_2_BE(crc, b) (table[(((crc) >> 24) ^ (b))] ^ ((crc) << 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT4(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 3) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 4; size -= 4, p += 4)
|
||||
{
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x000)[((v ) & 0xFF)]
|
||||
^ (table + 0x100)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((v >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdateT1_BeT8(UInt32 v, const void *data, size_t size, const UInt32 *table)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
table += 0x100;
|
||||
v = CRC_UINT32_SWAP(v);
|
||||
for (; size > 0 && ((unsigned)(ptrdiff_t)p & 7) != 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
for (; size >= 8; size -= 8, p += 8)
|
||||
{
|
||||
UInt32 d;
|
||||
v ^= *(const UInt32 *)p;
|
||||
v =
|
||||
(table + 0x400)[((v ) & 0xFF)]
|
||||
^ (table + 0x500)[((v >> 8) & 0xFF)]
|
||||
^ (table + 0x600)[((v >> 16) & 0xFF)]
|
||||
^ (table + 0x700)[((v >> 24))];
|
||||
d = *((const UInt32 *)p + 1);
|
||||
v ^=
|
||||
(table + 0x000)[((d ) & 0xFF)]
|
||||
^ (table + 0x100)[((d >> 8) & 0xFF)]
|
||||
^ (table + 0x200)[((d >> 16) & 0xFF)]
|
||||
^ (table + 0x300)[((d >> 24))];
|
||||
}
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE_2_BE(v, *p);
|
||||
return CRC_UINT32_SWAP(v);
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+488
-340
@@ -1,83 +1,184 @@
|
||||
/* 7zDec.c -- Decoding from 7z folder
|
||||
2010-11-02 : Igor Pavlov : Public domain */
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <boolean.h>
|
||||
|
||||
/* #define _7ZIP_PPMD_SUPPPORT */
|
||||
|
||||
#include "7z.h"
|
||||
#include "7zCrc.h"
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "Bra.h"
|
||||
#include "CpuArch.h"
|
||||
#include "Delta.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "Lzma2Dec.h"
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
#include "Ppmd7.h"
|
||||
#endif
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_Delta 3
|
||||
#define k_LZMA2 0x21
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_PPC 0x03030205
|
||||
#define k_ARM 0x03030501
|
||||
#define k_ARMT 0x03030701
|
||||
#define k_SPARC 0x03030805
|
||||
#define k_BCJ2 0x0303011B
|
||||
#define k_BCJ 0x3030103
|
||||
#define k_BCJ2 0x303011B
|
||||
#define k_PPC 0x3030205
|
||||
#define k_IA64 0x3030401
|
||||
#define k_ARM 0x3030501
|
||||
#define k_ARMT 0x3030701
|
||||
#define k_SPARC 0x3030805
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder,
|
||||
uint64_t inSize, ILookInStream *inStream,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
|
||||
#define k_PPMD 0x30401
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IByteIn vt;
|
||||
const Byte *cur;
|
||||
const Byte *end;
|
||||
const Byte *begin;
|
||||
UInt64 processed;
|
||||
BoolInt extra;
|
||||
SRes res;
|
||||
const ILookInStream *inStream;
|
||||
} CByteInToLook;
|
||||
|
||||
static Byte ReadByte(const IByteIn *pp)
|
||||
{
|
||||
CByteInToLook *p = CONTAINER_FROM_VTBL(pp, CByteInToLook, vt);
|
||||
if (p->cur != p->end)
|
||||
return *p->cur++;
|
||||
if (p->res == SZ_OK)
|
||||
{
|
||||
size_t size = p->cur - p->begin;
|
||||
p->processed += size;
|
||||
p->res = ILookInStream_Skip(p->inStream, size);
|
||||
size = (1 << 25);
|
||||
p->res = ILookInStream_Look(p->inStream, (const void **)&p->begin, &size);
|
||||
p->cur = p->begin;
|
||||
p->end = p->begin + size;
|
||||
if (size != 0)
|
||||
return *p->cur++;;
|
||||
}
|
||||
p->extra = True;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SRes SzDecodePpmd(const Byte *props, unsigned propsSize, UInt64 inSize, const ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
CPpmd7 ppmd;
|
||||
CByteInToLook s;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
s.vt.Read = ReadByte;
|
||||
s.inStream = inStream;
|
||||
s.begin = s.end = s.cur = NULL;
|
||||
s.extra = False;
|
||||
s.res = SZ_OK;
|
||||
s.processed = 0;
|
||||
|
||||
if (propsSize != 5)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
{
|
||||
unsigned order = props[0];
|
||||
UInt32 memSize = GetUi32(props + 1);
|
||||
if (order < PPMD7_MIN_ORDER ||
|
||||
order > PPMD7_MAX_ORDER ||
|
||||
memSize < PPMD7_MIN_MEM_SIZE ||
|
||||
memSize > PPMD7_MAX_MEM_SIZE)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
Ppmd7_Construct(&ppmd);
|
||||
if (!Ppmd7_Alloc(&ppmd, memSize, allocMain))
|
||||
return SZ_ERROR_MEM;
|
||||
Ppmd7_Init(&ppmd, order);
|
||||
}
|
||||
{
|
||||
CPpmd7z_RangeDec rc;
|
||||
Ppmd7z_RangeDec_CreateVTable(&rc);
|
||||
rc.Stream = &s.vt;
|
||||
if (!Ppmd7z_RangeDec_Init(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
else if (s.extra)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < outSize; i++)
|
||||
{
|
||||
int sym = Ppmd7_DecodeSymbol(&ppmd, &rc.vt);
|
||||
if (s.extra || sym < 0)
|
||||
break;
|
||||
outBuffer[i] = (Byte)sym;
|
||||
}
|
||||
if (i != outSize)
|
||||
res = (s.res != SZ_OK ? s.res : SZ_ERROR_DATA);
|
||||
else if (s.processed + (s.cur - s.begin) != inSize || !Ppmd7z_RangeDec_IsFinishedOK(&rc))
|
||||
res = SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
Ppmd7_Free(&ppmd, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeLzma(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
int result;
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
result = LzmaDec_AllocateProbs(
|
||||
&state, coder->Props.data,
|
||||
(unsigned)coder->Props.size, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
state.dic = outBuffer;
|
||||
RINOK(LzmaDec_AllocateProbs(&state, props, propsSize, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *inBuf = NULL;
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
size_t inProcessed = (size_t)lookahead, dicPos = state.dicPos;
|
||||
res = LzmaDec_DecodeToDic(
|
||||
&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
if (
|
||||
state.dicPos == state.dicBufSize ||
|
||||
(inProcessed == 0 && dicPos == state.dicPos))
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
if (
|
||||
state.dicBufSize != outSize ||
|
||||
lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
if (outSize != state.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (outSize == state.dicPos && inSize == 0 && status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
break;
|
||||
|
||||
if (inProcessed == 0 && dicPos == state.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
@@ -87,357 +188,404 @@ static SRes SzDecodeLzma(CSzCoderInfo *coder,
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeLzma2(CSzCoderInfo *coder,
|
||||
uint64_t inSize, ILookInStream *inStream,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
|
||||
static SRes SzDecodeLzma2(const Byte *props, unsigned propsSize, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain)
|
||||
{
|
||||
int result;
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
CLzma2Dec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (coder->Props.size != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
Lzma2Dec_Construct(&state);
|
||||
if (propsSize != 1)
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(Lzma2Dec_AllocateProbs(&state, props[0], allocMain));
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
result = Lzma2Dec_AllocateProbs(&state, coder->Props.data[0], allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
for (;;)
|
||||
{
|
||||
const void *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = ILookInStream_Look(inStream, &inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
state.decoder.dic = outBuffer;
|
||||
state.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &lookahead);
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.decoder.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = Lzma2Dec_DecodeToDic(&state, outSize, (const Byte *)inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
break;
|
||||
|
||||
if (status == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
ELzmaStatus status;
|
||||
size_t inProcessed = (size_t)lookahead, dicPos = state.decoder.dicPos;
|
||||
res = Lzma2Dec_DecodeToDic(
|
||||
&state, outSize, inBuf, &inProcessed,
|
||||
LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (
|
||||
state.decoder.dicPos == state.decoder.dicBufSize ||
|
||||
(inProcessed == 0 && dicPos == state.decoder.dicPos))
|
||||
{
|
||||
if (state.decoder.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK))
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (outSize != state.decoder.dicPos || inSize != 0)
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
if (inProcessed == 0 && dicPos == state.decoder.dicPos)
|
||||
{
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
|
||||
res = ILookInStream_Skip(inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Lzma2Dec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeCopy(uint64_t inSize,
|
||||
ILookInStream *inStream, uint8_t *outBuffer)
|
||||
#endif
|
||||
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
int result;
|
||||
void *inBuf = NULL;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
result = inStream->Look(
|
||||
(void *)inStream, (const void **)&inBuf, &curSize);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
result = inStream->Skip((void *)inStream, curSize);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
}
|
||||
return SZ_OK;
|
||||
while (inSize > 0)
|
||||
{
|
||||
const void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(ILookInStream_Look(inStream, &inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(ILookInStream_Skip(inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static bool is_main_method(uint32_t m)
|
||||
static BoolInt IS_MAIN_METHOD(UInt32 m)
|
||||
{
|
||||
switch(m)
|
||||
{
|
||||
case k_Copy:
|
||||
case k_LZMA:
|
||||
case k_LZMA2:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
switch (m)
|
||||
{
|
||||
case k_Copy:
|
||||
case k_LZMA:
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
case k_LZMA2:
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
case k_PPMD:
|
||||
#endif
|
||||
return True;
|
||||
}
|
||||
return False;
|
||||
}
|
||||
|
||||
static bool is_supported_coder(const CSzCoderInfo *c)
|
||||
static BoolInt IS_SUPPORTED_CODER(const CSzCoderInfo *c)
|
||||
{
|
||||
return
|
||||
c->NumInStreams == 1 &&
|
||||
c->NumOutStreams == 1 &&
|
||||
c->MethodID <= (uint32_t)0xFFFFFFFF &&
|
||||
is_main_method((uint32_t)c->MethodID);
|
||||
c->NumStreams == 1
|
||||
/* && c->MethodID <= (UInt32)0xFFFFFFFF */
|
||||
&& IS_MAIN_METHOD((UInt32)c->MethodID);
|
||||
}
|
||||
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumInStreams == 4 && (c)->NumOutStreams == 1)
|
||||
#define IS_BCJ2(c) ((c)->MethodID == k_BCJ2 && (c)->NumStreams == 4)
|
||||
|
||||
static SRes check_supported_folder(const CSzFolder *f)
|
||||
static SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
if (!is_supported_coder(&f->Coders[0]))
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
switch (f->NumCoders)
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
case 1:
|
||||
if ( f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBindPairs != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
case 2:
|
||||
{
|
||||
CSzCoderInfo *c = &f->Coders[1];
|
||||
|
||||
if (c->MethodID > (uint32_t)0xFFFFFFFF ||
|
||||
c->NumInStreams != 1 ||
|
||||
c->NumOutStreams != 1 ||
|
||||
f->NumPackStreams != 1 ||
|
||||
f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 ||
|
||||
f->BindPairs[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
switch ((uint32_t)c->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
case k_ARM:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
return SZ_OK;
|
||||
case 4:
|
||||
if (!is_supported_coder(&f->Coders[1]) ||
|
||||
!is_supported_coder(&f->Coders[2]) ||
|
||||
!IS_BCJ2(&f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 ||
|
||||
f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 ||
|
||||
f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 ||
|
||||
f->BindPairs[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBonds != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
const CSzCoderInfo *c = &f->Coders[1];
|
||||
if (
|
||||
/* c->MethodID > (UInt32)0xFFFFFFFF || */
|
||||
c->NumStreams != 1
|
||||
|| f->NumPackStreams != 1
|
||||
|| f->PackStreams[0] != 0
|
||||
|| f->NumBonds != 1
|
||||
|| f->Bonds[0].InIndex != 1
|
||||
|| f->Bonds[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch ((UInt32)c->MethodID)
|
||||
{
|
||||
case k_Delta:
|
||||
case k_BCJ:
|
||||
case k_PPC:
|
||||
case k_IA64:
|
||||
case k_SPARC:
|
||||
case k_ARM:
|
||||
case k_ARMT:
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (!IS_SUPPORTED_CODER(&f->Coders[1])
|
||||
|| !IS_SUPPORTED_CODER(&f->Coders[2])
|
||||
|| !IS_BCJ2(&f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4
|
||||
|| f->PackStreams[0] != 2
|
||||
|| f->PackStreams[1] != 6
|
||||
|| f->PackStreams[2] != 1
|
||||
|| f->PackStreams[3] != 0
|
||||
|| f->NumBonds != 3
|
||||
|| f->Bonds[0].InIndex != 5 || f->Bonds[0].OutIndex != 0
|
||||
|| f->Bonds[1].InIndex != 4 || f->Bonds[1].OutIndex != 1
|
||||
|| f->Bonds[2].InIndex != 3 || f->Bonds[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static uint64_t get_sum(const uint64_t *values, uint32_t idx)
|
||||
{
|
||||
uint64_t sum = 0;
|
||||
uint32_t i;
|
||||
for (i = 0; i < idx; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
#define CASE_BRA_CONV(isa) case k_ ## isa: isa ## _Convert(outBuffer, outSize, 0, 0); break;
|
||||
|
||||
static SRes SzFolder_Decode2(const CSzFolder *folder,
|
||||
const uint64_t *packSizes,
|
||||
ILookInStream *inStream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain,
|
||||
uint8_t *tempBuf[])
|
||||
const Byte *propsData,
|
||||
const UInt64 *unpackSizes,
|
||||
const UInt64 *packPositions,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAllocPtr allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
uint32_t ci;
|
||||
size_t tempSizes[3] = { 0, 0, 0};
|
||||
size_t tempSize3 = 0;
|
||||
uint8_t *tempBuf3 = 0;
|
||||
int result = check_supported_folder(folder);
|
||||
UInt32 ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
const CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (is_main_method((uint32_t)coder->MethodID))
|
||||
if (IS_MAIN_METHOD((UInt32)coder->MethodID))
|
||||
{
|
||||
UInt32 si = 0;
|
||||
UInt64 offset;
|
||||
UInt64 inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
int result;
|
||||
uint64_t offset = 0;
|
||||
uint64_t inSize = 0;
|
||||
uint32_t si = 0;
|
||||
uint8_t *outBufCur = outBuffer;
|
||||
size_t outSizeCur = outSize;
|
||||
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
uint32_t indices[] = { 3, 2, 0 };
|
||||
uint64_t unpackSize = folder->UnpackSizes[ci];
|
||||
si = indices[ci];
|
||||
|
||||
if (ci < 2)
|
||||
{
|
||||
uint8_t *temp;
|
||||
outSizeCur = (size_t)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (uint8_t *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer
|
||||
+ (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (size_t)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
offset = get_sum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
result = LookInStream_SeekTo(inStream, startPos + offset);
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_Copy:
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
result = SzDecodeCopy(inSize, inStream, outBufCur);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
case k_LZMA:
|
||||
result = SzDecodeLzma(
|
||||
coder, inSize, inStream,
|
||||
outBufCur, outSizeCur, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
case k_LZMA2:
|
||||
result = SzDecodeLzma2(
|
||||
coder, inSize, inStream,
|
||||
outBufCur, outSizeCur, allocMain);
|
||||
if (result != 0)
|
||||
return result;
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = unpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)ISzAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (!temp && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
offset = packPositions[si];
|
||||
inSize = packPositions[(size_t)si + 1] - offset;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
SRes res;
|
||||
int result;
|
||||
uint64_t offset = get_sum(packSizes, 1);
|
||||
uint64_t s3Size = packSizes[1];
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else if (coder->MethodID == k_LZMA)
|
||||
{
|
||||
RINOK(SzDecodeLzma(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#ifndef _7Z_NO_METHOD_LZMA2
|
||||
else if (coder->MethodID == k_LZMA2)
|
||||
{
|
||||
RINOK(SzDecodeLzma2(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
#ifdef _7ZIP_PPMD_SUPPPORT
|
||||
else if (coder->MethodID == k_PPMD)
|
||||
{
|
||||
RINOK(SzDecodePpmd(propsData + coder->PropsOffset, coder->PropsSize, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = packPositions[1];
|
||||
UInt64 s3Size = packPositions[2] - offset;
|
||||
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)ISzAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (!tempBuf[2] && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
RINOK(SzDecodeCopy(s3Size, inStream, tempBuf[2]));
|
||||
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if ((tempSizes[0] & 3) != 0 ||
|
||||
(tempSizes[1] & 3) != 0 ||
|
||||
tempSize3 + tempSizes[0] + tempSizes[1] != outSize)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
result = LookInStream_SeekTo(inStream, startPos + offset);
|
||||
{
|
||||
CBcj2Dec p;
|
||||
|
||||
p.bufs[0] = tempBuf3; p.lims[0] = tempBuf3 + tempSize3;
|
||||
p.bufs[1] = tempBuf[0]; p.lims[1] = tempBuf[0] + tempSizes[0];
|
||||
p.bufs[2] = tempBuf[1]; p.lims[2] = tempBuf[1] + tempSizes[1];
|
||||
p.bufs[3] = tempBuf[2]; p.lims[3] = tempBuf[2] + tempSizes[2];
|
||||
|
||||
p.dest = outBuffer;
|
||||
p.destLim = outBuffer + outSize;
|
||||
|
||||
Bcj2Dec_Init(&p);
|
||||
RINOK(Bcj2Dec_Decode(&p));
|
||||
|
||||
if (result != 0)
|
||||
return result;
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < 4; i++)
|
||||
if (p.bufs[i] != p.lims[i])
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (!Bcj2Dec_IsFinished(&p))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
tempSizes[2] = (size_t)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
tempBuf[2] = (uint8_t *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
if (res != 0)
|
||||
return res;
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (p.dest != p.destLim
|
||||
|| p.state != BCJ2_STREAM_MAIN)
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifndef _7Z_NO_METHODS_FILTERS
|
||||
else if (ci == 1)
|
||||
{
|
||||
if (coder->MethodID == k_Delta)
|
||||
{
|
||||
if (coder->PropsSize != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
{
|
||||
Byte state[DELTA_STATE_SIZE];
|
||||
Delta_Init(state);
|
||||
Delta_Decode(state, (unsigned)(propsData[coder->PropsOffset]) + 1, outBuffer, outSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ci != 1)
|
||||
if (coder->PropsSize != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch (coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
UInt32 state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
CASE_BRA_CONV(PPC)
|
||||
CASE_BRA_CONV(IA64)
|
||||
CASE_BRA_CONV(SPARC)
|
||||
CASE_BRA_CONV(ARM)
|
||||
CASE_BRA_CONV(ARMT)
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
switch(coder->MethodID)
|
||||
{
|
||||
case k_BCJ:
|
||||
{
|
||||
uint32_t state;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
break;
|
||||
}
|
||||
case k_ARM:
|
||||
ARM_Convert(outBuffer, outSize, 0, 0);
|
||||
break;
|
||||
default:
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzFolder_Decode(const CSzFolder *folder, const uint64_t *packSizes,
|
||||
ILookInStream *inStream, uint64_t startPos,
|
||||
uint8_t *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
|
||||
SRes SzAr_DecodeFolder(const CSzAr *p, UInt32 folderIndex,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize,
|
||||
ISzAllocPtr allocMain)
|
||||
{
|
||||
int i;
|
||||
uint8_t *tempBuf[3] = { 0, 0, 0};
|
||||
SRes res = SzFolder_Decode2(folder,
|
||||
packSizes, inStream, startPos,
|
||||
outBuffer, (size_t)outSize, allocMain, tempBuf);
|
||||
SRes res;
|
||||
CSzFolder folder;
|
||||
CSzData sd;
|
||||
|
||||
const Byte *data = p->CodersData + p->FoCodersOffsets[folderIndex];
|
||||
sd.Data = data;
|
||||
sd.Size = p->FoCodersOffsets[(size_t)folderIndex + 1] - p->FoCodersOffsets[folderIndex];
|
||||
|
||||
res = SzGetNextFolderItem(&folder, &sd);
|
||||
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
if (sd.Size != 0
|
||||
|| folder.UnpackStream != p->FoToMainUnpackSizeIndex[folderIndex]
|
||||
|| outSize != SzAr_GetFolderUnpackSize(p, folderIndex))
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
unsigned i;
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
|
||||
res = SzFolder_Decode2(&folder, data,
|
||||
&p->CoderUnpackSizes[p->FoToCoderUnpackSizes[folderIndex]],
|
||||
p->PackPositions + p->FoStartPackStreamIndex[folderIndex],
|
||||
inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
ISzAlloc_Free(allocMain, tempBuf[i]);
|
||||
|
||||
if (res == SZ_OK)
|
||||
if (SzBitWithVals_Check(&p->FolderCRCs, folderIndex))
|
||||
if (CrcCalc(outBuffer, outSize) != p->FolderCRCs.Vals[folderIndex])
|
||||
res = SZ_ERROR_CRC;
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
Vendored
+216
-90
@@ -1,160 +1,286 @@
|
||||
/* 7zFile.c -- File IO
|
||||
2009-11-24 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#define SKIP_STDIO_REDEFINES
|
||||
#include <streams/file_stream_transforms.h>
|
||||
#include "7zFile.h"
|
||||
|
||||
#ifndef USE_WINDOWS_FILE
|
||||
|
||||
#ifndef UNDER_CE
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
ReadFile and WriteFile functions in Windows have BUG:
|
||||
If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1)
|
||||
from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES
|
||||
(Insufficient system resources exist to complete the requested service).
|
||||
Probably in some version of Windows there are problems with other sizes:
|
||||
for 32 MB (maybe also for 16 MB).
|
||||
And message can be "Network connection was lost"
|
||||
*/
|
||||
|
||||
#define kChunkSizeMax (1 << 22)
|
||||
|
||||
#endif
|
||||
|
||||
void File_Construct(CSzFile *p)
|
||||
{
|
||||
p->file = NULL;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
p->handle = INVALID_HANDLE_VALUE;
|
||||
#else
|
||||
p->file = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||
static WRes File_Open(CSzFile *p, const char *name, int writeMode)
|
||||
{
|
||||
p->file = rfopen(name, writeMode ? "wb+" : "rb");
|
||||
if (!p->file)
|
||||
{
|
||||
#ifdef UNDER_CE
|
||||
return 2; /* ENOENT */
|
||||
#else
|
||||
return errno;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
p->handle = CreateFileA(name,
|
||||
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL,
|
||||
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||
#else
|
||||
p->file = fopen(name, writeMode ? "wb+" : "rb");
|
||||
return (p->file != 0) ? 0 :
|
||||
#ifdef UNDER_CE
|
||||
2; /* ENOENT */
|
||||
#else
|
||||
errno;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); }
|
||||
WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); }
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes InFile_Open(CSzFile *p, const char *name)
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode)
|
||||
{
|
||||
return File_Open(p, name, 0);
|
||||
}
|
||||
|
||||
WRes OutFile_Open(CSzFile *p, const char *name)
|
||||
{
|
||||
return File_Open(p, name, 1);
|
||||
p->handle = CreateFileW(name,
|
||||
writeMode ? GENERIC_WRITE : GENERIC_READ,
|
||||
FILE_SHARE_READ, NULL,
|
||||
writeMode ? CREATE_ALWAYS : OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError();
|
||||
}
|
||||
WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); }
|
||||
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); }
|
||||
#endif
|
||||
|
||||
WRes File_Close(CSzFile *p)
|
||||
{
|
||||
if (p->file)
|
||||
{
|
||||
int res = rfclose((RFILE*)p->file);
|
||||
if (res != 0)
|
||||
return res;
|
||||
p->file = NULL;
|
||||
}
|
||||
return 0;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
if (p->handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (!CloseHandle(p->handle))
|
||||
return GetLastError();
|
||||
p->handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#else
|
||||
if (p->file != NULL)
|
||||
{
|
||||
int res = fclose(p->file);
|
||||
if (res != 0)
|
||||
return res;
|
||||
p->file = NULL;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
WRes File_Read(CSzFile *p, void *data, size_t *size)
|
||||
{
|
||||
int64_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
size_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
|
||||
*size = rfread(data, 1, originalSize, (RFILE*)p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return rferror((RFILE*)p->file);
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
*size = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||
DWORD processed = 0;
|
||||
BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL);
|
||||
data = (void *)((Byte *)data + processed);
|
||||
originalSize -= processed;
|
||||
*size += processed;
|
||||
if (!res)
|
||||
return GetLastError();
|
||||
if (processed == 0)
|
||||
break;
|
||||
}
|
||||
while (originalSize > 0);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
*size = fread(data, 1, originalSize, p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return ferror(p->file);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_Write(CSzFile *p, const void *data, size_t *size)
|
||||
{
|
||||
int64_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
size_t originalSize = *size;
|
||||
if (originalSize == 0)
|
||||
return 0;
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
*size = rfwrite(data, 1, originalSize, (RFILE*)p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return rferror((RFILE*)p->file);
|
||||
*size = 0;
|
||||
do
|
||||
{
|
||||
DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize;
|
||||
DWORD processed = 0;
|
||||
BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL);
|
||||
data = (void *)((Byte *)data + processed);
|
||||
originalSize -= processed;
|
||||
*size += processed;
|
||||
if (!res)
|
||||
return GetLastError();
|
||||
if (processed == 0)
|
||||
break;
|
||||
}
|
||||
while (originalSize > 0);
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
*size = fwrite(data, 1, originalSize, p->file);
|
||||
if (*size == originalSize)
|
||||
return 0;
|
||||
return ferror(p->file);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_Seek(CSzFile *p, int64_t *pos, ESzSeek origin)
|
||||
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
int whence;
|
||||
int64_t res;
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET:
|
||||
whence = SEEK_SET;
|
||||
break;
|
||||
case SZ_SEEK_CUR:
|
||||
whence = SEEK_CUR;
|
||||
break;
|
||||
case SZ_SEEK_END:
|
||||
whence = SEEK_END;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
res = rfseek((RFILE*)p->file, (int64_t)*pos, whence);
|
||||
*pos = rftell((RFILE*)p->file);
|
||||
return res;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
LARGE_INTEGER value;
|
||||
DWORD moveMethod;
|
||||
value.LowPart = (DWORD)*pos;
|
||||
value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break;
|
||||
case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break;
|
||||
case SZ_SEEK_END: moveMethod = FILE_END; break;
|
||||
default: return ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod);
|
||||
if (value.LowPart == 0xFFFFFFFF)
|
||||
{
|
||||
WRes res = GetLastError();
|
||||
if (res != NO_ERROR)
|
||||
return res;
|
||||
}
|
||||
*pos = ((Int64)value.HighPart << 32) | value.LowPart;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
int moveMethod;
|
||||
int res;
|
||||
switch (origin)
|
||||
{
|
||||
case SZ_SEEK_SET: moveMethod = SEEK_SET; break;
|
||||
case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break;
|
||||
case SZ_SEEK_END: moveMethod = SEEK_END; break;
|
||||
default: return 1;
|
||||
}
|
||||
res = fseek(p->file, (long)*pos, moveMethod);
|
||||
*pos = ftell(p->file);
|
||||
return res;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
WRes File_GetLength(CSzFile *p, uint64_t *length)
|
||||
WRes File_GetLength(CSzFile *p, UInt64 *length)
|
||||
{
|
||||
int64_t pos = rftell((RFILE*)p->file);
|
||||
int64_t res = rfseek((RFILE*)p->file, 0, SEEK_END);
|
||||
*length = rftell((RFILE*)p->file);
|
||||
rfseek((RFILE*)p->file, pos, SEEK_SET);
|
||||
return res;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
DWORD sizeHigh;
|
||||
DWORD sizeLow = GetFileSize(p->handle, &sizeHigh);
|
||||
if (sizeLow == 0xFFFFFFFF)
|
||||
{
|
||||
DWORD res = GetLastError();
|
||||
if (res != NO_ERROR)
|
||||
return res;
|
||||
}
|
||||
*length = (((UInt64)sizeHigh) << 32) + sizeLow;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
|
||||
long pos = ftell(p->file);
|
||||
int res = fseek(p->file, 0, SEEK_END);
|
||||
*length = ftell(p->file);
|
||||
fseek(p->file, pos, SEEK_SET);
|
||||
return res;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileSeqInStream ---------- */
|
||||
|
||||
static SRes FileSeqInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileSeqInStream *p = (CFileSeqInStream *)pp;
|
||||
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||
CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt);
|
||||
return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
void FileSeqInStream_CreateVTable(CFileSeqInStream *p)
|
||||
{
|
||||
p->s.Read = FileSeqInStream_Read;
|
||||
p->vt.Read = FileSeqInStream_Read;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileInStream ---------- */
|
||||
|
||||
static SRes FileInStream_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
static SRes FileInStream_Seek(void *pp, int64_t *pos, ESzSeek origin)
|
||||
static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CFileInStream *p = (CFileInStream *)pp;
|
||||
return File_Seek(&p->file, pos, origin);
|
||||
CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt);
|
||||
return File_Seek(&p->file, pos, origin);
|
||||
}
|
||||
|
||||
void FileInStream_CreateVTable(CFileInStream *p)
|
||||
{
|
||||
p->s.Read = FileInStream_Read;
|
||||
p->s.Seek = FileInStream_Seek;
|
||||
p->vt.Read = FileInStream_Read;
|
||||
p->vt.Seek = FileInStream_Seek;
|
||||
}
|
||||
|
||||
|
||||
/* ---------- FileOutStream ---------- */
|
||||
|
||||
static size_t FileOutStream_Write(void *pp, const void *data, size_t size)
|
||||
static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size)
|
||||
{
|
||||
CFileOutStream *p = (CFileOutStream *)pp;
|
||||
File_Write(&p->file, data, &size);
|
||||
return size;
|
||||
CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt);
|
||||
File_Write(&p->file, data, &size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p)
|
||||
{
|
||||
p->s.Write = FileOutStream_Write;
|
||||
p->vt.Write = FileOutStream_Write;
|
||||
}
|
||||
|
||||
#undef SKIP_STDIO_REDEFINES
|
||||
Vendored
+27
-13
@@ -1,27 +1,43 @@
|
||||
/* 7zFile.h -- File IO
|
||||
2009-11-24 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_FILE_H
|
||||
#define __7Z_FILE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_FILE
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- File ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *file;
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
HANDLE handle;
|
||||
#else
|
||||
FILE *file;
|
||||
#endif
|
||||
} CSzFile;
|
||||
|
||||
void File_Construct(CSzFile *p);
|
||||
#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE)
|
||||
WRes InFile_Open(CSzFile *p, const char *name);
|
||||
WRes OutFile_Open(CSzFile *p, const char *name);
|
||||
#endif
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
WRes InFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||
WRes OutFile_OpenW(CSzFile *p, const WCHAR *name);
|
||||
#endif
|
||||
WRes File_Close(CSzFile *p);
|
||||
|
||||
/* reads max(*size, remain file's size) bytes */
|
||||
@@ -30,15 +46,15 @@ WRes File_Read(CSzFile *p, void *data, size_t *size);
|
||||
/* writes *size bytes */
|
||||
WRes File_Write(CSzFile *p, const void *data, size_t *size);
|
||||
|
||||
WRes File_Seek(CSzFile *p, int64_t *pos, ESzSeek origin);
|
||||
WRes File_GetLength(CSzFile *p, uint64_t *length);
|
||||
WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin);
|
||||
WRes File_GetLength(CSzFile *p, UInt64 *length);
|
||||
|
||||
|
||||
/* ---------- FileInStream ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ISeqInStream vt;
|
||||
CSzFile file;
|
||||
} CFileSeqInStream;
|
||||
|
||||
@@ -47,7 +63,7 @@ void FileSeqInStream_CreateVTable(CFileSeqInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeekInStream s;
|
||||
ISeekInStream vt;
|
||||
CSzFile file;
|
||||
} CFileInStream;
|
||||
|
||||
@@ -56,14 +72,12 @@ void FileInStream_CreateVTable(CFileInStream *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqOutStream s;
|
||||
ISeqOutStream vt;
|
||||
CSzFile file;
|
||||
} CFileOutStream;
|
||||
|
||||
void FileOutStream_CreateVTable(CFileOutStream *p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
-1631
File diff suppressed because it is too large.
Load diff
Vendored
+116
-124
@@ -1,184 +1,176 @@
|
||||
/* 7zStream.c -- 7z Stream functions
|
||||
2010-03-11 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
SRes SeqInStream_Readuint8_t(ISeqInStream *stream, uint8_t *buf)
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
size_t processed = 1;
|
||||
int result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed != 1)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
return SZ_OK;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
int result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((uint8_t *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf)
|
||||
{
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
size_t processed = 1;
|
||||
RINOK(ISeqInStream_Read(stream, buf, &processed));
|
||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
|
||||
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, uint64_t offset)
|
||||
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset)
|
||||
{
|
||||
int64_t t = offset;
|
||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||
Int64 t = offset;
|
||||
return ILookInStream_Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size)
|
||||
{
|
||||
int result;
|
||||
const void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
result = stream->Look(stream, &lookBuf, size);
|
||||
if (result != 0)
|
||||
return result;
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return stream->Skip(stream, *size);
|
||||
const void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
RINOK(ILookInStream_Look(stream, &lookBuf, size));
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return ILookInStream_Skip(stream, *size);
|
||||
}
|
||||
|
||||
SRes LookInStream_Read2(ILookInStream *stream,
|
||||
void *buf, size_t size, SRes errorType)
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
int result = stream->Read(stream, buf, &processed);
|
||||
if (result != 0)
|
||||
return result;
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((uint8_t *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(ILookInStream_Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||
SRes LookInStream_Read(const 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)
|
||||
|
||||
|
||||
#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt);
|
||||
|
||||
static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
size2 = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
SRes res = SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size != 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
p->size = 0;
|
||||
size2 = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Exact(void *pp, const void **buf, size_t *size)
|
||||
static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
if (*size > LookToRead_BUF_SIZE)
|
||||
*size = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
SRes res = SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size != 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
p->size = 0;
|
||||
if (*size > p->bufSize)
|
||||
*size = p->bufSize;
|
||||
res = ISeekInStream_Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (*size > size2)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||
static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
GET_LookToRead2
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
GET_LookToRead2
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return ISeekInStream_Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Seek(void *pp, int64_t *pos, ESzSeek origin)
|
||||
static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos = p->size = 0;
|
||||
return p->realStream->Seek(p->realStream, pos, origin);
|
||||
GET_LookToRead2
|
||||
p->pos = p->size = 0;
|
||||
return ISeekInStream_Seek(p->realStream, pos, origin);
|
||||
}
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead)
|
||||
{
|
||||
p->s.Look = lookahead ?
|
||||
LookToRead_Look_Lookahead :
|
||||
LookToRead_Look_Exact;
|
||||
p->s.Skip = LookToRead_Skip;
|
||||
p->s.Read = LookToRead_Read;
|
||||
p->s.Seek = LookToRead_Seek;
|
||||
p->vt.Look = lookahead ?
|
||||
LookToRead2_Look_Lookahead :
|
||||
LookToRead2_Look_Exact;
|
||||
p->vt.Skip = LookToRead2_Skip;
|
||||
p->vt.Read = LookToRead2_Read;
|
||||
p->vt.Seek = LookToRead2_Seek;
|
||||
}
|
||||
|
||||
void LookToRead_Init(CLookToRead *p)
|
||||
{
|
||||
p->pos = p->size = 0;
|
||||
}
|
||||
|
||||
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||
|
||||
static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToLook *p = (CSecToLook *)pp;
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt);
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p)
|
||||
{
|
||||
p->s.Read = SecToLook_Read;
|
||||
p->vt.Read = SecToLook_Read;
|
||||
}
|
||||
|
||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||
static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToRead *p = (CSecToRead *)pp;
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt);
|
||||
return ILookInStream_Read(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p)
|
||||
{
|
||||
p->s.Read = SecToRead_Read;
|
||||
p->vt.Read = SecToRead_Read;
|
||||
}
|
||||
Vendored
+267
-65
@@ -1,10 +1,13 @@
|
||||
/* 7zTypes.h -- Basic types
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
2018-08-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef _WIN32
|
||||
/* #include <windows.h> */
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef EXTERN_C_BEGIN
|
||||
@@ -19,10 +22,6 @@
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#ifndef _7ZIP_ST
|
||||
#define _7ZIP_ST
|
||||
#endif
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
@@ -41,56 +40,157 @@ EXTERN_C_BEGIN
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int64_t SRes;
|
||||
typedef int SRes;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* typedef DWORD WRes; */
|
||||
typedef unsigned WRes;
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x)
|
||||
|
||||
#else
|
||||
|
||||
typedef int WRes;
|
||||
#define MY__FACILITY_WIN32 7
|
||||
#define MY__FACILITY__WRes MY__FACILITY_WIN32
|
||||
#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000)))
|
||||
|
||||
#endif
|
||||
|
||||
typedef int64_t WRes;
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
#ifndef ZCONF_H
|
||||
typedef unsigned char Byte;
|
||||
#endif
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#if defined(_LZMA_UINT32_IS_ULONG) && !defined(__LP64__)
|
||||
typedef long Int32;
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#define UINT64_CONST(n) n
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#define UINT64_CONST(n) n ## ULL
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||
typedef UInt32 SizeT;
|
||||
#else
|
||||
typedef size_t SizeT;
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MY_FAST_CALL __fastcall
|
||||
typedef int BoolInt;
|
||||
/* typedef BoolInt Bool; */
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MY_STD_CALL __stdcall
|
||||
#else
|
||||
#define MY_FAST_CALL
|
||||
#define MY_STD_CALL
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_FORCE_INLINE __forceinline
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_FAST_CALL __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_NO_INLINE
|
||||
#define MY_FORCE_INLINE
|
||||
#define MY_CDECL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
/* inline keyword : for C++ / C99 */
|
||||
|
||||
/* GCC, clang: */
|
||||
/*
|
||||
#if defined (__GNUC__) && (__GNUC__ >= 4)
|
||||
#define MY_FORCE_INLINE __attribute__((always_inline))
|
||||
#define MY_NO_INLINE __attribute__((noinline))
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
typedef struct IByteIn IByteIn;
|
||||
struct IByteIn
|
||||
{
|
||||
unsigned char (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
} IByteIn;
|
||||
Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */
|
||||
};
|
||||
#define IByteIn_Read(p) (p)->Read(p)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*Write)(void *p, unsigned char b);
|
||||
} IByteOut;
|
||||
|
||||
typedef struct
|
||||
typedef struct IByteOut IByteOut;
|
||||
struct IByteOut
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
void (*Write)(const IByteOut *p, Byte b);
|
||||
};
|
||||
#define IByteOut_Write(p, b) (p)->Write(p, b)
|
||||
|
||||
|
||||
typedef struct ISeqInStream ISeqInStream;
|
||||
struct ISeqInStream
|
||||
{
|
||||
SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
} ISeqInStream;
|
||||
};
|
||||
#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
|
||||
/* it can return SZ_ERROR_INPUT_EOF */
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, unsigned char *buf);
|
||||
SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf);
|
||||
|
||||
typedef struct
|
||||
|
||||
typedef struct ISeqOutStream ISeqOutStream;
|
||||
struct ISeqOutStream
|
||||
{
|
||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||
size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
} ISeqOutStream;
|
||||
};
|
||||
#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
@@ -99,76 +199,178 @@ typedef enum
|
||||
SZ_SEEK_END = 2
|
||||
} ESzSeek;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, int64_t *pos, ESzSeek origin);
|
||||
} ISeekInStream;
|
||||
|
||||
typedef struct
|
||||
typedef struct ISeekInStream ISeekInStream;
|
||||
struct ISeekInStream
|
||||
{
|
||||
SRes (*Look)(void *p, const void **buf, size_t *size);
|
||||
SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin);
|
||||
};
|
||||
#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
typedef struct ILookInStream ILookInStream;
|
||||
struct ILookInStream
|
||||
{
|
||||
SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) > input(*size)) is not allowed
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
SRes (*Skip)(void *p, size_t offset);
|
||||
SRes (*Skip)(const ILookInStream *p, size_t offset);
|
||||
/* offset must be <= output(*size) of Look */
|
||||
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
SRes (*Read)(const ILookInStream *p, void *buf, size_t *size);
|
||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, int64_t *pos, ESzSeek origin);
|
||||
} ILookInStream;
|
||||
SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin);
|
||||
};
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, uint64_t offset);
|
||||
#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size)
|
||||
#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset)
|
||||
#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size)
|
||||
#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin)
|
||||
|
||||
|
||||
SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset);
|
||||
|
||||
/* reads via ILookInStream::Read */
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||
SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size);
|
||||
|
||||
|
||||
#define LookToRead_BUF_SIZE (1 << 14)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ILookInStream s;
|
||||
ISeekInStream *realStream;
|
||||
ILookInStream vt;
|
||||
const ISeekInStream *realStream;
|
||||
|
||||
size_t pos;
|
||||
size_t size;
|
||||
unsigned char buf[LookToRead_BUF_SIZE];
|
||||
} CLookToRead;
|
||||
size_t size; /* it's data size */
|
||||
|
||||
/* the following variables must be set outside */
|
||||
Byte *buf;
|
||||
size_t bufSize;
|
||||
} CLookToRead2;
|
||||
|
||||
void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead);
|
||||
|
||||
#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; }
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||
void LookToRead_Init(CLookToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToLook;
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p);
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
ISeqInStream vt;
|
||||
const ILookInStream *realStream;
|
||||
} CSecToRead;
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Progress)(void *p, uint64_t inSize, uint64_t outSize);
|
||||
} ICompressProgress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
typedef struct ICompressProgress ICompressProgress;
|
||||
|
||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||
struct ICompressProgress
|
||||
{
|
||||
SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||
};
|
||||
#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize)
|
||||
|
||||
|
||||
|
||||
typedef struct ISzAlloc ISzAlloc;
|
||||
typedef const ISzAlloc * ISzAllocPtr;
|
||||
|
||||
struct ISzAlloc
|
||||
{
|
||||
void *(*Alloc)(ISzAllocPtr p, size_t size);
|
||||
void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */
|
||||
};
|
||||
|
||||
#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size)
|
||||
#define ISzAlloc_Free(p, a) (p)->Free(p, a)
|
||||
|
||||
/* deprecated */
|
||||
#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size)
|
||||
#define IAlloc_Free(p, a) ISzAlloc_Free(p, a)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifndef MY_offsetof
|
||||
#ifdef offsetof
|
||||
#define MY_offsetof(type, m) offsetof(type, m)
|
||||
/*
|
||||
#define MY_offsetof(type, m) FIELD_OFFSET(type, m)
|
||||
*/
|
||||
#else
|
||||
#define MY_offsetof(type, m) ((size_t)&(((type *)0)->m))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef MY_container_of
|
||||
|
||||
/*
|
||||
#define MY_container_of(ptr, type, m) container_of(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m)
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m)))
|
||||
#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m))))
|
||||
*/
|
||||
|
||||
/*
|
||||
GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly"
|
||||
GCC 3.4.4 : classes with constructor
|
||||
GCC 4.8.1 : classes with non-public variable members"
|
||||
*/
|
||||
|
||||
#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m)))
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr))
|
||||
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
*/
|
||||
#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m)
|
||||
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m)
|
||||
/*
|
||||
#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '\\'
|
||||
#define WCHAR_PATH_SEPARATOR L'\\'
|
||||
#define STRING_PATH_SEPARATOR "\\"
|
||||
#define WSTRING_PATH_SEPARATOR L"\\"
|
||||
|
||||
#else
|
||||
|
||||
#define CHAR_PATH_SEPARATOR '/'
|
||||
#define WCHAR_PATH_SEPARATOR L'/'
|
||||
#define STRING_PATH_SEPARATOR "/"
|
||||
#define WSTRING_PATH_SEPARATOR L"/"
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
Vendored
+26
-6
@@ -1,7 +1,27 @@
|
||||
#define MY_VER_MAJOR 9
|
||||
#define MY_VER_MINOR 20
|
||||
#define MY_VER_MAJOR 19
|
||||
#define MY_VER_MINOR 00
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION "9.20"
|
||||
#define MY_DATE "2010-11-18"
|
||||
#define MY_COPYRIGHT ": Igor Pavlov : Public domain"
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION " " MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_NUMBERS "19.00"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
#define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")"
|
||||
#else
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2019-02-21"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
#else
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_PD
|
||||
#endif
|
||||
|
||||
#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE
|
||||
#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE
|
||||
Vendored
+235
-125
@@ -1,149 +1,259 @@
|
||||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.c -- BCJ2 Decoder (Converter for x86 code)
|
||||
2018-04-28 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Bcj2.h"
|
||||
#include "CpuArch.h"
|
||||
|
||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||
#define CProb UInt16
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((uint32_t)1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#undef kTopValue
|
||||
#define kTopValue ((UInt32)1 << 24)
|
||||
#define kNumModelBits 11
|
||||
#undef kBitModelTotal
|
||||
#define kBitModelTotal (1 << kNumModelBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define _IF_BIT_0 ttt = *prob; bound = (p->range >> kNumModelBits) * ttt; if (p->code < bound)
|
||||
#define _UPDATE_0 p->range = bound; *prob = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
#define _UPDATE_1 p->range -= bound; p->code -= bound; *prob = (CProb)(ttt - (ttt >> kNumMoveBits));
|
||||
|
||||
int Bcj2_Decode(
|
||||
const uint8_t *buf0, size_t size0,
|
||||
const uint8_t *buf1, size_t size1,
|
||||
const uint8_t *buf2, size_t size2,
|
||||
const uint8_t *buf3, size_t size3,
|
||||
uint8_t *outBuf, size_t outSize)
|
||||
void Bcj2Dec_Init(CBcj2Dec *p)
|
||||
{
|
||||
uint16_t p[256 + 2];
|
||||
size_t inPos = 0, outPos = 0;
|
||||
unsigned i;
|
||||
|
||||
const uint8_t *buffer, *bufferLim;
|
||||
uint32_t range, codes = 0;
|
||||
uint8_t prevuint8_t = 0;
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
p->ip = 0;
|
||||
p->temp[3] = 0;
|
||||
p->range = 0;
|
||||
p->code = 0;
|
||||
for (i = 0; i < sizeof(p->probs) / sizeof(p->probs[0]); i++)
|
||||
p->probs[i] = kBitModelTotal >> 1;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[i] = kBitModelTotal >> 1;
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p)
|
||||
{
|
||||
if (p->range <= 5)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
for (; p->range != 5; p->range++)
|
||||
{
|
||||
if (p->range == 1 && p->code != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
range = 0xFFFFFFFF;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
if (p->code == 0xFFFFFFFF)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
p->range = 0xFFFFFFFF;
|
||||
}
|
||||
else if (p->state >= BCJ2_DEC_STATE_ORIG_0)
|
||||
{
|
||||
while (p->state <= BCJ2_DEC_STATE_ORIG_3)
|
||||
{
|
||||
Byte *dest = p->dest;
|
||||
if (dest == p->destLim)
|
||||
return SZ_OK;
|
||||
*dest = p->temp[(size_t)p->state - BCJ2_DEC_STATE_ORIG_0];
|
||||
p->state++;
|
||||
p->dest = dest + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
/*
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
{
|
||||
const Byte *cur = p->bufs[p->state];
|
||||
if (cur == p->lims[p->state])
|
||||
return SZ_OK;
|
||||
p->bufs[p->state] = cur + 4;
|
||||
|
||||
{
|
||||
UInt32 val;
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
p->ip += 4;
|
||||
val = GetBe32(cur) - p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
if (rem < 4)
|
||||
{
|
||||
SizeT i;
|
||||
SetUi32(p->temp, val);
|
||||
for (i = 0; i < rem; i++)
|
||||
dest[i] = p->temp[i];
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
for (;;)
|
||||
{
|
||||
if (BCJ2_IS_32BIT_STREAM(p->state))
|
||||
p->state = BCJ2_DEC_STATE_OK;
|
||||
else
|
||||
{
|
||||
if (p->range < kTopValue)
|
||||
{
|
||||
if (p->bufs[BCJ2_STREAM_RC] == p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->state = BCJ2_STREAM_RC;
|
||||
return SZ_OK;
|
||||
}
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t b;
|
||||
uint16_t *prob;
|
||||
uint32_t bound;
|
||||
uint32_t ttt;
|
||||
{
|
||||
const Byte *src = p->bufs[BCJ2_STREAM_MAIN];
|
||||
const Byte *srcLim;
|
||||
Byte *dest;
|
||||
SizeT num = p->lims[BCJ2_STREAM_MAIN] - src;
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_STREAM_MAIN;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dest = p->dest;
|
||||
if (num > (SizeT)(p->destLim - dest))
|
||||
{
|
||||
num = p->destLim - dest;
|
||||
if (num == 0)
|
||||
{
|
||||
p->state = BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
srcLim = src + num;
|
||||
|
||||
size_t limit = size0 - inPos;
|
||||
if (outSize - outPos < limit)
|
||||
limit = outSize - outPos;
|
||||
while (limit != 0)
|
||||
{
|
||||
b = buf0[inPos];
|
||||
outBuf[outPos++] = b;
|
||||
if (IsJ(prevuint8_t, b))
|
||||
if (p->temp[3] == 0x0F && (src[0] & 0xF0) == 0x80)
|
||||
*dest = src[0];
|
||||
else for (;;)
|
||||
{
|
||||
Byte b = *src;
|
||||
*dest = b;
|
||||
if (b != 0x0F)
|
||||
{
|
||||
if ((b & 0xFE) == 0xE8)
|
||||
break;
|
||||
dest++;
|
||||
if (++src != srcLim)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
dest++;
|
||||
if (++src == srcLim)
|
||||
break;
|
||||
inPos++;
|
||||
prevuint8_t = b;
|
||||
limit--;
|
||||
if ((*src & 0xF0) != 0x80)
|
||||
continue;
|
||||
*dest = *src;
|
||||
break;
|
||||
}
|
||||
|
||||
num = src - p->bufs[BCJ2_STREAM_MAIN];
|
||||
|
||||
if (src == srcLim)
|
||||
{
|
||||
p->temp[3] = src[-1];
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src;
|
||||
p->ip += (UInt32)num;
|
||||
p->dest += num;
|
||||
p->state =
|
||||
p->bufs[BCJ2_STREAM_MAIN] ==
|
||||
p->lims[BCJ2_STREAM_MAIN] ?
|
||||
(unsigned)BCJ2_STREAM_MAIN :
|
||||
(unsigned)BCJ2_DEC_STATE_ORIG;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
{
|
||||
UInt32 bound, ttt;
|
||||
CProb *prob;
|
||||
Byte b = src[0];
|
||||
Byte prev = (Byte)(num == 0 ? p->temp[3] : src[-1]);
|
||||
|
||||
p->temp[3] = b;
|
||||
p->bufs[BCJ2_STREAM_MAIN] = src + 1;
|
||||
num++;
|
||||
p->ip += (UInt32)num;
|
||||
p->dest += num;
|
||||
|
||||
prob = p->probs + (unsigned)(b == 0xE8 ? 2 + (unsigned)prev : (b == 0xE9 ? 1 : 0));
|
||||
|
||||
_IF_BIT_0
|
||||
{
|
||||
_UPDATE_0
|
||||
continue;
|
||||
}
|
||||
_UPDATE_1
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (limit == 0 || outPos == outSize)
|
||||
break;
|
||||
{
|
||||
UInt32 val;
|
||||
unsigned cj = (p->temp[3] == 0xE8) ? BCJ2_STREAM_CALL : BCJ2_STREAM_JUMP;
|
||||
const Byte *cur = p->bufs[cj];
|
||||
Byte *dest;
|
||||
SizeT rem;
|
||||
|
||||
if (cur == p->lims[cj])
|
||||
{
|
||||
p->state = cj;
|
||||
break;
|
||||
}
|
||||
|
||||
val = GetBe32(cur);
|
||||
p->bufs[cj] = cur + 4;
|
||||
|
||||
b = buf0[inPos++];
|
||||
|
||||
if (b == 0xE8)
|
||||
prob = p + prevuint8_t;
|
||||
else if (b == 0xE9)
|
||||
prob = p + 256;
|
||||
else
|
||||
prob = p + 257;
|
||||
|
||||
ttt = *(prob);
|
||||
bound = (range >> kNumBitModelTotalBits) * ttt;
|
||||
|
||||
if (codes < bound)
|
||||
p->ip += 4;
|
||||
val -= p->ip;
|
||||
dest = p->dest;
|
||||
rem = p->destLim - dest;
|
||||
|
||||
if (rem < 4)
|
||||
{
|
||||
range = bound;
|
||||
*(prob) = (uint16_t)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
|
||||
|
||||
if (range < kTopValue)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
range <<= 8;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
prevuint8_t = b;
|
||||
p->temp[0] = (Byte)val; if (rem > 0) dest[0] = (Byte)val; val >>= 8;
|
||||
p->temp[1] = (Byte)val; if (rem > 1) dest[1] = (Byte)val; val >>= 8;
|
||||
p->temp[2] = (Byte)val; if (rem > 2) dest[2] = (Byte)val; val >>= 8;
|
||||
p->temp[3] = (Byte)val;
|
||||
p->dest = dest + rem;
|
||||
p->state = BCJ2_DEC_STATE_ORIG_0 + (unsigned)rem;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dest;
|
||||
const uint8_t *v;
|
||||
|
||||
SetUi32(dest, val);
|
||||
p->temp[3] = (Byte)(val >> 24);
|
||||
p->dest = dest + 4;
|
||||
}
|
||||
}
|
||||
|
||||
range -= bound;
|
||||
codes -= bound;
|
||||
*(prob) = (uint16_t)(ttt - (ttt >> kNumMoveBits));
|
||||
if (p->range < kTopValue && p->bufs[BCJ2_STREAM_RC] != p->lims[BCJ2_STREAM_RC])
|
||||
{
|
||||
p->range <<= 8;
|
||||
p->code = (p->code << 8) | *(p->bufs[BCJ2_STREAM_RC])++;
|
||||
}
|
||||
|
||||
if (range < kTopValue)
|
||||
{
|
||||
if (buffer == bufferLim)
|
||||
return SZ_ERROR_DATA;
|
||||
range <<= 8;
|
||||
codes = (codes << 8) | RC_READ_BYTE;
|
||||
}
|
||||
|
||||
if (b == 0xE8)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
}
|
||||
dest = (((uint32_t)v[0] << 24) | ((uint32_t)v[1] << 16) |
|
||||
((uint32_t)v[2] << 8) | ((uint32_t)v[3])) - ((uint32_t)outPos + 4);
|
||||
outBuf[outPos++] = (uint8_t)dest;
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (uint8_t)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (uint8_t)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevuint8_t = (uint8_t)(dest >> 24);
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
return SZ_OK;
|
||||
}
|
||||
Vendored
+133
-25
@@ -1,38 +1,146 @@
|
||||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
/* Bcj2.h -- BCJ2 Converter for x86 code
|
||||
2014-11-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define BCJ2_NUM_STREAMS 4
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_STREAM_MAIN,
|
||||
BCJ2_STREAM_CALL,
|
||||
BCJ2_STREAM_JUMP,
|
||||
BCJ2_STREAM_RC
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS,
|
||||
BCJ2_DEC_STATE_ORIG_1,
|
||||
BCJ2_DEC_STATE_ORIG_2,
|
||||
BCJ2_DEC_STATE_ORIG_3,
|
||||
|
||||
BCJ2_DEC_STATE_ORIG,
|
||||
BCJ2_DEC_STATE_OK
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS,
|
||||
BCJ2_ENC_STATE_OK
|
||||
};
|
||||
|
||||
|
||||
#define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP)
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
outSize <= FullOutputSize,
|
||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||
|
||||
If buf0 overlaps outBuf, there are two required conditions:
|
||||
1) (buf0 >= outBuf)
|
||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
CBcj2Dec / CBcj2Enc
|
||||
bufs sizes:
|
||||
BUF_SIZE(n) = lims[n] - bufs[n]
|
||||
bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be mutliply of 4:
|
||||
(BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0
|
||||
(BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0
|
||||
*/
|
||||
|
||||
int Bcj2_Decode(
|
||||
const uint8_t *buf0, size_t size0,
|
||||
const uint8_t *buf1, size_t size1,
|
||||
const uint8_t *buf2, size_t size2,
|
||||
const uint8_t *buf3, size_t size3,
|
||||
uint8_t *outBuf, size_t outSize);
|
||||
/*
|
||||
CBcj2Dec:
|
||||
dest is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions:
|
||||
bufs[BCJ2_STREAM_MAIN] >= dest &&
|
||||
bufs[BCJ2_STREAM_MAIN] - dest >= tempReserv +
|
||||
BUF_SIZE(BCJ2_STREAM_CALL) +
|
||||
BUF_SIZE(BCJ2_STREAM_JUMP)
|
||||
tempReserv = 0 : for first call of Bcj2Dec_Decode
|
||||
tempReserv = 4 : for any other calls of Bcj2Dec_Decode
|
||||
overlap with offset = 1 is not allowed
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
typedef struct
|
||||
{
|
||||
const Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
Byte *dest;
|
||||
const Byte *destLim;
|
||||
|
||||
unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */
|
||||
|
||||
UInt32 ip;
|
||||
Byte temp[4];
|
||||
UInt32 range;
|
||||
UInt32 code;
|
||||
UInt16 probs[2 + 256];
|
||||
} CBcj2Dec;
|
||||
|
||||
void Bcj2Dec_Init(CBcj2Dec *p);
|
||||
|
||||
/* Returns: SZ_OK or SZ_ERROR_DATA */
|
||||
SRes Bcj2Dec_Decode(CBcj2Dec *p);
|
||||
|
||||
#define Bcj2Dec_IsFinished(_p_) ((_p_)->code == 0)
|
||||
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCJ2_ENC_FINISH_MODE_CONTINUE,
|
||||
BCJ2_ENC_FINISH_MODE_END_BLOCK,
|
||||
BCJ2_ENC_FINISH_MODE_END_STREAM
|
||||
} EBcj2Enc_FinishMode;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *bufs[BCJ2_NUM_STREAMS];
|
||||
const Byte *lims[BCJ2_NUM_STREAMS];
|
||||
const Byte *src;
|
||||
const Byte *srcLim;
|
||||
|
||||
unsigned state;
|
||||
EBcj2Enc_FinishMode finishMode;
|
||||
|
||||
Byte prevByte;
|
||||
|
||||
Byte cache;
|
||||
UInt32 range;
|
||||
UInt64 low;
|
||||
UInt64 cacheSize;
|
||||
|
||||
UInt32 ip;
|
||||
|
||||
/* 32-bit ralative offset in JUMP/CALL commands is
|
||||
- (mod 4 GB) in 32-bit mode
|
||||
- signed Int32 in 64-bit mode
|
||||
We use (mod 4 GB) check for fileSize.
|
||||
Use fileSize up to 2 GB, if you want to support 32-bit and 64-bit code conversion. */
|
||||
UInt32 fileIp;
|
||||
UInt32 fileSize; /* (fileSize <= ((UInt32)1 << 31)), 0 means no_limit */
|
||||
UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)), 0 means desable_conversion */
|
||||
|
||||
UInt32 tempTarget;
|
||||
unsigned tempPos;
|
||||
Byte temp[4 * 2];
|
||||
|
||||
unsigned flushPos;
|
||||
|
||||
UInt16 probs[2 + 256];
|
||||
} CBcj2Enc;
|
||||
|
||||
void Bcj2Enc_Init(CBcj2Enc *p);
|
||||
void Bcj2Enc_Encode(CBcj2Enc *p);
|
||||
|
||||
#define Bcj2Enc_Get_InputData_Size(p) ((SizeT)((p)->srcLim - (p)->src) + (p)->tempPos)
|
||||
#define Bcj2Enc_IsFinished(p) ((p)->flushPos == 5)
|
||||
|
||||
|
||||
#define BCJ2_RELAT_LIMIT_NUM_BITS 26
|
||||
#define BCJ2_RELAT_LIMIT ((UInt32)1 << BCJ2_RELAT_LIMIT_NUM_BITS)
|
||||
|
||||
/* limit for CBcj2Enc::fileSize variable */
|
||||
#define BCJ2_FileSize_MAX ((UInt32)1 << 31)
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+212
-116
@@ -1,134 +1,230 @@
|
||||
/* Bra.c -- Converters for RISC code
|
||||
2010-04-16 : Igor Pavlov : Public domain */
|
||||
2017-04-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
size_t ARM_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 8;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if (data[i + 3] == 0xEB)
|
||||
{
|
||||
uint32_t dest;
|
||||
uint32_t src = ((uint32_t)data[i + 2] << 16) | ((uint32_t)data[i + 1] << 8) | (data[i + 0]);
|
||||
src <<= 2;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
dest >>= 2;
|
||||
data[i + 2] = (uint8_t)(dest >> 16);
|
||||
data[i + 1] = (uint8_t)(dest >> 8);
|
||||
data[i + 0] = (uint8_t)dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip += 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v += ip + (UInt32)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
if (p[-1] == 0xEB)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetUi32(p - 4);
|
||||
v <<= 2;
|
||||
v -= ip + (UInt32)(p - data);
|
||||
v >>= 2;
|
||||
v &= 0x00FFFFFF;
|
||||
v |= 0xEB000000;
|
||||
SetUi32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t ARMT_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 4;
|
||||
for (i = 0; i <= size; i += 2)
|
||||
{
|
||||
if ((data[i + 1] & 0xF8) == 0xF0 &&
|
||||
(data[i + 3] & 0xF8) == 0xF8)
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)1;
|
||||
p = data;
|
||||
lim = data + size - 4;
|
||||
|
||||
if (encoding)
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b1;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v =
|
||||
((UInt32)b1 << 19)
|
||||
+ (((UInt32)p[1] & 0x7) << 8)
|
||||
+ (((UInt32)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
uint32_t dest;
|
||||
uint32_t src =
|
||||
(((uint32_t)data[i + 1] & 0x7) << 19) |
|
||||
((uint32_t)data[i + 0] << 11) |
|
||||
(((uint32_t)data[i + 3] & 0x7) << 8) |
|
||||
(data[i + 2]);
|
||||
|
||||
src <<= 1;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
dest >>= 1;
|
||||
|
||||
data[i + 1] = (uint8_t)(0xF0 | ((dest >> 19) & 0x7));
|
||||
data[i + 0] = (uint8_t)(dest >> 11);
|
||||
data[i + 3] = (uint8_t)(0xF8 | ((dest >> 8) & 0x7));
|
||||
data[i + 2] = (uint8_t)dest;
|
||||
i += 2;
|
||||
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
|
||||
v += cur;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b1;
|
||||
for (;;)
|
||||
{
|
||||
UInt32 b3;
|
||||
if (p > lim)
|
||||
return p - data;
|
||||
b1 = p[1];
|
||||
b3 = p[3];
|
||||
p += 2;
|
||||
b1 ^= 8;
|
||||
if ((b3 & b1) >= 0xF8)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v =
|
||||
((UInt32)b1 << 19)
|
||||
+ (((UInt32)p[1] & 0x7) << 8)
|
||||
+ (((UInt32)p[-2] << 11))
|
||||
+ (p[0]);
|
||||
|
||||
p += 2;
|
||||
{
|
||||
UInt32 cur = (ip + (UInt32)(p - data)) >> 1;
|
||||
v -= cur;
|
||||
}
|
||||
|
||||
/*
|
||||
SetUi16(p - 4, (UInt16)(((v >> 11) & 0x7FF) | 0xF000));
|
||||
SetUi16(p - 2, (UInt16)(v | 0xF800));
|
||||
*/
|
||||
|
||||
p[-4] = (Byte)(v >> 11);
|
||||
p[-3] = (Byte)(0xF0 | ((v >> 19) & 0x7));
|
||||
p[-2] = (Byte)v;
|
||||
p[-1] = (Byte)(0xF8 | (v >> 8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t PPC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
{
|
||||
size_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if ((data[i] >> 2) == 0x12 && (data[i + 3] & 3) == 1)
|
||||
{
|
||||
uint32_t src = ((uint32_t)(data[i + 0] & 3) << 24) |
|
||||
((uint32_t)data[i + 1] << 16) |
|
||||
((uint32_t)data[i + 2] << 8) |
|
||||
((uint32_t)data[i + 3] & (~3));
|
||||
|
||||
uint32_t dest;
|
||||
if (encoding)
|
||||
dest = ip + (uint32_t)i + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)i);
|
||||
data[i + 0] = (uint8_t)(0x48 | ((dest >> 24) & 0x3));
|
||||
data[i + 1] = (uint8_t)(dest >> 16);
|
||||
data[i + 2] = (uint8_t)(dest >> 8);
|
||||
data[i + 3] &= 0x3;
|
||||
data[i + 3] |= dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
p += 4;
|
||||
/* if ((v & 0xFC000003) == 0x48000001) */
|
||||
if ((p[-4] & 0xFC) == 0x48 && (p[-1] & 3) == 1)
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetBe32(p - 4);
|
||||
if (encoding)
|
||||
v += ip + (UInt32)(p - data);
|
||||
else
|
||||
v -= ip + (UInt32)(p - data);
|
||||
v &= 0x03FFFFFF;
|
||||
v |= 0x48000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t SPARC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding)
|
||||
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
uint32_t i;
|
||||
if (size < 4)
|
||||
return 0;
|
||||
size -= 4;
|
||||
for (i = 0; i <= size; i += 4)
|
||||
{
|
||||
if ((data[i] == 0x40 && (data[i + 1] & 0xC0) == 0x00) ||
|
||||
(data[i] == 0x7F && (data[i + 1] & 0xC0) == 0xC0))
|
||||
{
|
||||
uint32_t src =
|
||||
((uint32_t)data[i + 0] << 24) |
|
||||
((uint32_t)data[i + 1] << 16) |
|
||||
((uint32_t)data[i + 2] << 8) |
|
||||
((uint32_t)data[i + 3]);
|
||||
uint32_t dest;
|
||||
Byte *p;
|
||||
const Byte *lim;
|
||||
size &= ~(size_t)3;
|
||||
ip -= 4;
|
||||
p = data;
|
||||
lim = data + size;
|
||||
|
||||
src <<= 2;
|
||||
if (encoding)
|
||||
dest = ip + i + src;
|
||||
else
|
||||
dest = src - (ip + i);
|
||||
dest >>= 2;
|
||||
|
||||
dest = (((0 - ((dest >> 22) & 1)) << 22) & 0x3FFFFFFF) | (dest & 0x3FFFFF) | 0x40000000;
|
||||
|
||||
data[i + 0] = (uint8_t)(dest >> 24);
|
||||
data[i + 1] = (uint8_t)(dest >> 16);
|
||||
data[i + 2] = (uint8_t)(dest >> 8);
|
||||
data[i + 3] = (uint8_t)dest;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
for (;;)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
if (p >= lim)
|
||||
return p - data;
|
||||
/*
|
||||
v = GetBe32(p);
|
||||
p += 4;
|
||||
m = v + ((UInt32)5 << 29);
|
||||
m ^= (UInt32)7 << 29;
|
||||
m += (UInt32)1 << 22;
|
||||
if ((m & ((UInt32)0x1FF << 23)) == 0)
|
||||
break;
|
||||
*/
|
||||
p += 4;
|
||||
if ((p[-4] == 0x40 && (p[-3] & 0xC0) == 0) ||
|
||||
(p[-4] == 0x7F && (p[-3] >= 0xC0)))
|
||||
break;
|
||||
}
|
||||
{
|
||||
UInt32 v = GetBe32(p - 4);
|
||||
v <<= 2;
|
||||
if (encoding)
|
||||
v += ip + (UInt32)(p - data);
|
||||
else
|
||||
v -= ip + (UInt32)(p - data);
|
||||
|
||||
v &= 0x01FFFFFF;
|
||||
v -= (UInt32)1 << 24;
|
||||
v ^= 0xFF000000;
|
||||
v >>= 2;
|
||||
v |= 0x40000000;
|
||||
SetBe32(p - 4, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+46
-50
@@ -1,68 +1,64 @@
|
||||
/* Bra.h -- Branch converters for executables
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
Returns:
|
||||
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.
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Returns:
|
||||
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.
|
||||
Example:
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Example:
|
||||
|
||||
uint32_t ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
size_t processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
UInt32 ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
SizeT processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
*/
|
||||
|
||||
#define x86_Convert_Init(state) { state = 0; }
|
||||
size_t x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state, int encoding);
|
||||
size_t ARM_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t ARMT_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t PPC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t SPARC_Convert(uint8_t *data, size_t size, uint32_t ip, int encoding);
|
||||
size_t IA64_Convert(uint8_t *data, size_t size, uint32_t ip, 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 ARMT_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 IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+66
-70
@@ -1,86 +1,82 @@
|
||||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include "Bra.h"
|
||||
|
||||
#define Test86MSuint8_t(b) ((b) == 0 || (b) == 0xFF)
|
||||
#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0)
|
||||
|
||||
const uint8_t kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||
const uint8_t kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
|
||||
size_t x86_Convert(uint8_t *data, size_t size, uint32_t ip, uint32_t *state, int encoding)
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
size_t bufferPos = 0, prevPosT;
|
||||
uint32_t prevMask = *state & 0x7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
ip += 5;
|
||||
prevPosT = (size_t)0 - 1;
|
||||
SizeT pos = 0;
|
||||
UInt32 mask = *state & 7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
size -= 4;
|
||||
ip += 5;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *p = data + bufferPos;
|
||||
uint8_t *limit = data + size - 4;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (size_t)(p - data);
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + pos;
|
||||
const Byte *limit = data + size;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT d = (SizeT)(p - data - pos);
|
||||
pos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
{
|
||||
*state = (d > 2 ? 0 : mask >> (unsigned)d);
|
||||
return pos;
|
||||
}
|
||||
if (d > 2)
|
||||
mask = 0;
|
||||
else
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
{
|
||||
uint8_t b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSuint8_t(b))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mask >>= (unsigned)d;
|
||||
if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1])))
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos;
|
||||
}
|
||||
|
||||
if (Test86MSuint8_t(p[4]))
|
||||
{
|
||||
uint32_t src = ((uint32_t)p[4] << 24) | ((uint32_t)p[3] << 16) | ((uint32_t)p[2] << 8) | ((uint32_t)p[1]);
|
||||
uint32_t dest;
|
||||
for (;;)
|
||||
{
|
||||
uint8_t b;
|
||||
int idx;
|
||||
if (encoding)
|
||||
dest = (ip + (uint32_t)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (uint32_t)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
idx = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (uint8_t)(dest >> (24 - idx));
|
||||
if (!Test86MSuint8_t(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - idx)) - 1);
|
||||
}
|
||||
p[4] = (uint8_t)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (uint8_t)(dest >> 16);
|
||||
p[2] = (uint8_t)(dest >> 8);
|
||||
p[1] = (uint8_t)dest;
|
||||
bufferPos += 5;
|
||||
}
|
||||
if (Test86MSByte(p[4]))
|
||||
{
|
||||
UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||
UInt32 cur = ip + (UInt32)pos;
|
||||
pos += 5;
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
if (mask != 0)
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
unsigned sh = (mask & 6) << 2;
|
||||
if (Test86MSByte((Byte)(v >> sh)))
|
||||
{
|
||||
v ^= (((UInt32)0x100 << sh) - 1);
|
||||
if (encoding)
|
||||
v += cur;
|
||||
else
|
||||
v -= cur;
|
||||
}
|
||||
mask = 0;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
p[1] = (Byte)v;
|
||||
p[2] = (Byte)(v >> 8);
|
||||
p[3] = (Byte)(v >> 16);
|
||||
p[4] = (Byte)(0 - ((v >> 24) & 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = (mask >> 1) | 4;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+53
@@ -0,0 +1,53 @@
|
||||
/* BraIA64.c -- Converter for IA-64 code
|
||||
2017-01-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
#include "Bra.h"
|
||||
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding)
|
||||
{
|
||||
SizeT i;
|
||||
if (size < 16)
|
||||
return 0;
|
||||
size -= 16;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
unsigned m = ((UInt32)0x334B0000 >> (data[i] & 0x1E)) & 3;
|
||||
if (m)
|
||||
{
|
||||
m++;
|
||||
do
|
||||
{
|
||||
Byte *p = data + (i + (size_t)m * 5 - 8);
|
||||
if (((p[3] >> m) & 15) == 5
|
||||
&& (((p[-1] | ((UInt32)p[0] << 8)) >> m) & 0x70) == 0)
|
||||
{
|
||||
unsigned raw = GetUi32(p);
|
||||
unsigned v = raw >> m;
|
||||
v = (v & 0xFFFFF) | ((v & (1 << 23)) >> 3);
|
||||
|
||||
v <<= 4;
|
||||
if (encoding)
|
||||
v += ip + (UInt32)i;
|
||||
else
|
||||
v -= ip + (UInt32)i;
|
||||
v >>= 4;
|
||||
|
||||
v &= 0x1FFFFF;
|
||||
v += 0x700000;
|
||||
v &= 0x8FFFFF;
|
||||
raw &= ~((UInt32)0x8FFFFF << m);
|
||||
raw |= (v << m);
|
||||
SetUi32(p, raw);
|
||||
}
|
||||
}
|
||||
while (++m <= 4);
|
||||
}
|
||||
i += 16;
|
||||
}
|
||||
while (i <= size);
|
||||
return i;
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
/* Compiler.h
|
||||
2017-04-03 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_COMPILER_H
|
||||
#define __7Z_COMPILER_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#ifdef UNDER_CE
|
||||
#define RPC_NO_WINDOWS_H
|
||||
/* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */
|
||||
#pragma warning(disable : 4201) /* nonstandard extension used : nameless struct/union */
|
||||
#pragma warning(disable : 4214) /* nonstandard extension used : bit field types other than int */
|
||||
#endif
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#pragma warning(disable : 4996) /* This function or variable may be unsafe */
|
||||
#else
|
||||
#pragma warning(disable : 4511) /* copy constructor could not be generated */
|
||||
#pragma warning(disable : 4512) /* assignment operator could not be generated */
|
||||
#pragma warning(disable : 4514) /* unreferenced inline function has been removed */
|
||||
#pragma warning(disable : 4702) /* unreachable code */
|
||||
#pragma warning(disable : 4710) /* not inlined */
|
||||
#pragma warning(disable : 4714) /* function marked as __forceinline not inlined */
|
||||
#pragma warning(disable : 4786) /* identifier was truncated to '255' characters in the debug information */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNUSED_VAR(x) (void)x;
|
||||
/* #define UNUSED_VAR(x) x=x; */
|
||||
|
||||
#endif
|
||||
Vendored
+218
@@ -0,0 +1,218 @@
|
||||
/* CpuArch.c -- CPU specific code
|
||||
2018-02-18: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "CpuArch.h"
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
#if (defined(_MSC_VER) && !defined(MY_CPU_AMD64)) || defined(__GNUC__)
|
||||
#define USE_ASM
|
||||
#endif
|
||||
|
||||
#if !defined(USE_ASM) && _MSC_VER >= 1500
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(USE_ASM) && !defined(MY_CPU_AMD64)
|
||||
static UInt32 CheckFlag(UInt32 flag)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
__asm pushfd;
|
||||
__asm pop EAX;
|
||||
__asm mov EDX, EAX;
|
||||
__asm xor EAX, flag;
|
||||
__asm push EAX;
|
||||
__asm popfd;
|
||||
__asm pushfd;
|
||||
__asm pop EAX;
|
||||
__asm xor EAX, EDX;
|
||||
__asm push EDX;
|
||||
__asm popfd;
|
||||
__asm and flag, EAX;
|
||||
#else
|
||||
__asm__ __volatile__ (
|
||||
"pushf\n\t"
|
||||
"pop %%EAX\n\t"
|
||||
"movl %%EAX,%%EDX\n\t"
|
||||
"xorl %0,%%EAX\n\t"
|
||||
"push %%EAX\n\t"
|
||||
"popf\n\t"
|
||||
"pushf\n\t"
|
||||
"pop %%EAX\n\t"
|
||||
"xorl %%EDX,%%EAX\n\t"
|
||||
"push %%EDX\n\t"
|
||||
"popf\n\t"
|
||||
"andl %%EAX, %0\n\t":
|
||||
"=c" (flag) : "c" (flag) :
|
||||
"%eax", "%edx");
|
||||
#endif
|
||||
return flag;
|
||||
}
|
||||
#define CHECK_CPUID_IS_SUPPORTED if (CheckFlag(1 << 18) == 0 || CheckFlag(1 << 21) == 0) return False;
|
||||
#else
|
||||
#define CHECK_CPUID_IS_SUPPORTED
|
||||
#endif
|
||||
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d)
|
||||
{
|
||||
#ifdef USE_ASM
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
UInt32 a2, b2, c2, d2;
|
||||
__asm xor EBX, EBX;
|
||||
__asm xor ECX, ECX;
|
||||
__asm xor EDX, EDX;
|
||||
__asm mov EAX, function;
|
||||
__asm cpuid;
|
||||
__asm mov a2, EAX;
|
||||
__asm mov b2, EBX;
|
||||
__asm mov c2, ECX;
|
||||
__asm mov d2, EDX;
|
||||
|
||||
*a = a2;
|
||||
*b = b2;
|
||||
*c = c2;
|
||||
*d = d2;
|
||||
|
||||
#else
|
||||
|
||||
__asm__ __volatile__ (
|
||||
#if defined(MY_CPU_AMD64) && defined(__PIC__)
|
||||
"mov %%rbx, %%rdi;"
|
||||
"cpuid;"
|
||||
"xchg %%rbx, %%rdi;"
|
||||
: "=a" (*a) ,
|
||||
"=D" (*b) ,
|
||||
#elif defined(MY_CPU_X86) && defined(__PIC__)
|
||||
"mov %%ebx, %%edi;"
|
||||
"cpuid;"
|
||||
"xchgl %%ebx, %%edi;"
|
||||
: "=a" (*a) ,
|
||||
"=D" (*b) ,
|
||||
#else
|
||||
"cpuid"
|
||||
: "=a" (*a) ,
|
||||
"=b" (*b) ,
|
||||
#endif
|
||||
"=c" (*c) ,
|
||||
"=d" (*d)
|
||||
: "0" (function)) ;
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, function);
|
||||
*a = CPUInfo[0];
|
||||
*b = CPUInfo[1];
|
||||
*c = CPUInfo[2];
|
||||
*d = CPUInfo[3];
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p)
|
||||
{
|
||||
CHECK_CPUID_IS_SUPPORTED
|
||||
MyCPUID(0, &p->maxFunc, &p->vendor[0], &p->vendor[2], &p->vendor[1]);
|
||||
MyCPUID(1, &p->ver, &p->b, &p->c, &p->d);
|
||||
return True;
|
||||
}
|
||||
|
||||
static const UInt32 kVendors[][3] =
|
||||
{
|
||||
{ 0x756E6547, 0x49656E69, 0x6C65746E},
|
||||
{ 0x68747541, 0x69746E65, 0x444D4163},
|
||||
{ 0x746E6543, 0x48727561, 0x736C7561}
|
||||
};
|
||||
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < sizeof(kVendors) / sizeof(kVendors[i]); i++)
|
||||
{
|
||||
const UInt32 *v = kVendors[i];
|
||||
if (v[0] == p->vendor[0] &&
|
||||
v[1] == p->vendor[1] &&
|
||||
v[2] == p->vendor[2])
|
||||
return (int)i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
BoolInt CPU_Is_InOrder(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
int firm;
|
||||
UInt32 family, model;
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return True;
|
||||
|
||||
family = x86cpuid_GetFamily(p.ver);
|
||||
model = x86cpuid_GetModel(p.ver);
|
||||
|
||||
firm = x86cpuid_GetFirm(&p);
|
||||
|
||||
switch (firm)
|
||||
{
|
||||
case CPU_FIRM_INTEL: return (family < 6 || (family == 6 && (
|
||||
/* In-Order Atom CPU */
|
||||
model == 0x1C /* 45 nm, N4xx, D4xx, N5xx, D5xx, 230, 330 */
|
||||
|| model == 0x26 /* 45 nm, Z6xx */
|
||||
|| model == 0x27 /* 32 nm, Z2460 */
|
||||
|| model == 0x35 /* 32 nm, Z2760 */
|
||||
|| model == 0x36 /* 32 nm, N2xxx, D2xxx */
|
||||
)));
|
||||
case CPU_FIRM_AMD: return (family < 5 || (family == 5 && (model < 6 || model == 0xA)));
|
||||
case CPU_FIRM_VIA: return (family < 6 || (family == 6 && model < 0xF));
|
||||
}
|
||||
return True;
|
||||
}
|
||||
|
||||
#if !defined(MY_CPU_AMD64) && defined(_WIN32)
|
||||
#include <windows.h>
|
||||
static BoolInt CPU_Sys_Is_SSE_Supported(void)
|
||||
{
|
||||
OSVERSIONINFO vi;
|
||||
vi.dwOSVersionInfoSize = sizeof(vi);
|
||||
if (!GetVersionEx(&vi))
|
||||
return False;
|
||||
return (vi.dwMajorVersion >= 5);
|
||||
}
|
||||
#define CHECK_SYS_SSE_SUPPORT if (!CPU_Sys_Is_SSE_Supported()) return False;
|
||||
#else
|
||||
#define CHECK_SYS_SSE_SUPPORT
|
||||
#endif
|
||||
|
||||
BoolInt CPU_Is_Aes_Supported(void)
|
||||
{
|
||||
Cx86cpuid p;
|
||||
CHECK_SYS_SSE_SUPPORT
|
||||
if (!x86cpuid_CheckAndRead(&p))
|
||||
return False;
|
||||
return (p.c >> 25) & 1;
|
||||
}
|
||||
|
||||
BoolInt CPU_IsSupported_PageGB(void)
|
||||
{
|
||||
Cx86cpuid cpuid;
|
||||
if (!x86cpuid_CheckAndRead(&cpuid))
|
||||
return False;
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(0x80000000, &d[0], &d[1], &d[2], &d[3]);
|
||||
if (d[0] < 0x80000001)
|
||||
return False;
|
||||
}
|
||||
{
|
||||
UInt32 d[4] = { 0 };
|
||||
MyCPUID(0x80000001, &d[0], &d[1], &d[2], &d[3]);
|
||||
return (d[3] >> 26) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Vendored
+309
-29
@@ -1,56 +1,336 @@
|
||||
/* CpuArch.h -- CPU specific code
|
||||
2010-10-26: Igor Pavlov : Public domain */
|
||||
2018-02-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __CPU_ARCH_H
|
||||
#define __CPU_ARCH_H
|
||||
|
||||
#include <retro_endianness.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* 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.
|
||||
/*
|
||||
MY_CPU_LE means that CPU is LITTLE ENDIAN.
|
||||
MY_CPU_BE means that CPU is BIG ENDIAN.
|
||||
If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform.
|
||||
|
||||
MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses.
|
||||
*/
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(__x86_64__)
|
||||
#define MY_CPU_AMD64
|
||||
#if defined(_M_X64) \
|
||||
|| defined(_M_AMD64) \
|
||||
|| defined(__x86_64__) \
|
||||
|| defined(__AMD64__) \
|
||||
|| defined(__amd64__)
|
||||
#define MY_CPU_AMD64
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "x32"
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_AMD64) || defined(_M_IA64)
|
||||
#define MY_CPU_64BIT
|
||||
|
||||
#if defined(_M_IX86) \
|
||||
|| defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
#define MY_CPU_NAME "x86"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define MY_CPU_X86
|
||||
|
||||
#if defined(_M_ARM64) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__aarch64__)
|
||||
#define MY_CPU_ARM64
|
||||
#define MY_CPU_NAME "arm64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM) \
|
||||
|| defined(_M_ARM_NT) \
|
||||
|| defined(_M_ARMT) \
|
||||
|| defined(__arm__) \
|
||||
|| defined(__thumb__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__THUMBEB__)
|
||||
#define MY_CPU_ARM
|
||||
#define MY_CPU_NAME "arm"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_IA64) \
|
||||
|| defined(__ia64__)
|
||||
#define MY_CPU_IA64
|
||||
#define MY_CPU_NAME "ia64"
|
||||
#define MY_CPU_64BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__mips64) \
|
||||
|| defined(__mips64__) \
|
||||
|| (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3))
|
||||
#define MY_CPU_NAME "mips64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__mips__)
|
||||
#define MY_CPU_NAME "mips"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__ppc64__) \
|
||||
|| defined(__powerpc64__)
|
||||
#ifdef __ILP32__
|
||||
#define MY_CPU_NAME "ppc64-32"
|
||||
#else
|
||||
#define MY_CPU_NAME "ppc64"
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__ppc__) \
|
||||
|| defined(__powerpc__)
|
||||
#define MY_CPU_NAME "ppc"
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__sparc64__)
|
||||
#define MY_CPU_NAME "sparc64"
|
||||
#define MY_CPU_64BIT
|
||||
#elif defined(__sparc__)
|
||||
#define MY_CPU_NAME "sparc"
|
||||
/* #define MY_CPU_32BIT */
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64)
|
||||
#define MY_CPU_X86_OR_AMD64
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86) || defined(_M_ARM)
|
||||
#define MY_CPU_32BIT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && defined(_M_ARM)
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_WIN32) && defined(_M_IA64)
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
#ifdef MY_CPU_ARM
|
||||
#define MY_CPU_ARM_LE
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#ifdef MY_CPU_ARM64
|
||||
#define MY_CPU_ARM64_LE
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#ifdef _M_IA64
|
||||
#define MY_CPU_IA64_LE
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_LE) \
|
||||
|| defined(MY_CPU_ARM64_LE) \
|
||||
|| defined(MY_CPU_IA64_LE) \
|
||||
|| defined(__LITTLE_ENDIAN__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
|| defined(__AARCH64EL__) \
|
||||
|| defined(__MIPSEL__) \
|
||||
|| defined(__MIPSEL) \
|
||||
|| defined(_MIPSEL) \
|
||||
|| defined(__BFIN__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
#define MY_CPU_LE
|
||||
#endif
|
||||
|
||||
#if defined(__BIG_ENDIAN__) \
|
||||
|| defined(__ARMEB__) \
|
||||
|| defined(__THUMBEB__) \
|
||||
|| defined(__AARCH64EB__) \
|
||||
|| defined(__MIPSEB__) \
|
||||
|| defined(__MIPSEB) \
|
||||
|| defined(_MIPSEB) \
|
||||
|| defined(__m68k__) \
|
||||
|| defined(__s390__) \
|
||||
|| defined(__s390x__) \
|
||||
|| defined(__zarch__) \
|
||||
|| (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define MY_CPU_BE
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_LE) && defined(MY_CPU_BE)
|
||||
#error Stop_Compiling_Bad_Endian
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT)
|
||||
#error Stop_Compiling_Bad_32_64_BIT
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef MY_CPU_NAME
|
||||
#ifdef MY_CPU_LE
|
||||
#define MY_CPU_NAME "LE"
|
||||
#elif defined(MY_CPU_BE)
|
||||
#define MY_CPU_NAME "BE"
|
||||
#else
|
||||
/*
|
||||
#define MY_CPU_NAME ""
|
||||
*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM64) \
|
||||
|| defined(__ARM_FEATURE_UNALIGNED)
|
||||
#define MY_CPU_LE_UNALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MY_CPU_LE_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(const void *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(const void *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(const void *)(p))
|
||||
|
||||
#define SetUi16(p, v) { *(UInt16 *)(p) = (v); }
|
||||
#define SetUi32(p, v) { *(UInt32 *)(p) = (v); }
|
||||
#define SetUi64(p, v) { *(UInt64 *)(p) = (v); }
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) ( (UInt16) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt16)((const Byte *)(p))[1] << 8) ))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); }
|
||||
|
||||
#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)_vvv_; \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[3] = (Byte)(_vvv_ >> 24); }
|
||||
|
||||
#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \
|
||||
SetUi32(_ppp2_ , (UInt32)_vvv2_); \
|
||||
SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __has_builtin
|
||||
#define MY__has_builtin(x) __has_builtin(x)
|
||||
#else
|
||||
#define MY__has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300)
|
||||
|
||||
/* Note: we use bswap instruction, that is unsupported in 386 cpu */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#pragma intrinsic(_byteswap_ushort)
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
|
||||
/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v)
|
||||
|
||||
#elif defined(MY_CPU_LE_UNALIGN) && ( \
|
||||
(defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \
|
||||
|| (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) )
|
||||
|
||||
/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */
|
||||
#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v)
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||
((const Byte *)(p))[3] )
|
||||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \
|
||||
_ppp_[0] = (Byte)(_vvv_ >> 24); \
|
||||
_ppp_[1] = (Byte)(_vvv_ >> 16); \
|
||||
_ppp_[2] = (Byte)(_vvv_ >> 8); \
|
||||
_ppp_[3] = (Byte)_vvv_; }
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef GetBe16
|
||||
|
||||
#define GetBe16(p) ( (UInt16) ( \
|
||||
((UInt16)((const Byte *)(p))[0] << 8) | \
|
||||
((const Byte *)(p))[1] ))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 maxFunc;
|
||||
UInt32 vendor[3];
|
||||
UInt32 ver;
|
||||
UInt32 b;
|
||||
UInt32 c;
|
||||
UInt32 d;
|
||||
} Cx86cpuid;
|
||||
|
||||
enum
|
||||
{
|
||||
CPU_FIRM_INTEL,
|
||||
CPU_FIRM_AMD,
|
||||
CPU_FIRM_VIA
|
||||
};
|
||||
|
||||
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
|
||||
|
||||
BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
|
||||
int x86cpuid_GetFirm(const Cx86cpuid *p);
|
||||
|
||||
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
|
||||
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
|
||||
#define x86cpuid_GetStepping(ver) (ver & 0xF)
|
||||
|
||||
BoolInt CPU_Is_InOrder(void);
|
||||
BoolInt CPU_Is_Aes_Supported(void);
|
||||
BoolInt CPU_IsSupported_PageGB(void);
|
||||
|
||||
#endif
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+64
@@ -0,0 +1,64 @@
|
||||
/* Delta.c -- Delta converter
|
||||
2009-05-26 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#include "Delta.h"
|
||||
|
||||
void Delta_Init(Byte *state)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < DELTA_STATE_SIZE; i++)
|
||||
state[i] = 0;
|
||||
}
|
||||
|
||||
static void MyMemCpy(Byte *dest, const Byte *src, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < size; i++)
|
||||
dest[i] = src[i];
|
||||
}
|
||||
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
Byte b = data[i];
|
||||
data[i] = (Byte)(b - buf[j]);
|
||||
buf[j] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size)
|
||||
{
|
||||
Byte buf[DELTA_STATE_SIZE];
|
||||
unsigned j = 0;
|
||||
MyMemCpy(buf, state, delta);
|
||||
{
|
||||
SizeT i;
|
||||
for (i = 0; i < size;)
|
||||
{
|
||||
for (j = 0; j < delta && i < size; i++, j++)
|
||||
{
|
||||
buf[j] = data[i] = (Byte)(buf[j] + data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j == delta)
|
||||
j = 0;
|
||||
MyMemCpy(state, buf + j, delta - j);
|
||||
MyMemCpy(state + delta - j, buf, j);
|
||||
}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
/* Delta.h -- Delta converter
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __DELTA_H
|
||||
#define __DELTA_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
#define DELTA_STATE_SIZE 256
|
||||
|
||||
void Delta_Init(Byte *state);
|
||||
void Delta_Encode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
void Delta_Decode(Byte *state, unsigned delta, Byte *data, SizeT size);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+478
-181
File diff suppressed because it is too large.
Load diff
Vendored
+50
-46
@@ -1,5 +1,5 @@
|
||||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2015-10-15 : Igor Pavlov : Public domain */
|
||||
2017-06-10 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZ_FIND_H
|
||||
#define __LZ_FIND_H
|
||||
@@ -8,45 +8,47 @@
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
typedef uint32_t CLzRef;
|
||||
typedef UInt32 CLzRef;
|
||||
|
||||
typedef struct _CMatchFinder
|
||||
{
|
||||
unsigned char *buffer;
|
||||
uint32_t pos;
|
||||
uint32_t posLimit;
|
||||
uint32_t streamPos;
|
||||
uint32_t lenLimit;
|
||||
Byte *buffer;
|
||||
UInt32 pos;
|
||||
UInt32 posLimit;
|
||||
UInt32 streamPos;
|
||||
UInt32 lenLimit;
|
||||
|
||||
uint32_t cyclicBufferPos;
|
||||
uint32_t cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
UInt32 cyclicBufferPos;
|
||||
UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
unsigned char streamEndWasReached;
|
||||
unsigned char btMode;
|
||||
unsigned char bigHash;
|
||||
unsigned char directInput;
|
||||
Byte streamEndWasReached;
|
||||
Byte btMode;
|
||||
Byte bigHash;
|
||||
Byte directInput;
|
||||
|
||||
uint32_t matchMaxLen;
|
||||
UInt32 matchMaxLen;
|
||||
CLzRef *hash;
|
||||
CLzRef *son;
|
||||
uint32_t hashMask;
|
||||
uint32_t cutValue;
|
||||
UInt32 hashMask;
|
||||
UInt32 cutValue;
|
||||
|
||||
unsigned char *bufferBase;
|
||||
Byte *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
|
||||
UInt32 blockSize;
|
||||
UInt32 keepSizeBefore;
|
||||
UInt32 keepSizeAfter;
|
||||
|
||||
uint32_t blockSize;
|
||||
uint32_t keepSizeBefore;
|
||||
uint32_t keepSizeAfter;
|
||||
|
||||
uint32_t numHashBytes;
|
||||
UInt32 numHashBytes;
|
||||
size_t directInputRem;
|
||||
uint32_t historySize;
|
||||
uint32_t fixedHashSize;
|
||||
uint32_t hashSizeSum;
|
||||
UInt32 historySize;
|
||||
UInt32 fixedHashSize;
|
||||
UInt32 hashSizeSum;
|
||||
SRes result;
|
||||
uint32_t crc[256];
|
||||
UInt32 crc[256];
|
||||
size_t numRefs;
|
||||
|
||||
UInt64 expectedDataSize;
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
@@ -57,9 +59,9 @@ typedef struct _CMatchFinder
|
||||
((p)->streamEndWasReached \
|
||||
&& (p)->streamPos == (p)->pos \
|
||||
&& (!(p)->directInput || (p)->directInputRem == 0))
|
||||
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
unsigned char *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||
|
||||
@@ -69,16 +71,16 @@ void MatchFinder_Construct(CMatchFinder *p);
|
||||
historySize <= 3 GB
|
||||
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||
*/
|
||||
int MatchFinder_Create(CMatchFinder *p, uint32_t historySize,
|
||||
uint32_t keepAddBufferBefore, uint32_t matchMaxLen, uint32_t keepAddBufferAfter,
|
||||
ISzAlloc *alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
|
||||
void MatchFinder_Normalize3(uint32_t subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, uint32_t subValue);
|
||||
int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
|
||||
UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
|
||||
ISzAllocPtr alloc);
|
||||
void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc);
|
||||
void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
|
||||
|
||||
uint32_t * GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos, const unsigned char *buffer, CLzRef *son,
|
||||
uint32_t _cyclicBufferPos, uint32_t _cyclicBufferSize, uint32_t _cutValue,
|
||||
uint32_t *distances, uint32_t maxLen);
|
||||
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
|
||||
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
|
||||
UInt32 *distances, UInt32 maxLen);
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
@@ -87,10 +89,10 @@ Conditions:
|
||||
*/
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef uint32_t (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const unsigned char * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef uint32_t (*Mf_GetMatches_Func)(void *object, uint32_t *distances);
|
||||
typedef void (*Mf_Skip_Func)(void *object, uint32_t);
|
||||
typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
|
||||
typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
|
||||
typedef void (*Mf_Skip_Func)(void *object, UInt32);
|
||||
|
||||
typedef struct _IMatchFinder
|
||||
{
|
||||
@@ -103,14 +105,16 @@ typedef struct _IMatchFinder
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
void MatchFinder_Init_2(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init_LowHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_HighHash(CMatchFinder *p);
|
||||
void MatchFinder_Init_3(CMatchFinder *p, int readData);
|
||||
void MatchFinder_Init(CMatchFinder *p);
|
||||
|
||||
uint32_t Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances);
|
||||
uint32_t Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances);
|
||||
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num);
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
Vendored
+13
-12
@@ -12,44 +12,45 @@
|
||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hv = cur[0] | ((uint32_t)cur[1] << 8);
|
||||
#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8);
|
||||
|
||||
#define HASH3_CALC { \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
hv = (temp ^ ((uint32_t)cur[2] << 8)) & p->hashMask; }
|
||||
hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
|
||||
|
||||
#define HASH4_CALC { \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((uint32_t)cur[2] << 8); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
|
||||
|
||||
#define HASH5_CALC { \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((uint32_t)cur[2] << 8); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
temp ^= (p->crc[cur[3]] << 5); \
|
||||
h4 = temp & (kHash4Size - 1); \
|
||||
hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; }
|
||||
|
||||
#define HASH_ZIP_CALC hv = ((cur[2] | ((uint32_t)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
|
||||
#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
|
||||
#define MT_HASH2_CALC \
|
||||
h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC { \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
h3 = (temp ^ ((uint32_t)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
|
||||
|
||||
#define MT_HASH4_CALC { \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
h2 = temp & (kHash2Size - 1); \
|
||||
temp ^= ((uint32_t)cur[2] << 8); \
|
||||
temp ^= ((UInt32)cur[2] << 8); \
|
||||
h3 = temp & (kHash3Size - 1); \
|
||||
h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
|
||||
|
||||
|
||||
Vendored
+439
-308
@@ -1,357 +1,488 @@
|
||||
/* Lzma2Dec.c -- LZMA2 Decoder
|
||||
2009-05-03 : Igor Pavlov : Public domain */
|
||||
2019-02-02 : Igor Pavlov : Public domain */
|
||||
|
||||
/* #define SHOW_DEBUG_INFO */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Lzma2Dec.h"
|
||||
|
||||
/*
|
||||
00000000 - EOS
|
||||
00000001 U U - Uncompressed Reset Dic
|
||||
00000010 U U - Uncompressed No Reset
|
||||
100uuuuu U U P P - LZMA no reset
|
||||
101uuuuu U U P P - LZMA reset state
|
||||
110uuuuu U U P P S - LZMA reset state + new prop
|
||||
111uuuuu U U P P S - LZMA reset state + new prop + reset dic
|
||||
00000000 - End of data
|
||||
00000001 U U - Uncompressed, reset dic, need reset state and set new prop
|
||||
00000010 U U - Uncompressed, no reset
|
||||
100uuuuu U U P P - LZMA, no reset
|
||||
101uuuuu U U P P - LZMA, reset state
|
||||
110uuuuu U U P P S - LZMA, reset state + set new prop
|
||||
111uuuuu U U P P S - LZMA, reset state + set new prop, reset dic
|
||||
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
u, U - Unpack Size
|
||||
P - Pack Size
|
||||
S - Props
|
||||
*/
|
||||
|
||||
#define LZMA2_CONTROL_LZMA (1 << 7)
|
||||
#define LZMA2_CONTROL_COPY_NO_RESET 2
|
||||
#define LZMA2_CONTROL_COPY_RESET_DIC 1
|
||||
#define LZMA2_CONTROL_EOF 0
|
||||
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & LZMA2_CONTROL_LZMA) == 0)
|
||||
|
||||
#define LZMA2_GET_LZMA_MODE(p) (((p)->control >> 5) & 3)
|
||||
#define LZMA2_IS_THERE_PROP(mode) ((mode) >= 2)
|
||||
#define LZMA2_IS_UNCOMPRESSED_STATE(p) (((p)->control & (1 << 7)) == 0)
|
||||
|
||||
#define LZMA2_LCLP_MAX 4
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((uint32_t)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
#define LZMA2_DIC_SIZE_FROM_PROP(p) (((UInt32)2 | ((p) & 1)) << ((p) / 2 + 11))
|
||||
|
||||
#ifdef SHOW_DEBUG_INFO
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA2_STATE_CONTROL,
|
||||
LZMA2_STATE_UNPACK0,
|
||||
LZMA2_STATE_UNPACK1,
|
||||
LZMA2_STATE_PACK0,
|
||||
LZMA2_STATE_PACK1,
|
||||
LZMA2_STATE_PROP,
|
||||
LZMA2_STATE_DATA,
|
||||
LZMA2_STATE_DATA_CONT,
|
||||
LZMA2_STATE_FINISHED,
|
||||
LZMA2_STATE_ERROR
|
||||
LZMA2_STATE_CONTROL,
|
||||
LZMA2_STATE_UNPACK0,
|
||||
LZMA2_STATE_UNPACK1,
|
||||
LZMA2_STATE_PACK0,
|
||||
LZMA2_STATE_PACK1,
|
||||
LZMA2_STATE_PROP,
|
||||
LZMA2_STATE_DATA,
|
||||
LZMA2_STATE_DATA_CONT,
|
||||
LZMA2_STATE_FINISHED,
|
||||
LZMA2_STATE_ERROR
|
||||
} ELzma2State;
|
||||
|
||||
static SRes Lzma2Dec_GetOldProps(uint8_t prop, uint8_t *props)
|
||||
static SRes Lzma2Dec_GetOldProps(Byte prop, Byte *props)
|
||||
{
|
||||
uint32_t dicSize;
|
||||
if (prop > 40)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||
props[0] = (uint8_t)LZMA2_LCLP_MAX;
|
||||
props[1] = (uint8_t)(dicSize);
|
||||
props[2] = (uint8_t)(dicSize >> 8);
|
||||
props[3] = (uint8_t)(dicSize >> 16);
|
||||
props[4] = (uint8_t)(dicSize >> 24);
|
||||
return SZ_OK;
|
||||
UInt32 dicSize;
|
||||
if (prop > 40)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
dicSize = (prop == 40) ? 0xFFFFFFFF : LZMA2_DIC_SIZE_FROM_PROP(prop);
|
||||
props[0] = (Byte)LZMA2_LCLP_MAX;
|
||||
props[1] = (Byte)(dicSize);
|
||||
props[2] = (Byte)(dicSize >> 8);
|
||||
props[3] = (Byte)(dicSize >> 16);
|
||||
props[4] = (Byte)(dicSize >> 24);
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc)
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
int result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_AllocateProbs(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc)
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc)
|
||||
{
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
int result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
Byte props[LZMA_PROPS_SIZE];
|
||||
RINOK(Lzma2Dec_GetOldProps(prop, props));
|
||||
return LzmaDec_Allocate(&p->decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
}
|
||||
|
||||
void Lzma2Dec_Init(CLzma2Dec *p)
|
||||
{
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitDic = true;
|
||||
p->needInitState = true;
|
||||
p->needInitProp = true;
|
||||
LzmaDec_Init(&p->decoder);
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
p->needInitLevel = 0xE0;
|
||||
p->isExtraMode = False;
|
||||
p->unpackSize = 0;
|
||||
|
||||
/* p->decoder.dicPos = 0; // we can use it instead of full init */
|
||||
LzmaDec_Init(&p->decoder);
|
||||
}
|
||||
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, uint8_t b)
|
||||
static ELzma2State Lzma2Dec_UpdateState(CLzma2Dec *p, Byte b)
|
||||
{
|
||||
switch(p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->control = b;
|
||||
PRF(printf("\n %4X ", p->decoder.dicPos));
|
||||
PRF(printf(" %2X", b));
|
||||
if (p->control == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if ((p->control & 0x7F) > 2)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->unpackSize = 0;
|
||||
}
|
||||
else
|
||||
p->unpackSize = (uint32_t)(p->control & 0x1F) << 16;
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
p->unpackSize |= (uint32_t)b << 8;
|
||||
return LZMA2_STATE_UNPACK1;
|
||||
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (uint32_t)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %8d", p->unpackSize));
|
||||
return (LZMA2_IS_UNCOMPRESSED_STATE(p)) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (uint32_t)b << 8;
|
||||
return LZMA2_STATE_PACK1;
|
||||
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (uint32_t)b;
|
||||
p->packSize++;
|
||||
PRF(printf(" %8d", p->packSize));
|
||||
return LZMA2_IS_THERE_PROP(LZMA2_GET_LZMA_MODE(p)) ? LZMA2_STATE_PROP:
|
||||
(p->needInitProp ? LZMA2_STATE_ERROR : LZMA2_STATE_DATA);
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
int lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = b / 5;
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = lc;
|
||||
p->decoder.prop.lp = lp;
|
||||
p->needInitProp = false;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const uint8_t *src, size_t size)
|
||||
{
|
||||
memcpy(p->dic + p->dicPos, src, size);
|
||||
p->dicPos += size;
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
p->processedPos += (uint32_t)size;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, bool initDic, bool initState);
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
size_t inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
size_t dicPos = p->decoder.dicPos;
|
||||
if (p->state == LZMA2_STATE_ERROR)
|
||||
return SZ_ERROR_DATA;
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
switch (p->state)
|
||||
{
|
||||
case LZMA2_STATE_CONTROL:
|
||||
p->isExtraMode = False;
|
||||
p->control = b;
|
||||
PRF(printf("\n %8X", (unsigned)p->decoder.dicPos));
|
||||
PRF(printf(" %02X", (unsigned)b));
|
||||
if (b == 0)
|
||||
return LZMA2_STATE_FINISHED;
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
continue;
|
||||
}
|
||||
{
|
||||
size_t destSizeCur = dicLimit - dicPos;
|
||||
size_t srcSizeCur = inSize - *srcLen;
|
||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||
|
||||
if (p->unpackSize <= destSizeCur)
|
||||
{
|
||||
destSizeCur = (size_t)p->unpackSize;
|
||||
curFinishMode = LZMA_FINISH_END;
|
||||
}
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
bool initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
if (initDic)
|
||||
p->needInitProp = p->needInitState = true;
|
||||
else if (p->needInitDic)
|
||||
return SZ_ERROR_DATA;
|
||||
p->needInitDic = false;
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, false);
|
||||
}
|
||||
|
||||
if (srcSizeCur > destSizeCur)
|
||||
srcSizeCur = destSizeCur;
|
||||
|
||||
if (srcSizeCur == 0)
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, srcSizeCur);
|
||||
|
||||
src += srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
p->unpackSize -= (uint32_t)srcSizeCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t outSizeProcessed;
|
||||
SRes res;
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
int mode = LZMA2_GET_LZMA_MODE(p);
|
||||
bool initDic = (mode == 3);
|
||||
bool initState = (mode > 0);
|
||||
if ((!initDic && p->needInitDic) || (!initState && p->needInitState))
|
||||
return SZ_ERROR_DATA;
|
||||
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->needInitDic = false;
|
||||
p->needInitState = false;
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
if (srcSizeCur > p->packSize)
|
||||
srcSizeCur = (size_t)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + destSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||
|
||||
src += srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
p->packSize -= (uint32_t)srcSizeCur;
|
||||
|
||||
outSizeProcessed = p->decoder.dicPos - dicPos;
|
||||
p->unpackSize -= (uint32_t)outSizeProcessed;
|
||||
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
return res;
|
||||
|
||||
if (srcSizeCur == 0 && outSizeProcessed == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK ||
|
||||
p->unpackSize != 0 || p->packSize != 0)
|
||||
return SZ_ERROR_DATA;
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
if (*status == LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
}
|
||||
}
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
size_t outSize = *destLen, inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
for (;;)
|
||||
{
|
||||
size_t srcSizeCur = inSize, outSizeCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||
p->decoder.dicPos = 0;
|
||||
dicPos = p->decoder.dicPos;
|
||||
if (outSize > p->decoder.dicBufSize - dicPos)
|
||||
{
|
||||
outSizeCur = p->decoder.dicBufSize;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
if (b == LZMA2_CONTROL_COPY_RESET_DIC)
|
||||
p->needInitLevel = 0xC0;
|
||||
else if (b > 2 || p->needInitLevel == 0xE0)
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
outSizeCur = dicPos + outSize;
|
||||
curFinishMode = finishMode;
|
||||
if (b < p->needInitLevel)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->needInitLevel = 0;
|
||||
p->unpackSize = (UInt32)(b & 0x1F) << 16;
|
||||
}
|
||||
return LZMA2_STATE_UNPACK0;
|
||||
|
||||
case LZMA2_STATE_UNPACK0:
|
||||
p->unpackSize |= (UInt32)b << 8;
|
||||
return LZMA2_STATE_UNPACK1;
|
||||
|
||||
case LZMA2_STATE_UNPACK1:
|
||||
p->unpackSize |= (UInt32)b;
|
||||
p->unpackSize++;
|
||||
PRF(printf(" %7u", (unsigned)p->unpackSize));
|
||||
return LZMA2_IS_UNCOMPRESSED_STATE(p) ? LZMA2_STATE_DATA : LZMA2_STATE_PACK0;
|
||||
|
||||
case LZMA2_STATE_PACK0:
|
||||
p->packSize = (UInt32)b << 8;
|
||||
return LZMA2_STATE_PACK1;
|
||||
|
||||
case LZMA2_STATE_PACK1:
|
||||
p->packSize |= (UInt32)b;
|
||||
p->packSize++;
|
||||
/* if (p->packSize < 5) return LZMA2_STATE_ERROR; */
|
||||
PRF(printf(" %5u", (unsigned)p->packSize));
|
||||
return (p->control & 0x40) ? LZMA2_STATE_PROP : LZMA2_STATE_DATA;
|
||||
|
||||
case LZMA2_STATE_PROP:
|
||||
{
|
||||
unsigned lc, lp;
|
||||
if (b >= (9 * 5 * 5))
|
||||
return LZMA2_STATE_ERROR;
|
||||
lc = b % 9;
|
||||
b /= 9;
|
||||
p->decoder.prop.pb = (Byte)(b / 5);
|
||||
lp = b % 5;
|
||||
if (lc + lp > LZMA2_LCLP_MAX)
|
||||
return LZMA2_STATE_ERROR;
|
||||
p->decoder.prop.lc = (Byte)lc;
|
||||
p->decoder.prop.lp = (Byte)lp;
|
||||
return LZMA2_STATE_DATA;
|
||||
}
|
||||
}
|
||||
return LZMA2_STATE_ERROR;
|
||||
}
|
||||
|
||||
static void LzmaDec_UpdateWithUncompressed(CLzmaDec *p, const Byte *src, SizeT size)
|
||||
{
|
||||
memcpy(p->dic + p->dicPos, src, size);
|
||||
p->dicPos += size;
|
||||
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= size)
|
||||
p->checkDicSize = p->prop.dicSize;
|
||||
p->processedPos += (UInt32)size;
|
||||
}
|
||||
|
||||
void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState);
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
SizeT dicPos;
|
||||
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
{
|
||||
*status = LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
dicPos = p->decoder.dicPos;
|
||||
|
||||
if (dicPos == dicLimit && finishMode == LZMA_FINISH_ANY)
|
||||
{
|
||||
*status = LZMA_STATUS_NOT_FINISHED;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
(*srcLen)++;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
if (dicPos == dicLimit && p->state != LZMA2_STATE_FINISHED)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
SizeT outCur = dicLimit - dicPos;
|
||||
ELzmaFinishMode curFinishMode = LZMA_FINISH_ANY;
|
||||
|
||||
if (outCur >= p->unpackSize)
|
||||
{
|
||||
outCur = (SizeT)p->unpackSize;
|
||||
curFinishMode = LZMA_FINISH_END;
|
||||
}
|
||||
|
||||
res = Lzma2Dec_DecodeToDic(p, outSizeCur, src, &srcSizeCur, curFinishMode, status);
|
||||
src += srcSizeCur;
|
||||
inSize -= srcSizeCur;
|
||||
*srcLen += srcSizeCur;
|
||||
outSizeCur = p->decoder.dicPos - dicPos;
|
||||
memcpy(dest, p->decoder.dic + dicPos, outSizeCur);
|
||||
dest += outSizeCur;
|
||||
outSize -= outSizeCur;
|
||||
*destLen += outSizeCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outSizeCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
{
|
||||
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control == LZMA2_CONTROL_COPY_RESET_DIC);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, False);
|
||||
}
|
||||
|
||||
if (inCur > outCur)
|
||||
inCur = outCur;
|
||||
if (inCur == 0)
|
||||
break;
|
||||
|
||||
LzmaDec_UpdateWithUncompressed(&p->decoder, src, inCur);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->unpackSize -= (UInt32)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
SRes res;
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
BoolInt initDic = (p->control >= 0xE0);
|
||||
BoolInt initState = (p->control >= 0xA0);
|
||||
LzmaDec_InitDicAndState(&p->decoder, initDic, initState);
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
res = LzmaDec_DecodeToDic(&p->decoder, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
p->unpackSize -= (UInt32)outCur;
|
||||
|
||||
if (res != 0)
|
||||
break;
|
||||
|
||||
if (*status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
{
|
||||
if (p->packSize == 0)
|
||||
break;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (inCur == 0 && outCur == 0)
|
||||
{
|
||||
if (*status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
|| p->unpackSize != 0
|
||||
|| p->packSize != 0)
|
||||
break;
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return SZ_ERROR_DATA;
|
||||
}
|
||||
|
||||
SRes Lzma2Decode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
uint8_t prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc)
|
||||
|
||||
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize,
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock)
|
||||
{
|
||||
SRes res;
|
||||
int result;
|
||||
CLzma2Dec decoder;
|
||||
size_t outSize = *destLen, inSize = *srcLen;
|
||||
uint8_t props[LZMA_PROPS_SIZE];
|
||||
SizeT inSize = *srcLen;
|
||||
*srcLen = 0;
|
||||
|
||||
Lzma2Dec_Construct(&decoder);
|
||||
while (p->state != LZMA2_STATE_ERROR)
|
||||
{
|
||||
if (p->state == LZMA2_STATE_FINISHED)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_FINISHED_WITH_MARK;
|
||||
|
||||
*destLen = *srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
decoder.decoder.dic = dest;
|
||||
decoder.decoder.dicBufSize = outSize;
|
||||
if (outSize == 0 && !checkFinishBlock)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
if (p->state != LZMA2_STATE_DATA && p->state != LZMA2_STATE_DATA_CONT)
|
||||
{
|
||||
if (*srcLen == inSize)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
(*srcLen)++;
|
||||
|
||||
result = Lzma2Dec_GetOldProps(prop, props);
|
||||
if (result != 0)
|
||||
return result;
|
||||
result = LzmaDec_AllocateProbs(&decoder.decoder, props, LZMA_PROPS_SIZE, alloc);
|
||||
if (result != 0)
|
||||
return result;
|
||||
p->state = Lzma2Dec_UpdateState(p, *src++);
|
||||
|
||||
*srcLen = inSize;
|
||||
res = Lzma2Dec_DecodeToDic(&decoder, outSize, src, srcLen, finishMode, status);
|
||||
*destLen = decoder.decoder.dicPos;
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
if (p->state == LZMA2_STATE_UNPACK0)
|
||||
{
|
||||
/* if (p->decoder.dicPos != 0) */
|
||||
if (p->control == LZMA2_CONTROL_COPY_RESET_DIC || p->control >= 0xE0)
|
||||
return LZMA2_PARSE_STATUS_NEW_BLOCK;
|
||||
/* if (outSize == 0) return LZMA_STATUS_NOT_FINISHED; */
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&decoder.decoder, alloc);
|
||||
return res;
|
||||
/* The following code can be commented.
|
||||
* It's not big problem, if we read additional input bytes.
|
||||
* It will be stopped later in LZMA2_STATE_DATA / LZMA2_STATE_DATA_CONT state. */
|
||||
|
||||
if (outSize == 0 && p->state != LZMA2_STATE_FINISHED)
|
||||
{
|
||||
/* checkFinishBlock is true. So we expect that block must be finished,
|
||||
* We can return LZMA_STATUS_NOT_SPECIFIED or LZMA_STATUS_NOT_FINISHED here
|
||||
* break; */
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
}
|
||||
|
||||
if (p->state == LZMA2_STATE_DATA)
|
||||
return LZMA2_PARSE_STATUS_NEW_CHUNK;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (outSize == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_FINISHED;
|
||||
|
||||
{
|
||||
SizeT inCur = inSize - *srcLen;
|
||||
|
||||
if (LZMA2_IS_UNCOMPRESSED_STATE(p))
|
||||
{
|
||||
if (inCur == 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
if (inCur > p->unpackSize)
|
||||
inCur = p->unpackSize;
|
||||
if (inCur > outSize)
|
||||
inCur = outSize;
|
||||
p->decoder.dicPos += inCur;
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
outSize -= inCur;
|
||||
p->unpackSize -= (UInt32)inCur;
|
||||
p->state = (p->unpackSize == 0) ? LZMA2_STATE_CONTROL : LZMA2_STATE_DATA_CONT;
|
||||
}
|
||||
else
|
||||
{
|
||||
p->isExtraMode = True;
|
||||
|
||||
if (inCur == 0)
|
||||
{
|
||||
if (p->packSize != 0)
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NEEDS_MORE_INPUT;
|
||||
}
|
||||
else if (p->state == LZMA2_STATE_DATA)
|
||||
{
|
||||
p->state = LZMA2_STATE_DATA_CONT;
|
||||
if (*src != 0)
|
||||
{
|
||||
/* first byte of lzma chunk must be Zero */
|
||||
*srcLen += 1;
|
||||
p->packSize--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (inCur > p->packSize)
|
||||
inCur = (SizeT)p->packSize;
|
||||
|
||||
src += inCur;
|
||||
*srcLen += inCur;
|
||||
p->packSize -= (UInt32)inCur;
|
||||
|
||||
if (p->packSize == 0)
|
||||
{
|
||||
SizeT rem = outSize;
|
||||
if (rem > p->unpackSize)
|
||||
rem = p->unpackSize;
|
||||
p->decoder.dicPos += rem;
|
||||
p->unpackSize -= (UInt32)rem;
|
||||
outSize -= rem;
|
||||
if (p->unpackSize == 0)
|
||||
p->state = LZMA2_STATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p->state = LZMA2_STATE_ERROR;
|
||||
return (ELzma2ParseStatus)LZMA_STATUS_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
|
||||
{
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*srcLen = *destLen = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
SizeT inCur = inSize, outCur, dicPos;
|
||||
ELzmaFinishMode curFinishMode;
|
||||
SRes res;
|
||||
|
||||
if (p->decoder.dicPos == p->decoder.dicBufSize)
|
||||
p->decoder.dicPos = 0;
|
||||
dicPos = p->decoder.dicPos;
|
||||
curFinishMode = LZMA_FINISH_ANY;
|
||||
outCur = p->decoder.dicBufSize - dicPos;
|
||||
|
||||
if (outCur >= outSize)
|
||||
{
|
||||
outCur = outSize;
|
||||
curFinishMode = finishMode;
|
||||
}
|
||||
|
||||
res = Lzma2Dec_DecodeToDic(p, dicPos + outCur, src, &inCur, curFinishMode, status);
|
||||
|
||||
src += inCur;
|
||||
inSize -= inCur;
|
||||
*srcLen += inCur;
|
||||
outCur = p->decoder.dicPos - dicPos;
|
||||
memcpy(dest, p->decoder.dic + dicPos, outCur);
|
||||
dest += outCur;
|
||||
outSize -= outCur;
|
||||
*destLen += outCur;
|
||||
if (res != 0)
|
||||
return res;
|
||||
if (outCur == 0 || outSize == 0)
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc)
|
||||
{
|
||||
CLzma2Dec p;
|
||||
SRes res;
|
||||
SizeT outSize = *destLen, inSize = *srcLen;
|
||||
*destLen = *srcLen = 0;
|
||||
*status = LZMA_STATUS_NOT_SPECIFIED;
|
||||
Lzma2Dec_Construct(&p);
|
||||
RINOK(Lzma2Dec_AllocateProbs(&p, prop, alloc));
|
||||
p.decoder.dic = dest;
|
||||
p.decoder.dicBufSize = outSize;
|
||||
Lzma2Dec_Init(&p);
|
||||
*srcLen = inSize;
|
||||
res = Lzma2Dec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
|
||||
*destLen = p.decoder.dicPos;
|
||||
if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
|
||||
res = SZ_ERROR_INPUT_EOF;
|
||||
Lzma2Dec_FreeProbs(&p, alloc);
|
||||
return res;
|
||||
}
|
||||
Vendored
+61
-26
@@ -1,39 +1,35 @@
|
||||
/* Lzma2Dec.h -- LZMA2 Decoder
|
||||
2009-05-03 : Igor Pavlov : Public domain */
|
||||
2018-02-19 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA2_DEC_H
|
||||
#define __LZMA2_DEC_H
|
||||
|
||||
#include <boolean.h>
|
||||
#include "LzmaDec.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* ---------- State Interface ---------- */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned state;
|
||||
Byte control;
|
||||
Byte needInitLevel;
|
||||
Byte isExtraMode;
|
||||
Byte _pad_;
|
||||
UInt32 packSize;
|
||||
UInt32 unpackSize;
|
||||
CLzmaDec decoder;
|
||||
uint32_t packSize;
|
||||
uint32_t unpackSize;
|
||||
int state;
|
||||
uint8_t control;
|
||||
bool needInitDic;
|
||||
bool needInitState;
|
||||
bool needInitProp;
|
||||
} CLzma2Dec;
|
||||
|
||||
#define Lzma2Dec_Construct(p) LzmaDec_Construct(&(p)->decoder)
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc);
|
||||
#define Lzma2Dec_FreeProbs(p, alloc) LzmaDec_FreeProbs(&(p)->decoder, alloc)
|
||||
#define Lzma2Dec_Free(p, alloc) LzmaDec_Free(&(p)->decoder, alloc)
|
||||
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, uint8_t prop, ISzAlloc *alloc);
|
||||
SRes Lzma2Dec_AllocateProbs(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
SRes Lzma2Dec_Allocate(CLzma2Dec *p, Byte prop, ISzAllocPtr alloc);
|
||||
void Lzma2Dec_Init(CLzma2Dec *p);
|
||||
|
||||
|
||||
/*
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen or dicLimit).
|
||||
@@ -49,11 +45,52 @@ Returns:
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes Lzma2Dec_DecodeToDic(CLzma2Dec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, uint8_t *dest, size_t *destLen,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes Lzma2Dec_DecodeToBuf(CLzma2Dec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- LZMA2 block and chunk parsing ---------- */
|
||||
|
||||
/*
|
||||
Lzma2Dec_Parse() parses compressed data stream up to next independent block or next chunk data.
|
||||
It can return LZMA_STATUS_* code or LZMA2_PARSE_STATUS_* code:
|
||||
- LZMA2_PARSE_STATUS_NEW_BLOCK - there is new block, and 1 additional byte (control byte of next block header) was read from input.
|
||||
- LZMA2_PARSE_STATUS_NEW_CHUNK - there is new chunk, and only lzma2 header of new chunk was read.
|
||||
CLzma2Dec::unpackSize contains unpack size of that chunk
|
||||
*/
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*
|
||||
LZMA_STATUS_NOT_SPECIFIED // data error
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED //
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK // unused
|
||||
*/
|
||||
LZMA2_PARSE_STATUS_NEW_BLOCK = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + 1,
|
||||
LZMA2_PARSE_STATUS_NEW_CHUNK
|
||||
} ELzma2ParseStatus;
|
||||
|
||||
ELzma2ParseStatus Lzma2Dec_Parse(CLzma2Dec *p,
|
||||
SizeT outSize, /* output size */
|
||||
const Byte *src, SizeT *srcLen,
|
||||
int checkFinishBlock /* set (checkFinishBlock = 1), if it must read full input data, if decoder.dicPos reaches blockMax position. */
|
||||
);
|
||||
|
||||
/*
|
||||
LZMA2 parser doesn't decode LZMA chunks, so we must read
|
||||
full input LZMA chunk to decode some part of LZMA chunk.
|
||||
|
||||
Lzma2Dec_GetUnpackExtra() returns the value that shows
|
||||
max possible number of output bytes that can be output by decoder
|
||||
at current input positon.
|
||||
*/
|
||||
|
||||
#define Lzma2Dec_GetUnpackExtra(p) ((p)->isExtraMode ? (p)->unpackSize : 0);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
@@ -75,11 +112,9 @@ Returns:
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes Lzma2Decode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
uint8_t prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc);
|
||||
SRes Lzma2Decode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
Byte prop, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+998
-882
File diff suppressed because it is too large.
Load diff
Vendored
+175
-161
@@ -1,174 +1,190 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2009-02-07 : Igor Pavlov : Public domain */
|
||||
2018-04-21 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_DEC_H
|
||||
#define __LZMA_DEC_H
|
||||
|
||||
#include "7zTypes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
typedef
|
||||
#ifdef _LZMA_PROB32
|
||||
UInt32
|
||||
#else
|
||||
UInt16
|
||||
#endif
|
||||
CLzmaProb;
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
uint32_t dicSize;
|
||||
} CLzmaProps;
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
Byte lc;
|
||||
Byte lp;
|
||||
Byte pb;
|
||||
Byte _pad_;
|
||||
UInt32 dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const uint8_t *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.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
|
||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProps prop;
|
||||
uint16_t *probs;
|
||||
uint8_t *dic;
|
||||
const uint8_t *buf;
|
||||
uint32_t range, code;
|
||||
size_t dicPos;
|
||||
size_t dicBufSize;
|
||||
uint32_t processedPos;
|
||||
uint32_t checkDicSize;
|
||||
unsigned state;
|
||||
uint32_t reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
uint32_t numProbs;
|
||||
unsigned tempBufSize;
|
||||
uint8_t tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const uint8_t *props, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const uint8_t *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
typedef struct
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
/* Don't change this structure. ASM code can use it. */
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
CLzmaProb *probs_1664;
|
||||
Byte *dic;
|
||||
SizeT dicBufSize;
|
||||
SizeT dicPos;
|
||||
const Byte *buf;
|
||||
UInt32 range;
|
||||
UInt32 code;
|
||||
UInt32 processedPos;
|
||||
UInt32 checkDicSize;
|
||||
UInt32 reps[4];
|
||||
UInt32 state;
|
||||
UInt32 remainLen;
|
||||
|
||||
UInt32 numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
- Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
- Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc);
|
||||
void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Construct()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
*/
|
||||
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, size_t dicLimit,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- Buffer Interface ---------- */
|
||||
@@ -179,13 +195,13 @@ SZ_ERROR_DATA - Data error
|
||||
to work with CLzmaDec variables manually.
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, uint8_t *dest, size_t *destLen,
|
||||
const uint8_t *src, size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
@@ -193,28 +209,26 @@ SRes LzmaDec_DecodeToBuf(CLzmaDec *p, uint8_t *dest, size_t *destLen,
|
||||
/* LzmaDecode
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes LzmaDecode(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t *srcLen,
|
||||
const uint8_t *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAllocPtr alloc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
EXTERN_C_END
|
||||
|
||||
#endif
|
||||
Vendored
+2167
-1500
File diff suppressed because it is too large.
Load diff
Vendored
+29
-33
@@ -1,11 +1,9 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2013-01-18 : Igor Pavlov : Public domain */
|
||||
2017-07-27 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMA_ENC_H
|
||||
#define __LZMA_ENC_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "7zTypes.h"
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
@@ -14,12 +12,10 @@ EXTERN_C_BEGIN
|
||||
|
||||
typedef struct _CLzmaEncProps
|
||||
{
|
||||
int level; /* 0 <= level <= 9 */
|
||||
uint32_t dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (1 << 30) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
uint64_t reduceSize; /* estimated size of data that will be compressed. default = 0xFFFFFFFF.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
int level; /* 0 <= level <= 9 */
|
||||
UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
|
||||
(1 << 12) <= dictSize <= (3 << 29) for 64-bit version
|
||||
default = (1 << 24) */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||
@@ -27,53 +23,53 @@ typedef struct _CLzmaEncProps
|
||||
int fb; /* 5 <= fb <= 273, default = 32 */
|
||||
int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
|
||||
int numHashBytes; /* 2, 3 or 4, default = 4 */
|
||||
uint32_t mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
|
||||
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
|
||||
UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1.
|
||||
Encoder uses this value to reduce dictionary size */
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
void LzmaEncProps_Normalize(CLzmaEncProps *p);
|
||||
uint32_t LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
|
||||
|
||||
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||
|
||||
/* LzmaEnc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
/* LzmaEnc* functions can return the following exit codes:
|
||||
SRes:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error.
|
||||
SZ_ERROR_WRITE - ISeqOutStream write callback error
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
SZ_ERROR_THREAD - error in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void * CLzmaEncHandle;
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc);
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, unsigned char *properties, size_t *size);
|
||||
void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
|
||||
unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p);
|
||||
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaEncode
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
SRes LzmaEncode(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
const CLzmaEncProps *props, unsigned char *propsEncoded, size_t *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/* Precomp.h -- StdAfx
|
||||
2013-11-12 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_PRECOMP_H
|
||||
#define __7Z_PRECOMP_H
|
||||
|
||||
#include "Compiler.h"
|
||||
/* #include "7zTypes.h" */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,58 @@
|
||||
|
||||
OBJDIR = ../obj-unix
|
||||
|
||||
TEST_UNIT_CFLAGS = $(CFLAGS) -Iinclude $(LDFLAGS) -lcheck $(LIBCHECK_CFLAGS) -Werror -Wdeclaration-after-statement -fsanitize=address -fsanitize=undefined -ftest-coverage -fprofile-arcs -ggdb
|
||||
|
||||
TEST_GENERIC_QUEUE = test/queues/test_generic_queue
|
||||
TEST_GENERIC_QUEUE_SRC = test/queues/test_generic_queue.c queues/generic_queue.c
|
||||
|
||||
TEST_LINKED_LIST = test/lists/test_linked_list
|
||||
TEST_LINKED_LIST_SRC = test/lists/test_linked_list.c lists/linked_list.c
|
||||
|
||||
TEST_STDSTRING = test/string/test_stdstring
|
||||
TEST_STDSTRING_SRC = test/string/test_stdstring.c string/stdstring.c encodings/encoding_utf.c \
|
||||
compat/compat_strl.c
|
||||
|
||||
TEST_UTILS = test/utils/test_utils
|
||||
TEST_UTILS_SRC = test/utils/test_utils.c utils/md5.c encodings/encoding_crc32.c \
|
||||
streams/file_stream.c vfs/vfs_implementation.c file/file_path.c \
|
||||
compat/compat_strl.c time/rtime.c string/stdstring.c encodings/encoding_utf.c
|
||||
|
||||
TEST_HASH = test/hash/test_hash
|
||||
TEST_HASH_SRC = test/hash/test_hash.c hash/lrc_hash.c \
|
||||
streams/file_stream.c vfs/vfs_implementation.c file/file_path.c \
|
||||
compat/compat_strl.c time/rtime.c string/stdstring.c encodings/encoding_utf.c
|
||||
|
||||
all:
|
||||
# Build and execute tests in order, to avoid coverage file collision
|
||||
# string
|
||||
$(CC) $(TEST_UNIT_CFLAGS) $(TEST_STDSTRING_SRC) -o $(TEST_STDSTRING)
|
||||
$(TEST_STDSTRING)
|
||||
lcov -c -d . -o `dirname $(TEST_STDSTRING)`/coverage.info
|
||||
# utils
|
||||
$(CC) $(TEST_UNIT_CFLAGS) $(TEST_UTILS_SRC) -o $(TEST_UTILS)
|
||||
$(TEST_UTILS)
|
||||
lcov -c -d . -o `dirname $(TEST_UTILS)`/coverage.info
|
||||
# utils
|
||||
$(CC) $(TEST_UNIT_CFLAGS) $(TEST_HASH_SRC) -o $(TEST_HASH)
|
||||
$(TEST_HASH)
|
||||
lcov -c -d . -o `dirname $(TEST_HASH)`/coverage.info
|
||||
# list
|
||||
$(CC) $(TEST_UNIT_CFLAGS) $(TEST_LINKED_LIST_SRC) -o $(TEST_LINKED_LIST)
|
||||
$(TEST_LINKED_LIST)
|
||||
lcov -c -d . -o `dirname $(TEST_LINKED_LIST)`/coverage.info
|
||||
# queue
|
||||
$(CC) $(TEST_UNIT_CFLAGS) $(TEST_GENERIC_QUEUE_SRC) -o $(TEST_GENERIC_QUEUE)
|
||||
$(TEST_GENERIC_QUEUE)
|
||||
lcov -c -d . -o `dirname $(TEST_GENERIC_QUEUE)`/coverage.info
|
||||
|
||||
lcov -o test/coverage.info \
|
||||
-a test/utils/coverage.info \
|
||||
-a test/string/coverage.info \
|
||||
-a test/lists/coverage.info \
|
||||
-a test/queues/coverage.info
|
||||
genhtml -o test/coverage/ test/coverage.info
|
||||
|
||||
clean:
|
||||
rm -f *.gcda *.gcno
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
|
||||
#ifdef __SSE__
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MEMBER(v, i) ((v).m128_f32[(i)])
|
||||
#else
|
||||
#define MEMBER(v, i) ((v)[(i)])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__AVX__)
|
||||
@@ -75,16 +81,15 @@ typedef struct rarch_sinc_resampler
|
||||
float *phase_table;
|
||||
float *buffer_l;
|
||||
float *buffer_r;
|
||||
unsigned enable_avx;
|
||||
unsigned phase_bits;
|
||||
unsigned subphase_bits;
|
||||
unsigned subphase_mask;
|
||||
unsigned taps;
|
||||
unsigned ptr;
|
||||
unsigned num_channels;
|
||||
uint32_t time;
|
||||
float subphase_mod;
|
||||
float kaiser_beta;
|
||||
enum sinc_window window_type;
|
||||
} rarch_sinc_resampler_t;
|
||||
|
||||
#if (defined(__ARM_NEON__) && !defined(DONT_WANT_ARM_OPTIMIZATIONS)) || defined(HAVE_NEON)
|
||||
@@ -154,6 +159,89 @@ static void resampler_sinc_process_neon(void *re_, struct resampler_data *data)
|
||||
#endif
|
||||
|
||||
#if defined(__AVX__)
|
||||
static void resampler_sinc_process_avx_kaiser(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
unsigned phases = 1 << (resamp->phase_bits + resamp->subphase_bits);
|
||||
|
||||
uint32_t ratio = phases / data->ratio;
|
||||
const float *input = data->data_in;
|
||||
float *output = data->data_out;
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
while (frames)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
__m256 delta = _mm256_set1_ps((float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod);
|
||||
|
||||
__m256 sum_l = _mm256_setzero_ps();
|
||||
__m256 sum_r = _mm256_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 8)
|
||||
{
|
||||
__m256 buf_l = _mm256_loadu_ps(buffer_l + i);
|
||||
__m256 buf_r = _mm256_loadu_ps(buffer_r + i);
|
||||
__m256 deltas = _mm256_load_ps(delta_table + i);
|
||||
__m256 sinc = _mm256_add_ps(_mm256_load_ps((const float*)phase_table + i),
|
||||
_mm256_mul_ps(deltas, delta));
|
||||
|
||||
sum_l = _mm256_add_ps(sum_l, _mm256_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm256_add_ps(sum_r, _mm256_mul_ps(buf_r, sinc));
|
||||
}
|
||||
|
||||
/* hadd on AVX is weird, and acts on low-lanes
|
||||
* and high-lanes separately. */
|
||||
__m256 res_l = _mm256_hadd_ps(sum_l, sum_l);
|
||||
__m256 res_r = _mm256_hadd_ps(sum_r, sum_r);
|
||||
res_l = _mm256_hadd_ps(res_l, res_l);
|
||||
res_r = _mm256_hadd_ps(res_r, res_r);
|
||||
res_l = _mm256_add_ps(_mm256_permute2f128_ps(res_l, res_l, 1), res_l);
|
||||
res_r = _mm256_add_ps(_mm256_permute2f128_ps(res_r, res_r, 1), res_r);
|
||||
|
||||
/* This is optimized to mov %xmmN, [mem].
|
||||
* There doesn't seem to be any _mm256_store_ss intrinsic. */
|
||||
_mm_store_ss(output + 0, _mm256_extractf128_ps(res_l, 0));
|
||||
_mm_store_ss(output + 1, _mm256_extractf128_ps(res_r, 0));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->output_frames = out_frames;
|
||||
}
|
||||
|
||||
static void resampler_sinc_process_avx(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
@@ -165,140 +253,66 @@ static void resampler_sinc_process_avx(void *re_, struct resampler_data *data)
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
if (resamp->window_type == SINC_WINDOW_KAISER)
|
||||
while (frames)
|
||||
{
|
||||
while (frames)
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
__m256 delta = _mm256_set1_ps((float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod);
|
||||
|
||||
__m256 sum_l = _mm256_setzero_ps();
|
||||
__m256 sum_r = _mm256_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 8)
|
||||
{
|
||||
__m256 buf_l = _mm256_loadu_ps(buffer_l + i);
|
||||
__m256 buf_r = _mm256_loadu_ps(buffer_r + i);
|
||||
__m256 deltas = _mm256_load_ps(delta_table + i);
|
||||
__m256 sinc = _mm256_add_ps(_mm256_load_ps((const float*)phase_table + i),
|
||||
_mm256_mul_ps(deltas, delta));
|
||||
|
||||
sum_l = _mm256_add_ps(sum_l, _mm256_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm256_add_ps(sum_r, _mm256_mul_ps(buf_r, sinc));
|
||||
}
|
||||
|
||||
/* hadd on AVX is weird, and acts on low-lanes
|
||||
* and high-lanes separately. */
|
||||
__m256 res_l = _mm256_hadd_ps(sum_l, sum_l);
|
||||
__m256 res_r = _mm256_hadd_ps(sum_r, sum_r);
|
||||
res_l = _mm256_hadd_ps(res_l, res_l);
|
||||
res_r = _mm256_hadd_ps(res_r, res_r);
|
||||
res_l = _mm256_add_ps(_mm256_permute2f128_ps(res_l, res_l, 1), res_l);
|
||||
res_r = _mm256_add_ps(_mm256_permute2f128_ps(res_r, res_r, 1), res_r);
|
||||
|
||||
/* This is optimized to mov %xmmN, [mem].
|
||||
* There doesn't seem to be any _mm256_store_ss intrinsic. */
|
||||
_mm_store_ss(output + 0, _mm256_extractf128_ps(res_l, 0));
|
||||
_mm_store_ss(output + 1, _mm256_extractf128_ps(res_r, 0));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (frames)
|
||||
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
unsigned i;
|
||||
__m256 delta;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
__m256 sum_l = _mm256_setzero_ps();
|
||||
__m256 sum_r = _mm256_setzero_ps();
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
for (i = 0; i < taps; i += 8)
|
||||
{
|
||||
unsigned i;
|
||||
__m256 delta;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
__m256 buf_l = _mm256_loadu_ps(buffer_l + i);
|
||||
__m256 buf_r = _mm256_loadu_ps(buffer_r + i);
|
||||
__m256 sinc = _mm256_load_ps((const float*)phase_table + i);
|
||||
|
||||
__m256 sum_l = _mm256_setzero_ps();
|
||||
__m256 sum_r = _mm256_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 8)
|
||||
{
|
||||
__m256 buf_l = _mm256_loadu_ps(buffer_l + i);
|
||||
__m256 buf_r = _mm256_loadu_ps(buffer_r + i);
|
||||
__m256 sinc = _mm256_load_ps((const float*)phase_table + i);
|
||||
|
||||
sum_l = _mm256_add_ps(sum_l, _mm256_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm256_add_ps(sum_r, _mm256_mul_ps(buf_r, sinc));
|
||||
}
|
||||
|
||||
/* hadd on AVX is weird, and acts on low-lanes
|
||||
* and high-lanes separately. */
|
||||
__m256 res_l = _mm256_hadd_ps(sum_l, sum_l);
|
||||
__m256 res_r = _mm256_hadd_ps(sum_r, sum_r);
|
||||
res_l = _mm256_hadd_ps(res_l, res_l);
|
||||
res_r = _mm256_hadd_ps(res_r, res_r);
|
||||
res_l = _mm256_add_ps(_mm256_permute2f128_ps(res_l, res_l, 1), res_l);
|
||||
res_r = _mm256_add_ps(_mm256_permute2f128_ps(res_r, res_r, 1), res_r);
|
||||
|
||||
/* This is optimized to mov %xmmN, [mem].
|
||||
* There doesn't seem to be any _mm256_store_ss intrinsic. */
|
||||
_mm_store_ss(output + 0, _mm256_extractf128_ps(res_l, 0));
|
||||
_mm_store_ss(output + 1, _mm256_extractf128_ps(res_r, 0));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
sum_l = _mm256_add_ps(sum_l, _mm256_mul_ps(buf_l, sinc));
|
||||
sum_r = _mm256_add_ps(sum_r, _mm256_mul_ps(buf_r, sinc));
|
||||
}
|
||||
|
||||
/* hadd on AVX is weird, and acts on low-lanes
|
||||
* and high-lanes separately. */
|
||||
__m256 res_l = _mm256_hadd_ps(sum_l, sum_l);
|
||||
__m256 res_r = _mm256_hadd_ps(sum_r, sum_r);
|
||||
res_l = _mm256_hadd_ps(res_l, res_l);
|
||||
res_r = _mm256_hadd_ps(res_r, res_r);
|
||||
res_l = _mm256_add_ps(_mm256_permute2f128_ps(res_l, res_l, 1), res_l);
|
||||
res_r = _mm256_add_ps(_mm256_permute2f128_ps(res_r, res_r, 1), res_r);
|
||||
|
||||
/* This is optimized to mov %xmmN, [mem].
|
||||
* There doesn't seem to be any _mm256_store_ss intrinsic. */
|
||||
_mm_store_ss(output + 0, _mm256_extractf128_ps(res_l, 0));
|
||||
_mm_store_ss(output + 1, _mm256_extractf128_ps(res_r, 0));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,6 +322,75 @@ static void resampler_sinc_process_avx(void *re_, struct resampler_data *data)
|
||||
#endif
|
||||
|
||||
#if defined(__SSE__)
|
||||
static void resampler_sinc_process_sse_kaiser(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
unsigned phases = 1 << (resamp->phase_bits + resamp->subphase_bits);
|
||||
|
||||
uint32_t ratio = phases / data->ratio;
|
||||
const float *input = data->data_in;
|
||||
float *output = data->data_out;
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
while (frames)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
__m128 delta = _mm_set1_ps((float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod);
|
||||
|
||||
__m128 sum_l = _mm_setzero_ps();
|
||||
__m128 sum_r = _mm_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 4)
|
||||
{
|
||||
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
|
||||
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
|
||||
__m128 deltas = _mm_load_ps(delta_table + i);
|
||||
__m128 _sinc = _mm_add_ps(_mm_load_ps((const float*)phase_table + i),
|
||||
_mm_mul_ps(deltas, delta));
|
||||
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, _sinc));
|
||||
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, _sinc));
|
||||
}
|
||||
|
||||
*(output++) = _mm_cvtss_f32(sum_l) + MEMBER(sum_l, 1) + MEMBER(sum_l, 2) + MEMBER(sum_l, 3);
|
||||
*(output++) = _mm_cvtss_f32(sum_r) + MEMBER(sum_r, 1) + MEMBER(sum_r, 2) + MEMBER(sum_r, 3);
|
||||
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data->output_frames = out_frames;
|
||||
}
|
||||
|
||||
static void resampler_sinc_process_sse(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
@@ -319,160 +402,52 @@ static void resampler_sinc_process_sse(void *re_, struct resampler_data *data)
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
if (resamp->window_type == SINC_WINDOW_KAISER)
|
||||
while (frames)
|
||||
{
|
||||
while (frames)
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
__m128 sum;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
__m128 delta = _mm_set1_ps((float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod);
|
||||
|
||||
__m128 sum_l = _mm_setzero_ps();
|
||||
__m128 sum_r = _mm_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 4)
|
||||
{
|
||||
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
|
||||
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
|
||||
__m128 deltas = _mm_load_ps(delta_table + i);
|
||||
__m128 _sinc = _mm_add_ps(_mm_load_ps((const float*)phase_table + i),
|
||||
_mm_mul_ps(deltas, delta));
|
||||
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, _sinc));
|
||||
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, _sinc));
|
||||
}
|
||||
|
||||
/* Them annoying shuffles.
|
||||
* sum_l = { l3, l2, l1, l0 }
|
||||
* sum_r = { r3, r2, r1, r0 }
|
||||
*/
|
||||
|
||||
sum = _mm_add_ps(_mm_shuffle_ps(sum_l, sum_r,
|
||||
_MM_SHUFFLE(1, 0, 1, 0)),
|
||||
_mm_shuffle_ps(sum_l, sum_r, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||
|
||||
/* sum = { r1, r0, l1, l0 } + { r3, r2, l3, l2 }
|
||||
* sum = { R1, R0, L1, L0 }
|
||||
*/
|
||||
|
||||
sum = _mm_add_ps(_mm_shuffle_ps(sum, sum, _MM_SHUFFLE(3, 3, 1, 1)), sum);
|
||||
|
||||
/* sum = {R1, R1, L1, L1 } + { R1, R0, L1, L0 }
|
||||
* sum = { X, R, X, L }
|
||||
*/
|
||||
|
||||
/* Store L */
|
||||
_mm_store_ss(output + 0, sum);
|
||||
|
||||
/* movehl { X, R, X, L } == { X, R, X, R } */
|
||||
_mm_store_ss(output + 1, _mm_movehl_ps(sum, sum));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (frames)
|
||||
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
unsigned i;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
__m128 sum_l = _mm_setzero_ps();
|
||||
__m128 sum_r = _mm_setzero_ps();
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
for (i = 0; i < taps; i += 4)
|
||||
{
|
||||
unsigned i;
|
||||
__m128 sum;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
|
||||
__m128 sum_l = _mm_setzero_ps();
|
||||
__m128 sum_r = _mm_setzero_ps();
|
||||
|
||||
for (i = 0; i < taps; i += 4)
|
||||
{
|
||||
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
|
||||
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
|
||||
__m128 _sinc = _mm_load_ps((const float*)phase_table + i);
|
||||
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, _sinc));
|
||||
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, _sinc));
|
||||
}
|
||||
|
||||
/* Them annoying shuffles.
|
||||
* sum_l = { l3, l2, l1, l0 }
|
||||
* sum_r = { r3, r2, r1, r0 }
|
||||
*/
|
||||
|
||||
sum = _mm_add_ps(_mm_shuffle_ps(sum_l, sum_r,
|
||||
_MM_SHUFFLE(1, 0, 1, 0)),
|
||||
_mm_shuffle_ps(sum_l, sum_r, _MM_SHUFFLE(3, 2, 3, 2)));
|
||||
|
||||
/* sum = { r1, r0, l1, l0 } + { r3, r2, l3, l2 }
|
||||
* sum = { R1, R0, L1, L0 }
|
||||
*/
|
||||
|
||||
sum = _mm_add_ps(_mm_shuffle_ps(sum, sum, _MM_SHUFFLE(3, 3, 1, 1)), sum);
|
||||
|
||||
/* sum = {R1, R1, L1, L1 } + { R1, R0, L1, L0 }
|
||||
* sum = { X, R, X, L }
|
||||
*/
|
||||
|
||||
/* Store L */
|
||||
_mm_store_ss(output + 0, sum);
|
||||
|
||||
/* movehl { X, R, X, L } == { X, R, X, R } */
|
||||
_mm_store_ss(output + 1, _mm_movehl_ps(sum, sum));
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
|
||||
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
|
||||
__m128 _sinc = _mm_load_ps((const float*)phase_table + i);
|
||||
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, _sinc));
|
||||
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, _sinc));
|
||||
}
|
||||
|
||||
*(output++) = _mm_cvtss_f32(sum_l) + MEMBER(sum_l, 1) + MEMBER(sum_l, 2) + MEMBER(sum_l, 3);
|
||||
*(output++) = _mm_cvtss_f32(sum_r) + MEMBER(sum_r, 1) + MEMBER(sum_r, 2) + MEMBER(sum_r, 3);
|
||||
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -481,6 +456,72 @@ static void resampler_sinc_process_sse(void *re_, struct resampler_data *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void resampler_sinc_process_c_kaiser(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
unsigned phases = 1 << (resamp->phase_bits + resamp->subphase_bits);
|
||||
|
||||
uint32_t ratio = phases / data->ratio;
|
||||
const float *input = data->data_in;
|
||||
float *output = data->data_out;
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
while (frames)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
float sum_l = 0.0f;
|
||||
float sum_r = 0.0f;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
float delta = (float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod;
|
||||
|
||||
for (i = 0; i < taps; i++)
|
||||
{
|
||||
float sinc_val = phase_table[i] + delta_table[i] * delta;
|
||||
|
||||
sum_l += buffer_l[i] * sinc_val;
|
||||
sum_r += buffer_r[i] * sinc_val;
|
||||
}
|
||||
|
||||
*output++ = sum_l;
|
||||
*output++ = sum_r;
|
||||
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data->output_frames = out_frames;
|
||||
}
|
||||
|
||||
static void resampler_sinc_process_c(void *re_, struct resampler_data *data)
|
||||
{
|
||||
rarch_sinc_resampler_t *resamp = (rarch_sinc_resampler_t*)re_;
|
||||
@@ -492,112 +533,53 @@ static void resampler_sinc_process_c(void *re_, struct resampler_data *data)
|
||||
size_t frames = data->input_frames;
|
||||
size_t out_frames = 0;
|
||||
|
||||
if (resamp->window_type == SINC_WINDOW_KAISER)
|
||||
while (frames)
|
||||
{
|
||||
while (frames)
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
unsigned i;
|
||||
float sum_l = 0.0f;
|
||||
float sum_r = 0.0f;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps * 2;
|
||||
float *delta_table = phase_table + taps;
|
||||
float delta = (float)
|
||||
(resamp->time & resamp->subphase_mask) * resamp->subphase_mod;
|
||||
|
||||
for (i = 0; i < taps; i++)
|
||||
{
|
||||
float sinc_val = phase_table[i] + delta_table[i] * delta;
|
||||
|
||||
sum_l += buffer_l[i] * sinc_val;
|
||||
sum_r += buffer_r[i] * sinc_val;
|
||||
}
|
||||
|
||||
output[0] = sum_l;
|
||||
output[1] = sum_r;
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (frames)
|
||||
|
||||
{
|
||||
while (frames && resamp->time >= phases)
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
{
|
||||
/* Push in reverse to make filter more obvious. */
|
||||
if (!resamp->ptr)
|
||||
resamp->ptr = resamp->taps;
|
||||
resamp->ptr--;
|
||||
unsigned i;
|
||||
float sum_l = 0.0f;
|
||||
float sum_r = 0.0f;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
|
||||
resamp->buffer_l[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_l[resamp->ptr] = *input++;
|
||||
|
||||
resamp->buffer_r[resamp->ptr + resamp->taps] =
|
||||
resamp->buffer_r[resamp->ptr] = *input++;
|
||||
|
||||
resamp->time -= phases;
|
||||
frames--;
|
||||
}
|
||||
|
||||
{
|
||||
const float *buffer_l = resamp->buffer_l + resamp->ptr;
|
||||
const float *buffer_r = resamp->buffer_r + resamp->ptr;
|
||||
unsigned taps = resamp->taps;
|
||||
while (resamp->time < phases)
|
||||
for (i = 0; i < taps; i++)
|
||||
{
|
||||
unsigned i;
|
||||
float sum_l = 0.0f;
|
||||
float sum_r = 0.0f;
|
||||
unsigned phase = resamp->time >> resamp->subphase_bits;
|
||||
float *phase_table = resamp->phase_table + phase * taps;
|
||||
float sinc_val = phase_table[i];
|
||||
|
||||
for (i = 0; i < taps; i++)
|
||||
{
|
||||
float sinc_val = phase_table[i];
|
||||
|
||||
sum_l += buffer_l[i] * sinc_val;
|
||||
sum_r += buffer_r[i] * sinc_val;
|
||||
}
|
||||
|
||||
output[0] = sum_l;
|
||||
output[1] = sum_r;
|
||||
|
||||
output += 2;
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
sum_l += buffer_l[i] * sinc_val;
|
||||
sum_r += buffer_r[i] * sinc_val;
|
||||
}
|
||||
}
|
||||
|
||||
*output++ = sum_l;
|
||||
*output++ = sum_r;
|
||||
|
||||
out_frames++;
|
||||
resamp->time += ratio;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data->output_frames = out_frames;
|
||||
@@ -735,14 +717,14 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
size_t phase_elems = 0;
|
||||
size_t elems = 0;
|
||||
unsigned sidelobes = 0;
|
||||
unsigned enable_avx = 0;
|
||||
enum sinc_window window_type = SINC_WINDOW_NONE;
|
||||
rarch_sinc_resampler_t *re = (rarch_sinc_resampler_t*)
|
||||
calloc(1, sizeof(*re));
|
||||
|
||||
if (!re)
|
||||
return NULL;
|
||||
|
||||
re->window_type = SINC_WINDOW_NONE;
|
||||
|
||||
switch (quality)
|
||||
{
|
||||
case RESAMPLER_QUALITY_LOWEST:
|
||||
@@ -750,34 +732,32 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
sidelobes = 2;
|
||||
re->phase_bits = 12;
|
||||
re->subphase_bits = 10;
|
||||
re->window_type = SINC_WINDOW_LANCZOS;
|
||||
re->enable_avx = 0;
|
||||
window_type = SINC_WINDOW_LANCZOS;
|
||||
break;
|
||||
case RESAMPLER_QUALITY_LOWER:
|
||||
cutoff = 0.98;
|
||||
sidelobes = 4;
|
||||
re->phase_bits = 12;
|
||||
re->subphase_bits = 10;
|
||||
re->window_type = SINC_WINDOW_LANCZOS;
|
||||
re->enable_avx = 0;
|
||||
window_type = SINC_WINDOW_LANCZOS;
|
||||
break;
|
||||
case RESAMPLER_QUALITY_HIGHER:
|
||||
cutoff = 0.90;
|
||||
sidelobes = 32;
|
||||
re->phase_bits = 10;
|
||||
re->subphase_bits = 14;
|
||||
re->window_type = SINC_WINDOW_KAISER;
|
||||
re->kaiser_beta = 10.5;
|
||||
re->enable_avx = 1;
|
||||
enable_avx = 1;
|
||||
window_type = SINC_WINDOW_KAISER;
|
||||
break;
|
||||
case RESAMPLER_QUALITY_HIGHEST:
|
||||
cutoff = 0.962;
|
||||
sidelobes = 128;
|
||||
re->phase_bits = 10;
|
||||
re->subphase_bits = 14;
|
||||
re->window_type = SINC_WINDOW_KAISER;
|
||||
re->kaiser_beta = 14.5;
|
||||
re->enable_avx = 1;
|
||||
enable_avx = 1;
|
||||
window_type = SINC_WINDOW_KAISER;
|
||||
break;
|
||||
case RESAMPLER_QUALITY_NORMAL:
|
||||
case RESAMPLER_QUALITY_DONTCARE:
|
||||
@@ -785,14 +765,14 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
sidelobes = 8;
|
||||
re->phase_bits = 8;
|
||||
re->subphase_bits = 16;
|
||||
re->window_type = SINC_WINDOW_KAISER;
|
||||
re->kaiser_beta = 5.5;
|
||||
re->enable_avx = 0;
|
||||
window_type = SINC_WINDOW_KAISER;
|
||||
break;
|
||||
}
|
||||
|
||||
re->subphase_mask = (1 << re->subphase_bits) - 1;
|
||||
re->subphase_mod = 1.0f / (1 << re->subphase_bits);
|
||||
re->num_channels = 2;
|
||||
re->taps = sidelobes * 2;
|
||||
|
||||
/* Downsampling, must lower cutoff, and extend number of
|
||||
@@ -805,7 +785,7 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
|
||||
/* Be SIMD-friendly. */
|
||||
#if defined(__AVX__)
|
||||
if (re->enable_avx)
|
||||
if (enable_avx)
|
||||
re->taps = (re->taps + 7) & ~7;
|
||||
else
|
||||
#endif
|
||||
@@ -818,7 +798,7 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
}
|
||||
|
||||
phase_elems = ((1 << re->phase_bits) * re->taps);
|
||||
if (re->window_type == SINC_WINDOW_KAISER)
|
||||
if (window_type == SINC_WINDOW_KAISER)
|
||||
phase_elems = phase_elems * 2;
|
||||
elems = phase_elems + 4 * re->taps;
|
||||
|
||||
@@ -832,7 +812,7 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
re->buffer_l = re->main_buffer + phase_elems;
|
||||
re->buffer_r = re->buffer_l + 2 * re->taps;
|
||||
|
||||
switch (re->window_type)
|
||||
switch (window_type)
|
||||
{
|
||||
case SINC_WINDOW_LANCZOS:
|
||||
sinc_init_table_lanczos(re, cutoff, re->phase_table,
|
||||
@@ -846,24 +826,30 @@ static void *resampler_sinc_new(const struct resampler_config *config,
|
||||
goto error;
|
||||
}
|
||||
|
||||
sinc_resampler.process = resampler_sinc_process_c;
|
||||
sinc_resampler.process = resampler_sinc_process_c;
|
||||
if (window_type == SINC_WINDOW_KAISER)
|
||||
sinc_resampler.process = resampler_sinc_process_c_kaiser;
|
||||
|
||||
if (mask & RESAMPLER_SIMD_AVX && re->enable_avx)
|
||||
if (mask & RESAMPLER_SIMD_AVX && enable_avx)
|
||||
{
|
||||
#if defined(__AVX__)
|
||||
sinc_resampler.process = resampler_sinc_process_avx;
|
||||
sinc_resampler.process = resampler_sinc_process_avx;
|
||||
if (window_type == SINC_WINDOW_KAISER)
|
||||
sinc_resampler.process = resampler_sinc_process_avx_kaiser;
|
||||
#endif
|
||||
}
|
||||
else if (mask & RESAMPLER_SIMD_SSE)
|
||||
{
|
||||
#if defined(__SSE__)
|
||||
sinc_resampler.process = resampler_sinc_process_sse;
|
||||
sinc_resampler.process = resampler_sinc_process_sse;
|
||||
if (window_type == SINC_WINDOW_KAISER)
|
||||
sinc_resampler.process = resampler_sinc_process_sse_kaiser;
|
||||
#endif
|
||||
}
|
||||
else if (mask & RESAMPLER_SIMD_NEON && re->window_type != SINC_WINDOW_KAISER)
|
||||
else if (mask & RESAMPLER_SIMD_NEON && window_type != SINC_WINDOW_KAISER)
|
||||
{
|
||||
#if defined(WANT_NEON)
|
||||
sinc_resampler.process = resampler_sinc_process_neon;
|
||||
sinc_resampler.process = resampler_sinc_process_neon;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ retro_perf_tick_t cpu_features_get_perf_counter(void)
|
||||
time_ticks = gettime();
|
||||
#elif !defined(__MACH__) && (defined(_XBOX360) || defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__) || defined(__PSL1GHT__) || defined(__PPC64__) || defined(__powerpc64__))
|
||||
time_ticks = __mftb();
|
||||
#elif defined(_POSIX_MONOTONIC_CLOCK) || defined(__QNX__) || defined(ANDROID) || defined(__MACH__)
|
||||
#elif (defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0) || defined(__QNX__) || defined(ANDROID)
|
||||
struct timespec tv = {0};
|
||||
if (ra_clock_gettime(CLOCK_MONOTONIC, &tv) == 0)
|
||||
time_ticks = (retro_perf_tick_t)tv.tv_sec * 1000000000 +
|
||||
@@ -191,6 +191,8 @@ retro_perf_tick_t cpu_features_get_perf_counter(void)
|
||||
time_ticks = (retro_perf_tick_t)a | ((retro_perf_tick_t)d << 32);
|
||||
#elif defined(__ARM_ARCH_6__)
|
||||
__asm__ volatile( "mrc p15, 0, %0, c9, c13, 0" : "=r"(time_ticks) );
|
||||
#elif defined(__aarch64__)
|
||||
__asm__ volatile( "mrs %0, cntvct_el0" : "=r"(time_ticks) );
|
||||
#elif defined(PSP) || defined(VITA)
|
||||
time_ticks = sceKernelGetSystemTimeWide();
|
||||
#elif defined(PS2)
|
||||
@@ -600,18 +602,20 @@ uint64_t cpu_features_get(void)
|
||||
#endif
|
||||
#if defined(__MACH__)
|
||||
size_t len = sizeof(size_t);
|
||||
|
||||
if (sysctlbyname("hw.optional.floatingpoint", NULL, &len, NULL, 0) == 0)
|
||||
{
|
||||
cpu |= RETRO_SIMD_CMOV;
|
||||
}
|
||||
|
||||
#if defined(CPU_X86)
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.mmx", NULL, &len, NULL, 0) == 0)
|
||||
{
|
||||
cpu |= RETRO_SIMD_MMX;
|
||||
cpu |= RETRO_SIMD_MMXEXT;
|
||||
}
|
||||
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.floatingpoint", NULL, &len, NULL, 0) == 0)
|
||||
{
|
||||
cpu |= RETRO_SIMD_CMOV;
|
||||
}
|
||||
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.sse", NULL, &len, NULL, 0) == 0)
|
||||
cpu |= RETRO_SIMD_SSE;
|
||||
@@ -652,10 +656,19 @@ uint64_t cpu_features_get(void)
|
||||
if (sysctlbyname("hw.optional.altivec", NULL, &len, NULL, 0) == 0)
|
||||
cpu |= RETRO_SIMD_VMX;
|
||||
|
||||
#else
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.neon", NULL, &len, NULL, 0) == 0)
|
||||
cpu |= RETRO_SIMD_NEON;
|
||||
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.neon_fp16", NULL, &len, NULL, 0) == 0)
|
||||
cpu |= RETRO_SIMD_VFPV3;
|
||||
|
||||
len = sizeof(size_t);
|
||||
if (sysctlbyname("hw.optional.neon_hpfp", NULL, &len, NULL, 0) == 0)
|
||||
cpu |= RETRO_SIMD_VFPV4;
|
||||
#endif
|
||||
#elif defined(_XBOX1)
|
||||
cpu |= RETRO_SIMD_MMX;
|
||||
cpu |= RETRO_SIMD_SSE;
|
||||
|
||||
@@ -370,8 +370,7 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state)
|
||||
|
||||
/**
|
||||
* file_archive_extract_file:
|
||||
* @archive_path : filename path to archive.
|
||||
* @archive_path_size : size of archive.
|
||||
* @archive_path : filename path to archive.
|
||||
* @valid_exts : valid extensions for the file.
|
||||
* @extraction_directory : the directory to extract temporary
|
||||
* file to.
|
||||
@@ -382,8 +381,7 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state)
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool file_archive_extract_file(
|
||||
char *archive_path,
|
||||
size_t archive_path_size,
|
||||
const char *archive_path,
|
||||
const char *valid_exts,
|
||||
const char *extraction_directory,
|
||||
char *out_path, size_t len)
|
||||
@@ -396,7 +394,6 @@ bool file_archive_extract_file(
|
||||
userdata.current_file_path[0] = '\0';
|
||||
userdata.first_extracted_file_path = NULL;
|
||||
userdata.extraction_directory = extraction_directory;
|
||||
userdata.archive_path_size = archive_path_size;
|
||||
userdata.ext = list;
|
||||
userdata.list = NULL;
|
||||
userdata.found_file = false;
|
||||
@@ -454,7 +451,6 @@ bool file_archive_get_file_list_noalloc(struct string_list *list,
|
||||
userdata.current_file_path[0] = '\0';
|
||||
userdata.first_extracted_file_path = NULL;
|
||||
userdata.extraction_directory = NULL;
|
||||
userdata.archive_path_size = 0;
|
||||
userdata.ext = NULL;
|
||||
userdata.list = list;
|
||||
userdata.found_file = false;
|
||||
@@ -484,7 +480,6 @@ struct string_list *file_archive_get_file_list(const char *path,
|
||||
userdata.current_file_path[0] = '\0';
|
||||
userdata.first_extracted_file_path = NULL;
|
||||
userdata.extraction_directory = NULL;
|
||||
userdata.archive_path_size = 0;
|
||||
userdata.ext = NULL;
|
||||
userdata.list = string_list_new();
|
||||
userdata.found_file = false;
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#define SEVENZIP_MAGIC "7z\xBC\xAF\x27\x1C"
|
||||
#define SEVENZIP_MAGIC_LEN 6
|
||||
#define SEVENZIP_LOOKTOREAD_BUF_SIZE (1 << 14)
|
||||
|
||||
/* Assume W-functions do not work below Win2K and Xbox platforms */
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
|
||||
@@ -50,25 +51,25 @@ struct sevenzip_context_t
|
||||
{
|
||||
uint8_t *output;
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CLookToRead2 lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
size_t temp_size;
|
||||
uint32_t block_index;
|
||||
uint32_t parse_index;
|
||||
uint32_t decompress_index;
|
||||
uint32_t packIndex;
|
||||
UInt32 block_index;
|
||||
};
|
||||
|
||||
static void *sevenzip_stream_alloc_impl(void *p, size_t size)
|
||||
static void *sevenzip_stream_alloc_impl(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void sevenzip_stream_free_impl(void *p, void *address)
|
||||
static void sevenzip_stream_free_impl(ISzAllocPtr p, void *address)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
@@ -76,7 +77,7 @@ static void sevenzip_stream_free_impl(void *p, void *address)
|
||||
free(address);
|
||||
}
|
||||
|
||||
static void *sevenzip_stream_alloc_tmp_impl(void *p, size_t size)
|
||||
static void *sevenzip_stream_alloc_tmp_impl(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
(void)p;
|
||||
if (size == 0)
|
||||
@@ -98,6 +99,12 @@ static void* sevenzip_stream_new(void)
|
||||
sevenzip_context->block_index = 0xFFFFFFFF;
|
||||
sevenzip_context->output = NULL;
|
||||
|
||||
sevenzip_context->lookStream.bufSize = SEVENZIP_LOOKTOREAD_BUF_SIZE * sizeof(Byte);
|
||||
sevenzip_context->lookStream.buf = (Byte*)malloc(sevenzip_context->lookStream.bufSize);
|
||||
|
||||
if (!sevenzip_context->lookStream.buf)
|
||||
sevenzip_context->lookStream.bufSize = 0;
|
||||
|
||||
return sevenzip_context;
|
||||
}
|
||||
|
||||
@@ -117,6 +124,9 @@ static void sevenzip_parse_file_free(void *context)
|
||||
SzArEx_Free(&sevenzip_context->db, &sevenzip_context->allocImp);
|
||||
File_Close(&sevenzip_context->archiveStream.file);
|
||||
|
||||
if (sevenzip_context->lookStream.buf)
|
||||
free(sevenzip_context->lookStream.buf);
|
||||
|
||||
free(sevenzip_context);
|
||||
}
|
||||
|
||||
@@ -131,7 +141,7 @@ static int64_t sevenzip_file_read(
|
||||
const char *optional_outfile)
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CLookToRead2 lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
@@ -145,6 +155,12 @@ static int64_t sevenzip_file_read(
|
||||
allocTempImp.Alloc = sevenzip_stream_alloc_tmp_impl;
|
||||
allocTempImp.Free = sevenzip_stream_free_impl;
|
||||
|
||||
lookStream.bufSize = SEVENZIP_LOOKTOREAD_BUF_SIZE * sizeof(Byte);
|
||||
lookStream.buf = (Byte*)malloc(lookStream.bufSize);
|
||||
|
||||
if (!lookStream.buf)
|
||||
lookStream.bufSize = 0;
|
||||
|
||||
#if defined(_WIN32) && defined(USE_WINDOWS_FILE) && !defined(LEGACY_WIN32)
|
||||
if (!string_is_empty(path))
|
||||
{
|
||||
@@ -169,51 +185,34 @@ static int64_t sevenzip_file_read(
|
||||
#endif
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead_CreateVTable(&lookStream, false);
|
||||
lookStream.realStream = &archiveStream.s;
|
||||
LookToRead_Init(&lookStream);
|
||||
LookToRead2_CreateVTable(&lookStream, false);
|
||||
lookStream.realStream = &archiveStream.vt;
|
||||
LookToRead2_Init(&lookStream);
|
||||
CrcGenerateTable();
|
||||
|
||||
db.db.PackSizes = NULL;
|
||||
db.db.PackCRCsDefined = NULL;
|
||||
db.db.PackCRCs = NULL;
|
||||
db.db.Folders = NULL;
|
||||
db.db.Files = NULL;
|
||||
db.db.NumPackStreams = 0;
|
||||
db.db.NumFolders = 0;
|
||||
db.db.NumFiles = 0;
|
||||
db.startPosAfterHeader = 0;
|
||||
db.dataPos = 0;
|
||||
db.FolderStartPackStreamIndex = NULL;
|
||||
db.PackStreamStartPositions = NULL;
|
||||
db.FolderStartFileIndex = NULL;
|
||||
db.FileIndexToFolderIndexMap = NULL;
|
||||
db.FileNameOffsets = NULL;
|
||||
db.FileNames.data = NULL;
|
||||
db.FileNames.size = 0;
|
||||
memset(&db, 0, sizeof(db));
|
||||
|
||||
SzArEx_Init(&db);
|
||||
|
||||
if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK)
|
||||
if (SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp) == SZ_OK)
|
||||
{
|
||||
uint32_t i;
|
||||
bool file_found = false;
|
||||
uint16_t *temp = NULL;
|
||||
size_t temp_size = 0;
|
||||
uint32_t block_index = 0xFFFFFFFF;
|
||||
UInt32 block_index = 0xFFFFFFFF;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
for (i = 0; i < db.NumFiles; i++)
|
||||
{
|
||||
size_t len;
|
||||
char infile[PATH_MAX_LENGTH];
|
||||
size_t offset = 0;
|
||||
size_t outSizeProcessed = 0;
|
||||
const CSzFileItem *f = db.db.Files + i;
|
||||
|
||||
/* We skip over everything which is not a directory.
|
||||
* FIXME: Why continue then if f->IsDir is true?*/
|
||||
if (f->IsDir)
|
||||
* FIXME: Why continue then if IsDir is true?*/
|
||||
if (SzArEx_IsDir(&db, i))
|
||||
continue;
|
||||
|
||||
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||
@@ -248,7 +247,7 @@ static int64_t sevenzip_file_read(
|
||||
* sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
|
||||
* */
|
||||
file_found = true;
|
||||
res = SzArEx_Extract(&db, &lookStream.s, i, &block_index,
|
||||
res = SzArEx_Extract(&db, &lookStream.vt, i, &block_index,
|
||||
&output, &output_size, &offset, &outSizeProcessed,
|
||||
&allocImp, &allocTempImp);
|
||||
|
||||
@@ -301,6 +300,9 @@ static int64_t sevenzip_file_read(
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
File_Close(&archiveStream.file);
|
||||
|
||||
if (lookStream.buf)
|
||||
free(lookStream.buf);
|
||||
|
||||
return outsize;
|
||||
}
|
||||
|
||||
@@ -331,7 +333,7 @@ static int sevenzip_stream_decompress_data_to_file_iterate(
|
||||
size_t outSizeProcessed = 0;
|
||||
|
||||
res = SzArEx_Extract(&sevenzip_context->db,
|
||||
&sevenzip_context->lookStream.s, sevenzip_context->decompress_index,
|
||||
&sevenzip_context->lookStream.vt, sevenzip_context->decompress_index,
|
||||
&sevenzip_context->block_index, &sevenzip_context->output,
|
||||
&output_size, &offset, &outSizeProcessed,
|
||||
&sevenzip_context->allocImp, &sevenzip_context->allocTempImp);
|
||||
@@ -388,17 +390,17 @@ static int sevenzip_parse_file_init(file_archive_transfer_t *state,
|
||||
#endif
|
||||
|
||||
FileInStream_CreateVTable(&sevenzip_context->archiveStream);
|
||||
LookToRead_CreateVTable(&sevenzip_context->lookStream, false);
|
||||
sevenzip_context->lookStream.realStream = &sevenzip_context->archiveStream.s;
|
||||
LookToRead_Init(&sevenzip_context->lookStream);
|
||||
LookToRead2_CreateVTable(&sevenzip_context->lookStream, false);
|
||||
sevenzip_context->lookStream.realStream = &sevenzip_context->archiveStream.vt;
|
||||
LookToRead2_Init(&sevenzip_context->lookStream);
|
||||
CrcGenerateTable();
|
||||
SzArEx_Init(&sevenzip_context->db);
|
||||
|
||||
if (SzArEx_Open(&sevenzip_context->db, &sevenzip_context->lookStream.s,
|
||||
if (SzArEx_Open(&sevenzip_context->db, &sevenzip_context->lookStream.vt,
|
||||
&sevenzip_context->allocImp, &sevenzip_context->allocTempImp) != SZ_OK)
|
||||
goto error;
|
||||
|
||||
state->step_total = sevenzip_context->db.db.NumFiles;
|
||||
state->step_total = sevenzip_context->db.NumFiles;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -414,9 +416,7 @@ static int sevenzip_parse_file_iterate_step_internal(
|
||||
uint32_t *size, uint32_t *csize, uint32_t *checksum,
|
||||
unsigned *payback, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
const CSzFileItem *file = sevenzip_context->db.db.Files + sevenzip_context->parse_index;
|
||||
|
||||
if (sevenzip_context->parse_index < sevenzip_context->db.db.NumFiles)
|
||||
if (sevenzip_context->parse_index < sevenzip_context->db.NumFiles)
|
||||
{
|
||||
size_t len = SzArEx_GetFileNameUtf16(&sevenzip_context->db,
|
||||
sevenzip_context->parse_index, NULL);
|
||||
@@ -424,11 +424,14 @@ static int sevenzip_parse_file_iterate_step_internal(
|
||||
|
||||
if (sevenzip_context->packIndex < sevenzip_context->db.db.NumPackStreams)
|
||||
{
|
||||
compressed_size = sevenzip_context->db.db.PackSizes[sevenzip_context->packIndex];
|
||||
compressed_size = sevenzip_context->db.db.PackPositions[sevenzip_context->packIndex + 1] -
|
||||
sevenzip_context->db.db.PackPositions[sevenzip_context->packIndex];
|
||||
|
||||
sevenzip_context->packIndex++;
|
||||
}
|
||||
|
||||
if (len < PATH_MAX_LENGTH && !file->IsDir)
|
||||
if (len < PATH_MAX_LENGTH &&
|
||||
!SzArEx_IsDir(&sevenzip_context->db, sevenzip_context->parse_index))
|
||||
{
|
||||
char infile[PATH_MAX_LENGTH];
|
||||
SRes res = SZ_ERROR_FAIL;
|
||||
@@ -455,8 +458,8 @@ static int sevenzip_parse_file_iterate_step_internal(
|
||||
strlcpy(filename, infile, PATH_MAX_LENGTH);
|
||||
|
||||
*cmode = 0; /* unused for 7zip */
|
||||
*checksum = file->Crc;
|
||||
*size = (uint32_t)file->Size;
|
||||
*checksum = sevenzip_context->db.CRCs.Vals[sevenzip_context->parse_index];
|
||||
*size = (uint32_t)SzArEx_GetFileSize(&sevenzip_context->db, sevenzip_context->parse_index);
|
||||
*csize = (uint32_t)compressed_size;
|
||||
|
||||
*cdata = (uint8_t *)(size_t)sevenzip_context->parse_index;
|
||||
|
||||
@@ -297,7 +297,8 @@ static int zip_file_decompressed(
|
||||
/* Called in case core has need_fullpath enabled. */
|
||||
bool success = filestream_write_file(decomp_state->opt_file, handle.data, size);
|
||||
|
||||
free(handle.data);
|
||||
/* Note: Do not free handle.data here - this
|
||||
* will be done when stream is deinitialised */
|
||||
handle.data = NULL;
|
||||
|
||||
decomp_state->size = 0;
|
||||
@@ -310,10 +311,50 @@ static int zip_file_decompressed(
|
||||
/* Called in case core has need_fullpath disabled.
|
||||
* Will move decompressed content directly into
|
||||
* RetroArch's ROM buffer. */
|
||||
*decomp_state->buf = handle.data;
|
||||
handle.data = NULL;
|
||||
zip_context_t *zip_context = (zip_context_t *)userdata->transfer->context;
|
||||
|
||||
decomp_state->size = size;
|
||||
decomp_state->size = 0;
|
||||
|
||||
/* Unlink data buffer from context (otherwise
|
||||
* it will be freed when the stream is deinitialised) */
|
||||
if (handle.data == zip_context->compressed_data)
|
||||
{
|
||||
/* Well this is fun...
|
||||
* If this is 'compressed' data (if the zip
|
||||
* file was created with the '-0 store only'
|
||||
* flag), and the origin file is mmapped, then
|
||||
* the context compressed_data buffer cannot be
|
||||
* reassigned (since it is not a traditional
|
||||
* block of user-assigned memory). We have to
|
||||
* create a copy of it instead... */
|
||||
#ifdef HAVE_MMAP
|
||||
if (zip_context->state->archive_mmap_data)
|
||||
{
|
||||
uint8_t *temp_buf = (uint8_t*)malloc(csize);
|
||||
|
||||
if (temp_buf)
|
||||
{
|
||||
memcpy(temp_buf, handle.data, csize);
|
||||
*decomp_state->buf = temp_buf;
|
||||
decomp_state->size = csize;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
*decomp_state->buf = handle.data;
|
||||
decomp_state->size = csize;
|
||||
zip_context->compressed_data = NULL;
|
||||
}
|
||||
}
|
||||
else if (handle.data == zip_context->decompressed_data)
|
||||
{
|
||||
*decomp_state->buf = handle.data;
|
||||
decomp_state->size = size;
|
||||
zip_context->decompressed_data = NULL;
|
||||
}
|
||||
|
||||
handle.data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <array/rhmap.h>
|
||||
|
||||
#define MAX_INCLUDE_DEPTH 16
|
||||
|
||||
@@ -273,6 +274,8 @@ static char *config_file_extract_value(char *line, bool is_value)
|
||||
static void config_file_add_child_list(config_file_t *parent, config_file_t *child)
|
||||
{
|
||||
struct config_entry_list *list = child->entries;
|
||||
bool merge_hash_map = false;
|
||||
|
||||
if (parent->entries)
|
||||
{
|
||||
struct config_entry_list *head = parent->entries;
|
||||
@@ -286,6 +289,8 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
list = list->next;
|
||||
}
|
||||
head->next = child->entries;
|
||||
|
||||
merge_hash_map = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -298,8 +303,6 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
parent->entries = child->entries;
|
||||
}
|
||||
|
||||
child->entries = NULL;
|
||||
|
||||
/* Rebase tail. */
|
||||
if (parent->entries)
|
||||
{
|
||||
@@ -312,6 +315,46 @@ static void config_file_add_child_list(config_file_t *parent, config_file_t *chi
|
||||
}
|
||||
else
|
||||
parent->tail = NULL;
|
||||
|
||||
/* Update hash map */
|
||||
if (merge_hash_map)
|
||||
{
|
||||
size_t i;
|
||||
size_t cap;
|
||||
|
||||
/* We are merging two lists - if any child entry
|
||||
* (key) is not present in the parent list, add it
|
||||
* to the parent hash map */
|
||||
for (i = 0, cap = RHMAP_CAP(child->entries_map); i != cap; i++)
|
||||
{
|
||||
uint32_t child_hash = RHMAP_KEY(child->entries_map, i);
|
||||
const char *child_key = RHMAP_KEY_STR(child->entries_map, i);
|
||||
|
||||
if (child_hash &&
|
||||
child_key &&
|
||||
!RHMAP_HAS_FULL(parent->entries_map, child_hash, child_key))
|
||||
{
|
||||
struct config_entry_list *entry = child->entries_map[i];
|
||||
|
||||
if (entry)
|
||||
RHMAP_SET_FULL(parent->entries_map, child_hash, child_key, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/* Child entries map is no longer required,
|
||||
* so free it now */
|
||||
RHMAP_FREE(child->entries_map);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If parent list was originally empty,
|
||||
* take map from child list */
|
||||
RHMAP_FREE(parent->entries_map);
|
||||
parent->entries_map = child->entries_map;
|
||||
child->entries_map = NULL;
|
||||
}
|
||||
|
||||
child->entries = NULL;
|
||||
}
|
||||
|
||||
static void config_file_get_realpath(char *s, size_t len,
|
||||
@@ -426,8 +469,21 @@ static int config_file_load_internal(
|
||||
|
||||
conf->tail = list;
|
||||
|
||||
if (cb && list->key && list->value)
|
||||
cb->config_file_new_entry_cb(list->key, list->value) ;
|
||||
if (list->key)
|
||||
{
|
||||
/* Only add entry to the map if an entry
|
||||
* with the specified value does not
|
||||
* already exist */
|
||||
uint32_t hash = rhmap_hash_string(list->key);
|
||||
|
||||
if (!RHMAP_HAS_FULL(conf->entries_map, hash, list->key))
|
||||
{
|
||||
RHMAP_SET_FULL(conf->entries_map, hash, list->key, list);
|
||||
|
||||
if (cb && list->value)
|
||||
cb->config_file_new_entry_cb(list->key, list->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
@@ -628,6 +684,16 @@ static int config_file_from_string_internal(
|
||||
conf->entries = list;
|
||||
|
||||
conf->tail = list;
|
||||
|
||||
if (list->key)
|
||||
{
|
||||
/* Only add entry to the map if an entry
|
||||
* with the specified value does not
|
||||
* already exist */
|
||||
uint32_t hash = rhmap_hash_string(list->key);
|
||||
if (!RHMAP_HAS_FULL(conf->entries_map, hash, list->key))
|
||||
RHMAP_SET_FULL(conf->entries_map, hash, list->key, list);
|
||||
}
|
||||
}
|
||||
|
||||
if (list != conf->tail)
|
||||
@@ -705,6 +771,9 @@ bool config_file_deinitialize(config_file_t *conf)
|
||||
|
||||
if (conf->path)
|
||||
free(conf->path);
|
||||
|
||||
RHMAP_FREE(conf->entries_map);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -718,9 +787,27 @@ void config_file_free(config_file_t *conf)
|
||||
bool config_append_file(config_file_t *conf, const char *path)
|
||||
{
|
||||
config_file_t *new_conf = config_file_new_from_path_to_string(path);
|
||||
size_t i;
|
||||
size_t cap;
|
||||
|
||||
if (!new_conf)
|
||||
return false;
|
||||
|
||||
/* Update hash map */
|
||||
for (i = 0, cap = RHMAP_CAP(new_conf->entries_map); i != cap; i++)
|
||||
{
|
||||
uint32_t new_hash = RHMAP_KEY(new_conf->entries_map, i);
|
||||
const char *new_key = RHMAP_KEY_STR(new_conf->entries_map, i);
|
||||
|
||||
if (new_hash && new_key)
|
||||
{
|
||||
struct config_entry_list *entry = new_conf->entries_map[i];
|
||||
|
||||
if (entry)
|
||||
RHMAP_SET_FULL(conf->entries_map, new_hash, new_key, entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_conf->tail)
|
||||
{
|
||||
new_conf->tail->next = conf->entries;
|
||||
@@ -818,6 +905,7 @@ void config_file_initialize(struct config_file *conf)
|
||||
return;
|
||||
|
||||
conf->path = NULL;
|
||||
conf->entries_map = NULL;
|
||||
conf->entries = NULL;
|
||||
conf->tail = NULL;
|
||||
conf->last = NULL;
|
||||
@@ -844,16 +932,18 @@ static struct config_entry_list *config_get_entry_internal(
|
||||
struct config_entry_list *entry = NULL;
|
||||
struct config_entry_list *previous = prev ? *prev : NULL;
|
||||
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
{
|
||||
if (string_is_equal(key, entry->key))
|
||||
return entry;
|
||||
entry = RHMAP_GET_STR(conf->entries_map, key);
|
||||
|
||||
previous = entry;
|
||||
}
|
||||
if (entry)
|
||||
return entry;
|
||||
|
||||
if (prev)
|
||||
{
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
previous = entry;
|
||||
|
||||
*prev = previous;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -861,16 +951,9 @@ static struct config_entry_list *config_get_entry_internal(
|
||||
struct config_entry_list *config_get_entry(
|
||||
const config_file_t *conf, const char *key)
|
||||
{
|
||||
struct config_entry_list *entry = NULL;
|
||||
for (entry = conf->entries; entry; entry = entry->next)
|
||||
{
|
||||
if (string_is_equal(key, entry->key))
|
||||
return entry;
|
||||
}
|
||||
return NULL;
|
||||
return RHMAP_GET_STR(conf->entries_map, key);
|
||||
}
|
||||
|
||||
|
||||
bool config_get_double(config_file_t *conf, const char *key, double *in)
|
||||
{
|
||||
const struct config_entry_list *entry = config_get_entry(conf, key);
|
||||
@@ -1141,6 +1224,8 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
|
||||
conf->entries = entry;
|
||||
|
||||
conf->last = entry;
|
||||
|
||||
RHMAP_SET_STR(conf->entries_map, entry->key, entry);
|
||||
}
|
||||
|
||||
void config_unset(config_file_t *conf, const char *key)
|
||||
@@ -1157,6 +1242,8 @@ void config_unset(config_file_t *conf, const char *key)
|
||||
if (!entry)
|
||||
return;
|
||||
|
||||
(void)RHMAP_DEL_STR(conf->entries_map, entry->key);
|
||||
|
||||
if (entry->key)
|
||||
free(entry->key);
|
||||
|
||||
@@ -1376,16 +1463,7 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
|
||||
|
||||
bool config_entry_exists(config_file_t *conf, const char *entry)
|
||||
{
|
||||
struct config_entry_list *list = conf->entries;
|
||||
|
||||
while (list)
|
||||
{
|
||||
if (string_is_equal(entry, list->key))
|
||||
return true;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return false;
|
||||
return (bool)RHMAP_HAS_STR(conf->entries_map, entry);
|
||||
}
|
||||
|
||||
bool config_get_entry_list_head(config_file_t *conf,
|
||||
|
||||
@@ -87,41 +87,53 @@ const char *path_get_archive_delim(const char *path)
|
||||
|
||||
buf[0] = '\0';
|
||||
|
||||
/* We search for delimiters after the last slash
|
||||
* in the file path to avoid capturing delimiter
|
||||
* characters in any parent directory names.
|
||||
* If there are no slashes in the file name, then
|
||||
* the path is just the file basename - in this
|
||||
* case we search the path in its entirety */
|
||||
if (!last_slash)
|
||||
return NULL;
|
||||
last_slash = path;
|
||||
|
||||
/* Find delimiter position */
|
||||
delim = strrchr(last_slash, '#');
|
||||
/* Find delimiter position
|
||||
* > Since filenames may contain '#' characters,
|
||||
* must loop until we find the first '#' that
|
||||
* is directly *after* a compression extension */
|
||||
delim = strchr(last_slash, '#');
|
||||
|
||||
if (!delim)
|
||||
return NULL;
|
||||
|
||||
/* Check whether this is a known archive type
|
||||
* > Note: The code duplication here is
|
||||
* deliberate, to maximise performance */
|
||||
if (delim - last_slash > 4)
|
||||
while (delim)
|
||||
{
|
||||
strlcpy(buf, delim - 4, sizeof(buf));
|
||||
buf[4] = '\0';
|
||||
/* Check whether this is a known archive type
|
||||
* > Note: The code duplication here is
|
||||
* deliberate, to maximise performance */
|
||||
if (delim - last_slash > 4)
|
||||
{
|
||||
strlcpy(buf, delim - 4, sizeof(buf));
|
||||
buf[4] = '\0';
|
||||
|
||||
string_to_lower(buf);
|
||||
string_to_lower(buf);
|
||||
|
||||
/* Check if this is a '.zip', '.apk' or '.7z' file */
|
||||
if (string_is_equal(buf, ".zip") ||
|
||||
string_is_equal(buf, ".apk") ||
|
||||
string_is_equal(buf + 1, ".7z"))
|
||||
return delim;
|
||||
}
|
||||
else if (delim - last_slash > 3)
|
||||
{
|
||||
strlcpy(buf, delim - 3, sizeof(buf));
|
||||
buf[3] = '\0';
|
||||
/* Check if this is a '.zip', '.apk' or '.7z' file */
|
||||
if (string_is_equal(buf, ".zip") ||
|
||||
string_is_equal(buf, ".apk") ||
|
||||
string_is_equal(buf + 1, ".7z"))
|
||||
return delim;
|
||||
}
|
||||
else if (delim - last_slash > 3)
|
||||
{
|
||||
strlcpy(buf, delim - 3, sizeof(buf));
|
||||
buf[3] = '\0';
|
||||
|
||||
string_to_lower(buf);
|
||||
string_to_lower(buf);
|
||||
|
||||
/* Check if this is a '.7z' file */
|
||||
if (string_is_equal(buf, ".7z"))
|
||||
return delim;
|
||||
/* Check if this is a '.7z' file */
|
||||
if (string_is_equal(buf, ".7z"))
|
||||
return delim;
|
||||
}
|
||||
|
||||
delim++;
|
||||
delim = strchr(delim, '#');
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -638,16 +650,31 @@ bool path_is_absolute(const char *path)
|
||||
char *path_resolve_realpath(char *buf, size_t size, bool resolve_symlinks)
|
||||
{
|
||||
#if !defined(RARCH_CONSOLE) && defined(RARCH_INTERNAL)
|
||||
char tmp[PATH_MAX_LENGTH];
|
||||
#ifdef _WIN32
|
||||
strlcpy(tmp, buf, sizeof(tmp));
|
||||
if (!_fullpath(buf, tmp, size))
|
||||
char *ret = NULL;
|
||||
wchar_t abs_path[PATH_MAX_LENGTH];
|
||||
wchar_t *rel_path = utf8_to_utf16_string_alloc(buf);
|
||||
|
||||
if (rel_path)
|
||||
{
|
||||
strlcpy(buf, tmp, size);
|
||||
return NULL;
|
||||
if (_wfullpath(abs_path, rel_path, PATH_MAX_LENGTH))
|
||||
{
|
||||
char *tmp = utf16_to_utf8_string_alloc(abs_path);
|
||||
|
||||
if (tmp)
|
||||
{
|
||||
strlcpy(buf, tmp, size);
|
||||
free(tmp);
|
||||
ret = buf;
|
||||
}
|
||||
}
|
||||
|
||||
free(rel_path);
|
||||
}
|
||||
return buf;
|
||||
|
||||
return ret;
|
||||
#else
|
||||
char tmp[PATH_MAX_LENGTH];
|
||||
size_t t;
|
||||
char *p;
|
||||
const char *next;
|
||||
|
||||
@@ -1235,7 +1235,13 @@ chd_error chd_get_metadata(chd_file *chd, UINT32 searchtag, UINT32 searchindex,
|
||||
UINT32 faux_length;
|
||||
|
||||
/* fill in the faux metadata */
|
||||
sprintf(faux_metadata, HARD_DISK_METADATA_FORMAT, chd->header.obsolete_cylinders, chd->header.obsolete_heads, chd->header.obsolete_sectors, chd->header.hunkbytes / chd->header.obsolete_hunksize);
|
||||
snprintf(faux_metadata,
|
||||
sizeof(faux_metadata),
|
||||
HARD_DISK_METADATA_FORMAT,
|
||||
chd->header.obsolete_cylinders,
|
||||
chd->header.obsolete_heads,
|
||||
chd->header.obsolete_sectors,
|
||||
chd->header.hunkbytes / chd->header.obsolete_hunksize);
|
||||
faux_length = (UINT32)strlen(faux_metadata) + 1;
|
||||
|
||||
/* copy the metadata itself */
|
||||
|
||||
@@ -42,12 +42,12 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <zlib.h>
|
||||
#include <libchdr/chd.h>
|
||||
#include <libchdr/minmax.h>
|
||||
#include <libchdr/cdrom.h>
|
||||
#include <libchdr/lzma.h>
|
||||
#include <libchdr/huffman.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#include <retro_inline.h>
|
||||
#include <streams/file_stream.h>
|
||||
|
||||
@@ -1035,7 +1035,9 @@ bool rpng_iterate_image(rpng_t *rpng)
|
||||
rpng->ihdr.interlace = buf[12];
|
||||
|
||||
if ( rpng->ihdr.width == 0
|
||||
|| rpng->ihdr.height == 0)
|
||||
|| rpng->ihdr.height == 0
|
||||
/* ensure multiplications don't overflow and wrap around, that'd give buffer overflow crashes */
|
||||
|| (uint64_t)rpng->ihdr.width*rpng->ihdr.height*sizeof(uint32_t) >= 0x80000000)
|
||||
return false;
|
||||
|
||||
if (!png_process_ihdr(&rpng->ihdr))
|
||||
@@ -1169,6 +1171,7 @@ error:
|
||||
if (rpng->process->stream)
|
||||
rpng->process->stream_backend->stream_free(rpng->process->stream);
|
||||
free(rpng->process);
|
||||
rpng->process = NULL;
|
||||
}
|
||||
return IMAGE_PROCESS_ERROR;
|
||||
}
|
||||
|
||||
@@ -109,18 +109,19 @@
|
||||
#define RHMAP_MAX(b) ((b) ? RHMAP__HDR(b)->maxlen : 0)
|
||||
#define RHMAP_CAP(b) ((b) ? RHMAP__HDR(b)->maxlen + 1 : 0)
|
||||
#define RHMAP_KEY(b, idx) (RHMAP__HDR(b)->keys[idx])
|
||||
#define RHMAP_KEY_STR(b, idx) (RHMAP__HDR(b)->key_strs[idx])
|
||||
#define RHMAP_SETNULLVAL(b, val) (RHMAP__FIT1(b), b[-1] = (val))
|
||||
#define RHMAP_CLEAR(b) ((b) ? (memset(RHMAP__HDR(b)->keys, 0, RHMAP_CAP(b) * sizeof(uint32_t)), RHMAP__HDR(b)->len = 0) : 0)
|
||||
#define RHMAP_FREE(b) ((b) ? (free(RHMAP__HDR(b)->keys), free(RHMAP__HDR(b)), (b) = NULL) : 0)
|
||||
#define RHMAP_FREE(b) ((b) ? (rhmap__free(RHMAP__HDR(b)), (b) = NULL) : 0)
|
||||
#define RHMAP_FIT(b, n) ((!(n) || ((b) && (size_t)(n) * 2 <= RHMAP_MAX(b))) ? 0 : RHMAP__GROW(b, n))
|
||||
#define RHMAP_TRYFIT(b, n) (RHMAP_FIT((b), (n)), (!(n) || ((b) && (size_t)(n) * 2 <= RHMAP_MAX(b))))
|
||||
|
||||
#define RHMAP_SET(b, key, val) (RHMAP__FIT1(b), b[rhmap__idx(RHMAP__HDR(b), (key), 1, 0)] = (val))
|
||||
#define RHMAP_GET(b, key) (RHMAP__FIT1(b), b[rhmap__idx(RHMAP__HDR(b), (key), 0, 0)])
|
||||
#define RHMAP_HAS(b, key) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), 0, 0) != -1 : 0)
|
||||
#define RHMAP_DEL(b, key) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), 0, sizeof(*(b))) != -1 : 0)
|
||||
#define RHMAP_PTR(b, key) (RHMAP__FIT1(b), &b[rhmap__idx(RHMAP__HDR(b), (key), 1, 0)])
|
||||
#define RHMAP_IDX(b, key) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), 0, 0) : -1)
|
||||
#define RHMAP_SET(b, key, val) RHMAP_SET_FULL(b, key, NULL, val)
|
||||
#define RHMAP_GET(b, key) RHMAP_GET_FULL(b, key, NULL)
|
||||
#define RHMAP_HAS(b, key) RHMAP_HAS_FULL(b, key, NULL)
|
||||
#define RHMAP_DEL(b, key) RHMAP_DEL_FULL(b, key, NULL)
|
||||
#define RHMAP_PTR(b, key) RHMAP_PTR_FULL(b, key, NULL)
|
||||
#define RHMAP_IDX(b, key) RHMAP_IDX_FULL(b, key, NULL)
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define RHMAP__UNUSED __attribute__((__unused__))
|
||||
@@ -133,14 +134,21 @@
|
||||
#pragma warning(disable:4505) //unreferenced local function has been removed
|
||||
#endif
|
||||
|
||||
#define RHMAP_SET_STR(b, string_key, val) RHMAP_SET(b, hash_string(string_key), val)
|
||||
#define RHMAP_GET_STR(b, string_key) RHMAP_GET(b, hash_string(string_key))
|
||||
#define RHMAP_HAS_STR(b, string_key) RHMAP_HAS(b, hash_string(string_key))
|
||||
#define RHMAP_DEL_STR(b, string_key) RHMAP_DEL(b, hash_string(string_key))
|
||||
#define RHMAP_PTR_STR(b, string_key) RHMAP_PTR(b, hash_string(string_key))
|
||||
#define RHMAP_IDX_STR(b, string_key) RHMAP_IDX(b, hash_string(string_key))
|
||||
#define RHMAP_SET_FULL(b, key, str, val) (RHMAP__FIT1(b), b[rhmap__idx(RHMAP__HDR(b), (key), (str), 1, 0)] = (val))
|
||||
#define RHMAP_GET_FULL(b, key, str) (RHMAP__FIT1(b), b[rhmap__idx(RHMAP__HDR(b), (key), (str), 0, 0)])
|
||||
#define RHMAP_HAS_FULL(b, key, str) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), (str), 0, 0) != -1 : 0)
|
||||
#define RHMAP_DEL_FULL(b, key, str) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), (str), 0, sizeof(*(b))) != -1 : 0)
|
||||
#define RHMAP_PTR_FULL(b, key, str) (RHMAP__FIT1(b), &b[rhmap__idx(RHMAP__HDR(b), (key), (str), 1, 0)])
|
||||
#define RHMAP_IDX_FULL(b, key, str) ((b) ? rhmap__idx(RHMAP__HDR(b), (key), (str), 0, 0) : -1)
|
||||
|
||||
RHMAP__UNUSED static uint32_t hash_string(const char* str)
|
||||
#define RHMAP_SET_STR(b, string_key, val) RHMAP_SET_FULL(b, rhmap_hash_string(string_key), string_key, val)
|
||||
#define RHMAP_GET_STR(b, string_key) RHMAP_GET_FULL(b, rhmap_hash_string(string_key), string_key)
|
||||
#define RHMAP_HAS_STR(b, string_key) RHMAP_HAS_FULL(b, rhmap_hash_string(string_key), string_key)
|
||||
#define RHMAP_DEL_STR(b, string_key) RHMAP_DEL_FULL(b, rhmap_hash_string(string_key), string_key)
|
||||
#define RHMAP_PTR_STR(b, string_key) RHMAP_PTR_FULL(b, rhmap_hash_string(string_key), string_key)
|
||||
#define RHMAP_IDX_STR(b, string_key) RHMAP_IDX_FULL(b, rhmap_hash_string(string_key), string_key)
|
||||
|
||||
RHMAP__UNUSED static uint32_t rhmap_hash_string(const char* str)
|
||||
{
|
||||
unsigned char c;
|
||||
uint32_t hash = (uint32_t)0x811c9dc5;
|
||||
@@ -149,7 +157,7 @@ RHMAP__UNUSED static uint32_t hash_string(const char* str)
|
||||
return (hash ? hash : 1);
|
||||
}
|
||||
|
||||
struct rhmap__hdr { size_t len, maxlen; uint32_t *keys; };
|
||||
struct rhmap__hdr { size_t len, maxlen; uint32_t *keys; char** key_strs; };
|
||||
#define RHMAP__HDR(b) (((struct rhmap__hdr *)&(b)[-1])-1)
|
||||
#define RHMAP__GROW(b, n) (*(void**)(&(b)) = rhmap__grow(RHMAP__HDR(b), (void*)(b), sizeof(*(b)), (size_t)(n)))
|
||||
#define RHMAP__FIT1(b) ((b) && RHMAP_LEN(b) * 2 <= RHMAP_MAX(b) ? 0 : RHMAP__GROW(b, 0))
|
||||
@@ -170,7 +178,19 @@ RHMAP__UNUSED static void* rhmap__grow(struct rhmap__hdr *old_hdr, void* old_ptr
|
||||
new_hdr->maxlen = new_max;
|
||||
new_hdr->keys = (uint32_t *)calloc(new_max + 1, sizeof(uint32_t));
|
||||
if (!new_hdr->keys)
|
||||
return (void*)((void)(free(new_hdr)), old_ptr); /* out of memory */
|
||||
{
|
||||
/* out of memory */
|
||||
free(new_hdr);
|
||||
return old_ptr;
|
||||
}
|
||||
new_hdr->key_strs = (char**)calloc(new_max + 1, sizeof(char*));
|
||||
if (!new_hdr->key_strs)
|
||||
{
|
||||
/* out of memory */
|
||||
free(new_hdr->keys);
|
||||
free(new_hdr);
|
||||
return old_ptr;
|
||||
}
|
||||
|
||||
new_vals = ((char*)(new_hdr + 1)) + elem_size;
|
||||
if (old_ptr)
|
||||
@@ -187,6 +207,7 @@ RHMAP__UNUSED static void* rhmap__grow(struct rhmap__hdr *old_hdr, void* old_ptr
|
||||
if (!new_hdr->keys[j &= new_hdr->maxlen])
|
||||
{
|
||||
new_hdr->keys[j] = key;
|
||||
new_hdr->key_strs[j] = old_hdr->key_strs[i];
|
||||
memcpy(new_vals + j * elem_size, old_vals + i * elem_size, elem_size);
|
||||
break;
|
||||
}
|
||||
@@ -195,6 +216,7 @@ RHMAP__UNUSED static void* rhmap__grow(struct rhmap__hdr *old_hdr, void* old_ptr
|
||||
memcpy(new_vals - elem_size, old_vals - elem_size, elem_size);
|
||||
new_hdr->len = old_hdr->len;
|
||||
free(old_hdr->keys);
|
||||
free(old_hdr->key_strs);
|
||||
free(old_hdr);
|
||||
}
|
||||
else
|
||||
@@ -205,7 +227,7 @@ RHMAP__UNUSED static void* rhmap__grow(struct rhmap__hdr *old_hdr, void* old_ptr
|
||||
return new_vals;
|
||||
}
|
||||
|
||||
RHMAP__UNUSED static ptrdiff_t rhmap__idx(struct rhmap__hdr* hdr, uint32_t key, int add, size_t del)
|
||||
RHMAP__UNUSED static ptrdiff_t rhmap__idx(struct rhmap__hdr* hdr, uint32_t key, const char * str, int add, size_t del)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
@@ -214,17 +236,21 @@ RHMAP__UNUSED static ptrdiff_t rhmap__idx(struct rhmap__hdr* hdr, uint32_t key,
|
||||
|
||||
for (i = key;; i++)
|
||||
{
|
||||
if (hdr->keys[i &= hdr->maxlen] == key)
|
||||
if (hdr->keys[i &= hdr->maxlen] == key && (!hdr->key_strs[i] || !str || !strcmp(hdr->key_strs[i], str)))
|
||||
{
|
||||
if (del)
|
||||
{
|
||||
hdr->len--;
|
||||
hdr->keys[i] = 0;
|
||||
free(hdr->key_strs[i]);
|
||||
hdr->key_strs[i] = NULL;
|
||||
while ((key = hdr->keys[i = (i + 1) & hdr->maxlen]) != 0)
|
||||
{
|
||||
if ((key = (uint32_t)rhmap__idx(hdr, key, 1, 0)) == i) continue;
|
||||
if ((key = (uint32_t)rhmap__idx(hdr, key, str, 1, 0)) == i) continue;
|
||||
hdr->len--;
|
||||
hdr->keys[i] = 0;
|
||||
free(hdr->key_strs[i]);
|
||||
hdr->key_strs[i] = NULL;
|
||||
memcpy(((char*)(hdr + 1)) + (key + 1) * del,
|
||||
((char*)(hdr + 1)) + (i + 1) * del, del);
|
||||
}
|
||||
@@ -233,12 +259,24 @@ RHMAP__UNUSED static ptrdiff_t rhmap__idx(struct rhmap__hdr* hdr, uint32_t key,
|
||||
}
|
||||
if (!hdr->keys[i])
|
||||
{
|
||||
if (add) { hdr->len++; hdr->keys[i] = key; return (ptrdiff_t)i; }
|
||||
if (add) { hdr->len++; hdr->keys[i] = key; if (str) hdr->key_strs[i] = strdup(str); return (ptrdiff_t)i; }
|
||||
return (ptrdiff_t)-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RHMAP__UNUSED static void rhmap__free(struct rhmap__hdr* hdr)
|
||||
{
|
||||
size_t i;
|
||||
for (i=0;i<hdr->maxlen+1;i++)
|
||||
{
|
||||
free(hdr->key_strs[i]);
|
||||
}
|
||||
free(hdr->key_strs);
|
||||
free(hdr->keys);
|
||||
free(hdr);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
/* Copyright (C) 2010-2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (cocoa_defines.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __COCOA_COMMON_DEFINES_H
|
||||
#define __COCOA_COMMON_DEFINES_H
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_12
|
||||
#define MAC_OS_X_VERSION_10_12 101200
|
||||
#endif
|
||||
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
|
||||
#define NSEventModifierFlagCommand NSCommandKeyMask
|
||||
#define NSEventModifierFlagControl NSControlKeyMask
|
||||
#define NSEventModifierFlagHelp NSHelpKeyMask
|
||||
#define NSEventModifierFlagNumericPad NSNumericPadKeyMask
|
||||
#define NSEventModifierFlagOption NSAlternateKeyMask
|
||||
#define NSEventModifierFlagShift NSShiftKeyMask
|
||||
#define NSCompositingOperationSourceOver NSCompositeSourceOver
|
||||
#define NSEventMaskApplicationDefined NSApplicationDefinedMask
|
||||
#define NSEventTypeApplicationDefined NSApplicationDefined
|
||||
#define NSEventTypeCursorUpdate NSCursorUpdate
|
||||
#define NSEventTypeMouseMoved NSMouseMoved
|
||||
#define NSEventTypeMouseEntered NSMouseEntered
|
||||
#define NSEventTypeMouseExited NSMouseExited
|
||||
#define NSEventTypeLeftMouseDown NSLeftMouseDown
|
||||
#define NSEventTypeRightMouseDown NSRightMouseDown
|
||||
#define NSEventTypeOtherMouseDown NSOtherMouseDown
|
||||
#define NSEventTypeLeftMouseUp NSLeftMouseUp
|
||||
#define NSEventTypeRightMouseUp NSRightMouseUp
|
||||
#define NSEventTypeOtherMouseUp NSOtherMouseUp
|
||||
#define NSEventTypeLeftMouseDragged NSLeftMouseDragged
|
||||
#define NSEventTypeRightMouseDragged NSRightMouseDragged
|
||||
#define NSEventTypeOtherMouseDragged NSOtherMouseDragged
|
||||
#define NSEventTypeScrollWheel NSScrollWheel
|
||||
#define NSEventTypeKeyDown NSKeyDown
|
||||
#define NSEventTypeKeyUp NSKeyUp
|
||||
#define NSEventTypeFlagsChanged NSFlagsChanged
|
||||
#define NSEventMaskAny NSAnyEventMask
|
||||
#define NSWindowStyleMaskBorderless NSBorderlessWindowMask
|
||||
#define NSWindowStyleMaskClosable NSClosableWindowMask
|
||||
#define NSWindowStyleMaskFullScreen NSFullScreenWindowMask
|
||||
#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
|
||||
#define NSWindowStyleMaskResizable NSResizableWindowMask
|
||||
#define NSWindowStyleMaskTitled NSTitledWindowMask
|
||||
#define NSAlertStyleCritical NSCriticalAlertStyle
|
||||
#define NSAlertStyleInformational NSInformationalAlertStyle
|
||||
#define NSAlertStyleWarning NSWarningAlertStyle
|
||||
#define NSEventModifierFlagCapsLock NSAlphaShiftKeyMask
|
||||
#define NSControlSizeRegular NSRegularControlSize
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,92 @@
|
||||
/* Copyright (C) 2010-2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (d3d_defines.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef D3DVIDEO_DEFINES_H
|
||||
#define D3DVIDEO_DEFINES_H
|
||||
|
||||
#if defined(DEBUG) || defined(_DEBUG)
|
||||
#define D3D_DEBUG_INFO
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D9)
|
||||
/* Direct3D 9 */
|
||||
#if 0
|
||||
#include <d3d9.h>
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define LPDIRECT3D LPDIRECT3D9
|
||||
#define LPDIRECT3DDEVICE LPDIRECT3DDEVICE9
|
||||
#define LPDIRECT3DTEXTURE LPDIRECT3DTEXTURE9
|
||||
#define LPDIRECT3DCUBETEXTURE LPDIRECT3DCUBETEXTURE9
|
||||
#define LPDIRECT3DVERTEXBUFFER LPDIRECT3DVERTEXBUFFER9
|
||||
#define LPDIRECT3DVERTEXSHADER LPDIRECT3DVERTEXSHADER9
|
||||
#define LPDIRECT3DPIXELSHADER LPDIRECT3DPIXELSHADER9
|
||||
#define LPDIRECT3DSURFACE LPDIRECT3DSURFACE9
|
||||
#define LPDIRECT3DVERTEXDECLARATION LPDIRECT3DVERTEXDECLARATION9
|
||||
#define LPDIRECT3DVOLUMETEXTURE LPDIRECT3DVOLUMETEXTURE9
|
||||
#define LPDIRECT3DRESOURCE LPDIRECT3DRESOURCE9
|
||||
#define D3DVERTEXELEMENT D3DVERTEXELEMENT9
|
||||
#define D3DVIEWPORT D3DVIEWPORT9
|
||||
#endif
|
||||
|
||||
#ifndef D3DCREATE_SOFTWARE_VERTEXPROCESSING
|
||||
#define D3DCREATE_SOFTWARE_VERTEXPROCESSING 0
|
||||
#endif
|
||||
|
||||
#elif defined(HAVE_D3D8)
|
||||
#if 0
|
||||
#ifdef _XBOX
|
||||
#include <xtl.h>
|
||||
#else
|
||||
#include "../gfx/include/d3d8/d3d8.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Direct3D 8 */
|
||||
#if 0
|
||||
#define LPDIRECT3D LPDIRECT3D8
|
||||
#define LPDIRECT3DDEVICE LPDIRECT3DDEVICE8
|
||||
#define LPDIRECT3DTEXTURE LPDIRECT3DTEXTURE8
|
||||
#define LPDIRECT3DCUBETEXTURE LPDIRECT3DCUBETEXTURE8
|
||||
#define LPDIRECT3DVOLUMETEXTURE LPDIRECT3DVOLUMETEXTURE8
|
||||
#define LPDIRECT3DVERTEXBUFFER LPDIRECT3DVERTEXBUFFER8
|
||||
#define LPDIRECT3DVERTEXDECLARATION (void*)
|
||||
#define LPDIRECT3DSURFACE LPDIRECT3DSURFACE8
|
||||
#define LPDIRECT3DRESOURCE LPDIRECT3DRESOURCE8
|
||||
#define D3DVERTEXELEMENT D3DVERTEXELEMENT8
|
||||
#define D3DVIEWPORT D3DVIEWPORT8
|
||||
#endif
|
||||
|
||||
#if !defined(D3DLOCK_NOSYSLOCK) && defined(_XBOX)
|
||||
#define D3DLOCK_NOSYSLOCK (0)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define D3DSAMP_ADDRESSU D3DTSS_ADDRESSU
|
||||
#define D3DSAMP_ADDRESSV D3DTSS_ADDRESSV
|
||||
#define D3DSAMP_MAGFILTER D3DTSS_MAGFILTER
|
||||
#define D3DSAMP_MINFILTER D3DTSS_MINFILTER
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Copyright (C) 2010-2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (gx_defines.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GX_DEFINES_H
|
||||
#define _GX_DEFINES_H
|
||||
|
||||
#ifdef GEKKO
|
||||
|
||||
#define SYSMEM1_SIZE 0x01800000
|
||||
|
||||
#define _SHIFTL(v, s, w) ((uint32_t) (((uint32_t)(v) & ((0x01 << (w)) - 1)) << (s)))
|
||||
#define _SHIFTR(v, s, w) ((uint32_t)(((uint32_t)(v) >> (s)) & ((0x01 << (w)) - 1)))
|
||||
|
||||
#define OSThread lwp_t
|
||||
#define OSCond lwpq_t
|
||||
#define OSThreadQueue lwpq_t
|
||||
|
||||
#define OSInitMutex(mutex) LWP_MutexInit(mutex, 0)
|
||||
#define OSLockMutex(mutex) LWP_MutexLock(mutex)
|
||||
#define OSUnlockMutex(mutex) LWP_MutexUnlock(mutex)
|
||||
#define OSTryLockMutex(mutex) LWP_MutexTryLock(mutex)
|
||||
|
||||
#define OSInitCond(cond) LWP_CondInit(cond)
|
||||
#define OSSignalCond(cond) LWP_ThreadSignal(cond)
|
||||
#define OSWaitCond(cond, mutex) LWP_CondWait(cond, mutex)
|
||||
|
||||
#define OSInitThreadQueue(queue) LWP_InitQueue(queue)
|
||||
#define OSCloseThreadQueue(queue) LWP_CloseQueue(queue)
|
||||
#define OSSleepThread(queue) LWP_ThreadSleep(queue)
|
||||
#define OSJoinThread(thread, val) LWP_JoinThread(thread, val)
|
||||
|
||||
#define OSCreateThread(thread, func, intarg, ptrarg, stackbase, stacksize, priority, attrs) LWP_CreateThread(thread, func, ptrarg, stackbase, stacksize, priority)
|
||||
|
||||
#define BLIT_LINE_16(off) \
|
||||
{ \
|
||||
const uint32_t *tmp_src = src; \
|
||||
uint32_t *tmp_dst = dst; \
|
||||
for (unsigned x = 0; x < width2 >> 1; x++, tmp_src += 2, tmp_dst += 8) \
|
||||
{ \
|
||||
tmp_dst[ 0 + off] = BLIT_LINE_16_CONV(tmp_src[0]); \
|
||||
tmp_dst[ 1 + off] = BLIT_LINE_16_CONV(tmp_src[1]); \
|
||||
} \
|
||||
src += tmp_pitch; \
|
||||
}
|
||||
|
||||
#define BLIT_LINE_32(off) \
|
||||
{ \
|
||||
const uint16_t *tmp_src = src; \
|
||||
uint16_t *tmp_dst = dst; \
|
||||
for (unsigned x = 0; x < width2 >> 3; x++, tmp_src += 8, tmp_dst += 32) \
|
||||
{ \
|
||||
tmp_dst[ 0 + off] = tmp_src[0] | 0xFF00; \
|
||||
tmp_dst[ 16 + off] = tmp_src[1]; \
|
||||
tmp_dst[ 1 + off] = tmp_src[2] | 0xFF00; \
|
||||
tmp_dst[ 17 + off] = tmp_src[3]; \
|
||||
tmp_dst[ 2 + off] = tmp_src[4] | 0xFF00; \
|
||||
tmp_dst[ 18 + off] = tmp_src[5]; \
|
||||
tmp_dst[ 3 + off] = tmp_src[6] | 0xFF00; \
|
||||
tmp_dst[ 19 + off] = tmp_src[7]; \
|
||||
} \
|
||||
src += tmp_pitch; \
|
||||
}
|
||||
|
||||
#define CHUNK_FRAMES 64
|
||||
#define CHUNK_SIZE (CHUNK_FRAMES * sizeof(uint32_t))
|
||||
#define BLOCKS 16
|
||||
|
||||
#define AIInit AUDIO_Init
|
||||
#define AIInitDMA AUDIO_InitDMA
|
||||
#define AIStartDMA AUDIO_StartDMA
|
||||
#define AIStopDMA AUDIO_StopDMA
|
||||
#define AIRegisterDMACallback AUDIO_RegisterDMACallback
|
||||
#define AISetDSPSampleRate AUDIO_SetDSPSampleRate
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,704 @@
|
||||
/* Copyright (C) 2010-2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (ps3_defines.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _PS3_DEFINES_H
|
||||
#define _PS3_DEFINES_H
|
||||
|
||||
/*============================================================
|
||||
AUDIO PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <audio/audio.h>
|
||||
#include <sys/thread.h>
|
||||
|
||||
#include <sys/event_queue.h>
|
||||
#include <lv2/mutex.h>
|
||||
#include <lv2/cond.h>
|
||||
|
||||
/*forward decl. for audioAddData */
|
||||
extern int audioAddData(uint32_t portNum, float *data,
|
||||
uint32_t frames, float volume);
|
||||
|
||||
#define PS3_SYS_NO_TIMEOUT 0
|
||||
#define param_attrib attrib
|
||||
|
||||
#else
|
||||
#include <sdk_version.h>
|
||||
#include <cell/audio.h>
|
||||
#include <sys/event.h>
|
||||
#include <sys/synchronization.h>
|
||||
|
||||
#define numChannels nChannel
|
||||
#define numBlocks nBlock
|
||||
#define param_attrib attr
|
||||
|
||||
#define audioQuit cellAudioQuit
|
||||
#define audioInit cellAudioInit
|
||||
#define audioPortStart cellAudioPortStart
|
||||
#define audioPortOpen cellAudioPortOpen
|
||||
#define audioPortClose cellAudioPortClose
|
||||
#define audioPortStop cellAudioPortStop
|
||||
#define audioPortParam CellAudioPortParam
|
||||
#define audioPortOpen cellAudioPortOpen
|
||||
#define audioAddData cellAudioAddData
|
||||
|
||||
/* event queue functions */
|
||||
#define sysEventQueueReceive sys_event_queue_receive
|
||||
#define audioSetNotifyEventQueue cellAudioSetNotifyEventQueue
|
||||
#define audioRemoveNotifyEventQueue cellAudioRemoveNotifyEventQueue
|
||||
#define audioCreateNotifyEventQueue cellAudioCreateNotifyEventQueue
|
||||
|
||||
#define sysLwCondCreate sys_lwcond_create
|
||||
#define sysLwCondDestroy sys_lwcond_destroy
|
||||
#define sysLwCondWait sys_lwcond_wait
|
||||
#define sysLwCondSignal sys_lwcond_signal
|
||||
|
||||
#define sysLwMutexDestroy sys_lwmutex_destroy
|
||||
#define sysLwMutexLock sys_lwmutex_lock
|
||||
#define sysLwMutexUnlock sys_lwmutex_unlock
|
||||
#define sysLwMutexCreate sys_lwmutex_create
|
||||
|
||||
#define AUDIO_BLOCK_SAMPLES CELL_AUDIO_BLOCK_SAMPLES
|
||||
#define SYSMODULE_NET CELL_SYSMODULE_NET
|
||||
#define PS3_SYS_NO_TIMEOUT SYS_NO_TIMEOUT
|
||||
|
||||
#define sys_lwmutex_attr_t sys_lwmutex_attribute_t
|
||||
#define sys_lwcond_attr_t sys_lwcond_attribute_t
|
||||
#define sys_sem_t sys_semaphore_t
|
||||
|
||||
#define sysGetSystemTime sys_time_get_system_time
|
||||
#define sysModuleLoad cellSysmoduleLoadModule
|
||||
#define sysModuleUnload cellSysmoduleUnloadModule
|
||||
|
||||
#define netInitialize sys_net_initialize_network
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
INPUT PAD PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <io/pad.h>
|
||||
#define CELL_PAD_CAPABILITY_SENSOR_MODE 4
|
||||
#define CELL_PAD_SETTING_SENSOR_ON 4
|
||||
#define CELL_PAD_STATUS_ASSIGN_CHANGES 2
|
||||
#define CELL_PAD_BTN_OFFSET_DIGITAL1 2
|
||||
#define CELL_PAD_BTN_OFFSET_DIGITAL2 3
|
||||
#define CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_X 4
|
||||
#define CELL_PAD_BTN_OFFSET_ANALOG_RIGHT_Y 5
|
||||
#define CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X 6
|
||||
#define CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y 7
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_RIGHT 8
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_LEFT 9
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_UP 10
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_DOWN 11
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_TRIANGLE 12
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_CIRCLE 13
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_CROSS 14
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_SQUARE 15
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_L1 16
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_R1 17
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_L2 18
|
||||
#define CELL_PAD_BTN_OFFSET_PRESS_R2 19
|
||||
#define CELL_PAD_BTN_OFFSET_SENSOR_X 20
|
||||
#define CELL_PAD_BTN_OFFSET_SENSOR_Y 21
|
||||
#define CELL_PAD_BTN_OFFSET_SENSOR_Z 22
|
||||
#define CELL_PAD_BTN_OFFSET_SENSOR_G 23
|
||||
#define CELL_PAD_CTRL_LEFT (128)
|
||||
#define CELL_PAD_CTRL_DOWN (64)
|
||||
#define CELL_PAD_CTRL_RIGHT (32)
|
||||
#define CELL_PAD_CTRL_UP (16)
|
||||
#define CELL_PAD_CTRL_START (8)
|
||||
#define CELL_PAD_CTRL_R3 (4)
|
||||
#define CELL_PAD_CTRL_L3 (2)
|
||||
#define CELL_PAD_CTRL_SELECT (1)
|
||||
#define CELL_PAD_CTRL_SQUARE (128)
|
||||
#define CELL_PAD_CTRL_CROSS (64)
|
||||
#define CELL_PAD_CTRL_CIRCLE (32)
|
||||
#define CELL_PAD_CTRL_TRIANGLE (16)
|
||||
#define CELL_PAD_CTRL_R1 (8)
|
||||
#define CELL_PAD_CTRL_L1 (4)
|
||||
#define CELL_PAD_CTRL_R2 (2)
|
||||
#define CELL_PAD_CTRL_L2 (1)
|
||||
#define CELL_PAD_CTRL_LDD_PS (1)
|
||||
#define CELL_PAD_STATUS_CONNECTED (1)
|
||||
#define CELL_SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN SYSUTIL_SYSTEMPARAM_ID_ENTER_BUTTON_ASSIGN
|
||||
#define CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CROSS (1)
|
||||
#define CELL_SYSUTIL_ENTER_BUTTON_ASSIGN_CIRCLE (0)
|
||||
#define now_connect connected
|
||||
#define CellPadActParam padActParam
|
||||
#define cellPadSetPortSetting ioPadSetPortSetting
|
||||
#define cellSysutilGetSystemParamInt sysUtilGetSystemParamInt
|
||||
#define cellPadSetActDirect ioPadSetActDirect
|
||||
#define CellPadInfo2 padInfo2
|
||||
#define cellPadGetInfo2 ioPadGetInfo2
|
||||
#define CellPadData padData
|
||||
#define cellPadGetData ioPadGetData
|
||||
#define cellPadInit ioPadInit
|
||||
#define cellPadEnd ioPadEnd
|
||||
#else
|
||||
#include <cell/pad.h>
|
||||
#define padInfo2 CellPadInfo2
|
||||
#define padData CellPadData
|
||||
#define ioPadGetInfo2 cellPadGetInfo2
|
||||
#define ioPadGetData cellPadGetData
|
||||
#define ioPadInit cellPadInit
|
||||
#define ioPadEnd cellPadEnd
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
INPUT MOUSE PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef HAVE_MOUSE
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <io/mouse.h>
|
||||
|
||||
/* define ps3 mouse structs */
|
||||
#define CellMouseInfo mouseInfo
|
||||
#define CellMouseData mouseData
|
||||
|
||||
/* define all the ps3 mouse functions */
|
||||
#define cellMouseInit ioMouseInit
|
||||
#define cellMouseGetData ioMouseGetData
|
||||
#define cellMouseEnd ioMouseEnd
|
||||
#define cellMouseGetInfo ioMouseGetInfo
|
||||
|
||||
/* PSL1GHT does not define these in its header */
|
||||
#define CELL_MOUSE_BUTTON_1 (UINT64_C(1) << 0) /* Button 1 */
|
||||
#define CELL_MOUSE_BUTTON_2 (UINT64_C(1) << 1) /* Button 2 */
|
||||
#define CELL_MOUSE_BUTTON_3 (UINT64_C(1) << 2) /* Button 3 */
|
||||
#define CELL_MOUSE_BUTTON_4 (UINT64_C(1) << 3) /* Button 4 */
|
||||
#define CELL_MOUSE_BUTTON_5 (UINT64_C(1) << 4) /* Button 5 */
|
||||
#define CELL_MOUSE_BUTTON_6 (UINT64_C(1) << 5) /* Button 6 */
|
||||
#define CELL_MOUSE_BUTTON_7 (UINT64_C(1) << 6) /* Button 7 */
|
||||
#define CELL_MOUSE_BUTTON_8 (UINT64_C(1) << 7) /* Button 8 */
|
||||
|
||||
#else
|
||||
#include <cell/mouse.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
OSK PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysutil/osk.h>
|
||||
/* define all the OSK functions */
|
||||
#define pOskLoadAsync oskLoadAsync
|
||||
#define pOskSetLayoutMode oskSetLayoutMode
|
||||
#define pOskSetKeyLayoutOption oskSetKeyLayoutOption
|
||||
#define pOskGetSize oskGetSize
|
||||
#define pOskDisableDimmer oskDisableDimmer
|
||||
#define pOskAbort oskAbort
|
||||
#define pOskUnloadAsync oskUnloadAsync
|
||||
|
||||
/* define OSK structs / types */
|
||||
#define sys_memory_container_t sys_mem_container_t
|
||||
#define CellOskDialogPoint oskPoint
|
||||
#define CellOskDialogInputFieldInfo oskInputFieldInfo
|
||||
#define CellOskDialogCallbackReturnParam oskCallbackReturnParam
|
||||
#define CellOskDialogParam oskParam
|
||||
|
||||
#define osk_allowed_panels allowedPanels
|
||||
#define osk_prohibit_flags prohibitFlags
|
||||
|
||||
#define osk_inputfield_message message
|
||||
#define osk_inputfield_starttext startText
|
||||
#define osk_inputfield_max_length maxLength
|
||||
#define osk_callback_return_param res
|
||||
#define osk_callback_num_chars len
|
||||
#define osk_callback_return_string str
|
||||
|
||||
/* define the OSK defines */
|
||||
#define CELL_OSKDIALOG_10KEY_PANEL OSK_10KEY_PANEL
|
||||
#define CELL_OSKDIALOG_FULLKEY_PANEL OSK_FULLKEY_PANEL
|
||||
#define CELL_OSKDIALOG_LAYOUTMODE_X_ALIGN_CENTER OSK_LAYOUTMODE_HORIZONTAL_ALIGN_CENTER
|
||||
#define CELL_OSKDIALOG_LAYOUTMODE_Y_ALIGN_TOP OSK_LAYOUTMODE_VERTICAL_ALIGN_TOP
|
||||
#define CELL_OSKDIALOG_PANELMODE_NUMERAL OSK_PANEL_TYPE_NUMERAL
|
||||
#define CELL_OSKDIALOG_PANELMODE_NUMERAL_FULL_WIDTH OSK_PANEL_TYPE_NUMERAL_FULL_WIDTH
|
||||
#define CELL_OSKDIALOG_PANELMODE_ALPHABET OSK_PANEL_TYPE_ALPHABET
|
||||
#define CELL_OSKDIALOG_PANELMODE_ENGLISH OSK_PANEL_TYPE_ENGLISH
|
||||
#define CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK (0)
|
||||
#define CELL_OSKDIALOG_INPUT_FIELD_RESULT_CANCELED (1)
|
||||
#define CELL_OSKDIALOG_INPUT_FIELD_RESULT_ABORT (2)
|
||||
#define CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT (3)
|
||||
#define CELL_OSKDIALOG_STRING_SIZE (512)
|
||||
#else
|
||||
#include <sysutil/sysutil_oskdialog.h>
|
||||
/* define all the OSK functions */
|
||||
#define pOskLoadAsync cellOskDialogLoadAsync
|
||||
#define pOskSetLayoutMode cellOskDialogSetLayoutMode
|
||||
#define pOskSetKeyLayoutOption cellOskDialogSetKeyLayoutOption
|
||||
#define pOskGetSize cellOskDialogGetSize
|
||||
#define pOskDisableDimmer cellOskDialogDisableDimmer
|
||||
#define pOskAbort cellOskDialogAbort
|
||||
#define pOskUnloadAsync cellOskDialogUnloadAsync
|
||||
|
||||
/* define OSK structs / types */
|
||||
#define osk_allowed_panels allowOskPanelFlg
|
||||
#define osk_prohibit_flags prohibitFlgs
|
||||
#define osk_inputfield_message message
|
||||
#define osk_inputfield_starttext init_text
|
||||
#define osk_inputfield_max_length limit_length
|
||||
#define osk_callback_return_param result
|
||||
#define osk_callback_num_chars numCharsResultString
|
||||
#define osk_callback_return_string pResultString
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
JPEG/PNG DECODING/ENCODING PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
|
||||
#define spu_enable enable
|
||||
#define stream_select stream
|
||||
#define color_alpha alpha
|
||||
#define color_space space
|
||||
#define output_mode mode
|
||||
#define output_bytes_per_line bytes_per_line
|
||||
#define output_width width
|
||||
#define output_height height
|
||||
|
||||
#define CELL_OK 0
|
||||
#define PTR_NULL 0
|
||||
|
||||
#else
|
||||
/* define the JPEG/PNG struct member names */
|
||||
#define spu_enable spuThreadEnable
|
||||
#define ppu_prio ppuThreadPriority
|
||||
#define spu_prio spuThreadPriority
|
||||
#define malloc_func cbCtrlMallocFunc
|
||||
#define malloc_arg cbCtrlMallocArg
|
||||
#define free_func cbCtrlFreeFunc
|
||||
#define free_arg cbCtrlFreeArg
|
||||
#define stream_select srcSelect
|
||||
#define file_name fileName
|
||||
#define file_offset fileOffset
|
||||
#define file_size fileSize
|
||||
#define stream_ptr streamPtr
|
||||
#define stream_size streamSize
|
||||
#define down_scale downScale
|
||||
#define color_alpha outputColorAlpha
|
||||
#define color_space outputColorSpace
|
||||
#define cmd_ptr commandPtr
|
||||
#define quality method
|
||||
#define output_mode outputMode
|
||||
#define output_bytes_per_line outputBytesPerLine
|
||||
#define output_width outputWidth
|
||||
#define output_height outputHeight
|
||||
#define bit_depth outputBitDepth
|
||||
#define pack_flag outputPackFlag
|
||||
#define alpha_select outputAlphaSelect
|
||||
|
||||
#define PTR_NULL NULL
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
TIMER PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#define sys_timer_usleep usleep
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
THREADING PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sys/thread.h>
|
||||
|
||||
/* FIXME - not sure if this is correct -> FIXED! 1 and not 0 */
|
||||
#define SYS_THREAD_CREATE_JOINABLE THREAD_JOINABLE
|
||||
|
||||
#else
|
||||
#include <sys/ppu_thread.h>
|
||||
|
||||
#define SYS_PROCESS_SPAWN_STACK_SIZE_1M SYS_PROCESS_PRIMARY_STACK_SIZE_1M
|
||||
#define SYS_THREAD_CREATE_JOINABLE SYS_PPU_THREAD_CREATE_JOINABLE
|
||||
|
||||
#define sysThreadCreate sys_ppu_thread_create
|
||||
#define sysThreadJoin sys_ppu_thread_join
|
||||
#define sysThreadExit sys_ppu_thread_exit
|
||||
|
||||
#define sysProcessExit sys_process_exit
|
||||
#define sysProcessExitSpawn2 sys_game_process_exitspawn
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
MEMORY PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifndef __PSL1GHT__
|
||||
#define sysMemContainerCreate sys_memory_container_create
|
||||
#define sysMemContainerDestroy sys_memory_container_destroy
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
RSX PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysutil/video.h>
|
||||
#define CELL_GCM_FALSE GCM_FALSE
|
||||
#define CELL_GCM_TRUE GCM_TRUE
|
||||
|
||||
#define CELL_GCM_ONE GCM_ONE
|
||||
#define CELL_GCM_ZERO GCM_ZERO
|
||||
#define CELL_GCM_ALWAYS GCM_ALWAYS
|
||||
|
||||
#define CELL_GCM_LOCATION_LOCAL GCM_LOCATION_RSX
|
||||
#define CELL_GCM_LOCATION_MAIN GCM_LOCATION_CELL
|
||||
|
||||
#define CELL_GCM_MAX_RT_DIMENSION (4096)
|
||||
|
||||
#define CELL_GCM_TEXTURE_LINEAR_NEAREST GCM_TEXTURE_LINEAR_MIPMAP_NEAREST
|
||||
#define CELL_GCM_TEXTURE_LINEAR_LINEAR GCM_TEXTURE_LINEAR_MIPMAP_LINEAR
|
||||
#define CELL_GCM_TEXTURE_NEAREST_LINEAR GCM_TEXTURE_NEAREST_MIPMAP_LINEAR
|
||||
#define CELL_GCM_TEXTURE_NEAREST_NEAREST GCM_TEXTURE_NEAREST_MIPMAP_NEAREST
|
||||
#define CELL_GCM_TEXTURE_NEAREST GCM_TEXTURE_NEAREST
|
||||
#define CELL_GCM_TEXTURE_LINEAR GCM_TEXTURE_LINEAR
|
||||
|
||||
#define CELL_GCM_TEXTURE_A8R8G8B8 GCM_TEXTURE_FORMAT_A8R8G8B8
|
||||
#define CELL_GCM_TEXTURE_R5G6B5 GCM_TEXTURE_FORMAT_R5G6B5
|
||||
#define CELL_GCM_TEXTURE_A1R5G5B5 GCM_TEXTURE_FORMAT_A1R5G5B5
|
||||
|
||||
#define CELL_GCM_TEXTURE_CLAMP_TO_EDGE GCM_TEXTURE_CLAMP_TO_EDGE
|
||||
|
||||
#define CELL_GCM_TEXTURE_MAX_ANISO_1 GCM_TEXTURE_MAX_ANISO_1
|
||||
#define CELL_GCM_TEXTURE_CONVOLUTION_QUINCUNX GCM_TEXTURE_CONVOLUTION_QUINCUNX
|
||||
#define CELL_GCM_TEXTURE_ZFUNC_NEVER GCM_TEXTURE_ZFUNC_NEVER
|
||||
|
||||
#define CELL_GCM_DISPLAY_HSYNC GCM_FLIP_HSYNC
|
||||
#define CELL_GCM_DISPLAY_VSYNC GCM_FLIP_VSYNC
|
||||
|
||||
#define CELL_GCM_CLEAR_R GCM_CLEAR_R
|
||||
#define CELL_GCM_CLEAR_G GCM_CLEAR_G
|
||||
#define CELL_GCM_CLEAR_B GCM_CLEAR_B
|
||||
#define CELL_GCM_CLEAR_A GCM_CLEAR_A
|
||||
|
||||
#define CELL_GCM_FUNC_ADD GCM_FUNC_ADD
|
||||
|
||||
#define CELL_GCM_SMOOTH (0x1D01)
|
||||
#define CELL_GCM_DEBUG_LEVEL2 2
|
||||
|
||||
#define CELL_GCM_COMPMODE_DISABLED 0
|
||||
|
||||
#define CELL_GCM_TRANSFER_LOCAL_TO_LOCAL 0
|
||||
|
||||
#define CELL_GCM_TEXTURE_REMAP_ORDER_XYXY (0)
|
||||
#define CELL_GCM_TEXTURE_REMAP_ORDER_XXXY (1)
|
||||
|
||||
#define CELL_GCM_TEXTURE_UNSIGNED_REMAP_NORMAL (0)
|
||||
|
||||
#define CELL_GCM_TEXTURE_REMAP_FROM_A (0)
|
||||
#define CELL_GCM_TEXTURE_REMAP_FROM_R (1)
|
||||
#define CELL_GCM_TEXTURE_REMAP_FROM_G (2)
|
||||
#define CELL_GCM_TEXTURE_REMAP_FROM_B (3)
|
||||
|
||||
#define CELL_GCM_TEXTURE_REMAP_ZERO (0)
|
||||
#define CELL_GCM_TEXTURE_REMAP_ONE (1)
|
||||
#define CELL_GCM_TEXTURE_REMAP_REMAP (2)
|
||||
|
||||
#define CELL_GCM_MAX_TEXIMAGE_COUNT (16)
|
||||
|
||||
#define CELL_GCM_TEXTURE_WRAP (1)
|
||||
|
||||
#define CELL_GCM_TEXTURE_NR (0x00)
|
||||
#define CELL_GCM_TEXTURE_LN (0x20)
|
||||
|
||||
#define CELL_GCM_TEXTURE_B8 (0x81)
|
||||
|
||||
#define CELL_RESC_720x480 RESC_720x480
|
||||
#define CELL_RESC_720x576 RESC_720x576
|
||||
#define CELL_RESC_1280x720 RESC_1280x720
|
||||
#define CELL_RESC_1920x1080 RESC_1920x1080
|
||||
|
||||
#define CELL_RESC_FULLSCREEN RESC_FULLSCREEN
|
||||
#define CELL_RESC_PANSCAN RESC_PANSCAN
|
||||
#define CELL_RESC_LETTERBOX RESC_LETTERBOX
|
||||
#define CELL_RESC_CONSTANT_VRAM RESC_CONSTANT_VRAM
|
||||
#define CELL_RESC_MINIMUM_GPU_LOAD RESC_MINIMUM_GPU_LOAD
|
||||
|
||||
#define CELL_RESC_PAL_50 RESC_PAL_50
|
||||
#define CELL_RESC_PAL_60_DROP RESC_PAL_60_DROP
|
||||
#define CELL_RESC_PAL_60_INTERPOLATE RESC_PAL_60_INTERPOLATE
|
||||
#define CELL_RESC_PAL_60_INTERPOLATE_30_DROP RESC_PAL_60_INTERPOLATE_30_DROP
|
||||
#define CELL_RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE RESC_PAL_60_INTERPOLATE_DROP_FLEXIBLE
|
||||
|
||||
#define CELL_RESC_INTERLACE_FILTER RESC_INTERLACE_FILTER
|
||||
#define CELL_RESC_NORMAL_BILINEAR RESC_NORMAL_BILINEAR
|
||||
|
||||
#define CELL_RESC_ELEMENT_HALF RESC_ELEMENT_HALF
|
||||
|
||||
#define CELL_VIDEO_OUT_ASPECT_AUTO VIDEO_ASPECT_AUTO
|
||||
#define CELL_VIDEO_OUT_ASPECT_4_3 VIDEO_ASPECT_4_3
|
||||
#define CELL_VIDEO_OUT_ASPECT_16_9 VIDEO_ASPECT_16_9
|
||||
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_480 VIDEO_RESOLUTION_480
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_576 VIDEO_RESOLUTION_576
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_720 VIDEO_RESOLUTION_720
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_1080 VIDEO_RESOLUTION_1080
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_960x1080 VIDEO_RESOLUTION_960x1080
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_1280x1080 VIDEO_RESOLUTION_1280x1080
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_1440x1080 VIDEO_RESOLUTION_1440x1080
|
||||
#define CELL_VIDEO_OUT_RESOLUTION_1600x1080 VIDEO_RESOLUTION_1600x1080
|
||||
|
||||
#define CELL_VIDEO_OUT_SCAN_MODE_PROGRESSIVE VIDEO_SCANMODE_PROGRESSIVE
|
||||
|
||||
#define CELL_VIDEO_OUT_PRIMARY VIDEO_PRIMARY
|
||||
|
||||
#define CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8 VIDEO_BUFFER_FORMAT_XRGB
|
||||
#define CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT VIDEO_BUFFER_FORMAT_FLOAT
|
||||
|
||||
#define CellGcmSurface gcmSurface
|
||||
#define CellGcmTexture gcmTexture
|
||||
#define CellGcmContextData _gcmCtxData
|
||||
#define CellGcmConfig gcmConfiguration
|
||||
#define CellVideoOutConfiguration videoConfiguration
|
||||
#define CellVideoOutResolution videoResolution
|
||||
#define CellVideoOutState videoState
|
||||
|
||||
#define CellRescInitConfig rescInitConfig
|
||||
#define CellRescSrc rescSrc
|
||||
#define CellRescBufferMode rescBufferMode
|
||||
|
||||
#define resolutionId resolution
|
||||
#define memoryFrequency memoryFreq
|
||||
#define coreFrequency coreFreq
|
||||
|
||||
#define cellGcmFinish rsxFinish
|
||||
|
||||
#define cellGcmGetFlipStatus gcmGetFlipStatus
|
||||
#define cellGcmResetFlipStatus gcmResetFlipStatus
|
||||
#define cellGcmSetWaitFlip gcmSetWaitFlip
|
||||
#define cellGcmSetDebugOutputLevel gcmSetDebugOutputLevel
|
||||
#define cellGcmSetDisplayBuffer gcmSetDisplayBuffer
|
||||
#define cellGcmSetGraphicsHandler gcmSetGraphicsHandler
|
||||
#define cellGcmSetFlipHandler gcmSetFlipHandler
|
||||
#define cellGcmSetVBlankHandler gcmSetVBlankHandler
|
||||
#define cellGcmGetConfiguration gcmGetConfiguration
|
||||
#define cellGcmSetJumpCommand rsxSetJumpCommand
|
||||
#define cellGcmFlush rsxFlushBuffer
|
||||
#define cellGcmSetFlipMode gcmSetFlipMode
|
||||
#define cellGcmSetFlip gcmSetFlip
|
||||
#define cellGcmGetLabelAddress gcmGetLabelAddress
|
||||
#define cellGcmUnbindTile gcmUnbindTile
|
||||
#define cellGcmBindTile gcmBindTile
|
||||
#define cellGcmSetTileInfo gcmSetTileInfo
|
||||
#define cellGcmAddressToOffset gcmAddressToOffset
|
||||
|
||||
#define cellRescCreateInterlaceTable rescCreateInterlaceTable
|
||||
#define cellRescSetDisplayMode rescSetDisplayMode
|
||||
#define cellRescGetNumColorBuffers rescGetNumColorBuffers
|
||||
#define cellRescGetBufferSize rescGetBufferSize
|
||||
#define cellRescSetBufferAddress rescSetBufferAddress
|
||||
#define cellRescGetFlipStatus rescGetFlipStatus
|
||||
#define cellRescResetFlipStatus rescResetFlipStatus
|
||||
#define cellRescSetConvertAndFlip rescSetConvertAndFlip
|
||||
#define cellRescSetVBlankHandler rescSetVBlankHandler
|
||||
#define cellRescSetFlipHandler rescSetFlipHandler
|
||||
#define cellRescAdjustAspectRatio rescAdjustAspectRatio
|
||||
#define cellRescSetWaitFlip rescSetWaitFlip
|
||||
#define cellRescSetSrc rescSetSrc
|
||||
#define cellRescInit rescInit
|
||||
#define cellRescExit rescExit
|
||||
|
||||
#define cellVideoOutConfigure videoConfigure
|
||||
#define cellVideoOutGetState videoGetState
|
||||
#define cellVideoOutGetResolution videoGetResolution
|
||||
#define cellVideoOutGetResolutionAvailability videoGetResolutionAvailability
|
||||
|
||||
#define cellGcmSetViewportInline rsxSetViewport
|
||||
#define cellGcmSetReferenceCommandInline rsxSetReferenceCommand
|
||||
#define cellGcmSetBlendEquationInline rsxSetBlendEquation
|
||||
#define cellGcmSetWriteBackEndLabelInline rsxSetWriteBackendLabel
|
||||
#define cellGcmSetWaitLabelInline rsxSetWaitLabel
|
||||
#define cellGcmSetDepthTestEnableInline rsxSetDepthTestEnable
|
||||
#define cellGcmSetScissorInline rsxSetScissor
|
||||
#define cellGcmSetBlendEnableInline rsxSetBlendEnable
|
||||
#define cellGcmSetClearColorInline rsxSetClearColor
|
||||
#define cellGcmSetBlendFuncInline rsxSetBlendFunc
|
||||
#define cellGcmSetBlendColorInline rsxSetBlendColor
|
||||
#define cellGcmSetTextureFilterInline rsxTextureFilter
|
||||
#define cellGcmSetTextureControlInline rsxTextureControl
|
||||
#define cellGcmSetCullFaceEnableInline rsxSetCullFaceEnable
|
||||
#define cellGcmSetShadeModeInline rsxSetShadeModel
|
||||
#define cellGcmSetTransferImage rsxSetTransferImage
|
||||
#define cellGcmSetBlendColor rsxSetBlendColor
|
||||
#define cellGcmSetBlendEquation rsxSetBlendEquation
|
||||
#define cellGcmSetBlendFunc rsxSetBlendFunc
|
||||
#define cellGcmSetClearColor rsxSetClearColor
|
||||
#define cellGcmSetScissor rsxSetScissor
|
||||
#define celGcmSetInvalidateVertexCache(fifo) rsxInvalidateTextureCache(fifo, GCM_INVALIDATE_VERTEX_TEXTURE)
|
||||
#else
|
||||
#define cellGcmSetTransferImage cellGcmSetTransferImageInline
|
||||
#define celGcmSetInvalidateVertexCache cellGcmSetInvalidateVertexCacheInline
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
NETWORK PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <net/netctl.h>
|
||||
|
||||
#define cellNetCtlInit netCtlInit
|
||||
#define cellNetCtlGetState netCtlGetState
|
||||
#define cellNetCtlTerm netCtlTerm
|
||||
|
||||
#define CELL_NET_CTL_STATE_IPObtained NET_CTL_STATE_IPObtained
|
||||
#else
|
||||
#define netCtlInit cellNetCtlInit
|
||||
#define netCtlGetState cellNetCtlGetState
|
||||
#define netCtlTerm cellNetCtlTerm
|
||||
#define NET_CTL_STATE_IPObtained CELL_NET_CTL_STATE_IPObtained
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
NET PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#if defined(HAVE_NETWORKING)
|
||||
#ifdef __PSL1GHT__
|
||||
#include <net/net.h>
|
||||
|
||||
#define socketselect select
|
||||
#define socketclose close
|
||||
|
||||
#define sys_net_initialize_network netInitialize
|
||||
#define sys_net_finalize_network netFinalizeNetwork
|
||||
#else
|
||||
#include <netex/net.h>
|
||||
#include <np.h>
|
||||
#include <np/drm.h>
|
||||
|
||||
#define netInitialize sys_net_initialize_network
|
||||
#define netFinalizeNetwork sys_net_finalize_network
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
SYSUTIL PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysutil/game.h>
|
||||
#define CellGameContentSize sysGameContentSize
|
||||
#define cellGameContentPermit sysGameContentPermit
|
||||
#define cellGameBootCheck sysGameBootCheck
|
||||
|
||||
#define CELL_GAME_ATTRIBUTE_APP_HOME (UINT64_C(1) <<1) /* boot from / app_home/PS3_GAME */
|
||||
#define CELL_GAME_DIRNAME_SIZE 32
|
||||
|
||||
#define CELL_GAME_GAMETYPE_SYS 0
|
||||
#define CELL_GAME_GAMETYPE_DISC 1
|
||||
#define CELL_GAME_GAMETYPE_HDD 2
|
||||
#define CELL_GAME_GAMETYPE_GAMEDATA 3
|
||||
#define CELL_GAME_GAMETYPE_HOME 4
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYSUTILS)
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysutil/sysutil.h>
|
||||
|
||||
#define CELL_SYSUTIL_REQUEST_EXITGAME SYSUTIL_EXIT_GAME
|
||||
|
||||
#define cellSysutilRegisterCallback sysUtilRegisterCallback
|
||||
#define cellSysutilCheckCallback sysUtilCheckCallback
|
||||
#else
|
||||
#include <sysutil/sysutil_screenshot.h>
|
||||
#include <sysutil/sysutil_common.h>
|
||||
#include <sysutil/sysutil_gamecontent.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if(CELL_SDK_VERSION > 0x340000)
|
||||
#include <sysutil/sysutil_bgmplayback.h>
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
SYSMODULE PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#if defined(HAVE_SYSMODULES)
|
||||
#ifdef __PSL1GHT__
|
||||
#include <sysmodule/sysmodule.h>
|
||||
|
||||
#define CELL_SYSMODULE_IO SYSMODULE_IO
|
||||
#define CELL_SYSMODULE_FS SYSMODULE_FS
|
||||
#define CELL_SYSMODULE_NET SYSMODULE_NET
|
||||
#define CELL_SYSMODULE_SYSUTIL_NP SYSMODULE_SYSUTIL_NP
|
||||
#define CELL_SYSMODULE_JPGDEC SYSMODULE_JPGDEC
|
||||
#define CELL_SYSMODULE_PNGDEC SYSMODULE_PNGDEC
|
||||
|
||||
#define cellSysmoduleLoadModule sysModuleLoad
|
||||
#define cellSysmoduleUnloadModule sysModuleUnload
|
||||
|
||||
#else
|
||||
#include <cell/sysmodule.h>
|
||||
|
||||
#define sysModuleLoad cellSysmoduleLoadModule
|
||||
#define sysModuleUnload cellSysmoduleUnloadModule
|
||||
#define SYSMODULE_NET CELL_SYSMODULE_NET
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
FS PROTOTYPES
|
||||
============================================================ */
|
||||
#define FS_SUCCEEDED 0
|
||||
#define FS_TYPE_DIR 1
|
||||
#ifdef __PSL1GHT__
|
||||
#include <lv2/sysfs.h>
|
||||
#define O_RDONLY SYS_O_RDONLY
|
||||
#define O_WRONLY SYS_O_WRONLY
|
||||
#define O_CREAT SYS_O_CREAT
|
||||
#define O_TRUNC SYS_O_TRUNC
|
||||
#define O_RDWR SYS_O_RDWR
|
||||
#else
|
||||
#include <cell/cell_fs.h>
|
||||
#define O_RDONLY CELL_FS_O_RDONLY
|
||||
#define O_WRONLY CELL_FS_O_WRONLY
|
||||
#define O_CREAT CELL_FS_O_CREAT
|
||||
#define O_TRUNC CELL_FS_O_TRUNC
|
||||
#define O_RDWR CELL_FS_O_RDWR
|
||||
#define sysFsStat cellFsStat
|
||||
#define sysFSStat CellFsStat
|
||||
#define sysFSDirent CellFsDirent
|
||||
#define sysFsOpendir cellFsOpendir
|
||||
#define sysFsReaddir cellFsReaddir
|
||||
#define sysFSDirent CellFsDirent
|
||||
#define sysFsClosedir cellFsClosedir
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
/* Copyright (C) 2010-2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (psp_defines.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _PSP_DEFINES_H
|
||||
#define _PSP_DEFINES_H
|
||||
|
||||
/*============================================================
|
||||
ERROR PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#ifndef SCE_OK
|
||||
#define SCE_OK 0
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
DISPLAY PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#if defined(SN_TARGET_PSP2) || defined(VITA)
|
||||
|
||||
#ifdef VITA
|
||||
int sceClibPrintf ( const char * format, ... );
|
||||
#define printf sceClibPrintf
|
||||
#define PSP_DISPLAY_PIXEL_FORMAT_8888 (SCE_DISPLAY_PIXELFORMAT_A8B8G8R8)
|
||||
#else
|
||||
#define PSP_DISPLAY_PIXEL_FORMAT_8888 (SCE_DISPLAY_PIXELFORMAT_A8B8G8R8)
|
||||
#endif
|
||||
|
||||
#define DisplaySetFrameBuf(topaddr, bufferwidth, pixelformat, sync) sceDisplaySetFrameBuf(topaddr, sync)
|
||||
|
||||
#define PSP_FB_WIDTH 960
|
||||
#define PSP_FB_HEIGHT 544
|
||||
#define PSP_PITCH_PIXELS 1024
|
||||
|
||||
// Memory left to the system for threads and other internal stuffs
|
||||
#ifdef SCE_LIBC_SIZE
|
||||
#define RAM_THRESHOLD 0x2000000 + SCE_LIBC_SIZE
|
||||
#else
|
||||
#define RAM_THRESHOLD 0x2000000
|
||||
#endif
|
||||
|
||||
#elif defined(PSP)
|
||||
#define DisplaySetFrameBuf(topaddr, bufferwidth, pixelformat, sync) sceDisplaySetFrameBuf(topaddr, bufferwidth, pixelformat, sync)
|
||||
|
||||
#define SCE_DISPLAY_UPDATETIMING_NEXTVSYNC 1
|
||||
|
||||
#define PSP_FB_WIDTH 512
|
||||
#define PSP_FB_HEIGHT 512
|
||||
#define PSP_PITCH_PIXELS 512
|
||||
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
INPUT PROTOTYPES
|
||||
============================================================ */
|
||||
|
||||
#if defined(SN_TARGET_PSP2) || defined(VITA)
|
||||
|
||||
#define STATE_BUTTON(state) ((state).buttons)
|
||||
#define STATE_ANALOGLX(state) ((state).lx)
|
||||
#define STATE_ANALOGLY(state) ((state).ly)
|
||||
#define STATE_ANALOGRX(state) ((state).rx)
|
||||
#define STATE_ANALOGRY(state) ((state).ry)
|
||||
|
||||
#if defined(VITA)
|
||||
#define DEFAULT_SAMPLING_MODE (SCE_CTRL_MODE_ANALOG)
|
||||
|
||||
#define PSP_CTRL_LEFT SCE_CTRL_LEFT
|
||||
#define PSP_CTRL_DOWN SCE_CTRL_DOWN
|
||||
#define PSP_CTRL_RIGHT SCE_CTRL_RIGHT
|
||||
#define PSP_CTRL_UP SCE_CTRL_UP
|
||||
#define PSP_CTRL_START SCE_CTRL_START
|
||||
#define PSP_CTRL_SELECT SCE_CTRL_SELECT
|
||||
#define PSP_CTRL_TRIANGLE SCE_CTRL_TRIANGLE
|
||||
#define PSP_CTRL_SQUARE SCE_CTRL_SQUARE
|
||||
#define PSP_CTRL_CROSS SCE_CTRL_CROSS
|
||||
#define PSP_CTRL_CIRCLE SCE_CTRL_CIRCLE
|
||||
#define PSP_CTRL_L SCE_CTRL_L1
|
||||
#define PSP_CTRL_R SCE_CTRL_R1
|
||||
#define PSP_CTRL_L2 SCE_CTRL_LTRIGGER
|
||||
#define PSP_CTRL_R2 SCE_CTRL_RTRIGGER
|
||||
#define PSP_CTRL_L3 SCE_CTRL_L3
|
||||
#define PSP_CTRL_R3 SCE_CTRL_R3
|
||||
#else
|
||||
#define DEFAULT_SAMPLING_MODE (SCE_CTRL_MODE_DIGITALANALOG)
|
||||
|
||||
#define PSP_CTRL_LEFT SCE_CTRL_LEFT
|
||||
#define PSP_CTRL_DOWN SCE_CTRL_DOWN
|
||||
#define PSP_CTRL_RIGHT SCE_CTRL_RIGHT
|
||||
#define PSP_CTRL_UP SCE_CTRL_UP
|
||||
#define PSP_CTRL_START SCE_CTRL_START
|
||||
#define PSP_CTRL_SELECT SCE_CTRL_SELECT
|
||||
#define PSP_CTRL_TRIANGLE SCE_CTRL_TRIANGLE
|
||||
#define PSP_CTRL_SQUARE SCE_CTRL_SQUARE
|
||||
#define PSP_CTRL_CROSS SCE_CTRL_CROSS
|
||||
#define PSP_CTRL_CIRCLE SCE_CTRL_CIRCLE
|
||||
#define PSP_CTRL_L SCE_CTRL_L
|
||||
#define PSP_CTRL_R SCE_CTRL_R
|
||||
#endif
|
||||
|
||||
#if defined(VITA)
|
||||
#define CtrlSetSamplingMode(mode) sceCtrlSetSamplingModeExt(mode)
|
||||
#define CtrlPeekBufferPositive(port, pad_data, bufs) sceCtrlPeekBufferPositiveExt2(port, pad_data, bufs)
|
||||
#else
|
||||
#define CtrlSetSamplingMode(mode) sceCtrlSetSamplingMode(mode)
|
||||
#define CtrlPeekBufferPositive(port, pad_data, bufs) sceCtrlPeekBufferPositive(port, pad_data, bufs)
|
||||
#endif
|
||||
|
||||
#elif defined(PSP)
|
||||
|
||||
#define PSP_CTRL_L PSP_CTRL_LTRIGGER
|
||||
#define PSP_CTRL_R PSP_CTRL_RTRIGGER
|
||||
|
||||
#define STATE_BUTTON(state) ((state).Buttons)
|
||||
#define STATE_ANALOGLX(state) ((state).Lx)
|
||||
#define STATE_ANALOGLY(state) ((state).Ly)
|
||||
#define STATE_ANALOGRX(state) ((state).Rx)
|
||||
#define STATE_ANALOGRY(state) ((state).Ry)
|
||||
|
||||
#define DEFAULT_SAMPLING_MODE (PSP_CTRL_MODE_ANALOG)
|
||||
|
||||
#define CtrlSetSamplingMode(mode) sceCtrlSetSamplingMode(mode)
|
||||
#define CtrlPeekBufferPositive(port, pad_data, bufs) sceCtrlPeekBufferPositive(pad_data, bufs)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -96,7 +96,6 @@ struct archive_extract_userdata
|
||||
/* Not used by the processing, free to use outside or in iterate callback */
|
||||
decompress_state_t *dec;
|
||||
void* cb_data;
|
||||
size_t archive_path_size;
|
||||
uint32_t crc;
|
||||
char archive_path[PATH_MAX_LENGTH];
|
||||
char current_file_path[PATH_MAX_LENGTH];
|
||||
@@ -149,8 +148,7 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state);
|
||||
|
||||
/**
|
||||
* file_archive_extract_file:
|
||||
* @archive_path : filename path to ZIP archive.
|
||||
* @archive_path_size : size of ZIP archive.
|
||||
* @archive_path : filename path to ZIP archive.
|
||||
* @valid_exts : valid extensions for a file.
|
||||
* @extraction_directory : the directory to extract the temporary
|
||||
* file to.
|
||||
@@ -160,7 +158,7 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state);
|
||||
*
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool file_archive_extract_file(char *archive_path, size_t archive_path_size,
|
||||
bool file_archive_extract_file(const char *archive_path,
|
||||
const char *valid_exts, const char *extraction_dir,
|
||||
char *out_path, size_t len);
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ struct config_file
|
||||
{
|
||||
char *path;
|
||||
char *reference;
|
||||
struct config_entry_list **entries_map;
|
||||
struct config_entry_list *entries;
|
||||
struct config_entry_list *tail;
|
||||
struct config_entry_list *last;
|
||||
|
||||
@@ -1378,6 +1378,121 @@ enum retro_mod
|
||||
* call will target the newly initialized driver.
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_FASTFORWARDING_OVERRIDE 64
|
||||
/* const struct retro_fastforwarding_override * --
|
||||
* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend.
|
||||
* If NULL is passed to this function, the frontend
|
||||
* will return true if fastforwarding override
|
||||
* functionality is supported (no change in
|
||||
* fastforwarding state will occur in this case).
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE 65
|
||||
/* const struct retro_system_content_info_override * --
|
||||
* Allows an implementation to override 'global' content
|
||||
* info parameters reported by retro_get_system_info().
|
||||
* Overrides also affect subsystem content info parameters
|
||||
* set via RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO.
|
||||
* This function must be called inside retro_set_environment().
|
||||
* If callback returns false, content info overrides
|
||||
* are unsupported by the frontend, and will be ignored.
|
||||
* If callback returns true, extended game info may be
|
||||
* retrieved by calling RETRO_ENVIRONMENT_GET_GAME_INFO_EXT
|
||||
* in retro_load_game() or retro_load_game_special().
|
||||
*
|
||||
* 'data' points to an array of retro_system_content_info_override
|
||||
* structs terminated by a { NULL, false, false } element.
|
||||
* If 'data' is NULL, no changes will be made to the frontend;
|
||||
* a core may therefore pass NULL in order to test whether
|
||||
* the RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE and
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT callbacks are supported
|
||||
* by the frontend.
|
||||
*
|
||||
* For struct member descriptions, see the definition of
|
||||
* struct retro_system_content_info_override.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* - struct retro_system_info:
|
||||
* {
|
||||
* "My Core", // library_name
|
||||
* "v1.0", // library_version
|
||||
* "m3u|md|cue|iso|chd|sms|gg|sg", // valid_extensions
|
||||
* true, // need_fullpath
|
||||
* false // block_extract
|
||||
* }
|
||||
*
|
||||
* - Array of struct retro_system_content_info_override:
|
||||
* {
|
||||
* {
|
||||
* "md|sms|gg", // extensions
|
||||
* false, // need_fullpath
|
||||
* true // persistent_data
|
||||
* },
|
||||
* {
|
||||
* "sg", // extensions
|
||||
* false, // need_fullpath
|
||||
* false // persistent_data
|
||||
* },
|
||||
* { NULL, false, false }
|
||||
* }
|
||||
*
|
||||
* Result:
|
||||
* - Files of type m3u, cue, iso, chd will not be
|
||||
* loaded by the frontend. Frontend will pass a
|
||||
* valid path to the core, and core will handle
|
||||
* loading internally
|
||||
* - Files of type md, sms, gg will be loaded by
|
||||
* the frontend. A valid memory buffer will be
|
||||
* passed to the core. This memory buffer will
|
||||
* remain valid until retro_deinit() returns
|
||||
* - Files of type sg will be loaded by the frontend.
|
||||
* A valid memory buffer will be passed to the core.
|
||||
* This memory buffer will remain valid until
|
||||
* retro_load_game() (or retro_load_game_special())
|
||||
* returns
|
||||
*
|
||||
* NOTE: If an extension is listed multiple times in
|
||||
* an array of retro_system_content_info_override
|
||||
* structs, only the first instance will be registered
|
||||
*/
|
||||
|
||||
#define RETRO_ENVIRONMENT_GET_GAME_INFO_EXT 66
|
||||
/* const struct retro_game_info_ext ** --
|
||||
* Allows an implementation to fetch extended game
|
||||
* information, providing additional content path
|
||||
* and memory buffer status details.
|
||||
* This function may only be called inside
|
||||
* retro_load_game() or retro_load_game_special().
|
||||
* If callback returns false, extended game information
|
||||
* is unsupported by the frontend. In this case, only
|
||||
* regular retro_game_info will be available.
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT is guaranteed
|
||||
* to return true if RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE
|
||||
* returns true.
|
||||
*
|
||||
* 'data' points to an array of retro_game_info_ext structs.
|
||||
*
|
||||
* For struct member descriptions, see the definition of
|
||||
* struct retro_game_info_ext.
|
||||
*
|
||||
* - If function is called inside retro_load_game(),
|
||||
* the retro_game_info_ext array is guaranteed to
|
||||
* have a size of 1 - i.e. the returned pointer may
|
||||
* be used to access directly the members of the
|
||||
* first retro_game_info_ext struct, for example:
|
||||
*
|
||||
* struct retro_game_info_ext *game_info_ext;
|
||||
* if (environ_cb(RETRO_ENVIRONMENT_GET_GAME_INFO_EXT, &game_info_ext))
|
||||
* printf("Content Directory: %s\n", game_info_ext->dir);
|
||||
*
|
||||
* - If the function is called inside retro_load_game_special(),
|
||||
* the retro_game_info_ext array is guaranteed to have a
|
||||
* size equal to the num_info argument passed to
|
||||
* retro_load_game_special()
|
||||
*/
|
||||
|
||||
/* VFS functionality */
|
||||
|
||||
/* File paths:
|
||||
@@ -2781,6 +2896,213 @@ struct retro_system_info
|
||||
bool block_extract;
|
||||
};
|
||||
|
||||
/* Defines overrides which modify frontend handling of
|
||||
* specific content file types.
|
||||
* An array of retro_system_content_info_override is
|
||||
* passed to RETRO_ENVIRONMENT_SET_CONTENT_INFO_OVERRIDE
|
||||
* NOTE: In the following descriptions, references to
|
||||
* retro_load_game() may be replaced with
|
||||
* retro_load_game_special() */
|
||||
struct retro_system_content_info_override
|
||||
{
|
||||
/* A list of file extensions for which the override
|
||||
* should apply, delimited by a 'pipe' character
|
||||
* (e.g. "md|sms|gg")
|
||||
* Permitted file extensions are limited to those
|
||||
* included in retro_system_info::valid_extensions
|
||||
* and/or retro_subsystem_rom_info::valid_extensions */
|
||||
const char *extensions;
|
||||
|
||||
/* Overrides the need_fullpath value set in
|
||||
* retro_system_info and/or retro_subsystem_rom_info.
|
||||
* To reiterate:
|
||||
*
|
||||
* If need_fullpath is true and retro_load_game() is called:
|
||||
* - retro_game_info::path is guaranteed to contain a valid
|
||||
* path to an existent file
|
||||
* - retro_game_info::data and retro_game_info::size are invalid
|
||||
*
|
||||
* If need_fullpath is false and retro_load_game() is called:
|
||||
* - retro_game_info::path may be NULL
|
||||
* - retro_game_info::data and retro_game_info::size are guaranteed
|
||||
* to be valid
|
||||
*
|
||||
* In addition:
|
||||
*
|
||||
* If need_fullpath is true and retro_load_game() is called:
|
||||
* - retro_game_info_ext::full_path is guaranteed to contain a valid
|
||||
* path to an existent file
|
||||
* - retro_game_info_ext::archive_path may be NULL
|
||||
* - retro_game_info_ext::archive_file may be NULL
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a valid path
|
||||
* to the directory in which the content file exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain the
|
||||
* basename of the content file, without extension
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file in lower case format
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are invalid
|
||||
*
|
||||
* If need_fullpath is false and retro_load_game() is called:
|
||||
* - If retro_game_info_ext::file_in_archive is false:
|
||||
* - retro_game_info_ext::full_path is guaranteed to contain
|
||||
* a valid path to an existent file
|
||||
* - retro_game_info_ext::archive_path may be NULL
|
||||
* - retro_game_info_ext::archive_file may be NULL
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a
|
||||
* valid path to the directory in which the content file exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain the
|
||||
* basename of the content file, without extension
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file in lower case format
|
||||
* - If retro_game_info_ext::file_in_archive is true:
|
||||
* - retro_game_info_ext::full_path may be NULL
|
||||
* - retro_game_info_ext::archive_path is guaranteed to
|
||||
* contain a valid path to an existent compressed file
|
||||
* inside which the content file is located
|
||||
* - retro_game_info_ext::archive_file is guaranteed to
|
||||
* contain a valid path to an existent content file
|
||||
* inside the compressed file referred to by
|
||||
* retro_game_info_ext::archive_path
|
||||
* e.g. for a compressed file '/path/to/foo.zip'
|
||||
* containing 'bar.sfc'
|
||||
* > retro_game_info_ext::archive_path will be '/path/to/foo.zip'
|
||||
* > retro_game_info_ext::archive_file will be 'bar.sfc'
|
||||
* - retro_game_info_ext::dir is guaranteed to contain a
|
||||
* valid path to the directory in which the compressed file
|
||||
* (containing the content file) exists
|
||||
* - retro_game_info_ext::name is guaranteed to contain
|
||||
* EITHER
|
||||
* 1) the basename of the compressed file (containing
|
||||
* the content file), without extension
|
||||
* OR
|
||||
* 2) the basename of the content file inside the
|
||||
* compressed file, without extension
|
||||
* In either case, a core should consider 'name' to
|
||||
* be the canonical name/ID of the the content file
|
||||
* - retro_game_info_ext::ext is guaranteed to contain the
|
||||
* extension of the content file inside the compressed file,
|
||||
* in lower case format
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size are
|
||||
* guaranteed to be valid */
|
||||
bool need_fullpath;
|
||||
|
||||
/* If need_fullpath is false, specifies whether the content
|
||||
* data buffer available in retro_load_game() is 'persistent'
|
||||
*
|
||||
* If persistent_data is false and retro_load_game() is called:
|
||||
* - retro_game_info::data and retro_game_info::size
|
||||
* are valid only until retro_load_game() returns
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are valid only until retro_load_game() returns
|
||||
*
|
||||
* If persistent_data is true and retro_load_game() is called:
|
||||
* - retro_game_info::data and retro_game_info::size
|
||||
* are valid until retro_deinit() returns
|
||||
* - retro_game_info_ext::data and retro_game_info_ext::size
|
||||
* are valid until retro_deinit() returns */
|
||||
bool persistent_data;
|
||||
};
|
||||
|
||||
/* Similar to retro_game_info, but provides extended
|
||||
* information about the source content file and
|
||||
* game memory buffer status.
|
||||
* And array of retro_game_info_ext is returned by
|
||||
* RETRO_ENVIRONMENT_GET_GAME_INFO_EXT
|
||||
* NOTE: In the following descriptions, references to
|
||||
* retro_load_game() may be replaced with
|
||||
* retro_load_game_special() */
|
||||
struct retro_game_info_ext
|
||||
{
|
||||
/* - If file_in_archive is false, contains a valid
|
||||
* path to an existent content file (UTF-8 encoded)
|
||||
* - If file_in_archive is true, may be NULL */
|
||||
const char *full_path;
|
||||
|
||||
/* - If file_in_archive is false, may be NULL
|
||||
* - If file_in_archive is true, contains a valid path
|
||||
* to an existent compressed file inside which the
|
||||
* content file is located (UTF-8 encoded) */
|
||||
const char *archive_path;
|
||||
|
||||
/* - If file_in_archive is false, may be NULL
|
||||
* - If file_in_archive is true, contain a valid path
|
||||
* to an existent content file inside the compressed
|
||||
* file referred to by archive_path (UTF-8 encoded)
|
||||
* e.g. for a compressed file '/path/to/foo.zip'
|
||||
* containing 'bar.sfc'
|
||||
* > archive_path will be '/path/to/foo.zip'
|
||||
* > archive_file will be 'bar.sfc' */
|
||||
const char *archive_file;
|
||||
|
||||
/* - If file_in_archive is false, contains a valid path
|
||||
* to the directory in which the content file exists
|
||||
* (UTF-8 encoded)
|
||||
* - If file_in_archive is true, contains a valid path
|
||||
* to the directory in which the compressed file
|
||||
* (containing the content file) exists (UTF-8 encoded) */
|
||||
const char *dir;
|
||||
|
||||
/* Contains the canonical name/ID of the content file
|
||||
* (UTF-8 encoded). Intended for use when identifying
|
||||
* 'complementary' content named after the loaded file -
|
||||
* i.e. companion data of a different format (a CD image
|
||||
* required by a ROM), texture packs, internally handled
|
||||
* save files, etc.
|
||||
* - If file_in_archive is false, contains the basename
|
||||
* of the content file, without extension
|
||||
* - If file_in_archive is true, then string is
|
||||
* implementation specific. A frontend may choose to
|
||||
* set a name value of:
|
||||
* EITHER
|
||||
* 1) the basename of the compressed file (containing
|
||||
* the content file), without extension
|
||||
* OR
|
||||
* 2) the basename of the content file inside the
|
||||
* compressed file, without extension
|
||||
* RetroArch sets the 'name' value according to (1).
|
||||
* A frontend that supports routine loading of
|
||||
* content from archives containing multiple unrelated
|
||||
* content files may set the 'name' value according
|
||||
* to (2). */
|
||||
const char *name;
|
||||
|
||||
/* - If file_in_archive is false, contains the extension
|
||||
* of the content file in lower case format
|
||||
* - If file_in_archive is true, contains the extension
|
||||
* of the content file inside the compressed file,
|
||||
* in lower case format */
|
||||
const char *ext;
|
||||
|
||||
/* String of implementation specific meta-data. */
|
||||
const char *meta;
|
||||
|
||||
/* Memory buffer of loaded game content. Will be NULL:
|
||||
* IF
|
||||
* - retro_system_info::need_fullpath is true and
|
||||
* retro_system_content_info_override::need_fullpath
|
||||
* is unset
|
||||
* OR
|
||||
* - retro_system_content_info_override::need_fullpath
|
||||
* is true */
|
||||
const void *data;
|
||||
|
||||
/* Size of game content memory buffer, in bytes */
|
||||
size_t size;
|
||||
|
||||
/* True if loaded content file is inside a compressed
|
||||
* archive */
|
||||
bool file_in_archive;
|
||||
|
||||
/* - If data is NULL, value is unset/ignored
|
||||
* - If data is non-NULL:
|
||||
* - If persistent_data is false, data and size are
|
||||
* valid only until retro_load_game() returns
|
||||
* - If persistent_data is true, data and size are
|
||||
* are valid until retro_deinit() returns */
|
||||
bool persistent_data;
|
||||
};
|
||||
|
||||
struct retro_game_geometry
|
||||
{
|
||||
unsigned base_width; /* Nominal video width of game. */
|
||||
@@ -2938,6 +3260,47 @@ struct retro_framebuffer
|
||||
Set by frontend in GET_CURRENT_SOFTWARE_FRAMEBUFFER. */
|
||||
};
|
||||
|
||||
/* Used by a libretro core to override the current
|
||||
* fastforwarding mode of the frontend */
|
||||
struct retro_fastforwarding_override
|
||||
{
|
||||
/* Specifies the runtime speed multiplier that
|
||||
* will be applied when 'fastforward' is true.
|
||||
* For example, a value of 5.0 when running 60 FPS
|
||||
* content will cap the fast-forward rate at 300 FPS.
|
||||
* Note that the target multiplier may not be achieved
|
||||
* if the host hardware has insufficient processing
|
||||
* power.
|
||||
* Setting a value of 0.0 (or greater than 0.0 but
|
||||
* less than 1.0) will result in an uncapped
|
||||
* fast-forward rate (limited only by hardware
|
||||
* capacity).
|
||||
* If the value is negative, it will be ignored
|
||||
* (i.e. the frontend will use a runtime speed
|
||||
* multiplier of its own choosing) */
|
||||
float ratio;
|
||||
|
||||
/* If true, fastforwarding mode will be enabled.
|
||||
* If false, fastforwarding mode will be disabled. */
|
||||
bool fastforward;
|
||||
|
||||
/* If true, and if supported by the frontend, an
|
||||
* on-screen notification will be displayed while
|
||||
* 'fastforward' is true.
|
||||
* If false, and if supported by the frontend, any
|
||||
* on-screen fast-forward notifications will be
|
||||
* suppressed */
|
||||
bool notification;
|
||||
|
||||
/* If true, the core will have sole control over
|
||||
* when fastforwarding mode is enabled/disabled;
|
||||
* the frontend will not be able to change the
|
||||
* state set by 'fastforward' until either
|
||||
* 'inhibit_toggle' is set to false, or the core
|
||||
* is unloaded */
|
||||
bool inhibit_toggle;
|
||||
};
|
||||
|
||||
/* Callbacks */
|
||||
|
||||
/* Environment callback. Gives implementations a way of performing
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (linked_list.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_LINKED_LIST_H
|
||||
#define __LIBRETRO_SDK_LINKED_LIST_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <stddef.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Represents a linked list. Contains any number of elements.
|
||||
*/
|
||||
typedef struct linked_list linked_list_t;
|
||||
|
||||
/**
|
||||
* Represents an iterator for iterating over a linked list. The iterator can
|
||||
* go through the linked list forwards or backwards.
|
||||
*/
|
||||
typedef struct linked_list_iterator linked_list_iterator_t;
|
||||
|
||||
/**
|
||||
* Creates a new linked list with no elements.
|
||||
*
|
||||
* @return New linked list
|
||||
*/
|
||||
linked_list_t *linked_list_new(void);
|
||||
|
||||
/**
|
||||
* @brief frees the memory used by the linked list
|
||||
*
|
||||
* Frees all of the memory used by this linked list. The values of all
|
||||
* remaining elements are freed using the "free_value" function. Does
|
||||
* nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to free
|
||||
* @param free_value function to use to free remaining values
|
||||
*/
|
||||
void linked_list_free(linked_list_t *list, void (*free_value)(void *value));
|
||||
|
||||
/**
|
||||
* @brief adds an element to the linked list
|
||||
*
|
||||
* Add a new element to the end of this linked list. Does nothing if
|
||||
* "list" is NULL.
|
||||
*
|
||||
* @param list list to add the element to
|
||||
* @param value new value to add to the linked list
|
||||
*/
|
||||
void linked_list_add(linked_list_t *list, void *value);
|
||||
|
||||
/**
|
||||
* @brief inserts a value into the linked list
|
||||
*
|
||||
* Inserts a value into the linked list at the specified index. Does
|
||||
* nothing if "list" is NULL.
|
||||
*
|
||||
* @param list list to insert the value into
|
||||
* @param index index where the value should be inserted at (can be equal to list size)
|
||||
* @param value value to insert into the linked list
|
||||
*/
|
||||
void linked_list_insert(linked_list_t *list, size_t index, void *value);
|
||||
|
||||
/**
|
||||
* @brief Get the value in the linked list at the provided index.
|
||||
*
|
||||
* Return the value vstored in the linked list at the provided index. Does
|
||||
* nothing if "list" is NULL.
|
||||
*
|
||||
* @param list list to get the value from
|
||||
* @param index index of the value to return
|
||||
* @return value in the list at the provided index
|
||||
*/
|
||||
void *linked_list_get(linked_list_t *list, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Get the first value that is matched by the provided function
|
||||
*
|
||||
* Return the first value that the function matches. The matches function
|
||||
* parameters are value from the linked list and the provided state.
|
||||
*
|
||||
* @param list list to get the value from
|
||||
* @param matches function to test the values with
|
||||
* @param usrptr user data to pass to the matches function
|
||||
* @return first value that matches otherwise NULL
|
||||
*/
|
||||
void *linked_list_get_first_matching(linked_list_t *list, bool (*matches)(void *item, void *usrptr), void *usrptr);
|
||||
|
||||
/**
|
||||
* @brief Get the last value that is matched by the provided function
|
||||
*
|
||||
* Return the last value that the function matches. The matches function
|
||||
* parameters are value from the linked list and the provided state.
|
||||
*
|
||||
* @param list list to get the value from
|
||||
* @param matches function to test the values with
|
||||
* @param usrptr user data to pass to the matches function
|
||||
* @return last value that matches otherwise NULL
|
||||
*/
|
||||
void *linked_list_get_last_matching(linked_list_t *list, bool (*matches)(void *item, void *usrptr), void *usrptr);
|
||||
|
||||
/**
|
||||
* @brief Remove the element at the provided index
|
||||
*
|
||||
* Removes the element of the linked list at the provided index.
|
||||
*
|
||||
* @param list linked list to remove the element from
|
||||
* @param index index of the element to remove
|
||||
* @return value of the element that was removed, NULL if list is NULL or
|
||||
* index is invalid
|
||||
*/
|
||||
void *linked_list_remove_at(linked_list_t *list, size_t index);
|
||||
|
||||
/**
|
||||
* @brief Remove the first element with the provided value
|
||||
*
|
||||
* Removes the first element with a value equal to the provided value.
|
||||
* Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to remove the element from
|
||||
* @param value value of the element to remove
|
||||
* @return value if a matching element was removed
|
||||
*/
|
||||
void *linked_list_remove_first(linked_list_t *list, void *value);
|
||||
|
||||
/**
|
||||
* @brief Remove the last element with the provided value
|
||||
*
|
||||
* Removes the last element with a value equal to the provided value.
|
||||
* Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to remove the element from
|
||||
* @param value value of the element to remove
|
||||
* @return value if a matching element was removed
|
||||
*/
|
||||
void *linked_list_remove_last(linked_list_t *list, void *value);
|
||||
|
||||
/**
|
||||
* @brief Remove all elements with the provided value
|
||||
*
|
||||
* Removes all elements with a value equal to the provided value.
|
||||
* Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to remove the elements from
|
||||
* @param value value of the elements to remove
|
||||
* @return value if any matching element(s) where removed
|
||||
*/
|
||||
void *linked_list_remove_all(linked_list_t *list, void *value);
|
||||
|
||||
/**
|
||||
* @brief Remove the first matching element
|
||||
*
|
||||
* Removes the first matching element from the linked list. The "matches" function
|
||||
* is used to test for matching element values. Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to remove the element from
|
||||
* @param matches function to use for testing element values for a match
|
||||
* @return value if a matching element was removed
|
||||
*/
|
||||
void *linked_list_remove_first_matching(linked_list_t *list, bool (*matches)(void *value));
|
||||
|
||||
/**
|
||||
* @brief Remove the last matching element
|
||||
*
|
||||
* Removes the last matching element from the linked list. The "matches" function
|
||||
* is used to test for matching element values.
|
||||
*
|
||||
* @param list linked list to remove the element from
|
||||
* @param matches function to use for testing element value for a match
|
||||
* @return value if a matching element was removed
|
||||
*/
|
||||
void *linked_list_remove_last_matching(linked_list_t *list, bool (*matches)(void *value));
|
||||
|
||||
/**
|
||||
* @brief Remove all matching elements
|
||||
*
|
||||
* Removes all matching elements from the linked list. The "matches" function
|
||||
* is used to test for matching element values. Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to remove the elements from
|
||||
* @param matches function to use for testing element values for a match
|
||||
*/
|
||||
void linked_list_remove_all_matching(linked_list_t *list, bool (*matches)(void *value));
|
||||
|
||||
/**
|
||||
* @brief Replace the value of the element at the provided index
|
||||
*
|
||||
* Replaces the value of the element at the provided index. The linked list must
|
||||
* contain an element at the index.
|
||||
*
|
||||
* @param list linked list to replace the value in
|
||||
* @param index index of the element to replace the value of
|
||||
* @param value new value for the selected element
|
||||
* @return whether an element was updated
|
||||
*/
|
||||
bool linked_list_set_at(linked_list_t *list, size_t index, void *value);
|
||||
|
||||
/**
|
||||
* @brief Get the size of the linked list
|
||||
*
|
||||
* Returns the number of elements in the linked list.
|
||||
*
|
||||
* @param linked list to get the size of
|
||||
* @return number of elements in the linked list, 0 if linked list is NULL
|
||||
*/
|
||||
size_t linked_list_size(linked_list_t *list);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator for the linked list
|
||||
*
|
||||
* Returns a new iterator for the linked list. Can be either a forward or backward
|
||||
* iterator.
|
||||
*
|
||||
* @param list linked list to iterate over
|
||||
* @param forward true for a forward iterator, false for backwards
|
||||
* @return new iterator for the linked list in the specified direction, NULL if
|
||||
* "list" is NULL
|
||||
*/
|
||||
linked_list_iterator_t *linked_list_iterator(linked_list_t *list, bool forward);
|
||||
|
||||
/**
|
||||
* @brief Move to the next element in the linked list
|
||||
*
|
||||
* Moves the iterator to the next element in the linked list. The direction is
|
||||
* specified when retrieving a new iterator.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return iterator for the next element, NULL if iterator is NULL or "iterator"
|
||||
* is at the last element
|
||||
*/
|
||||
linked_list_iterator_t *linked_list_iterator_next(linked_list_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Get the value of the element for the iterator
|
||||
*
|
||||
* Returns the value of the element that the iterator is at.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return value of the element for the iterator
|
||||
*/
|
||||
void *linked_list_iterator_value(linked_list_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Remove the element that the iterator is at
|
||||
*
|
||||
* Removes the element that the iterator is at. The iterator is updated to the
|
||||
* next element.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return updated iterator or NULL if the last element was removed
|
||||
*/
|
||||
linked_list_iterator_t *linked_list_iterator_remove(linked_list_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Release the memory for the iterator
|
||||
*
|
||||
* Frees the memory for the provided iterator. Does nothing if "iterator" is NULL.
|
||||
*
|
||||
* @param iterator iterator to free
|
||||
*/
|
||||
void linked_list_iterator_free(linked_list_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Apply the provided function to all values in the linked list
|
||||
*
|
||||
* Apply the provied function to all values in the linked list. The values are applied
|
||||
* in the forward direction. Does nothing if "list" is NULL.
|
||||
*
|
||||
* @param list linked list to apply the function to
|
||||
* @param fn function to apply to all elements
|
||||
*/
|
||||
void linked_list_foreach(linked_list_t *list, void (*fn)(size_t index, void *value));
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,208 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (generic_queue.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_GENERIC_QUEUE_H
|
||||
#define __LIBRETRO_SDK_GENERIC_QUEUE_H
|
||||
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <boolean.h>
|
||||
#include <stddef.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* Represents a generic queue. Can contain any number of elements. Each element contains
|
||||
* a value of type "void *". Can be used as a FIFO or LIFO queue.
|
||||
*/
|
||||
typedef struct generic_queue generic_queue_t;
|
||||
|
||||
/**
|
||||
* Represents an iterator for iterating over a queue.
|
||||
*/
|
||||
typedef struct generic_queue_iterator generic_queue_iterator_t;
|
||||
|
||||
/**
|
||||
* Creates a new queue with no elements.
|
||||
*
|
||||
* @return New queue
|
||||
*/
|
||||
generic_queue_t *generic_queue_new(void);
|
||||
|
||||
/**
|
||||
* @brief frees the memory used by the queue
|
||||
*
|
||||
* Frees all of the memory used by this queue. The values of all
|
||||
* remaining elements are freed using the "free_value" function. Does
|
||||
* nothing if "queue" is NULL.
|
||||
*
|
||||
* @param queue queue to free
|
||||
* @param free_value function to use to free remaining values
|
||||
*/
|
||||
void generic_queue_free(generic_queue_t *queue, void (*free_value)(void *value));
|
||||
|
||||
/**
|
||||
* @brief Push a new value onto the queue
|
||||
*
|
||||
* Pushes a new value onto the end of the queue. Does nothing if "queue"
|
||||
* is NULL.
|
||||
*
|
||||
* @param queue queue to the push the value onto
|
||||
* @param value value to push onto the queue
|
||||
*/
|
||||
void generic_queue_push(generic_queue_t *queue, void *value);
|
||||
|
||||
/**
|
||||
* @brief Remove the last value from the queue
|
||||
*
|
||||
* Removes the last element from the queue. Does nothing if the queue is
|
||||
* NULL.
|
||||
*
|
||||
* @param queue queue to get the value from
|
||||
* @return value of the last element, NULL if queue is empty or NULL
|
||||
*/
|
||||
void *generic_queue_pop(generic_queue_t *queue);
|
||||
|
||||
/**
|
||||
* @brief Get the last value from the queue
|
||||
*
|
||||
* Returns the value of the last element in the queue. Returns NULL if the
|
||||
* queue is NULL or empty.
|
||||
*
|
||||
* @param queue queue to get the last value from
|
||||
* @return value of the last element or NULL
|
||||
*/
|
||||
void *generic_queue_peek(generic_queue_t *queue);
|
||||
|
||||
/**
|
||||
* @brief Get the first value from the queue
|
||||
*
|
||||
* Returns the value of the first element in the queue. Returns NULL if the
|
||||
* queue is NULL or empty.
|
||||
*
|
||||
* @param queue queue to get the first value from
|
||||
* @return value of the first element or NULL
|
||||
*/
|
||||
void *generic_queue_peek_first(generic_queue_t *queue);
|
||||
|
||||
/**
|
||||
* @brief Push a new value onto the front of the queue
|
||||
*
|
||||
* Pushes a new value onto the front of the queue. Does nothing if "queue"
|
||||
* is NULL.
|
||||
*
|
||||
* @param queue queue to the push the value onto
|
||||
* @param value value to push onto the queue
|
||||
*/
|
||||
void generic_queue_shift(generic_queue_t *queue, void *value);
|
||||
|
||||
/**
|
||||
* @brief Remove the first value from the queue
|
||||
*
|
||||
* Removes the first element from the queue. Does nothing if the queue is
|
||||
* NULL.
|
||||
*
|
||||
* @param queue queue to get the value from
|
||||
* @return value of the last element, NULL if queue is empty or NULL
|
||||
*/
|
||||
void *generic_queue_unshift(generic_queue_t *queue);
|
||||
|
||||
/**
|
||||
* @brief Get the size of the queue
|
||||
*
|
||||
* Returns the number of elements in the queue.
|
||||
*
|
||||
* @param queue queue to get the size of
|
||||
* @return number of elements in the queue, 0 if queue is NULL
|
||||
*/
|
||||
size_t generic_queue_length(generic_queue_t *queue);
|
||||
|
||||
/**
|
||||
* @brief Remove the first element in the queue with the provided value
|
||||
*
|
||||
* Removes the first element with a value matching the provided value. Does
|
||||
* nothing if queue is NULL.
|
||||
*
|
||||
* @param queue queue to remove the element from
|
||||
* @param value value to look for in the queue
|
||||
* @return the value of the element removed, NULL if no element was removed
|
||||
*/
|
||||
void *generic_queue_remove(generic_queue_t *queue, void *value);
|
||||
|
||||
/**
|
||||
* @brief Get an iterator for the queue
|
||||
*
|
||||
* Returns a new iterator for the queue. Can be either a forward or backward
|
||||
* iterator.
|
||||
*
|
||||
* @param queue queue to iterate over
|
||||
* @param forward true for a forward iterator, false for backwards
|
||||
* @return new iterator for the queue in the specified direction, NULL if
|
||||
* "queue" is NULL
|
||||
*/
|
||||
generic_queue_iterator_t *generic_queue_iterator(generic_queue_t *queue, bool forward);
|
||||
|
||||
/**
|
||||
* @brief Move to the next element in the queue
|
||||
*
|
||||
* Moves the iterator to the next element in the queue. The direction is
|
||||
* specified when retrieving a new iterator.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return iterator for the next element, NULL if iterator is NULL or "iterator"
|
||||
* is at the last element
|
||||
*/
|
||||
generic_queue_iterator_t *generic_queue_iterator_next(generic_queue_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Get the value of the element for the iterator
|
||||
*
|
||||
* Returns the value of the element that the iterator is at.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return value of the element for the iterator
|
||||
*/
|
||||
void *generic_queue_iterator_value(generic_queue_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Remove the element that the iterator is at
|
||||
*
|
||||
* Removes the element that the iterator is at. The iterator is updated to the
|
||||
* next element.
|
||||
*
|
||||
* @param iterator iterator for the current element
|
||||
* @return updated iterator or NULL if the last element was removed
|
||||
*/
|
||||
generic_queue_iterator_t *generic_queue_iterator_remove(generic_queue_iterator_t *iterator);
|
||||
|
||||
/**
|
||||
* @brief Release the memory for the iterator
|
||||
*
|
||||
* Frees the memory for the provided iterator. Does nothing if "iterator" is NULL.
|
||||
*
|
||||
* @param iterator iterator to free
|
||||
*/
|
||||
void generic_queue_iterator_free(generic_queue_iterator_t *iterator);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
@@ -148,9 +148,61 @@ char *string_trim_whitespace_right(char *const s);
|
||||
/* Remove leading and trailing whitespaces */
|
||||
char *string_trim_whitespace(char *const s);
|
||||
|
||||
/* max_lines == 0 means no limit */
|
||||
char *word_wrap(char *buffer, const char *string,
|
||||
int line_width, bool unicode, unsigned max_lines);
|
||||
/*
|
||||
* Wraps string specified by 'src' to destination buffer
|
||||
* specified by 'dst' and 'dst_size'.
|
||||
* This function assumes that all glyphs in the string
|
||||
* have an on-screen pixel width similar to that of
|
||||
* regular Latin characters - i.e. it will not wrap
|
||||
* correctly any text containing so-called 'wide' Unicode
|
||||
* characters (e.g. CJK languages, emojis, etc.).
|
||||
*
|
||||
* @param dst pointer to destination buffer.
|
||||
* @param dst_size size of destination buffer.
|
||||
* @param src pointer to input string.
|
||||
* @param line_width max number of characters per line.
|
||||
* @param wideglyph_width not used, but is necessary to keep
|
||||
* compatibility with word_wrap_wideglyph().
|
||||
* @param max_lines max lines of destination string.
|
||||
* 0 means no limit.
|
||||
*/
|
||||
void word_wrap(char *dst, size_t dst_size, const char *src,
|
||||
int line_width, int wideglyph_width, unsigned max_lines);
|
||||
|
||||
/*
|
||||
* Wraps string specified by 'src' to destination buffer
|
||||
* specified by 'dst' and 'dst_size'.
|
||||
* This function assumes that all glyphs in the string
|
||||
* are:
|
||||
* - EITHER 'non-wide' Unicode glyphs, with an on-screen
|
||||
* pixel width similar to that of regular Latin characters
|
||||
* - OR 'wide' Unicode glyphs (e.g. CJK languages, emojis, etc.)
|
||||
* with an on-screen pixel width defined by 'wideglyph_width'
|
||||
* Note that wrapping may occur in inappropriate locations
|
||||
* if 'src' string contains 'wide' Unicode characters whose
|
||||
* on-screen pixel width deviates greatly from the set
|
||||
* 'wideglyph_width' value.
|
||||
*
|
||||
* @param dst pointer to destination buffer.
|
||||
* @param dst_size size of destination buffer.
|
||||
* @param src pointer to input string.
|
||||
* @param line_width max number of characters per line.
|
||||
* @param wideglyph_width effective width of 'wide' Unicode glyphs.
|
||||
* the value here is normalised relative to the
|
||||
* typical on-screen pixel width of a regular
|
||||
* Latin character:
|
||||
* - a regular Latin character is defined to
|
||||
* have an effective width of 100
|
||||
* - wideglyph_width = 100 * (wide_character_pixel_width / latin_character_pixel_width)
|
||||
* - e.g. if 'wide' Unicode characters in 'src'
|
||||
* have an on-screen pixel width twice that of
|
||||
* regular Latin characters, wideglyph_width
|
||||
* would be 200
|
||||
* @param max_lines max lines of destination string.
|
||||
* 0 means no limit.
|
||||
*/
|
||||
void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src,
|
||||
int line_width, int wideglyph_width, unsigned max_lines);
|
||||
|
||||
/* Splits string into tokens seperated by 'delim'
|
||||
* > Returned token string must be free()'d
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (linked_list.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <boolean.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <lists/linked_list.h>
|
||||
|
||||
struct linked_list_item_t
|
||||
{
|
||||
void *value;
|
||||
struct linked_list_item_t *previous;
|
||||
struct linked_list_item_t *next;
|
||||
};
|
||||
|
||||
struct linked_list
|
||||
{
|
||||
struct linked_list_item_t *first_item;
|
||||
struct linked_list_item_t *last_item;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct linked_list_iterator
|
||||
{
|
||||
linked_list_t *list;
|
||||
struct linked_list_item_t *item;
|
||||
bool forward;
|
||||
};
|
||||
|
||||
linked_list_t *linked_list_new(void)
|
||||
{
|
||||
linked_list_t *list;
|
||||
|
||||
list = (linked_list_t *)calloc(sizeof(linked_list_t), 1);
|
||||
return list;
|
||||
}
|
||||
|
||||
void linked_list_free(linked_list_t *list, void (*free_value)(void *value))
|
||||
{
|
||||
if (!list)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while (list->first_item)
|
||||
{
|
||||
struct linked_list_item_t *next;
|
||||
|
||||
next = list->first_item->next;
|
||||
if (free_value)
|
||||
free_value(list->first_item->value);
|
||||
free(list->first_item);
|
||||
|
||||
list->first_item = next;
|
||||
}
|
||||
|
||||
free (list);
|
||||
}
|
||||
|
||||
void linked_list_add(linked_list_t *list, void *value)
|
||||
{
|
||||
struct linked_list_item_t *new_item;
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
new_item = (struct linked_list_item_t *)malloc(sizeof(struct linked_list_item_t));
|
||||
new_item->value = value;
|
||||
new_item->previous = list->last_item;
|
||||
new_item->next = NULL;
|
||||
|
||||
if (list->length == 0)
|
||||
list->first_item = new_item;
|
||||
else
|
||||
list->last_item->next = new_item;
|
||||
|
||||
list->last_item = new_item;
|
||||
list->length++;
|
||||
}
|
||||
|
||||
void linked_list_insert(linked_list_t *list, size_t index, void *value)
|
||||
{
|
||||
size_t i;
|
||||
struct linked_list_item_t *previous_item;
|
||||
struct linked_list_item_t *next_item;
|
||||
struct linked_list_item_t *new_item;
|
||||
|
||||
if (!list || index > list->length)
|
||||
return;
|
||||
|
||||
previous_item = NULL;
|
||||
next_item = list->first_item;
|
||||
for (i = 1; i <= index; i++)
|
||||
{
|
||||
previous_item = next_item;
|
||||
next_item = next_item->next;
|
||||
}
|
||||
|
||||
new_item = (struct linked_list_item_t *)malloc(sizeof(struct linked_list_item_t));
|
||||
new_item->value = value;
|
||||
|
||||
if (previous_item)
|
||||
previous_item->next = new_item;
|
||||
else
|
||||
list->first_item = new_item;
|
||||
new_item->previous = previous_item;
|
||||
|
||||
if (next_item)
|
||||
next_item->previous = new_item;
|
||||
else
|
||||
list->last_item = new_item;
|
||||
new_item->next = next_item;
|
||||
|
||||
list->length++;
|
||||
}
|
||||
|
||||
void *linked_list_get(linked_list_t *list, size_t index)
|
||||
{
|
||||
size_t i;
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
if (index >= list->length)
|
||||
return NULL;
|
||||
|
||||
item = list->first_item;
|
||||
for (i = 1; i <= index; i++)
|
||||
item = item->next;
|
||||
|
||||
return item->value;
|
||||
}
|
||||
|
||||
void *linked_list_get_first_matching(linked_list_t *list, bool (*matches)(void *item, void *usrptr), void *usrptr)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list || !matches)
|
||||
return NULL;
|
||||
|
||||
for (item = list->first_item; item; item = item->next)
|
||||
{
|
||||
if (matches(item->value, usrptr))
|
||||
return item->value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *linked_list_get_last_matching(linked_list_t *list, bool (*matches)(void *item, void *usrptr), void *usrptr)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list || !matches)
|
||||
return NULL;
|
||||
|
||||
for (item = list->last_item; item; item = item->previous)
|
||||
{
|
||||
if (matches(item->value, usrptr))
|
||||
return item->value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _linked_list_remove_item(linked_list_t *list, struct linked_list_item_t *item)
|
||||
{
|
||||
struct linked_list_item_t *previous_item;
|
||||
struct linked_list_item_t *next_item;
|
||||
|
||||
previous_item = item->previous;
|
||||
next_item = item->next;
|
||||
free(item);
|
||||
list->length--;
|
||||
|
||||
if (previous_item)
|
||||
previous_item->next = next_item;
|
||||
else
|
||||
list->first_item = next_item;
|
||||
|
||||
if (next_item)
|
||||
next_item->previous = previous_item;
|
||||
else
|
||||
list->last_item = previous_item;
|
||||
}
|
||||
|
||||
void *linked_list_remove_at(linked_list_t *list, size_t index)
|
||||
{
|
||||
size_t i = 0;
|
||||
struct linked_list_item_t *item;
|
||||
void *value;
|
||||
|
||||
if (!list || list->length == 0 || index >= list->length)
|
||||
return NULL;
|
||||
|
||||
item = list->first_item;
|
||||
for (i = 1; i <= index; i++)
|
||||
item = item->next;
|
||||
|
||||
value = item->value;
|
||||
_linked_list_remove_item(list, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
void *linked_list_remove_first(linked_list_t *list, void *value)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (item = list->first_item; item; item = item->next)
|
||||
{
|
||||
if (item->value == value)
|
||||
break;
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
_linked_list_remove_item(list, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *linked_list_remove_last(linked_list_t *list, void *value)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (item = list->last_item; item; item = item->previous)
|
||||
{
|
||||
if (item->value == value)
|
||||
break;
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
_linked_list_remove_item(list, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *linked_list_remove_all(linked_list_t *list, void *value)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
bool found = false;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (item = list->first_item; item;)
|
||||
{
|
||||
if (item->value == value)
|
||||
{
|
||||
struct linked_list_item_t *next_item;
|
||||
|
||||
next_item = item->next;
|
||||
_linked_list_remove_item(list, item);
|
||||
found = true;
|
||||
item = next_item;
|
||||
} else
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
|
||||
return found ? value : NULL;
|
||||
}
|
||||
|
||||
void *linked_list_remove_first_matching(linked_list_t *list, bool (*matches)(void *value))
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (item = list->first_item; item; item = item->next)
|
||||
{
|
||||
if (matches(item->value))
|
||||
break;
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
void *value;
|
||||
|
||||
value = item->value;
|
||||
_linked_list_remove_item(list, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *linked_list_remove_last_matching(linked_list_t *list, bool (*matches)(void *value))
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
for (item = list->last_item; item; item = item->previous)
|
||||
{
|
||||
if (matches(item->value))
|
||||
break;
|
||||
}
|
||||
|
||||
if (item)
|
||||
{
|
||||
void *value;
|
||||
|
||||
value = item->value;
|
||||
_linked_list_remove_item(list, item);
|
||||
return value;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void linked_list_remove_all_matching(linked_list_t *list, bool (*matches)(void *value))
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
for (item = list->first_item; item;)
|
||||
{
|
||||
if (matches(item->value))
|
||||
{
|
||||
struct linked_list_item_t *next_item;
|
||||
|
||||
next_item = item->next;
|
||||
_linked_list_remove_item(list, item);
|
||||
item = next_item;
|
||||
} else
|
||||
{
|
||||
item = item->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool linked_list_set_at(linked_list_t *list, size_t index, void *value)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
size_t i;
|
||||
|
||||
if (!list || list->length == 0 || index >= list->length)
|
||||
return false;
|
||||
|
||||
item = list->first_item;
|
||||
for (i = 1; i <= index; i++)
|
||||
item = item->next;
|
||||
|
||||
if (item)
|
||||
{
|
||||
item->value = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t linked_list_size(linked_list_t *list)
|
||||
{
|
||||
if (list)
|
||||
return list->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
linked_list_iterator_t *linked_list_iterator(linked_list_t *list, bool forward)
|
||||
{
|
||||
linked_list_iterator_t *iterator;
|
||||
|
||||
if (!list || !list->first_item)
|
||||
return NULL;
|
||||
|
||||
iterator = (linked_list_iterator_t *)malloc(sizeof(linked_list_iterator_t));
|
||||
iterator->list = list;
|
||||
iterator->item = forward ? list->first_item : list->last_item;
|
||||
iterator->forward = forward;
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
linked_list_iterator_t *linked_list_iterator_next(linked_list_iterator_t *iterator)
|
||||
{
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!iterator)
|
||||
return NULL;
|
||||
|
||||
item = iterator->forward ? iterator->item->next : iterator->item->previous;
|
||||
if (item)
|
||||
{
|
||||
iterator->item = item;
|
||||
return iterator;
|
||||
} else
|
||||
{
|
||||
free(iterator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void *linked_list_iterator_value(linked_list_iterator_t *iterator)
|
||||
{
|
||||
if (iterator)
|
||||
return iterator->item->value;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
linked_list_iterator_t *linked_list_iterator_remove(linked_list_iterator_t *iterator)
|
||||
{
|
||||
struct linked_list_item_t *next_item;
|
||||
|
||||
if (!iterator)
|
||||
return NULL;
|
||||
|
||||
next_item = iterator->forward ? iterator->item->next : iterator->item->previous;
|
||||
_linked_list_remove_item(iterator->list, iterator->item);
|
||||
|
||||
if (next_item)
|
||||
{
|
||||
iterator->item = next_item;
|
||||
return iterator;
|
||||
} else
|
||||
{
|
||||
free(iterator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void linked_list_iterator_free(linked_list_iterator_t *iterator)
|
||||
{
|
||||
if (iterator)
|
||||
free(iterator);
|
||||
}
|
||||
|
||||
void linked_list_foreach(linked_list_t *list, void (*fn)(size_t index, void *value))
|
||||
{
|
||||
size_t i;
|
||||
struct linked_list_item_t *item;
|
||||
|
||||
if (!list || !fn)
|
||||
return;
|
||||
|
||||
i = 0;
|
||||
for (item = list->first_item; item; item = item->next)
|
||||
fn(i++, item->value);
|
||||
}
|
||||
@@ -171,7 +171,7 @@ bool net_ifinfo_new(net_ifinfo_t *list)
|
||||
char name[PATH_MAX_LENGTH];
|
||||
memset(name, 0, sizeof(name));
|
||||
|
||||
WideCharToMultiByte(CP_ACP, 0, aa->FriendlyName, wcslen(aa->FriendlyName),
|
||||
WideCharToMultiByte(CP_UTF8, 0, aa->FriendlyName, wcslen(aa->FriendlyName),
|
||||
name, PATH_MAX_LENGTH, NULL, NULL);
|
||||
|
||||
for (ua = aa->FirstUnicastAddress; ua != NULL; ua = ua->Next)
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (generic_queue.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <boolean.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <queues/generic_queue.h>
|
||||
|
||||
struct generic_queue_item_t
|
||||
{
|
||||
void *value;
|
||||
struct generic_queue_item_t *previous;
|
||||
struct generic_queue_item_t *next;
|
||||
};
|
||||
|
||||
struct generic_queue
|
||||
{
|
||||
struct generic_queue_item_t *first_item;
|
||||
struct generic_queue_item_t *last_item;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
struct generic_queue_iterator
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
struct generic_queue_item_t *item;
|
||||
bool forward;
|
||||
};
|
||||
|
||||
generic_queue_t *generic_queue_new(void)
|
||||
{
|
||||
return (generic_queue_t *)calloc(1, sizeof(generic_queue_t));
|
||||
}
|
||||
|
||||
void generic_queue_free(generic_queue_t *queue, void (*free_value)(void *value))
|
||||
{
|
||||
struct generic_queue_item_t *next_item;
|
||||
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
while (queue->first_item)
|
||||
{
|
||||
if (free_value)
|
||||
free_value(queue->first_item->value);
|
||||
|
||||
next_item = queue->first_item->next;
|
||||
free(queue->first_item);
|
||||
queue->first_item = next_item;
|
||||
}
|
||||
|
||||
free(queue);
|
||||
}
|
||||
|
||||
void generic_queue_push(generic_queue_t *queue, void *value)
|
||||
{
|
||||
struct generic_queue_item_t *new_item;
|
||||
|
||||
new_item = (struct generic_queue_item_t *)calloc(1, sizeof(struct generic_queue_item_t));
|
||||
new_item->value = value;
|
||||
new_item->previous = queue->last_item;
|
||||
new_item->next = NULL;
|
||||
|
||||
queue->last_item = new_item;
|
||||
queue->length++;
|
||||
|
||||
if (!queue->first_item)
|
||||
queue->first_item = new_item;
|
||||
else
|
||||
new_item->previous->next = new_item;
|
||||
}
|
||||
|
||||
void *generic_queue_pop(generic_queue_t *queue)
|
||||
{
|
||||
void *value;
|
||||
struct generic_queue_item_t *item;
|
||||
|
||||
if (!queue || !queue->last_item)
|
||||
return NULL;
|
||||
|
||||
item = queue->last_item;
|
||||
queue->last_item = queue->last_item->previous;
|
||||
queue->length--;
|
||||
|
||||
if (queue->length == 0)
|
||||
queue->first_item = NULL;
|
||||
|
||||
value = item->value;
|
||||
free(item);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void *generic_queue_peek(generic_queue_t *queue)
|
||||
{
|
||||
if (!queue || !queue->last_item)
|
||||
return NULL;
|
||||
|
||||
return queue->last_item->value;
|
||||
}
|
||||
|
||||
void *generic_queue_peek_first(generic_queue_t *queue)
|
||||
{
|
||||
if (!queue || !queue->first_item)
|
||||
return NULL;
|
||||
|
||||
return queue->first_item->value;
|
||||
}
|
||||
|
||||
void generic_queue_shift(generic_queue_t *queue, void *value)
|
||||
{
|
||||
struct generic_queue_item_t *new_item;
|
||||
|
||||
if (!queue)
|
||||
return;
|
||||
|
||||
new_item = (struct generic_queue_item_t *)calloc(1, sizeof(struct generic_queue_item_t));
|
||||
new_item->value = value;
|
||||
new_item->previous = NULL;
|
||||
new_item->next = queue->first_item;
|
||||
|
||||
queue->first_item = new_item;
|
||||
queue->length++;
|
||||
|
||||
if (!queue->last_item)
|
||||
queue->last_item = new_item;
|
||||
else
|
||||
new_item->next->previous = new_item;
|
||||
}
|
||||
|
||||
void *generic_queue_unshift(generic_queue_t *queue)
|
||||
{
|
||||
void *value;
|
||||
struct generic_queue_item_t *item;
|
||||
|
||||
if (!queue || !queue->first_item)
|
||||
return NULL;
|
||||
|
||||
item = queue->first_item;
|
||||
queue->first_item = queue->first_item->next;
|
||||
queue->length--;
|
||||
|
||||
if (queue->length == 0)
|
||||
queue->last_item = NULL;
|
||||
|
||||
value = item->value;
|
||||
free(item);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t generic_queue_length(generic_queue_t *queue)
|
||||
{
|
||||
if (queue)
|
||||
return queue->length;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *generic_queue_remove(generic_queue_t *queue, void *value)
|
||||
{
|
||||
struct generic_queue_item_t *item;
|
||||
|
||||
if (!queue)
|
||||
return NULL;
|
||||
|
||||
for (item = queue->first_item; item; item = item->next)
|
||||
{
|
||||
if (item->value == value)
|
||||
{
|
||||
if (item->previous)
|
||||
item->previous->next = item->next;
|
||||
else
|
||||
queue->first_item = item->next;
|
||||
|
||||
if (item->next)
|
||||
item->next->previous = item->previous;
|
||||
else
|
||||
queue->last_item = item->previous;
|
||||
|
||||
free(item);
|
||||
queue->length--;
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generic_queue_iterator_t *generic_queue_iterator(generic_queue_t *queue, bool forward)
|
||||
{
|
||||
if (queue && queue->first_item)
|
||||
{
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
iterator = (generic_queue_iterator_t *)malloc(sizeof(generic_queue_iterator_t));
|
||||
iterator->queue = queue;
|
||||
iterator->item = forward ? queue->first_item : queue->last_item;
|
||||
iterator->forward = forward;
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generic_queue_iterator_t *generic_queue_iterator_next(generic_queue_iterator_t *iterator)
|
||||
{
|
||||
if (iterator)
|
||||
{
|
||||
struct generic_queue_item_t *item;
|
||||
|
||||
item = iterator->forward ? iterator->item->next : iterator->item->previous;
|
||||
if (item)
|
||||
{
|
||||
iterator->item = item;
|
||||
return iterator;
|
||||
} else
|
||||
{
|
||||
free(iterator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *generic_queue_iterator_value(generic_queue_iterator_t *iterator)
|
||||
{
|
||||
if (iterator)
|
||||
return iterator->item->value;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generic_queue_iterator_t *generic_queue_iterator_remove(generic_queue_iterator_t *iterator)
|
||||
{
|
||||
struct generic_queue_item_t *item;
|
||||
|
||||
if (!iterator)
|
||||
return NULL;
|
||||
|
||||
item = iterator->forward ? iterator->queue->first_item : iterator->queue->last_item;
|
||||
while (item)
|
||||
{
|
||||
if (iterator->item == item)
|
||||
{
|
||||
if (iterator->queue->first_item == item)
|
||||
iterator->queue->first_item = item->next;
|
||||
else
|
||||
item->previous->next = item->next;
|
||||
|
||||
if (iterator->queue->last_item == item)
|
||||
iterator->queue->last_item = item->previous;
|
||||
else
|
||||
item->next->previous = item->previous;
|
||||
|
||||
iterator->queue->length--;
|
||||
|
||||
iterator->item = iterator->forward ? item->next : item->previous;
|
||||
free(item);
|
||||
if (iterator->item)
|
||||
{
|
||||
return iterator;
|
||||
} else
|
||||
{
|
||||
free(iterator);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
item = iterator->forward ? item->next : item->previous;
|
||||
}
|
||||
|
||||
return iterator;
|
||||
}
|
||||
|
||||
void generic_queue_iterator_free(generic_queue_iterator_t *iterator)
|
||||
{
|
||||
if (iterator)
|
||||
free(iterator);
|
||||
}
|
||||
@@ -521,10 +521,11 @@ int filestream_close(RFILE *stream)
|
||||
* @path : path to file.
|
||||
* @buf : buffer to allocate and read the contents of the
|
||||
* file into. Needs to be freed manually.
|
||||
* @len : optional output integer containing bytes read.
|
||||
*
|
||||
* Read the contents of a file into @buf.
|
||||
*
|
||||
* Returns: number of items read, -1 on error.
|
||||
* Returns: non zero on success.
|
||||
*/
|
||||
int64_t filestream_read_file(const char *path, void **buf, int64_t *len)
|
||||
{
|
||||
|
||||
@@ -187,88 +187,207 @@ char *string_trim_whitespace(char *const s)
|
||||
return s;
|
||||
}
|
||||
|
||||
char *word_wrap(char* buffer, const char *string, int line_width, bool unicode, unsigned max_lines)
|
||||
void word_wrap(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned len = (unsigned)strlen(string);
|
||||
unsigned lines = 1;
|
||||
char *lastspace = NULL;
|
||||
unsigned counter = 0;
|
||||
unsigned lines = 1;
|
||||
size_t src_len = strlen(src);
|
||||
const char *src_end = src + src_len;
|
||||
|
||||
while (i < len)
|
||||
/* Prevent buffer overflow */
|
||||
if (dst_size < src_len + 1)
|
||||
return;
|
||||
|
||||
/* Early return if src string length is less
|
||||
* than line width */
|
||||
if (src_len < line_width)
|
||||
{
|
||||
unsigned counter;
|
||||
int pos = (int)(&buffer[i] - buffer);
|
||||
strcpy(dst, src);
|
||||
return;
|
||||
}
|
||||
|
||||
/* copy string until the end of the line is reached */
|
||||
for (counter = 1; counter <= (unsigned)line_width; counter++)
|
||||
while (*src != '\0')
|
||||
{
|
||||
unsigned char_len;
|
||||
|
||||
char_len = (unsigned)(utf8skip(src, 1) - src);
|
||||
counter++;
|
||||
|
||||
if (*src == ' ')
|
||||
lastspace = dst; /* Remember the location of the whitespace */
|
||||
else if (*src == '\n')
|
||||
{
|
||||
const char *character;
|
||||
unsigned char_len;
|
||||
unsigned j = i;
|
||||
/* If newlines embedded in the input,
|
||||
* reset the index */
|
||||
lines++;
|
||||
counter = 0;
|
||||
|
||||
/* check if end of string reached */
|
||||
if (i == len)
|
||||
/* Early return if remaining src string
|
||||
* length is less than line width */
|
||||
if (src_end - src <= line_width)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
return buffer;
|
||||
strcpy(dst, src);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
character = utf8skip(&string[i], 1);
|
||||
char_len = (unsigned)(character - &string[i]);
|
||||
while (char_len--)
|
||||
*dst++ = *src++;
|
||||
|
||||
if (!unicode)
|
||||
counter += char_len - 1;
|
||||
|
||||
do
|
||||
{
|
||||
buffer[i] = string[i];
|
||||
char_len--;
|
||||
i++;
|
||||
} while (char_len);
|
||||
|
||||
/* check for newlines embedded in the original input
|
||||
* and reset the index */
|
||||
if (buffer[j] == '\n')
|
||||
{
|
||||
lines++;
|
||||
counter = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* check for whitespace */
|
||||
if (string[i] == ' ')
|
||||
if (counter >= (unsigned)line_width)
|
||||
{
|
||||
if ((max_lines == 0 || lines < max_lines))
|
||||
counter = 0;
|
||||
|
||||
if (lastspace && (max_lines == 0 || lines < max_lines))
|
||||
{
|
||||
buffer[i] = '\n';
|
||||
i++;
|
||||
/* Replace nearest (previous) whitespace
|
||||
* with newline character */
|
||||
*lastspace = '\n';
|
||||
lines++;
|
||||
|
||||
src -= dst - lastspace - 1;
|
||||
dst = lastspace + 1;
|
||||
lastspace = NULL;
|
||||
|
||||
/* Early return if remaining src string
|
||||
* length is less than line width */
|
||||
if (src_end - src < line_width)
|
||||
{
|
||||
strcpy(dst, src);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int k;
|
||||
|
||||
/* check for nearest whitespace back in string */
|
||||
for (k = i; k > 0; k--)
|
||||
{
|
||||
if (string[k] != ' ' || (max_lines != 0 && lines >= max_lines))
|
||||
continue;
|
||||
|
||||
buffer[k] = '\n';
|
||||
/* set string index back to character after this one */
|
||||
i = k + 1;
|
||||
lines++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (&buffer[i] - buffer == pos)
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[i] = 0;
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
return buffer;
|
||||
void word_wrap_wideglyph(char *dst, size_t dst_size, const char *src, int line_width, int wideglyph_width, unsigned max_lines)
|
||||
{
|
||||
char *lastspace = NULL;
|
||||
char *lastwideglyph = NULL;
|
||||
const char *src_end = src + strlen(src);
|
||||
unsigned lines = 1;
|
||||
/* 'line_width' means max numbers of characters per line,
|
||||
* but this metric is only meaningful when dealing with
|
||||
* 'regular' glyphs that have an on-screen pixel width
|
||||
* similar to that of regular Latin characters.
|
||||
* When handing so-called 'wide' Unicode glyphs, it is
|
||||
* necessary to consider the actual on-screen pixel width
|
||||
* of each character.
|
||||
* In order to do this, we create a distinction between
|
||||
* regular Latin 'non-wide' glyphs and 'wide' glyphs, and
|
||||
* normalise all values relative to the on-screen pixel
|
||||
* width of regular Latin characters:
|
||||
* - Regular 'non-wide' glyphs have a normalised width of 100
|
||||
* - 'line_width' is therefore normalised to 100 * (width_in_characters)
|
||||
* - 'wide' glyphs have a normalised width of
|
||||
* 100 * (wide_character_pixel_width / latin_character_pixel_width)
|
||||
* - When a character is detected, the position in the current
|
||||
* line is incremented by the regular normalised width of 100
|
||||
* - If that character is then determined to be a 'wide'
|
||||
* glyph, the position in the current line is further incremented
|
||||
* by the difference between the normalised 'wide' and 'non-wide'
|
||||
* width values */
|
||||
unsigned counter_normalized = 0;
|
||||
int line_width_normalized = line_width * 100;
|
||||
int additional_counter_normalized = wideglyph_width - 100;
|
||||
|
||||
/* Early return if src string length is less
|
||||
* than line width */
|
||||
if (src_end - src < line_width)
|
||||
{
|
||||
strlcpy(dst, src, dst_size);
|
||||
return;
|
||||
}
|
||||
|
||||
while (*src != '\0')
|
||||
{
|
||||
unsigned char_len;
|
||||
|
||||
char_len = (unsigned)(utf8skip(src, 1) - src);
|
||||
counter_normalized += 100;
|
||||
|
||||
/* Prevent buffer overflow */
|
||||
if (char_len >= dst_size)
|
||||
break;
|
||||
|
||||
if (*src == ' ')
|
||||
lastspace = dst; /* Remember the location of the whitespace */
|
||||
else if (*src == '\n')
|
||||
{
|
||||
/* If newlines embedded in the input,
|
||||
* reset the index */
|
||||
lines++;
|
||||
counter_normalized = 0;
|
||||
|
||||
/* Early return if remaining src string
|
||||
* length is less than line width */
|
||||
if (src_end - src <= line_width)
|
||||
{
|
||||
strlcpy(dst, src, dst_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (char_len >= 3)
|
||||
{
|
||||
/* Remember the location of the first byte
|
||||
* whose length as UTF-8 >= 3*/
|
||||
lastwideglyph = dst;
|
||||
counter_normalized += additional_counter_normalized;
|
||||
}
|
||||
|
||||
dst_size -= char_len;
|
||||
while (char_len--)
|
||||
*dst++ = *src++;
|
||||
|
||||
if (counter_normalized >= (unsigned)line_width_normalized)
|
||||
{
|
||||
counter_normalized = 0;
|
||||
|
||||
if (max_lines != 0 && lines >= max_lines)
|
||||
continue;
|
||||
else if (lastwideglyph && (!lastspace || lastwideglyph > lastspace))
|
||||
{
|
||||
/* Insert newline character */
|
||||
*lastwideglyph = '\n';
|
||||
lines++;
|
||||
src -= dst - lastwideglyph;
|
||||
dst = lastwideglyph + 1;
|
||||
lastwideglyph = NULL;
|
||||
|
||||
/* Early return if remaining src string
|
||||
* length is less than line width */
|
||||
if (src_end - src <= line_width)
|
||||
{
|
||||
strlcpy(dst, src, dst_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (lastspace)
|
||||
{
|
||||
/* Replace nearest (previous) whitespace
|
||||
* with newline character */
|
||||
*lastspace = '\n';
|
||||
lines++;
|
||||
src -= dst - lastspace - 1;
|
||||
dst = lastspace + 1;
|
||||
lastspace = NULL;
|
||||
|
||||
/* Early return if remaining src string
|
||||
* length is less than line width */
|
||||
if (src_end - src < line_width)
|
||||
{
|
||||
strlcpy(dst, src, dst_size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
/* Splits string into tokens seperated by 'delim'
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <lrc_hash.h>
|
||||
|
||||
#define SUITE_NAME "hash"
|
||||
|
||||
START_TEST (test_sha256)
|
||||
{
|
||||
char output[65];
|
||||
sha256_hash(output, (uint8_t*)"abc", 3);
|
||||
ck_assert(!strcmp(output,
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_sha1)
|
||||
{
|
||||
char output[41];
|
||||
char tmpfile[512];
|
||||
FILE *fd;
|
||||
tmpnam(tmpfile);
|
||||
fd = fopen(tmpfile, "wb");
|
||||
ck_assert(fd != NULL);
|
||||
fwrite("abc", 1, 3, fd);
|
||||
fclose(fd);
|
||||
sha1_calculate(tmpfile, output);
|
||||
|
||||
ck_assert(!strcmp(output,
|
||||
"A9993E364706816ABA3E25717850C26C9CD0D89D"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_djb2)
|
||||
{
|
||||
ck_assert_uint_eq(djb2_calculate("retroarch"), 0xFADF3BCF);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_sha256);
|
||||
tcase_add_test(tc_core, test_sha1);
|
||||
tcase_add_test(tc_core, test_djb2);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,410 @@
|
||||
/* Copyright (C) 2010-2020 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_generic_queue.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <queues/generic_queue.h>
|
||||
|
||||
#define SUITE_NAME "Generic Queue"
|
||||
|
||||
static char *_value_1 = "value1";
|
||||
static char *_value_2 = "value2";
|
||||
static char *_value_3 = "value3";
|
||||
|
||||
START_TEST (test_generic_queue_create)
|
||||
{
|
||||
generic_queue_t *queue = generic_queue_new();
|
||||
ck_assert_ptr_nonnull(queue);
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_free)
|
||||
{
|
||||
generic_queue_t *queue = generic_queue_new();
|
||||
generic_queue_free(queue, NULL);
|
||||
generic_queue_free(NULL, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_push_pop)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
char *value;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_push(queue, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
generic_queue_push(queue, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 2);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_pop(queue);
|
||||
ck_assert_ptr_eq(value, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_peek)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
ck_assert_ptr_null(generic_queue_peek(queue));
|
||||
ck_assert_ptr_null(generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_1);
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_2);
|
||||
ck_assert_ptr_eq(_value_2, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_push(queue, _value_3);
|
||||
ck_assert_ptr_eq(_value_3, generic_queue_peek(queue));
|
||||
ck_assert_ptr_eq(_value_1, generic_queue_peek_first(queue));
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_shift_unshift)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
char *value;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_shift(queue, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_1);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_shift(queue, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
generic_queue_shift(queue, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 2);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_3);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 1);
|
||||
value = (char *) generic_queue_unshift(queue);
|
||||
ck_assert_ptr_eq(value, _value_2);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_empty)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
ck_assert_ptr_null(generic_queue_pop(queue));
|
||||
ck_assert_ptr_null(generic_queue_unshift(queue));
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
void _free_value(void *value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_1);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_2);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_3);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_3);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_2);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(generic_queue_iterator_value(iterator), _value_1);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_shift_free)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
|
||||
generic_queue_shift(queue, _value_1);
|
||||
generic_queue_shift(queue, _value_2);
|
||||
generic_queue_shift(queue, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_remove_one)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
ck_assert_ptr_null(iterator);
|
||||
ck_assert_int_eq(generic_queue_length(queue), 0);
|
||||
|
||||
generic_queue_free(queue, NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void _verify_queue_values(generic_queue_t *queue, int count, ...)
|
||||
{
|
||||
va_list values_list;
|
||||
void **values;
|
||||
int i;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
values = (void **)malloc(count * sizeof(void *));
|
||||
|
||||
ck_assert_int_eq(count, generic_queue_length(queue));
|
||||
|
||||
va_start(values_list, count);
|
||||
for (i = 0; i < count; i++)
|
||||
values[i] = va_arg(values_list, void *);
|
||||
va_end(values_list);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(values[i], generic_queue_iterator_value(iterator));
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
}
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
for (i = count - 1; i >= 0; i--)
|
||||
{
|
||||
ck_assert_ptr_nonnull(iterator);
|
||||
ck_assert_ptr_eq(values[i], generic_queue_iterator_value(iterator));
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
}
|
||||
ck_assert_ptr_null(iterator);
|
||||
|
||||
free(values);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_first)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_2, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_middle)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
iterator = generic_queue_iterator_next(iterator);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_iterator_remove_last)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
iterator = generic_queue_iterator(queue, false);
|
||||
iterator = generic_queue_iterator_remove(iterator);
|
||||
generic_queue_iterator_free(iterator);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_2);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_generic_queue_remove_first)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_1), _value_1);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_2, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_remove_middle)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_2), _value_2);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_3);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_remove_last)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
generic_queue_push(queue, _value_2);
|
||||
generic_queue_push(queue, _value_3);
|
||||
|
||||
ck_assert_ptr_eq(generic_queue_remove(queue, _value_3), _value_3);
|
||||
|
||||
_verify_queue_values(queue, 2, _value_1, _value_2);
|
||||
|
||||
generic_queue_free(queue, &_free_value);
|
||||
}
|
||||
|
||||
START_TEST (test_generic_queue_iterator_free)
|
||||
{
|
||||
generic_queue_t *queue;
|
||||
generic_queue_iterator_t *iterator;
|
||||
|
||||
queue = generic_queue_new();
|
||||
generic_queue_push(queue, _value_1);
|
||||
iterator = generic_queue_iterator(queue, true);
|
||||
|
||||
generic_queue_iterator_free(iterator);
|
||||
generic_queue_iterator_free(NULL);
|
||||
|
||||
generic_queue_free(queue, _free_value);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_generic_queue_create);
|
||||
tcase_add_test(tc_core, test_generic_queue_free);
|
||||
tcase_add_test(tc_core, test_generic_queue_push_pop);
|
||||
tcase_add_test(tc_core, test_generic_queue_peek);
|
||||
tcase_add_test(tc_core, test_generic_queue_shift_unshift);
|
||||
tcase_add_test(tc_core, test_generic_queue_empty);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator);
|
||||
tcase_add_test(tc_core, test_generic_queue_shift_free);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_one);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_first);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_middle);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_remove_last);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_first);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_middle);
|
||||
tcase_add_test(tc_core, test_generic_queue_remove_last);
|
||||
tcase_add_test(tc_core, test_generic_queue_iterator_free);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string/stdstring.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#define SUITE_NAME "stdstring"
|
||||
|
||||
START_TEST (test_string_filter)
|
||||
{
|
||||
char test1[] = "foo bar some string";
|
||||
char test2[] = "";
|
||||
string_remove_all_chars(test1, 's');
|
||||
string_remove_all_chars(test2, '0');
|
||||
string_remove_all_chars(NULL, 'a');
|
||||
ck_assert(!strcmp(test1, "foo bar ome tring"));
|
||||
ck_assert(!strcmp(test2, ""));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_replace)
|
||||
{
|
||||
char test1[] = "foo bar some string";
|
||||
string_replace_all_chars(test1, 's', 'S');
|
||||
string_replace_all_chars(NULL, 'a', 'A');
|
||||
ck_assert(!strcmp(test1, "foo bar Some String"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_case)
|
||||
{
|
||||
char test1[] = "foo";
|
||||
char test2[] = "01foOo[]_";
|
||||
ck_assert(!strcmp(string_to_upper(test1), "FOO"));
|
||||
ck_assert(!strcmp(string_to_upper(test2), "01FOOO[]_"));
|
||||
ck_assert(!strcmp(string_to_lower(test2), "01fooo[]_"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_char_classify)
|
||||
{
|
||||
ck_assert(ISSPACE(' '));
|
||||
ck_assert(ISSPACE('\n'));
|
||||
ck_assert(ISSPACE('\r'));
|
||||
ck_assert(ISSPACE('\t'));
|
||||
ck_assert(!ISSPACE('a'));
|
||||
|
||||
ck_assert(ISALPHA('a'));
|
||||
ck_assert(ISALPHA('Z'));
|
||||
ck_assert(!ISALPHA('5'));
|
||||
|
||||
ck_assert(ISALNUM('a'));
|
||||
ck_assert(ISALNUM('Z'));
|
||||
ck_assert(ISALNUM('5'));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_num_conv)
|
||||
{
|
||||
ck_assert_uint_eq(3, string_to_unsigned("3"));
|
||||
ck_assert_uint_eq(2147483647, string_to_unsigned("2147483647"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned("foo"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned("-1"));
|
||||
ck_assert_uint_eq(0, string_to_unsigned(NULL));
|
||||
|
||||
ck_assert_uint_eq(10, string_hex_to_unsigned("0xa"));
|
||||
ck_assert_uint_eq(10, string_hex_to_unsigned("a"));
|
||||
ck_assert_uint_eq(255, string_hex_to_unsigned("FF"));
|
||||
ck_assert_uint_eq(255, string_hex_to_unsigned("0xff"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0xfzzf"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0x"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned("0xx"));
|
||||
ck_assert_uint_eq(0, string_hex_to_unsigned(NULL));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_tokenizer)
|
||||
{
|
||||
char *testinput = "@@1@@2@@3@@@@9@@@";
|
||||
char **ptr = &testinput;
|
||||
char *token = NULL;
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, ""));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "1"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "2"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "3"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, ""));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "9"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token != NULL);
|
||||
ck_assert(!strcmp(token, "@"));
|
||||
free(token);
|
||||
token = string_tokenize(ptr, "@@");
|
||||
ck_assert(token == NULL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_replacesubstr)
|
||||
{
|
||||
char *res = string_replace_substring("foobaarhellowooorldtest", "oo", "ooo");
|
||||
ck_assert(res != NULL);
|
||||
ck_assert(!strcmp(res, "fooobaarhellowoooorldtest"));
|
||||
free(res);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_trim)
|
||||
{
|
||||
char test1[] = "\t \t\nhey there \n \n";
|
||||
char test2[] = "\t \t\nhey there \n \n";
|
||||
char test3[] = "\t \t\nhey there \n \n";
|
||||
ck_assert(string_trim_whitespace_left(test1) == (char*)test1);
|
||||
ck_assert(!strcmp(test1, "hey there \n \n"));
|
||||
ck_assert(string_trim_whitespace_right(test2) == (char*)test2);
|
||||
ck_assert(!strcmp(test2, "\t \t\nhey there"));
|
||||
ck_assert(string_trim_whitespace(test3) == (char*)test3);
|
||||
ck_assert(!strcmp(test3, "hey there"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_string_comparison)
|
||||
{
|
||||
ck_assert(string_is_not_equal_fast("foo", "bar", 3));
|
||||
ck_assert(string_is_equal_fast("foo2", "foo2", 4));
|
||||
ck_assert(!string_is_equal_fast("foo1", "foo2", 4));
|
||||
ck_assert(string_is_equal_fast("foo1", "foo2", 3));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_word_wrap)
|
||||
{
|
||||
const char *testtxt = (
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam nec "
|
||||
"enim quis orci euismod efficitur at nec arcu. Vivamus imperdiet est "
|
||||
"feugiat massa rhoncus porttitor at vitae ante. Nunc a orci vel ipsum "
|
||||
"tempor posuere sed a lacus. Ut erat odio, ultrices vitae iaculis "
|
||||
"fringilla, iaculis ut eros.\nSed facilisis viverra lectus et "
|
||||
"ullamcorper. Aenean risus ex, ornare eget scelerisque ac, imperdiet eu "
|
||||
"ipsum. Morbi pellentesque erat metus, sit amet aliquet libero rutrum "
|
||||
"et. Integer non ullamcorper tellus.");
|
||||
const char *expected = (
|
||||
"Lorem ipsum dolor sit amet, consectetur\n"
|
||||
"adipiscing elit. Nam nec enim quis orci\n"
|
||||
"euismod efficitur at nec arcu. Vivamus\n"
|
||||
"imperdiet est feugiat massa rhoncus\n"
|
||||
"porttitor at vitae ante. Nunc a orci vel\n"
|
||||
"ipsum tempor posuere sed a lacus. Ut\n"
|
||||
"erat odio, ultrices vitae iaculis\n"
|
||||
"fringilla, iaculis ut eros.\n"
|
||||
"Sed facilisis viverra lectus et\n"
|
||||
"ullamcorper. "
|
||||
"Aenean risus ex, ornare eget scelerisque ac, imperdiet eu ipsum. Morbi "
|
||||
"pellentesque erat metus, sit amet aliquet libero rutrum et. Integer "
|
||||
"non ullamcorper tellus.");
|
||||
|
||||
char output[1024];
|
||||
|
||||
word_wrap(output, sizeof(output), testtxt, 40, 100, 10);
|
||||
ck_assert(!strcmp(output, expected));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strlcpy)
|
||||
{
|
||||
char buf1[8];
|
||||
ck_assert_uint_eq(3, strlcpy(buf1, "foo", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foo", 4));
|
||||
ck_assert_uint_eq(11, strlcpy(buf1, "foo12345678", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foo1234", 8));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strlcat)
|
||||
{
|
||||
char buf1[8];
|
||||
buf1[0] = 'f';
|
||||
buf1[1] = '\0';
|
||||
ck_assert_uint_eq(10, strlcat(buf1, "ooooooooo", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foooooo\0", 8));
|
||||
ck_assert_uint_eq(13, strlcat(buf1, "123456", sizeof(buf1)));
|
||||
ck_assert(!memcmp(buf1, "foooooo\0", 8));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_strldup)
|
||||
{
|
||||
char buf1[8] = "foo";
|
||||
char *tv1 = strldup(buf1, 16);
|
||||
char *tv2 = strldup(buf1, 2);
|
||||
ck_assert(tv1 != (char*)buf1);
|
||||
ck_assert(tv2 != (char*)buf1);
|
||||
ck_assert_uint_eq(strlen(tv2), 1);
|
||||
ck_assert(tv2[0] == 'f' && tv2[1] == 0);
|
||||
free(tv1);
|
||||
free(tv2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf8_conv_utf32)
|
||||
{
|
||||
uint32_t output[12];
|
||||
const char test1[] = "aæ⠻จйγチℝ\xff";
|
||||
ck_assert_uint_eq(8, utf8_conv_utf32(output, 12, test1, strlen(test1)));
|
||||
ck_assert_uint_eq(97, output[0]);
|
||||
ck_assert_uint_eq(230, output[1]);
|
||||
ck_assert_uint_eq(10299, output[2]);
|
||||
ck_assert_uint_eq(3592, output[3]);
|
||||
ck_assert_uint_eq(1081, output[4]);
|
||||
ck_assert_uint_eq(947, output[5]);
|
||||
ck_assert_uint_eq(12481, output[6]);
|
||||
ck_assert_uint_eq(8477, output[7]);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf8_util)
|
||||
{
|
||||
const char *test1 = "aæ⠻จ𠀤";
|
||||
const char **tptr = &test1;
|
||||
char out[64];
|
||||
ck_assert_uint_eq(utf8len(test1), 5);
|
||||
ck_assert_uint_eq(utf8len(NULL), 0);
|
||||
ck_assert(&test1[1 + 2 + 3] == utf8skip(test1, 3));
|
||||
|
||||
ck_assert_uint_eq(97, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(230, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(10299, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(3592, utf8_walk(tptr));
|
||||
ck_assert_uint_eq(131108, utf8_walk(tptr));
|
||||
|
||||
//ck_assert_uint_eq(1, utf8cpy(out, 64, test1, 1));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_utf16_conv)
|
||||
{
|
||||
const uint16_t test1[] = {0x0061, 0x00e6, 0x283b, 0x0e08, 0xd840, 0xdc24};
|
||||
char out[64];
|
||||
size_t outlen = sizeof(out);
|
||||
ck_assert(utf16_conv_utf8((uint8_t*)out, &outlen, test1, sizeof(test1) / 2));
|
||||
ck_assert_uint_eq(outlen, 13);
|
||||
ck_assert(!memcmp(out, "aæ⠻จ𠀤", 13));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_string_comparison);
|
||||
tcase_add_test(tc_core, test_string_num_conv);
|
||||
tcase_add_test(tc_core, test_string_char_classify);
|
||||
tcase_add_test(tc_core, test_string_case);
|
||||
tcase_add_test(tc_core, test_string_filter);
|
||||
tcase_add_test(tc_core, test_string_replace);
|
||||
tcase_add_test(tc_core, test_string_tokenizer);
|
||||
tcase_add_test(tc_core, test_string_trim);
|
||||
tcase_add_test(tc_core, test_string_replacesubstr);
|
||||
tcase_add_test(tc_core, test_word_wrap);
|
||||
tcase_add_test(tc_core, test_strlcpy);
|
||||
tcase_add_test(tc_core, test_strlcat);
|
||||
tcase_add_test(tc_core, test_strldup);
|
||||
tcase_add_test(tc_core, test_utf8_conv_utf32);
|
||||
tcase_add_test(tc_core, test_utf16_conv);
|
||||
tcase_add_test(tc_core, test_utf8_util);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/* Copyright (C) 2021 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (test_stdstring.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <check.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <utils/md5.h>
|
||||
#include <encodings/crc32.h>
|
||||
|
||||
#define SUITE_NAME "hash"
|
||||
|
||||
START_TEST (test_md5)
|
||||
{
|
||||
uint8_t output[16];
|
||||
MD5_CTX ctx;
|
||||
MD5_Init(&ctx);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04\xe9\x80\x09\x98\xec\xf8\x42\x7e",
|
||||
output, 16));
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\x9e\x10\x7d\x9d\x37\x2b\xb6\x82\x6b\xd8\x1d\x35\x42\xa4\x19\xd6",
|
||||
output, 16));
|
||||
MD5_Init(&ctx);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Update(&ctx, "The quick brown fox jumps over the lazy dog", 43);
|
||||
MD5_Final(output, &ctx);
|
||||
ck_assert(!memcmp(
|
||||
"\x4e\x67\xdb\x4a\x7a\x40\x6b\x0c\xfd\xad\xd8\x87\xcd\xe7\x88\x8e",
|
||||
output, 16));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_crc32)
|
||||
{
|
||||
char buf1[] = "retroarch";
|
||||
char buf2[] = "12345678";
|
||||
char buf3[] = "The quick brown fox jumps over the lazy dog";
|
||||
uint32_t test1 = encoding_crc32(0, (uint8_t*)buf1, strlen(buf1));
|
||||
uint32_t test2 = encoding_crc32(0, (uint8_t*)buf2, strlen(buf2));
|
||||
uint32_t test3 = encoding_crc32(0, (uint8_t*)buf3, strlen(buf3));
|
||||
ck_assert_uint_eq(0x3cae141a, test1);
|
||||
ck_assert_uint_eq(0x9ae0daaf, test2);
|
||||
ck_assert_uint_eq(0x414fa339, test3);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_crc32_file)
|
||||
{
|
||||
char tmpfile[512];
|
||||
FILE *fd;
|
||||
tmpnam(tmpfile);
|
||||
fd = fopen(tmpfile, "wb");
|
||||
ck_assert(fd != NULL);
|
||||
fwrite("12345678", 1, 8, fd);
|
||||
fclose(fd);
|
||||
|
||||
ck_assert_uint_eq(file_crc32(0, tmpfile), 0x9ae0daaf);
|
||||
/* Error checking */
|
||||
ck_assert_uint_eq(file_crc32(0, "/this/path/should/not/exist"), 0);
|
||||
ck_assert_uint_eq(file_crc32(0, NULL), 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *create_suite(void)
|
||||
{
|
||||
Suite *s = suite_create(SUITE_NAME);
|
||||
|
||||
TCase *tc_core = tcase_create("Core");
|
||||
tcase_add_test(tc_core, test_md5);
|
||||
tcase_add_test(tc_core, test_crc32);
|
||||
tcase_add_test(tc_core, test_crc32_file);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int num_fail;
|
||||
Suite *s = create_suite();
|
||||
SRunner *sr = srunner_create(s);
|
||||
srunner_run_all(sr, CK_NORMAL);
|
||||
num_fail = srunner_ntests_failed(sr);
|
||||
srunner_free(sr);
|
||||
return (num_fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||
}
|
||||
@@ -130,9 +130,12 @@
|
||||
#include <pspkernel.h>
|
||||
#endif
|
||||
|
||||
#if defined(__PS3__) || defined(__PSL1GHT__)
|
||||
#include <defines/ps3_defines.h>
|
||||
#if defined(__PSL1GHT__)
|
||||
#include <lv2/sysfs.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(VITA)
|
||||
#define FIO_S_ISDIR SCE_S_ISDIR
|
||||
|
||||
+42
-33
@@ -1185,11 +1185,12 @@ void zip_uncompress(char *in, char *out, char *lastfile)
|
||||
|
||||
/* 7zip */
|
||||
#ifdef HAVE_7ZIP
|
||||
#define SEVENZIP_LOOKTOREAD_BUF_SIZE (1 << 14)
|
||||
struct sevenzip_context_t
|
||||
{
|
||||
uint8_t *output;
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CLookToRead2 lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
@@ -1200,14 +1201,14 @@ struct sevenzip_context_t
|
||||
uint32_t packIndex;
|
||||
};
|
||||
|
||||
static void *sevenzip_stream_alloc_impl(void *p, size_t size)
|
||||
static void *sevenzip_stream_alloc_impl(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void sevenzip_stream_free_impl(void *p, void *address)
|
||||
static void sevenzip_stream_free_impl(ISzAllocPtr p, void *address)
|
||||
{
|
||||
(void)p;
|
||||
|
||||
@@ -1215,7 +1216,7 @@ static void sevenzip_stream_free_impl(void *p, void *address)
|
||||
free(address);
|
||||
}
|
||||
|
||||
static void *sevenzip_stream_alloc_tmp_impl(void *p, size_t size)
|
||||
static void *sevenzip_stream_alloc_tmp_impl(ISzAllocPtr p, size_t size)
|
||||
{
|
||||
(void)p;
|
||||
if (size == 0)
|
||||
@@ -1226,7 +1227,7 @@ static void *sevenzip_stream_alloc_tmp_impl(void *p, size_t size)
|
||||
void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
CLookToRead2 lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
@@ -1240,37 +1241,46 @@ void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
allocTempImp.Alloc = sevenzip_stream_alloc_tmp_impl;
|
||||
allocTempImp.Free = sevenzip_stream_free_impl;
|
||||
|
||||
lookStream.bufSize = SEVENZIP_LOOKTOREAD_BUF_SIZE * sizeof(Byte);
|
||||
lookStream.buf = (Byte*)malloc(lookStream.bufSize);
|
||||
|
||||
if (!lookStream.buf)
|
||||
lookStream.bufSize = 0;
|
||||
|
||||
#if defined(_WIN32) && defined(USE_WINDOWS_FILE) && !defined(LEGACY_WIN32)
|
||||
if (!string_is_empty(in))
|
||||
{
|
||||
wchar_t *pathW = utf8_to_utf16_string_alloc(in);
|
||||
|
||||
if (pathW)
|
||||
{
|
||||
/* Could not open 7zip archive? */
|
||||
if (InFile_OpenW(&archiveStream.file, pathW))
|
||||
{
|
||||
free(pathW);
|
||||
return;
|
||||
}
|
||||
|
||||
free(pathW);
|
||||
}
|
||||
}
|
||||
#else
|
||||
/* Could not open 7zip archive? */
|
||||
if (InFile_Open(&archiveStream.file, in))
|
||||
return;
|
||||
#endif
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead_CreateVTable(&lookStream, false);
|
||||
lookStream.realStream = &archiveStream.s;
|
||||
LookToRead_Init(&lookStream);
|
||||
LookToRead2_CreateVTable(&lookStream, false);
|
||||
lookStream.realStream = &archiveStream.vt;
|
||||
LookToRead2_Init(&lookStream);
|
||||
CrcGenerateTable();
|
||||
|
||||
db.db.PackSizes = NULL;
|
||||
db.db.PackCRCsDefined = NULL;
|
||||
db.db.PackCRCs = NULL;
|
||||
db.db.Folders = NULL;
|
||||
db.db.Files = NULL;
|
||||
db.db.NumPackStreams = 0;
|
||||
db.db.NumFolders = 0;
|
||||
db.db.NumFiles = 0;
|
||||
db.startPosAfterHeader = 0;
|
||||
db.dataPos = 0;
|
||||
db.FolderStartPackStreamIndex = NULL;
|
||||
db.PackStreamStartPositions = NULL;
|
||||
db.FolderStartFileIndex = NULL;
|
||||
db.FileIndexToFolderIndexMap = NULL;
|
||||
db.FileNameOffsets = NULL;
|
||||
db.FileNames.data = NULL;
|
||||
db.FileNames.size = 0;
|
||||
memset(&db, 0, sizeof(db));
|
||||
|
||||
SzArEx_Init(&db);
|
||||
|
||||
if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK)
|
||||
if (SzArEx_Open(&db, &lookStream.vt, &allocImp, &allocTempImp) == SZ_OK)
|
||||
{
|
||||
uint32_t i;
|
||||
uint16_t *temp = NULL;
|
||||
@@ -1279,14 +1289,13 @@ void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
SRes res = SZ_OK;
|
||||
size_t output_size = 0;
|
||||
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
for (i = 0; i < db.NumFiles; i++)
|
||||
{
|
||||
size_t j;
|
||||
size_t len;
|
||||
char infile[RETRO_PATH_MAX];
|
||||
size_t offset = 0;
|
||||
size_t outSizeProcessed = 0;
|
||||
const CSzFileItem *f = db.db.Files + i;
|
||||
|
||||
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||
|
||||
@@ -1317,7 +1326,7 @@ void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
/* C LZMA SDK does not support chunked extraction - see here:
|
||||
* sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
|
||||
* */
|
||||
res = SzArEx_Extract(&db, &lookStream.s, i, &block_index,
|
||||
res = SzArEx_Extract(&db, &lookStream.vt, i, &block_index,
|
||||
&output, &output_size, &offset, &outSizeProcessed,
|
||||
&allocImp, &allocTempImp);
|
||||
|
||||
@@ -1335,9 +1344,9 @@ void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
{
|
||||
if (full_path[j] == '/')
|
||||
{
|
||||
full_path[j] = 0;
|
||||
path_mkdir((const char *)full_path);
|
||||
full_path[j] = DIR_SEP_CHR;
|
||||
full_path[j] = 0;
|
||||
path_mkdir((const char *)full_path);
|
||||
full_path[j] = DIR_SEP_CHR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1345,7 +1354,7 @@ void sevenzip_uncompress(char *in, char *out, char *lastfile)
|
||||
|
||||
if (path_is_valid(full_path))
|
||||
continue;
|
||||
else if (f->IsDir)
|
||||
else if (SzArEx_IsDir(&db, i))
|
||||
{
|
||||
path_mkdir((const char *)temp);
|
||||
log_cb(RETRO_LOG_INFO, "Mkdir: %s\n", full_path);
|
||||
|
||||
Reference in new issue
Block a user