libretro-common + 7zip sync

This commit is contained in:
sonninnos committed 2021-07-20 21:28:55 +03:00
1 parent a411a3cb58
commit c12d2af1bd
72 files changed
+15161 -6730

No files matched your search

+2 -4
View File
@@ -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
View File
@@ -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
+128 -133
View File
@@ -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
+1771
View File
File diff suppressed because it is too large. Load diff
+23 -24
View File
@@ -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;
}
+18 -10
View File
@@ -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
+106 -54
View File
@@ -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
}
+6 -10
View File
@@ -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
+102 -25
View File
@@ -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
+488 -340
View File
@@ -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;
}
}
+216 -90
View File
@@ -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
+27 -13
View File
@@ -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
-1631
View File
File diff suppressed because it is too large. Load diff
+116 -124
View File
@@ -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;
}
+267 -65
View File
@@ -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
+26 -6
View File
@@ -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
+235 -125
View File
@@ -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;
}
+133 -25
View File
@@ -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
+212 -116
View File
@@ -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);
}
}
}
+46 -50
View File
@@ -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
+66 -70
View File
@@ -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++;
}
}
}
+53
View File
@@ -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;
}
+33
View File
@@ -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
+218
View File
@@ -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
+309 -29
View File
@@ -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
+64
View File
@@ -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);
}
+19
View File
@@ -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
+478 -181
View File
File diff suppressed because it is too large. Load diff
+50 -46
View File
@@ -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
+13 -12
View File
@@ -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); }
+439 -308
View File
@@ -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;
}
+61 -26
View File
@@ -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
+998 -882
View File
File diff suppressed because it is too large. Load diff
+175 -161
View File
@@ -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
+2167 -1500
View File
File diff suppressed because it is too large. Load diff
+29 -33
View File
@@ -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
+10
View File
@@ -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
+58
View File
@@ -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
}
+20 -7
View File
@@ -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;
+2 -7
View File
@@ -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;
+49 -46
View File
@@ -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;
+45 -4
View File
@@ -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;
}
}
+106 -28
View File
@@ -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,
+60 -33
View File
@@ -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>
+4 -1
View File
@@ -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;
}
+58 -20
View File
@@ -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
+2 -4
View File
@@ -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;
+363
View File
@@ -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
+298
View File
@@ -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
+55 -3
View File
@@ -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
+479
View File
@@ -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);
}
+1 -1
View File
@@ -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)
+303
View File
@@ -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);
}
+2 -1
View File
@@ -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)
{
+183 -64
View File
@@ -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'
+86
View File
@@ -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;
}
+112
View File
@@ -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;
}
+3
View File
@@ -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
View File
@@ -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);