Compression algo dependencies, still need hackery...
This commit is contained in:
parent
af234f3502
commit
2c8dc0b855
@ -43,6 +43,10 @@ include_directories(${Qt5Widgets_INCLUDE_DIRS})
|
||||
add_subdirectory(depends/quazip)
|
||||
include_directories(depends/quazip)
|
||||
|
||||
# Add lzma
|
||||
add_subdirectory(depends/lzma)
|
||||
include_directories(depends/lzma/include)
|
||||
|
||||
# Add the java launcher
|
||||
add_subdirectory(depends/launcher)
|
||||
|
||||
@ -60,6 +64,8 @@ include_directories(${LIBSETTINGS_INCLUDE_DIR})
|
||||
add_subdirectory(depends/groupview)
|
||||
include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
|
||||
|
||||
#pack 200
|
||||
add_subdirectory(depends/pack200)
|
||||
|
||||
################################ SET UP BUILD OPTIONS ################################
|
||||
|
||||
@ -345,8 +351,9 @@ ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32
|
||||
|
||||
# Link
|
||||
QT5_USE_MODULES(MultiMC Widgets Network Xml)
|
||||
TARGET_LINK_LIBRARIES(MultiMC quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libGroupView)
|
||||
TARGET_LINK_LIBRARIES(MultiMC quazip lzma libUtil libSettings libGroupView
|
||||
${MultiMC_LINK_ADDITIONAL_LIBS})
|
||||
#ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libGroupView)
|
||||
|
||||
|
||||
option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF)
|
||||
|
54
depends/lzma/CMakeLists.txt
Normal file
54
depends/lzma/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
PROJECT(lzma)
|
||||
|
||||
IF (WIN32)
|
||||
ADD_DEFINITIONS(-DWIN32)
|
||||
ENDIF (WIN32)
|
||||
|
||||
SET(SRCS
|
||||
# original code by Igor Pavlov
|
||||
# Lzma version 4.63
|
||||
# Minified ~_~
|
||||
pavlov/7zCrc.c
|
||||
pavlov/7zCrc.h
|
||||
pavlov/LzFind.c
|
||||
pavlov/LzFind.h
|
||||
pavlov/LzHash.h
|
||||
pavlov/LzmaDec.c
|
||||
pavlov/LzmaDec.h
|
||||
pavlov/LzmaEnc.c
|
||||
pavlov/LzmaEnc.h
|
||||
pavlov/LzmaLib.c
|
||||
pavlov/LzmaLib.h
|
||||
pavlov/Types.h
|
||||
|
||||
# Public headers
|
||||
include/common.h
|
||||
include/compress.h
|
||||
include/decompress.h
|
||||
include/simple.h
|
||||
|
||||
# Wrapper by Lloyd Hilaiel (lloyd@hilaiel.com)
|
||||
wrapper/common_internal.c
|
||||
wrapper/common_internal.h
|
||||
wrapper/compress.c
|
||||
wrapper/decompress.c
|
||||
wrapper/simple.c
|
||||
wrapper/lzip_header.c
|
||||
wrapper/lzip_header.h
|
||||
wrapper/lzma_header.c
|
||||
wrapper/lzma_header.h
|
||||
)
|
||||
|
||||
# an include directory to allow easylzma implementation to find public
|
||||
# headers
|
||||
INCLUDE_DIRECTORIES(include)
|
||||
ADD_LIBRARY(lzma STATIC ${SRCS})
|
||||
|
||||
# lzma compress/decompress tool
|
||||
ADD_EXECUTABLE(elzma elzma.c)
|
||||
TARGET_LINK_LIBRARIES(elzma lzma)
|
||||
# a simple test...
|
||||
ADD_EXECUTABLE(easylzma_test easylzma_test.c)
|
||||
TARGET_LINK_LIBRARIES(easylzma_test lzma)
|
9
depends/lzma/LICENSE.txt
Normal file
9
depends/lzma/LICENSE.txt
Normal file
@ -0,0 +1,9 @@
|
||||
# Written in 2009 by Lloyd Hilaiel
|
||||
# Butchered in 2013 by Petr Mrazek
|
||||
#
|
||||
# License
|
||||
#
|
||||
# All the cruft you find here is public domain. You don't have to credit
|
||||
# anyone to use this code, but my personal request is that you mention
|
||||
# Igor Pavlov for his hard, high quality work.
|
||||
#
|
282
depends/lzma/easylzma_test.c
Normal file
282
depends/lzma/easylzma_test.c
Normal file
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* Various compiled-in tests for the easylzma library which excercise
|
||||
* API correctness and handling of corrupt data.
|
||||
*/
|
||||
|
||||
#include "simple.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *sampleData =
|
||||
"Overview\n"
|
||||
"\n"
|
||||
"Easylzma is a C library and command line tools for LZMA compression and \n"
|
||||
"decompression. It uses a Igor Pavlov's reference implementation and SDK\n"
|
||||
"written in C.\n"
|
||||
"\n"
|
||||
"License\n"
|
||||
"\n"
|
||||
"All the cruft you find here is public domain. You don't have to credit\n"
|
||||
"anyone to use this code, but my personal request is that you mention\n"
|
||||
"Igor Pavlov for his hard, high quality work.\n"
|
||||
"\n"
|
||||
"Project Goals\n"
|
||||
"\n"
|
||||
"1. A tiny C wrapper and portable build system around a subset of\n"
|
||||
" Igor Pavlov's public domain LZMA compression and decompression\n"
|
||||
" implementation.\n"
|
||||
"2. A tiny and straighforward API\n"
|
||||
"3. Support for multiple different prominent LZMA file formats (see section on\n"
|
||||
" file formats below)\n"
|
||||
"4. easy to build and use everywhere (doze and nix alike)\n"
|
||||
"5. public domain licensing through and through. (hats off to Igor)\n"
|
||||
"\n"
|
||||
"Current State:\n"
|
||||
"\n"
|
||||
"THIS IS A WORK IN PROGRESS. The code here should be considered pre-alpha,\n"
|
||||
"and this should only be used by tinkerers or hackers at this point. Once\n"
|
||||
"feature completion is attained this message will be updated. See the\n"
|
||||
"TODO file distributed with the source for remaining work to be done.\n"
|
||||
"\n"
|
||||
"Platforms Supported\n"
|
||||
"\n"
|
||||
"0.0.2 has been successfully compiled and run basic round trip testing\n"
|
||||
"on the following platforms & compilers:\n"
|
||||
"\n"
|
||||
" * win32 - visual studio 2005\n"
|
||||
" * osx - 10.4 & 10.5 (intel)\n"
|
||||
" * netbsd ppc - 4.0.1 with gcc 4.1.2\n"
|
||||
" (NOTE: memory allocation errors when dict size is default)\n"
|
||||
" * freebsd 6.1 - amd64 gcc 3.4.4\n"
|
||||
"\n"
|
||||
"Features\n"
|
||||
"\n"
|
||||
"XXX: write me (and the code)\n"
|
||||
"\n"
|
||||
"Usage\n"
|
||||
"\n"
|
||||
"XXX: write me (and the code)\n"
|
||||
"\n"
|
||||
"The Saga of LZMA File Formats, and a couple cents.\n"
|
||||
"\n"
|
||||
"As far as I can tell, there are at least four different ways to put LZMA\n"
|
||||
"compressed data in a stream:\n"
|
||||
"\n"
|
||||
"1. The LZMA-Alone format, which consists of a 13 byte header including\n"
|
||||
" compression properties, dictionary size, and the uncompressed size of\n"
|
||||
" the file, followed by compressed data. This format has some support\n"
|
||||
" in Igor Pavlov's reference implementation and is in widespread use, as\n"
|
||||
" it's supported by lzmautils: http://tukaani.org/lzma/\n"
|
||||
"\n"
|
||||
" The canonical (afaict) implementation of this format (lzmautis) is\n"
|
||||
" BSD licensed.\n"
|
||||
"\n"
|
||||
"2. The lzip format (http://www.nongnu.org/lzip/lzip.html) - which\n"
|
||||
" includes a CRC footer and leading \"magic number\". The former\n"
|
||||
" affords data integrity gaurantees, while the latter simplifies\n"
|
||||
" heuristic determination of file format. This format looks to have\n"
|
||||
" reasonably widespread usage, though not quite as significant as\n"
|
||||
" LZMA-Alone.\n"
|
||||
"\n"
|
||||
" The only implementation of this format I can find (lzip) is GPL licensed.\n"
|
||||
"\n"
|
||||
"3. the xz format ( http://tukaani.org/xz/xz-file-format.txt ) which is\n"
|
||||
" a more complex representation that includes CRC support and a magic\n"
|
||||
" number. This format is to be supported by the next iteration of\n"
|
||||
" XZ Utils which is currently in beta. The source may be obtained\n"
|
||||
" here: git://ctrl.tukaani.org/xz.git\n"
|
||||
"\n"
|
||||
" This format will address some criticisms to the LZMA-Alone format and\n"
|
||||
" was developed collaboratively by Lasse Collin (the current maintainer\n"
|
||||
" of XZ utils) and Igor Pavlov (the author of 7zip and the refrence\n"
|
||||
" implementation of LZMA).\n"
|
||||
"\n"
|
||||
" The xz format will employ LZMA2 which consists of extensions on top\n"
|
||||
" of LZMA, in the xz utils maintainer's words:\n"
|
||||
"\n"
|
||||
" \"The primary compression algorithm in .xz is currently LZMA2, which\n"
|
||||
" is an extension on top of the orignal LZMA to fix a few practical\n"
|
||||
" issues, like adding support for flushing the encoder (equivalent\n"
|
||||
" to zlib's Z_SYNC_FLUSH), which isn't possible with the original\n"
|
||||
" LZMA.\"\n"
|
||||
"\n"
|
||||
" Again, maintainers words, regarding licensing:\n"
|
||||
"\n"
|
||||
" \"XZ Utils currently contains a zlib-like compression library and a \n"
|
||||
" gzip-like command line tool. It's currently under LGPLv2.1+ but I will \n"
|
||||
" put it into the public domain before the first stable release.\"\n"
|
||||
"\n"
|
||||
"4. The 7zip disk format which can contain multiple files possibly stored in\n"
|
||||
" LZMA compressed format.\n"
|
||||
"\n"
|
||||
"Given the state of things, the goal of this project is to develop something\n"
|
||||
"based on the existing formats, and quickly leverage code generated by the XZ\n"
|
||||
"Utils project, or simply kill this thing if that project produces something\n"
|
||||
"that's easy to embed and has a clean API at a similar level of abstraction\n"
|
||||
"as easylzma.\n"
|
||||
"\n"
|
||||
"lloyd - sometime in oh nine.\n";
|
||||
|
||||
/* a test that we can round trip compress/decompress data using LZMA or LZIP
|
||||
* formats */
|
||||
static int roundTripTest(elzma_file_format format)
|
||||
{
|
||||
int rc;
|
||||
unsigned char *compressed;
|
||||
unsigned char *decompressed;
|
||||
size_t sz;
|
||||
|
||||
rc = simpleCompress(format, (unsigned char *)sampleData, strlen(sampleData), &compressed,
|
||||
&sz);
|
||||
|
||||
if (rc != ELZMA_E_OK)
|
||||
return rc;
|
||||
|
||||
/* gross assurance that compression is actually compressing */
|
||||
if (sz > strlen(sampleData))
|
||||
{
|
||||
free(compressed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
rc = simpleDecompress(format, compressed, sz, &decompressed, &sz);
|
||||
|
||||
free(compressed);
|
||||
|
||||
if (rc != ELZMA_E_OK)
|
||||
return rc;
|
||||
|
||||
if (sz != strlen(sampleData) || 0 != memcmp(decompressed, sampleData, sz))
|
||||
{
|
||||
free(decompressed);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ELZMA_E_OK;
|
||||
}
|
||||
|
||||
/* "correct" lzip generated from the lzip program */
|
||||
/*|LZIP...3.?..????|*/
|
||||
/*|....?e2~........|*/
|
||||
static unsigned char correctLzip[] = {
|
||||
0x4c, 0x5a, 0x49, 0x50, 0x01, 0x0c, 0x00, 0x33, 0x1b, 0xec, 0x15, 0x07, 0xff, 0xff,
|
||||
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xa8, 0x65, 0x32, 0x7e, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
/* "correct" lzip generated from lzma utils */
|
||||
static unsigned char correctLzma[] = {0x5d, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x1b, 0xec, 0x14, 0x00, 0x00, 0x00};
|
||||
|
||||
/* lzip with a bad CRC */
|
||||
static unsigned char corruptCRC[] = {
|
||||
0x4c, 0x5a, 0x49, 0x50, 0x01, 0x0c, 0x00, 0x33, 0x1b, 0xec, 0x15, 0x07, 0xff, 0xff,
|
||||
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xa8, 0x65, 0x31, 0x7e, 0x04, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
/* lzip with a bad uncompressed size */
|
||||
static unsigned char corruptSize[] = {
|
||||
0x4c, 0x5a, 0x49, 0x50, 0x01, 0x0c, 0x00, 0x33, 0x1b, 0xec, 0x15, 0x07, 0xff, 0xff,
|
||||
0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0xa8, 0x65, 0x32, 0x7e, 0x04, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
/* lzma with a bad uncompressed size */
|
||||
static unsigned char corruptSizeLzma[] = {0x5d, 0x00, 0x00, 0x80, 0x00, 0x04, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x1b, 0xec, 0x14, 0x00, 0x00, 0x00};
|
||||
|
||||
/* lzma with a bad uncompressed size */
|
||||
static unsigned char corruptSizeLzma2[] = {0x5d, 0x00, 0x00, 0x80, 0x00, 0x03, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x1b, 0xec, 0x14, 0x00, 0x00, 0x00};
|
||||
|
||||
/* tests */
|
||||
static struct
|
||||
{
|
||||
const char *testName; /* the name of the test */
|
||||
int expectedCode; /* the expected output of the test */
|
||||
elzma_file_format format;
|
||||
unsigned char *data; /* input data */
|
||||
unsigned int dataSize;
|
||||
} tests[] = {
|
||||
{"correct lzip", ELZMA_E_OK, ELZMA_lzip, correctLzip, sizeof(correctLzip)},
|
||||
{"lzip as lzma", ELZMA_E_DECOMPRESS_ERROR, ELZMA_lzma, correctLzip, sizeof(correctLzip)},
|
||||
{"correct lzma", ELZMA_E_OK, ELZMA_lzma, correctLzma, sizeof(correctLzma)},
|
||||
{"lzma as lzip", ELZMA_E_CORRUPT_HEADER, ELZMA_lzip, correctLzma, sizeof(correctLzma)},
|
||||
{"corrupt crc", ELZMA_E_CRC32_MISMATCH, ELZMA_lzip, corruptCRC, sizeof(corruptCRC)},
|
||||
{"bad lzip size", ELZMA_E_SIZE_MISMATCH, ELZMA_lzip, corruptSize, sizeof(corruptSize)},
|
||||
{"bad lzma size", ELZMA_E_INSUFFICIENT_INPUT, ELZMA_lzma,
|
||||
corruptSizeLzma, sizeof(corruptSizeLzma)},
|
||||
{"bad lzma size 2", ELZMA_E_SIZE_MISMATCH, ELZMA_lzma,
|
||||
corruptSizeLzma2, sizeof(corruptSizeLzma2)}};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int testsPassed = 0;
|
||||
unsigned int testsRun = 0;
|
||||
|
||||
int rc = 0;
|
||||
|
||||
printf("round trip lzma test: ");
|
||||
fflush(stdout);
|
||||
testsRun++;
|
||||
if (ELZMA_E_OK != (rc = roundTripTest(ELZMA_lzma)))
|
||||
{
|
||||
printf("fail! (%d)\n", rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
testsPassed++;
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
printf("round trip lzip test: ");
|
||||
fflush(stdout);
|
||||
testsRun++;
|
||||
if (ELZMA_E_OK != (rc = roundTripTest(ELZMA_lzip)))
|
||||
{
|
||||
printf("fail (%d)!\n", rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
testsPassed++;
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
/* now run through the tests table */
|
||||
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
|
||||
{
|
||||
unsigned char *decompressed = NULL;
|
||||
size_t sz = 0;
|
||||
|
||||
printf("%s test: ", tests[i].testName);
|
||||
rc = simpleDecompress(tests[i].format, tests[i].data, tests[i].dataSize, &decompressed,
|
||||
&sz);
|
||||
|
||||
testsRun++;
|
||||
if (rc != tests[i].expectedCode)
|
||||
{
|
||||
printf("fail - got %d - expected %d\n", rc, tests[i].expectedCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
testsPassed++;
|
||||
printf("ok\n");
|
||||
free(decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n%d/%d tests passed\n", testsPassed, testsRun);
|
||||
|
||||
return (testsPassed == testsRun) ? 0 : 1;
|
||||
}
|
557
depends/lzma/elzma.c
Normal file
557
depends/lzma/elzma.c
Normal file
@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* command line elzma tool for lzma compression
|
||||
*
|
||||
* At time of writing, the primary purpose of this tool is to test the
|
||||
* easylzma library.
|
||||
*
|
||||
* TODO:
|
||||
* - stdin/stdout support
|
||||
* - multiple file support
|
||||
* - much more
|
||||
*/
|
||||
|
||||
#include "include/compress.h"
|
||||
#include "include/decompress.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <stdio.h>
|
||||
#define unlink _unlink
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int deleteFile(const char *path)
|
||||
{
|
||||
return unlink(path);
|
||||
}
|
||||
|
||||
/* a utility to open a pair of files */
|
||||
/* XXX: respect overwrite flag */
|
||||
static int openFiles(const char *ifname, FILE **inFile, const char *ofname, FILE **outFile,
|
||||
int overwrite)
|
||||
{
|
||||
*inFile = fopen(ifname, "rb");
|
||||
if (*inFile == NULL)
|
||||
{
|
||||
fprintf(stderr, "couldn't open '%s' for reading\n", ifname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
*outFile = fopen(ofname, "wb");
|
||||
if (*outFile == NULL)
|
||||
{
|
||||
fprintf(stderr, "couldn't open '%s' for writing\n", ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ELZMA_COMPRESS_USAGE \
|
||||
"Compress files using the LZMA algorithm (in place by default).\n" \
|
||||
"\n" \
|
||||
"Usage: elzma [options] [file]\n" \
|
||||
" -1 .. -9 compression level, -1 is fast, -9 is best (default 5)\n" \
|
||||
" -f, --force overwrite output files if they exist\n" \
|
||||
" -h, --help output this message and exit\n" \
|
||||
" -k, --keep don't delete input files\n" \
|
||||
" --lzip compress to lzip disk format (.lz extension)\n" \
|
||||
" --lzma compress to LZMA-Alone disk format (.lzma extension)\n" \
|
||||
" -v, --verbose output verbose status information while compressing\n" \
|
||||
" -z, --compress compress files (default when invoking elzma program)\n" \
|
||||
" -d, --decompress decompress files (default when invoking unelzma program)\n" \
|
||||
"\n" \
|
||||
"Advanced Options:\n" \
|
||||
" -s --set-max-dict (advanced) specify maximum dictionary size in bytes\n"
|
||||
|
||||
/* parse arguments populating output parameters, return nonzero on failure */
|
||||
static int parseCompressArgs(int argc, char **argv, unsigned char *level, char **fname,
|
||||
unsigned int *maxDictSize, unsigned int *verbose,
|
||||
unsigned int *keep, unsigned int *overwrite,
|
||||
elzma_file_format *format)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
char *val = NULL;
|
||||
char *arg = &(argv[i][1]);
|
||||
if (arg[0] == '-')
|
||||
arg++;
|
||||
|
||||
/* now see what argument this is */
|
||||
if (!strcmp(arg, "h") || !strcmp(arg, "help"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(arg, "s") || !strcmp(arg, "set-max-dict"))
|
||||
{
|
||||
unsigned int j = 0;
|
||||
val = argv[++i];
|
||||
|
||||
/* validate argument is numeric */
|
||||
for (j = 0; j < strlen(val); j++)
|
||||
{
|
||||
if (val[j] < '0' || val[j] > '9')
|
||||
return 1;
|
||||
}
|
||||
|
||||
*maxDictSize = strtoul(val, (char **)NULL, 10);
|
||||
|
||||
/* don't allow dictionary sizes less than 8k */
|
||||
if (*maxDictSize < (1 < 13))
|
||||
*maxDictSize = 1 < 13;
|
||||
else
|
||||
{
|
||||
/* make sure dict size is compatible with lzip,
|
||||
* this will effectively collapse it to a close power
|
||||
* of 2 */
|
||||
*maxDictSize = elzma_get_dict_size(*maxDictSize);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(arg, "v") || !strcmp(arg, "verbose"))
|
||||
{
|
||||
*verbose = 1;
|
||||
}
|
||||
else if (!strcmp(arg, "f") || !strcmp(arg, "force"))
|
||||
{
|
||||
*overwrite = 1;
|
||||
}
|
||||
else if (!strcmp(arg, "k") || !strcmp(arg, "keep"))
|
||||
{
|
||||
*keep = 1;
|
||||
}
|
||||
else if (strlen(arg) == 1 && arg[0] >= '1' && arg[0] <= '9')
|
||||
{
|
||||
*level = arg[0] - '0';
|
||||
}
|
||||
else if (!strcmp(arg, "lzma"))
|
||||
{
|
||||
*format = ELZMA_lzma;
|
||||
}
|
||||
else if (!strcmp(arg, "lzip"))
|
||||
{
|
||||
*format = ELZMA_lzip;
|
||||
}
|
||||
else if (!strcmp(arg, "z") || !strcmp(arg, "d") || !strcmp(arg, "compress") ||
|
||||
!strcmp(arg, "decompress"))
|
||||
{
|
||||
/* noop */
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*fname = argv[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* proper number of arguments? */
|
||||
if (i != argc - 1 || *fname == NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* callbacks for streamed input and output */
|
||||
static size_t elzmaWriteFunc(void *ctx, const void *buf, size_t size)
|
||||
{
|
||||
size_t wt;
|
||||
FILE *f = (FILE *)ctx;
|
||||
assert(f != NULL);
|
||||
|
||||
wt = fwrite(buf, 1, size, f);
|
||||
|
||||
return wt;
|
||||
}
|
||||
|
||||
static int elzmaReadFunc(void *ctx, void *buf, size_t *size)
|
||||
{
|
||||
FILE *f = (FILE *)ctx;
|
||||
assert(f != NULL);
|
||||
*size = fread(buf, 1, *size, f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void printProgressHeader(void)
|
||||
{
|
||||
printf("|0%% 50%% 100%%|\n");
|
||||
}
|
||||
|
||||
static void endProgress(int pCtx)
|
||||
{
|
||||
while (pCtx++ < 64)
|
||||
{
|
||||
printf(".");
|
||||
}
|
||||
printf("|\n");
|
||||
}
|
||||
|
||||
static void elzmaProgressFunc(void *ctx, size_t complete, size_t total)
|
||||
{
|
||||
int *dots = (int *)ctx;
|
||||
int wantDots = (int)(64 * (double)complete / (double)total);
|
||||
if (*dots == 0)
|
||||
{
|
||||
printf("|");
|
||||
(*dots)++;
|
||||
}
|
||||
while (wantDots > *dots)
|
||||
{
|
||||
printf(".");
|
||||
(*dots)++;
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
static int doCompress(int argc, char **argv)
|
||||
{
|
||||
/* default compression parameters, some of which may be overridded by
|
||||
* command line arguments */
|
||||
unsigned char level = 5;
|
||||
unsigned char lc = ELZMA_LC_DEFAULT;
|
||||
unsigned char lp = ELZMA_LP_DEFAULT;
|
||||
unsigned char pb = ELZMA_PB_DEFAULT;
|
||||
unsigned int maxDictSize = ELZMA_DICT_SIZE_DEFAULT_MAX;
|
||||
unsigned int dictSize = 0;
|
||||
elzma_file_format format = ELZMA_lzma;
|
||||
char *ext = ".lzma";
|
||||
char *ifname = NULL;
|
||||
char *ofname = NULL;
|
||||
unsigned int verbose = 0;
|
||||
FILE *inFile = NULL;
|
||||
FILE *outFile = NULL;
|
||||
elzma_compress_handle hand = NULL;
|
||||
/* XXX: large file support */
|
||||
unsigned int uncompressedSize = 0;
|
||||
unsigned int keep = 0;
|
||||
unsigned int overwrite = 0;
|
||||
|
||||
if (0 != parseCompressArgs(argc, argv, &level, &ifname, &maxDictSize, &verbose, &keep,
|
||||
&overwrite, &format))
|
||||
{
|
||||
fprintf(stderr, ELZMA_COMPRESS_USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* extension switching based on compression type*/
|
||||
if (format == ELZMA_lzip)
|
||||
ext = ".lz";
|
||||
|
||||
/* generate output file name */
|
||||
{
|
||||
ofname = malloc(strlen(ifname) + strlen(ext) + 1);
|
||||
ofname[0] = 0;
|
||||
strcat(ofname, ifname);
|
||||
strcat(ofname, ext);
|
||||
}
|
||||
|
||||
/* now attempt to open input and ouput files */
|
||||
/* XXX: stdin/stdout support */
|
||||
if (0 != openFiles(ifname, &inFile, ofname, &outFile, overwrite))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* set uncompressed size */
|
||||
if (0 != fseek(inFile, 0, SEEK_END) || 0 == (uncompressedSize = ftell(inFile)) ||
|
||||
0 != fseek(inFile, 0, SEEK_SET))
|
||||
{
|
||||
fprintf(stderr, "error seeking input file (%s) - zero length?\n", ifname);
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* determine a reasonable dictionary size given input size */
|
||||
dictSize = elzma_get_dict_size(uncompressedSize);
|
||||
if (dictSize > maxDictSize)
|
||||
dictSize = maxDictSize;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
printf("compressing '%s' to '%s'\n", ifname, ofname);
|
||||
printf("lc/lp/pb = %u/%u/%u | dictionary size = %u bytes\n", lc, lp, pb, dictSize);
|
||||
printf("input file is %u bytes\n", uncompressedSize);
|
||||
}
|
||||
|
||||
/* allocate a compression handle */
|
||||
hand = elzma_compress_alloc();
|
||||
if (hand == NULL)
|
||||
{
|
||||
fprintf(stderr, "couldn't allocate compression object\n");
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ELZMA_E_OK !=
|
||||
elzma_compress_config(hand, lc, lp, pb, level, dictSize, format, uncompressedSize))
|
||||
{
|
||||
fprintf(stderr, "couldn't configure compression with "
|
||||
"provided parameters\n");
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
{
|
||||
int rv;
|
||||
int pCtx = 0;
|
||||
|
||||
if (verbose)
|
||||
printProgressHeader();
|
||||
|
||||
rv = elzma_compress_run(hand, elzmaReadFunc, (void *)inFile, elzmaWriteFunc,
|
||||
(void *)outFile, (verbose ? elzmaProgressFunc : NULL), &pCtx);
|
||||
|
||||
if (verbose)
|
||||
endProgress(pCtx);
|
||||
|
||||
if (ELZMA_E_OK != rv)
|
||||
{
|
||||
fprintf(stderr, "error compressing\n");
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* clean up */
|
||||
elzma_compress_free(&hand);
|
||||
fclose(inFile);
|
||||
fclose(outFile);
|
||||
free(ofname);
|
||||
|
||||
if (!keep)
|
||||
deleteFile(ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ELZMA_DECOMPRESS_USAGE \
|
||||
"Decompress files compressed using the LZMA algorithm (in place by default).\n" \
|
||||
"\n" \
|
||||
"Usage: unelzma [options] [file]\n" \
|
||||
" -f, --force overwrite output files if they exist\n" \
|
||||
" -h, --help output this message and exit\n" \
|
||||
" -k, --keep don't delete input files\n" \
|
||||
" -v, --verbose output verbose status information while decompressing\n" \
|
||||
" -z, --compress compress files (default when invoking elzma program)\n" \
|
||||
" -d, --decompress decompress files (default when invoking unelzma program)\n" \
|
||||
"\n"
|
||||
/* parse arguments populating output parameters, return nonzero on failure */
|
||||
static int parseDecompressArgs(int argc, char **argv, char **fname, unsigned int *verbose,
|
||||
unsigned int *keep, unsigned int *overwrite)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc < 2)
|
||||
return 1;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
char *arg = &(argv[i][1]);
|
||||
if (arg[0] == '-')
|
||||
arg++;
|
||||
|
||||
/* now see what argument this is */
|
||||
if (!strcmp(arg, "h") || !strcmp(arg, "help"))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else if (!strcmp(arg, "v") || !strcmp(arg, "verbose"))
|
||||
{
|
||||
*verbose = 1;
|
||||
}
|
||||
else if (!strcmp(arg, "k") || !strcmp(arg, "keep"))
|
||||
{
|
||||
*keep = 1;
|
||||
}
|
||||
else if (!strcmp(arg, "f") || !strcmp(arg, "force"))
|
||||
{
|
||||
*overwrite = 1;
|
||||
}
|
||||
else if (!strcmp(arg, "z") || !strcmp(arg, "d") || !strcmp(arg, "compress") ||
|
||||
!strcmp(arg, "decompress"))
|
||||
{
|
||||
/* noop */
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*fname = argv[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* proper number of arguments? */
|
||||
if (i != argc - 1 || *fname == NULL)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int doDecompress(int argc, char **argv)
|
||||
{
|
||||
char *ifname = NULL;
|
||||
char *ofname = NULL;
|
||||
unsigned int verbose = 0;
|
||||
FILE *inFile = NULL;
|
||||
FILE *outFile = NULL;
|
||||
elzma_decompress_handle hand = NULL;
|
||||
unsigned int overwrite = 0;
|
||||
unsigned int keep = 0;
|
||||
elzma_file_format format;
|
||||
const char *lzmaExt = ".lzma";
|
||||
const char *lzipExt = ".lz";
|
||||
const char *ext = ".lz";
|
||||
|
||||
if (0 != parseDecompressArgs(argc, argv, &ifname, &verbose, &keep, &overwrite))
|
||||
{
|
||||
fprintf(stderr, ELZMA_DECOMPRESS_USAGE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* generate output file name */
|
||||
if (strlen(ifname) > strlen(lzmaExt) &&
|
||||
0 == strcmp(lzmaExt, ifname + strlen(ifname) - strlen(lzmaExt)))
|
||||
{
|
||||
format = ELZMA_lzma;
|
||||
ext = lzmaExt;
|
||||
}
|
||||
else if (strlen(ifname) > strlen(lzipExt) &&
|
||||
0 == strcmp(lzipExt, ifname + strlen(ifname) - strlen(lzipExt)))
|
||||
{
|
||||
format = ELZMA_lzip;
|
||||
ext = lzipExt;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "input file extension not recognized (expected either "
|
||||
"%s or %s)",
|
||||
lzmaExt, lzipExt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
ofname = malloc(strlen(ifname) - strlen(ext));
|
||||
ofname[0] = 0;
|
||||
strncat(ofname, ifname, strlen(ifname) - strlen(ext));
|
||||
|
||||
/* now attempt to open input and ouput files */
|
||||
/* XXX: stdin/stdout support */
|
||||
if (0 != openFiles(ifname, &inFile, ofname, &outFile, overwrite))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
hand = elzma_decompress_alloc();
|
||||
if (hand == NULL)
|
||||
{
|
||||
fprintf(stderr, "couldn't allocate decompression object\n");
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ELZMA_E_OK != elzma_decompress_run(hand, elzmaReadFunc, (void *)inFile, elzmaWriteFunc,
|
||||
(void *)outFile, format))
|
||||
{
|
||||
fprintf(stderr, "error decompressing\n");
|
||||
deleteFile(ofname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
elzma_decompress_free(&hand);
|
||||
|
||||
if (!keep)
|
||||
deleteFile(ifname);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *unelzma = "unelzma";
|
||||
const char *unelzmaLose = "unelzma.exe";
|
||||
const char *elzma = "elzma";
|
||||
const char *elzmaLose = "elzma.exe";
|
||||
|
||||
enum
|
||||
{
|
||||
RM_NONE,
|
||||
RM_COMPRESS,
|
||||
RM_DECOMPRESS
|
||||
} runmode = RM_NONE;
|
||||
|
||||
/* first we'll determine the mode we're running in, indicated by
|
||||
* the binary name (argv[0]) or by the presence of a flag:
|
||||
* one of -z, -d, -compress, --decompress */
|
||||
if ((strlen(argv[0]) >= strlen(unelzma) &&
|
||||
!strcmp((argv[0] + strlen(argv[0]) - strlen(unelzma)), unelzma)) ||
|
||||
(strlen(argv[0]) >= strlen(unelzmaLose) &&
|
||||
!strcmp((argv[0] + strlen(argv[0]) - strlen(unelzmaLose)), unelzmaLose)))
|
||||
{
|
||||
runmode = RM_DECOMPRESS;
|
||||
}
|
||||
else if ((strlen(argv[0]) >= strlen(elzma) &&
|
||||
!strcmp((argv[0] + strlen(argv[0]) - strlen(elzma)), elzma)) ||
|
||||
(strlen(argv[0]) >= strlen(elzmaLose) &&
|
||||
!strcmp((argv[0] + strlen(argv[0]) - strlen(elzmaLose)), elzmaLose)))
|
||||
{
|
||||
runmode = RM_COMPRESS;
|
||||
}
|
||||
|
||||
/* allow runmode to be overridded by a command line flag, first flag
|
||||
* wins */
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--decompress"))
|
||||
{
|
||||
runmode = RM_DECOMPRESS;
|
||||
break;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-z") || !strcmp(argv[i], "--compress"))
|
||||
{
|
||||
runmode = RM_COMPRESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (runmode != RM_COMPRESS && runmode != RM_DECOMPRESS)
|
||||
{
|
||||
fprintf(stderr, "couldn't determine whether "
|
||||
"you want to compress or decompress\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (runmode == RM_COMPRESS)
|
||||
return doCompress(argc, argv);
|
||||
return doDecompress(argc, argv);
|
||||
}
|
118
depends/lzma/include/common.h
Normal file
118
depends/lzma/include/common.h
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* easylzma/common.h - definitions common to both compression and
|
||||
* decompression
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* msft dll export gunk. To build a DLL on windows, you
|
||||
* must define WIN32, EASYLZMA_SHARED, and EASYLZMA_BUILD. To use a
|
||||
* DLL, you must define EASYLZMA_SHARED and WIN32 */
|
||||
#if defined(WIN32) && defined(EASYLZMA_SHARED)
|
||||
#ifdef EASYLZMA_BUILD
|
||||
#define EASYLZMA_API __declspec(dllexport)
|
||||
#else
|
||||
#define EASYLZMA_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define EASYLZMA_API
|
||||
#endif
|
||||
|
||||
/** error codes */
|
||||
|
||||
/** no error */
|
||||
#define ELZMA_E_OK 0
|
||||
/** bad parameters passed to an ELZMA function */
|
||||
#define ELZMA_E_BAD_PARAMS 10
|
||||
/** could not initialize the encode with configured parameters. */
|
||||
#define ELZMA_E_ENCODING_PROPERTIES_ERROR 11
|
||||
/** an error occured during compression (XXX: be more specific) */
|
||||
#define ELZMA_E_COMPRESS_ERROR 12
|
||||
/** currently unsupported lzma file format was specified*/
|
||||
#define ELZMA_E_UNSUPPORTED_FORMAT 13
|
||||
/** an error occured when reading input */
|
||||
#define ELZMA_E_INPUT_ERROR 14
|
||||
/** an error occured when writing output */
|
||||
#define ELZMA_E_OUTPUT_ERROR 15
|
||||
/** LZMA header couldn't be parsed */
|
||||
#define ELZMA_E_CORRUPT_HEADER 16
|
||||
/** an error occured during decompression (XXX: be more specific) */
|
||||
#define ELZMA_E_DECOMPRESS_ERROR 17
|
||||
/** the input stream returns EOF before the decompression could complete */
|
||||
#define ELZMA_E_INSUFFICIENT_INPUT 18
|
||||
/** for formats which have an emebedded crc, this error would indicated that
|
||||
* what came out was not what went in, i.e. data corruption */
|
||||
#define ELZMA_E_CRC32_MISMATCH 19
|
||||
/** for formats which have an emebedded uncompressed content length,
|
||||
* this error indicates that the amount we read was not what we expected */
|
||||
#define ELZMA_E_SIZE_MISMATCH 20
|
||||
|
||||
/** Supported file formats */
|
||||
typedef enum
|
||||
{
|
||||
ELZMA_lzip, /**< the lzip format which includes a magic number and
|
||||
* CRC check */
|
||||
ELZMA_lzma /**< the LZMA-Alone format, originally designed by
|
||||
* Igor Pavlov and in widespread use due to lzmautils,
|
||||
* lacking both aforementioned features of lzip */
|
||||
/* XXX: future, potentially ,
|
||||
ELZMA_xz
|
||||
*/
|
||||
} elzma_file_format;
|
||||
|
||||
/**
|
||||
* A callback invoked during elzma_[de]compress_run when the [de]compression
|
||||
* process has generated [de]compressed output.
|
||||
*
|
||||
* the size parameter indicates how much data is in buf to be written.
|
||||
* it is required that the write callback consume all data, and a return
|
||||
* value not equal to input size indicates and error.
|
||||
*/
|
||||
typedef size_t (*elzma_write_callback)(void *ctx, const void *buf, size_t size);
|
||||
|
||||
/**
|
||||
* A callback invoked during elzma_[de]compress_run when the [de]compression
|
||||
* process requires more [un]compressed input.
|
||||
*
|
||||
* the size parameter is an in/out argument. on input it indicates
|
||||
* the buffer size. on output it indicates the amount of data read into
|
||||
* buf. when *size is zero on output it indicates EOF.
|
||||
*
|
||||
* \returns the read callback should return nonzero on failure.
|
||||
*/
|
||||
typedef int (*elzma_read_callback)(void *ctx, void *buf, size_t *size);
|
||||
|
||||
/**
|
||||
* A callback invoked during elzma_[de]compress_run to report progress
|
||||
* on the [de]compression.
|
||||
*
|
||||
* \returns the read callback should return nonzero on failure.
|
||||
*/
|
||||
typedef void (*elzma_progress_callback)(void *ctx, size_t complete, size_t total);
|
||||
|
||||
/** pointer to a malloc function, supporting client overriding memory
|
||||
* allocation routines */
|
||||
typedef void *(*elzma_malloc)(void *ctx, unsigned int sz);
|
||||
|
||||
/** pointer to a free function, supporting client overriding memory
|
||||
* allocation routines */
|
||||
typedef void (*elzma_free)(void *ctx, void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
;
|
||||
#endif
|
77
depends/lzma/include/compress.h
Normal file
77
depends/lzma/include/compress.h
Normal file
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* compress.h - the API for LZMA compression using easylzma
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** suggested default values */
|
||||
#define ELZMA_LC_DEFAULT 3
|
||||
#define ELZMA_LP_DEFAULT 0
|
||||
#define ELZMA_PB_DEFAULT 2
|
||||
#define ELZMA_DICT_SIZE_DEFAULT_MAX (1 << 24)
|
||||
|
||||
/** an opaque handle to an lzma compressor */
|
||||
typedef struct _elzma_compress_handle *elzma_compress_handle;
|
||||
|
||||
/**
|
||||
* Allocate a handle to an LZMA compressor object.
|
||||
*/
|
||||
elzma_compress_handle EASYLZMA_API elzma_compress_alloc();
|
||||
|
||||
/**
|
||||
* set allocation routines (optional, if not called malloc & free will
|
||||
* be used)
|
||||
*/
|
||||
void EASYLZMA_API
|
||||
elzma_compress_set_allocation_callbacks(elzma_compress_handle hand, elzma_malloc mallocFunc,
|
||||
void *mallocFuncContext, elzma_free freeFunc,
|
||||
void *freeFuncContext);
|
||||
|
||||
/**
|
||||
* Free all data associated with an LZMA compressor object.
|
||||
*/
|
||||
void EASYLZMA_API elzma_compress_free(elzma_compress_handle *hand);
|
||||
|
||||
/**
|
||||
* Set configuration paramters for a compression run. If not called,
|
||||
* reasonable defaults will be used.
|
||||
*/
|
||||
int EASYLZMA_API elzma_compress_config(elzma_compress_handle hand, unsigned char lc,
|
||||
unsigned char lp, unsigned char pb, unsigned char level,
|
||||
unsigned int dictionarySize, elzma_file_format format,
|
||||
unsigned long long uncompressedSize);
|
||||
|
||||
/**
|
||||
* Run compression
|
||||
*/
|
||||
int EASYLZMA_API
|
||||
elzma_compress_run(elzma_compress_handle hand, elzma_read_callback inputStream,
|
||||
void *inputContext, elzma_write_callback outputStream, void *outputContext,
|
||||
elzma_progress_callback progressCallback, void *progressContext);
|
||||
|
||||
/**
|
||||
* a heuristic utility routine to guess a dictionary size that gets near
|
||||
* optimal compression while reducing memory usage.
|
||||
* accepts a size in bytes, returns a proposed dictionary size
|
||||
*/
|
||||
unsigned int EASYLZMA_API elzma_get_dict_size(unsigned long long size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
;
|
||||
#endif
|
58
depends/lzma/include/decompress.h
Normal file
58
depends/lzma/include/decompress.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* easylzma/decompress.h - The API for LZMA decompression using easylzma
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "include/common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** an opaque handle to an lzma decompressor */
|
||||
typedef struct _elzma_decompress_handle *elzma_decompress_handle;
|
||||
|
||||
/**
|
||||
* Allocate a handle to an LZMA decompressor object.
|
||||
*/
|
||||
elzma_decompress_handle EASYLZMA_API elzma_decompress_alloc();
|
||||
|
||||
/**
|
||||
* set allocation routines (optional, if not called malloc & free will
|
||||
* be used)
|
||||
*/
|
||||
void EASYLZMA_API
|
||||
elzma_decompress_set_allocation_callbacks(elzma_decompress_handle hand, elzma_malloc mallocFunc,
|
||||
void *mallocFuncContext, elzma_free freeFunc,
|
||||
void *freeFuncContext);
|
||||
|
||||
/**
|
||||
* Free all data associated with an LZMA decompressor object.
|
||||
*/
|
||||
void EASYLZMA_API elzma_decompress_free(elzma_decompress_handle *hand);
|
||||
|
||||
/**
|
||||
* Perform decompression
|
||||
*
|
||||
* XXX: should the library automatically detect format by reading stream?
|
||||
* currently it's based on data external to stream (such as extension
|
||||
* or convention)
|
||||
*/
|
||||
int EASYLZMA_API elzma_decompress_run(elzma_decompress_handle hand,
|
||||
elzma_read_callback inputStream, void *inputContext,
|
||||
elzma_write_callback outputStream, void *outputContext,
|
||||
elzma_file_format format);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
;
|
||||
#endif
|
37
depends/lzma/include/simple.h
Normal file
37
depends/lzma/include/simple.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* simple.h - a wrapper around easylzma to compress/decompress to memory
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "include/common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "include/compress.h"
|
||||
#include "include/decompress.h"
|
||||
|
||||
/* compress a chunk of memory and return a dynamically allocated buffer
|
||||
* if successful. return value is an easylzma error code */
|
||||
int EASYLZMA_API simpleCompress(elzma_file_format format, const unsigned char *inData,
|
||||
size_t inLen, unsigned char **outData, size_t *outLen);
|
||||
|
||||
/* decompress a chunk of memory and return a dynamically allocated buffer
|
||||
* if successful. return value is an easylzma error code */
|
||||
int EASYLZMA_API simpleDecompress(elzma_file_format format, const unsigned char *inData,
|
||||
size_t inLen, unsigned char **outData, size_t *outLen);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
;
|
||||
#endif
|
35
depends/lzma/pavlov/7zCrc.c
Executable file
35
depends/lzma/pavlov/7zCrc.c
Executable file
@ -0,0 +1,35 @@
|
||||
/* 7zCrc.c -- CRC32 calculation
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
uint32_t g_CrcTable[256];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcUpdate(uint32_t v, const void *data, size_t size)
|
||||
{
|
||||
const uint8_t *p = (const uint8_t *)data;
|
||||
for (; size > 0; size--, p++)
|
||||
v = CRC_UPDATE_BYTE(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
uint32_t MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
||||
}
|
24
depends/lzma/pavlov/7zCrc.h
Executable file
24
depends/lzma/pavlov/7zCrc.h
Executable file
@ -0,0 +1,24 @@
|
||||
/* 7zCrc.h -- CRC32 calculation
|
||||
2008-03-13
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
extern uint32_t g_CrcTable[];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
|
||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
||||
#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);
|
||||
|
||||
#endif
|
779
depends/lzma/pavlov/LzFind.c
Executable file
779
depends/lzma/pavlov/LzFind.c
Executable file
@ -0,0 +1,779 @@
|
||||
/* LzFind.c -- Match finder for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "LzFind.h"
|
||||
#include "LzHash.h"
|
||||
|
||||
#define kEmptyHashValue 0
|
||||
#define kMaxValForNormalize ((uint32_t)0xFFFFFFFF)
|
||||
#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
|
||||
#define kNormalizeMask (~(kNormalizeStepMin - 1))
|
||||
#define kMaxHistorySize ((uint32_t)3 << 30)
|
||||
|
||||
#define kStartMaxLen 3
|
||||
|
||||
static void LzInWindow_Free(CMatchFinder *p)
|
||||
{
|
||||
if (!p->directInput)
|
||||
{
|
||||
free(p->bufferBase);
|
||||
p->bufferBase = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
|
||||
|
||||
static int LzInWindow_Create(CMatchFinder *p, uint32_t keepSizeReserv)
|
||||
{
|
||||
uint32_t blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
|
||||
if (p->directInput)
|
||||
{
|
||||
p->blockSize = blockSize;
|
||||
return 1;
|
||||
}
|
||||
if (p->bufferBase == 0 || p->blockSize != blockSize)
|
||||
{
|
||||
LzInWindow_Free(p);
|
||||
p->blockSize = blockSize;
|
||||
p->bufferBase = (uint8_t *)malloc((size_t)blockSize);
|
||||
}
|
||||
return (p->bufferBase != 0);
|
||||
}
|
||||
|
||||
uint8_t *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p)
|
||||
{
|
||||
return p->buffer;
|
||||
}
|
||||
uint8_t MatchFinder_GetIndexByte(CMatchFinder *p, int32_t index)
|
||||
{
|
||||
return p->buffer[index];
|
||||
}
|
||||
|
||||
uint32_t MatchFinder_GetNumAvailableBytes(CMatchFinder *p)
|
||||
{
|
||||
return p->streamPos - p->pos;
|
||||
}
|
||||
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, uint32_t subValue)
|
||||
{
|
||||
p->posLimit -= subValue;
|
||||
p->pos -= subValue;
|
||||
p->streamPos -= subValue;
|
||||
}
|
||||
|
||||
static void MatchFinder_ReadBlock(CMatchFinder *p)
|
||||
{
|
||||
if (p->streamEndWasReached || p->result != SZ_OK)
|
||||
return;
|
||||
for (;;)
|
||||
{
|
||||
uint8_t *dest = p->buffer + (p->streamPos - p->pos);
|
||||
size_t size = (p->bufferBase + p->blockSize - dest);
|
||||
if (size == 0)
|
||||
return;
|
||||
p->result = p->stream->Read(p->stream, dest, &size);
|
||||
if (p->result != SZ_OK)
|
||||
return;
|
||||
if (size == 0)
|
||||
{
|
||||
p->streamEndWasReached = 1;
|
||||
return;
|
||||
}
|
||||
p->streamPos += (uint32_t)size;
|
||||
if (p->streamPos - p->pos > p->keepSizeAfter)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p)
|
||||
{
|
||||
memmove(p->bufferBase, p->buffer - p->keepSizeBefore,
|
||||
(size_t)(p->streamPos - p->pos + p->keepSizeBefore));
|
||||
p->buffer = p->bufferBase + p->keepSizeBefore;
|
||||
}
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p)
|
||||
{
|
||||
/* if (p->streamEndWasReached) return 0; */
|
||||
return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
|
||||
}
|
||||
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p)
|
||||
{
|
||||
if (p->streamEndWasReached)
|
||||
return;
|
||||
if (p->keepSizeAfter >= p->streamPos - p->pos)
|
||||
MatchFinder_ReadBlock(p);
|
||||
}
|
||||
|
||||
static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
|
||||
{
|
||||
if (MatchFinder_NeedMove(p))
|
||||
MatchFinder_MoveBlock(p);
|
||||
MatchFinder_ReadBlock(p);
|
||||
}
|
||||
|
||||
static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
|
||||
{
|
||||
p->cutValue = 32;
|
||||
p->btMode = 1;
|
||||
p->numHashBytes = 4;
|
||||
/* p->skipModeBits = 0; */
|
||||
p->directInput = 0;
|
||||
p->bigHash = 0;
|
||||
}
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
|
||||
void MatchFinder_Construct(CMatchFinder *p)
|
||||
{
|
||||
uint32_t i;
|
||||
p->bufferBase = 0;
|
||||
p->directInput = 0;
|
||||
p->hash = 0;
|
||||
MatchFinder_SetDefaultSettings(p);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
uint32_t r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
p->crc[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchFinder_FreeThisClassMemory(CMatchFinder *p)
|
||||
{
|
||||
free(p->hash);
|
||||
p->hash = 0;
|
||||
}
|
||||
|
||||
void MatchFinder_Free(CMatchFinder *p)
|
||||
{
|
||||
MatchFinder_FreeThisClassMemory(p);
|
||||
LzInWindow_Free(p);
|
||||
}
|
||||
|
||||
static CLzRef *AllocRefs(uint32_t num)
|
||||
{
|
||||
size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
|
||||
if (sizeInBytes / sizeof(CLzRef) != num)
|
||||
return 0;
|
||||
return (CLzRef *)malloc(sizeInBytes);
|
||||
}
|
||||
|
||||
int MatchFinder_Create(CMatchFinder *p, uint32_t historySize, uint32_t keepAddBufferBefore,
|
||||
uint32_t matchMaxLen, uint32_t keepAddBufferAfter)
|
||||
{
|
||||
uint32_t sizeReserv;
|
||||
if (historySize > kMaxHistorySize)
|
||||
{
|
||||
MatchFinder_Free(p);
|
||||
return 0;
|
||||
}
|
||||
sizeReserv = historySize >> 1;
|
||||
if (historySize > ((uint32_t)2 << 30))
|
||||
sizeReserv = historySize >> 2;
|
||||
sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
|
||||
|
||||
p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
|
||||
p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
|
||||
/* we need one additional byte, since we use MoveBlock after pos++ and before dictionary
|
||||
* using */
|
||||
if (LzInWindow_Create(p, sizeReserv))
|
||||
{
|
||||
uint32_t newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
|
||||
uint32_t hs;
|
||||
p->matchMaxLen = matchMaxLen;
|
||||
{
|
||||
p->fixedHashSize = 0;
|
||||
if (p->numHashBytes == 2)
|
||||
hs = (1 << 16) - 1;
|
||||
else
|
||||
{
|
||||
hs = historySize - 1;
|
||||
hs |= (hs >> 1);
|
||||
hs |= (hs >> 2);
|
||||
hs |= (hs >> 4);
|
||||
hs |= (hs >> 8);
|
||||
hs >>= 1;
|
||||
/* hs >>= p->skipModeBits; */
|
||||
hs |= 0xFFFF; /* don't change it! It's required for Deflate */
|
||||
if (hs > (1 << 24))
|
||||
{
|
||||
if (p->numHashBytes == 3)
|
||||
hs = (1 << 24) - 1;
|
||||
else
|
||||
hs >>= 1;
|
||||
}
|
||||
}
|
||||
p->hashMask = hs;
|
||||
hs++;
|
||||
if (p->numHashBytes > 2)
|
||||
p->fixedHashSize += kHash2Size;
|
||||
if (p->numHashBytes > 3)
|
||||
p->fixedHashSize += kHash3Size;
|
||||
if (p->numHashBytes > 4)
|
||||
p->fixedHashSize += kHash4Size;
|
||||
hs += p->fixedHashSize;
|
||||
}
|
||||
|
||||
{
|
||||
uint32_t prevSize = p->hashSizeSum + p->numSons;
|
||||
uint32_t newSize;
|
||||
p->historySize = historySize;
|
||||
p->hashSizeSum = hs;
|
||||
p->cyclicBufferSize = newCyclicBufferSize;
|
||||
p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
|
||||
newSize = p->hashSizeSum + p->numSons;
|
||||
if (p->hash != 0 && prevSize == newSize)
|
||||
return 1;
|
||||
MatchFinder_FreeThisClassMemory(p);
|
||||
p->hash = AllocRefs(newSize);
|
||||
if (p->hash != 0)
|
||||
{
|
||||
p->son = p->hash + p->hashSizeSum;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
MatchFinder_Free(p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void MatchFinder_SetLimits(CMatchFinder *p)
|
||||
{
|
||||
uint32_t limit = kMaxValForNormalize - p->pos;
|
||||
uint32_t limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
limit2 = p->streamPos - p->pos;
|
||||
if (limit2 <= p->keepSizeAfter)
|
||||
{
|
||||
if (limit2 > 0)
|
||||
limit2 = 1;
|
||||
}
|
||||
else
|
||||
limit2 -= p->keepSizeAfter;
|
||||
if (limit2 < limit)
|
||||
limit = limit2;
|
||||
{
|
||||
uint32_t lenLimit = p->streamPos - p->pos;
|
||||
if (lenLimit > p->matchMaxLen)
|
||||
lenLimit = p->matchMaxLen;
|
||||
p->lenLimit = lenLimit;
|
||||
}
|
||||
p->posLimit = p->pos + limit;
|
||||
}
|
||||
|
||||
void MatchFinder_Init(CMatchFinder *p)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < p->hashSizeSum; i++)
|
||||
p->hash[i] = kEmptyHashValue;
|
||||
p->cyclicBufferPos = 0;
|
||||
p->buffer = p->bufferBase;
|
||||
p->pos = p->streamPos = p->cyclicBufferSize;
|
||||
p->result = SZ_OK;
|
||||
p->streamEndWasReached = 0;
|
||||
MatchFinder_ReadBlock(p);
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
static uint32_t MatchFinder_GetSubValue(CMatchFinder *p)
|
||||
{
|
||||
return (p->pos - p->historySize - 1) & kNormalizeMask;
|
||||
}
|
||||
|
||||
void MatchFinder_Normalize3(uint32_t subValue, CLzRef *items, uint32_t numItems)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < numItems; i++)
|
||||
{
|
||||
uint32_t value = items[i];
|
||||
if (value <= subValue)
|
||||
value = kEmptyHashValue;
|
||||
else
|
||||
value -= subValue;
|
||||
items[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
static void MatchFinder_Normalize(CMatchFinder *p)
|
||||
{
|
||||
uint32_t subValue = MatchFinder_GetSubValue(p);
|
||||
MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
|
||||
MatchFinder_ReduceOffsets(p, subValue);
|
||||
}
|
||||
|
||||
static void MatchFinder_CheckLimits(CMatchFinder *p)
|
||||
{
|
||||
if (p->pos == kMaxValForNormalize)
|
||||
MatchFinder_Normalize(p);
|
||||
if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
|
||||
MatchFinder_CheckAndMoveAndRead(p);
|
||||
if (p->cyclicBufferPos == p->cyclicBufferSize)
|
||||
p->cyclicBufferPos = 0;
|
||||
MatchFinder_SetLimits(p);
|
||||
}
|
||||
|
||||
static uint32_t *Hc_GetMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
const uint8_t *cur, CLzRef *son, uint32_t _cyclicBufferPos,
|
||||
uint32_t _cyclicBufferSize, uint32_t cutValue,
|
||||
uint32_t *distances, uint32_t maxLen)
|
||||
{
|
||||
son[_cyclicBufferPos] = curMatch;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
return distances;
|
||||
{
|
||||
const uint8_t *pb = cur - delta;
|
||||
curMatch = son[_cyclicBufferPos - delta +
|
||||
((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
|
||||
if (pb[maxLen] == cur[maxLen] && *pb == *cur)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
return distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t *GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
const uint8_t *cur, CLzRef *son, uint32_t _cyclicBufferPos,
|
||||
uint32_t _cyclicBufferSize, uint32_t cutValue, uint32_t *distances,
|
||||
uint32_t maxLen)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
uint32_t len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
return distances;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta +
|
||||
((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0))
|
||||
<< 1);
|
||||
const uint8_t *pb = cur - delta;
|
||||
uint32_t len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
if (++len != lenLimit && pb[len] == cur[len])
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
if (maxLen < len)
|
||||
{
|
||||
*distances++ = maxLen = len;
|
||||
*distances++ = delta - 1;
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
return distances;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SkipMatchesSpec(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
const uint8_t *cur, CLzRef *son, uint32_t _cyclicBufferPos,
|
||||
uint32_t _cyclicBufferSize, uint32_t cutValue)
|
||||
{
|
||||
CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
|
||||
CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
|
||||
uint32_t len0 = 0, len1 = 0;
|
||||
for (;;)
|
||||
{
|
||||
uint32_t delta = pos - curMatch;
|
||||
if (cutValue-- == 0 || delta >= _cyclicBufferSize)
|
||||
{
|
||||
*ptr0 = *ptr1 = kEmptyHashValue;
|
||||
return;
|
||||
}
|
||||
{
|
||||
CLzRef *pair = son + ((_cyclicBufferPos - delta +
|
||||
((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0))
|
||||
<< 1);
|
||||
const uint8_t *pb = cur - delta;
|
||||
uint32_t len = (len0 < len1 ? len0 : len1);
|
||||
if (pb[len] == cur[len])
|
||||
{
|
||||
while (++len != lenLimit)
|
||||
if (pb[len] != cur[len])
|
||||
break;
|
||||
{
|
||||
if (len == lenLimit)
|
||||
{
|
||||
*ptr1 = pair[0];
|
||||
*ptr0 = pair[1];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pb[len] < cur[len])
|
||||
{
|
||||
*ptr1 = curMatch;
|
||||
ptr1 = pair + 1;
|
||||
curMatch = *ptr1;
|
||||
len1 = len;
|
||||
}
|
||||
else
|
||||
{
|
||||
*ptr0 = curMatch;
|
||||
ptr0 = pair;
|
||||
curMatch = *ptr0;
|
||||
len0 = len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define MOVE_POS \
|
||||
++p->cyclicBufferPos; \
|
||||
p->buffer++; \
|
||||
if (++p->pos == p->posLimit) \
|
||||
MatchFinder_CheckLimits(p);
|
||||
|
||||
#define MOVE_POS_RET MOVE_POS return offset;
|
||||
|
||||
static void MatchFinder_MovePos(CMatchFinder *p)
|
||||
{
|
||||
MOVE_POS;
|
||||
}
|
||||
|
||||
#define GET_MATCHES_HEADER2(minLen, ret_op) \
|
||||
uint32_t lenLimit; \
|
||||
uint32_t hashValue; \
|
||||
const uint8_t *cur; \
|
||||
uint32_t curMatch; \
|
||||
lenLimit = p->lenLimit; \
|
||||
{ \
|
||||
if (lenLimit < minLen) \
|
||||
{ \
|
||||
MatchFinder_MovePos(p); \
|
||||
ret_op; \
|
||||
} \
|
||||
} \
|
||||
cur = p->buffer;
|
||||
|
||||
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
|
||||
#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
|
||||
|
||||
#define MF_PARAMS(p) \
|
||||
p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
|
||||
|
||||
#define GET_MATCHES_FOOTER(offset, maxLen) \
|
||||
offset = (uint32_t)( \
|
||||
GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) - \
|
||||
distances); \
|
||||
MOVE_POS_RET;
|
||||
|
||||
#define SKIP_FOOTER \
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); \
|
||||
MOVE_POS;
|
||||
|
||||
static uint32_t Bt2_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
GET_MATCHES_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 1)
|
||||
}
|
||||
|
||||
uint32_t Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = 0;
|
||||
GET_MATCHES_FOOTER(offset, 2)
|
||||
}
|
||||
|
||||
static uint32_t Bt3_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t hash2Value, delta2, maxLen, offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
|
||||
HASH3_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[hash2Value];
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
|
||||
maxLen = 2;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[0] = maxLen;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static uint32_t Bt4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
|
||||
maxLen = 1;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
}
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
GET_MATCHES_FOOTER(offset, maxLen)
|
||||
}
|
||||
|
||||
static uint32_t Hc4_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t hash2Value, hash3Value, delta2, delta3, maxLen, offset;
|
||||
GET_MATCHES_HEADER(4)
|
||||
|
||||
HASH4_CALC;
|
||||
|
||||
delta2 = p->pos - p->hash[hash2Value];
|
||||
delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
|
||||
maxLen = 1;
|
||||
offset = 0;
|
||||
if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
|
||||
{
|
||||
distances[0] = maxLen = 2;
|
||||
distances[1] = delta2 - 1;
|
||||
offset = 2;
|
||||
}
|
||||
if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
|
||||
{
|
||||
maxLen = 3;
|
||||
distances[offset + 1] = delta3 - 1;
|
||||
offset += 2;
|
||||
delta2 = delta3;
|
||||
}
|
||||
if (offset != 0)
|
||||
{
|
||||
for (; maxLen != lenLimit; maxLen++)
|
||||
if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
|
||||
break;
|
||||
distances[offset - 2] = maxLen;
|
||||
if (maxLen == lenLimit)
|
||||
{
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS_RET;
|
||||
}
|
||||
}
|
||||
if (maxLen < 3)
|
||||
maxLen = 3;
|
||||
offset = (uint32_t)(
|
||||
Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances + offset, maxLen) -
|
||||
(distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
uint32_t Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, uint32_t *distances)
|
||||
{
|
||||
uint32_t offset;
|
||||
GET_MATCHES_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
offset = (uint32_t)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), distances, 2) -
|
||||
(distances));
|
||||
MOVE_POS_RET
|
||||
}
|
||||
|
||||
static void Bt2_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(2)
|
||||
HASH2_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
static void Bt3_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t hash2Value;
|
||||
SKIP_HEADER(3)
|
||||
HASH3_CALC;
|
||||
curMatch = p->hash[kFix3HashSize + hashValue];
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
static void Bt4_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t hash2Value, hash3Value;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hash3Value] = p->pos;
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
SKIP_FOOTER
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
static void Hc4_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
uint32_t hash2Value, hash3Value;
|
||||
SKIP_HEADER(4)
|
||||
HASH4_CALC;
|
||||
curMatch = p->hash[kFix4HashSize + hashValue];
|
||||
p->hash[hash2Value] = p->hash[kFix3HashSize + hash3Value] =
|
||||
p->hash[kFix4HashSize + hashValue] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num)
|
||||
{
|
||||
do
|
||||
{
|
||||
SKIP_HEADER(3)
|
||||
HASH_ZIP_CALC;
|
||||
curMatch = p->hash[hashValue];
|
||||
p->hash[hashValue] = p->pos;
|
||||
p->son[p->cyclicBufferPos] = curMatch;
|
||||
MOVE_POS
|
||||
} while (--num != 0);
|
||||
}
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
|
||||
{
|
||||
vTable->Init = (Mf_Init_Func)MatchFinder_Init;
|
||||
vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
|
||||
vTable->GetNumAvailableBytes =
|
||||
(Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
|
||||
vTable->GetPointerToCurrentPos =
|
||||
(Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
|
||||
if (!p->btMode)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
|
||||
}
|
||||
else if (p->numHashBytes == 2)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
|
||||
}
|
||||
else if (p->numHashBytes == 3)
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
|
||||
}
|
||||
else
|
||||
{
|
||||
vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
|
||||
vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
|
||||
}
|
||||
}
|
107
depends/lzma/pavlov/LzFind.h
Executable file
107
depends/lzma/pavlov/LzFind.h
Executable file
@ -0,0 +1,107 @@
|
||||
/* LzFind.h -- Match finder for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZFIND_H
|
||||
#define __LZFIND_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
typedef uint32_t CLzRef;
|
||||
|
||||
typedef struct _CMatchFinder
|
||||
{
|
||||
uint8_t *buffer;
|
||||
uint32_t pos;
|
||||
uint32_t posLimit;
|
||||
uint32_t streamPos;
|
||||
uint32_t lenLimit;
|
||||
|
||||
uint32_t cyclicBufferPos;
|
||||
uint32_t cyclicBufferSize; /* it must be = (historySize + 1) */
|
||||
|
||||
uint32_t matchMaxLen;
|
||||
CLzRef *hash;
|
||||
CLzRef *son;
|
||||
uint32_t hashMask;
|
||||
uint32_t cutValue;
|
||||
|
||||
uint8_t *bufferBase;
|
||||
ISeqInStream *stream;
|
||||
int streamEndWasReached;
|
||||
|
||||
uint32_t blockSize;
|
||||
uint32_t keepSizeBefore;
|
||||
uint32_t keepSizeAfter;
|
||||
|
||||
uint32_t numHashBytes;
|
||||
int directInput;
|
||||
int btMode;
|
||||
/* int skipModeBits; */
|
||||
int bigHash;
|
||||
uint32_t historySize;
|
||||
uint32_t fixedHashSize;
|
||||
uint32_t hashSizeSum;
|
||||
uint32_t numSons;
|
||||
SRes result;
|
||||
uint32_t crc[256];
|
||||
} CMatchFinder;
|
||||
|
||||
#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
|
||||
#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
|
||||
|
||||
#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
|
||||
|
||||
int MatchFinder_NeedMove(CMatchFinder *p);
|
||||
uint8_t *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
|
||||
void MatchFinder_MoveBlock(CMatchFinder *p);
|
||||
void MatchFinder_ReadIfRequired(CMatchFinder *p);
|
||||
|
||||
void MatchFinder_Construct(CMatchFinder *p);
|
||||
|
||||
/* Conditions:
|
||||
historySize <= 3 GB
|
||||
keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
|
||||
*/
|
||||
int MatchFinder_Create(CMatchFinder *p, uint32_t historySize, uint32_t keepAddBufferBefore,
|
||||
uint32_t matchMaxLen, uint32_t keepAddBufferAfter);
|
||||
void MatchFinder_Free(CMatchFinder *p);
|
||||
void MatchFinder_Normalize3(uint32_t subValue, CLzRef *items, uint32_t numItems);
|
||||
void MatchFinder_ReduceOffsets(CMatchFinder *p, uint32_t subValue);
|
||||
|
||||
uint32_t *GetMatchesSpec1(uint32_t lenLimit, uint32_t curMatch, uint32_t pos,
|
||||
const uint8_t *buffer, CLzRef *son, uint32_t _cyclicBufferPos,
|
||||
uint32_t _cyclicBufferSize, uint32_t _cutValue, uint32_t *distances,
|
||||
uint32_t maxLen);
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
|
||||
Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
|
||||
*/
|
||||
|
||||
typedef void (*Mf_Init_Func)(void *object);
|
||||
typedef uint8_t (*Mf_GetIndexByte_Func)(void *object, int32_t index);
|
||||
typedef uint32_t (*Mf_GetNumAvailableBytes_Func)(void *object);
|
||||
typedef const uint8_t *(*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 struct _IMatchFinder
|
||||
{
|
||||
Mf_Init_Func Init;
|
||||
Mf_GetIndexByte_Func GetIndexByte;
|
||||
Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
|
||||
Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
|
||||
Mf_GetMatches_Func GetMatches;
|
||||
Mf_Skip_Func Skip;
|
||||
} IMatchFinder;
|
||||
|
||||
void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
|
||||
|
||||
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);
|
||||
void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num);
|
||||
void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, uint32_t num);
|
||||
|
||||
#endif
|
62
depends/lzma/pavlov/LzHash.h
Executable file
62
depends/lzma/pavlov/LzHash.h
Executable file
@ -0,0 +1,62 @@
|
||||
/* LzHash.h -- HASH functions for LZ algorithms
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#pragma once
|
||||
|
||||
#define kHash2Size (1 << 10)
|
||||
#define kHash3Size (1 << 16)
|
||||
#define kHash4Size (1 << 20)
|
||||
|
||||
#define kFix3HashSize (kHash2Size)
|
||||
#define kFix4HashSize (kHash2Size + kHash3Size)
|
||||
#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
|
||||
|
||||
#define HASH2_CALC hashValue = cur[0] | ((uint32_t)cur[1] << 8);
|
||||
|
||||
#define HASH3_CALC \
|
||||
{ \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hashValue = (temp ^ ((uint32_t)cur[2] << 8)) & p->hashMask; \
|
||||
}
|
||||
|
||||
#define HASH4_CALC \
|
||||
{ \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((uint32_t)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hashValue = (temp ^ ((uint32_t)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; \
|
||||
}
|
||||
|
||||
#define HASH5_CALC \
|
||||
{ \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((uint32_t)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = (temp ^ ((uint32_t)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
|
||||
hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
|
||||
hash4Value &= (kHash4Size - 1); \
|
||||
}
|
||||
|
||||
/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((uint32_t)cur[1] << 8)) ^ p->crc[cur[2]]) &
|
||||
* 0xFFFF; */
|
||||
#define HASH_ZIP_CALC \
|
||||
hashValue = ((cur[2] | ((uint32_t)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
|
||||
|
||||
#define MT_HASH2_CALC hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
|
||||
|
||||
#define MT_HASH3_CALC \
|
||||
{ \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((uint32_t)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
}
|
||||
|
||||
#define MT_HASH4_CALC \
|
||||
{ \
|
||||
uint32_t temp = p->crc[cur[0]] ^ cur[1]; \
|
||||
hash2Value = temp & (kHash2Size - 1); \
|
||||
hash3Value = (temp ^ ((uint32_t)cur[2] << 8)) & (kHash3Size - 1); \
|
||||
hash4Value = \
|
||||
(temp ^ ((uint32_t)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); \
|
||||
}
|
1076
depends/lzma/pavlov/LzmaDec.c
Executable file
1076
depends/lzma/pavlov/LzmaDec.c
Executable file
File diff suppressed because it is too large
Load Diff
220
depends/lzma/pavlov/LzmaDec.h
Executable file
220
depends/lzma/pavlov/LzmaDec.h
Executable file
@ -0,0 +1,220 @@
|
||||
/* LzmaDec.h -- LZMA Decoder
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CLzmaProb UInt32
|
||||
#else
|
||||
#define CLzmaProb uint16_t
|
||||
#endif
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
uint32_t dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const uint8_t *data, unsigned size);
|
||||
|
||||
/* ---------- 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; */
|
||||
|
||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *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);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const uint8_t *prop, unsigned propsSize);
|
||||
void LzmaDec_Free(CLzmaDec *state);
|
||||
|
||||
/* ---------- 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)
|
||||
{
|
||||
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 !!!
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, size_t dicLimit, const uint8_t *src, size_t *srcLen,
|
||||
ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
/* ---------- Buffer Interface ---------- */
|
||||
|
||||
/* It's zlib-like interface.
|
||||
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
||||
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
||||
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).
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, uint8_t *dest, size_t *destLen, const uint8_t *src,
|
||||
size_t *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* 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).
|
||||
|
||||
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).
|
||||
*/
|
||||
|
||||
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);
|
2349
depends/lzma/pavlov/LzmaEnc.c
Executable file
2349
depends/lzma/pavlov/LzmaEnc.c
Executable file
File diff suppressed because it is too large
Load Diff
71
depends/lzma/pavlov/LzmaEnc.h
Executable file
71
depends/lzma/pavlov/LzmaEnc.h
Executable file
@ -0,0 +1,71 @@
|
||||
/* LzmaEnc.h -- LZMA Encoder
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMAENC_H
|
||||
#define __LZMAENC_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
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) */
|
||||
int lc; /* 0 <= lc <= 8, default = 3 */
|
||||
int lp; /* 0 <= lp <= 4, default = 0 */
|
||||
int pb; /* 0 <= pb <= 4, default = 2 */
|
||||
int algo; /* 0 - fast, 1 - normal, default = 1 */
|
||||
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 */
|
||||
unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
|
||||
int numThreads; /* 1 or 2, default = 2 */
|
||||
} CLzmaEncProps;
|
||||
|
||||
void LzmaEncProps_Init(CLzmaEncProps *p);
|
||||
void LzmaEncProps_Normalize(CLzmaEncProps *p);
|
||||
uint32_t LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
|
||||
|
||||
/* ---------- CLzmaEncHandle Interface ---------- */
|
||||
|
||||
/* LzmaEnc_* functions can return the following exit codes:
|
||||
Returns:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater in props
|
||||
SZ_ERROR_WRITE - Write callback error.
|
||||
SZ_ERROR_PROGRESS - some break from progress callback
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
*/
|
||||
|
||||
typedef void *CLzmaEncHandle;
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create();
|
||||
void LzmaEnc_Destroy(CLzmaEncHandle p);
|
||||
SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
|
||||
SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, uint8_t *properties, size_t *size);
|
||||
SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
|
||||
ICompressProgress *progress);
|
||||
SRes LzmaEnc_MemEncode(CLzmaEncHandle p, uint8_t *dest, size_t *destLen, const uint8_t *src,
|
||||
size_t srcLen, int writeEndMark, ICompressProgress *progress);
|
||||
|
||||
/* ---------- 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(uint8_t *dest, size_t *destLen, const uint8_t *src, size_t srcLen,
|
||||
const CLzmaEncProps *props, uint8_t *propsEncoded, size_t *propsSize,
|
||||
int writeEndMark, ICompressProgress *progress);
|
||||
|
||||
#endif
|
41
depends/lzma/pavlov/LzmaLib.c
Executable file
41
depends/lzma/pavlov/LzmaLib.c
Executable file
@ -0,0 +1,41 @@
|
||||
/* LzmaLib.c -- LZMA library wrapper
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "LzmaEnc.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "LzmaLib.h"
|
||||
|
||||
MY_STDAPI
|
||||
LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src, size_t srcLen,
|
||||
unsigned char *outProps, size_t *outPropsSize,
|
||||
int level, /* 0 <= level <= 9, default = 5 */
|
||||
unsigned dictSize, /* use (1 << N) or (3 << N). 4 KB < dictSize <= 128 MB */
|
||||
int lc, /* 0 <= lc <= 8, default = 3 */
|
||||
int lp, /* 0 <= lp <= 4, default = 0 */
|
||||
int pb, /* 0 <= pb <= 4, default = 2 */
|
||||
int fb, /* 5 <= fb <= 273, default = 32 */
|
||||
int numThreads /* 1 or 2, default = 2 */
|
||||
)
|
||||
{
|
||||
CLzmaEncProps props;
|
||||
LzmaEncProps_Init(&props);
|
||||
props.level = level;
|
||||
props.dictSize = dictSize;
|
||||
props.lc = lc;
|
||||
props.lp = lp;
|
||||
props.pb = pb;
|
||||
props.fb = fb;
|
||||
props.numThreads = numThreads;
|
||||
|
||||
return LzmaEncode(dest, destLen, src, srcLen, &props, outProps, outPropsSize, 0, NULL);
|
||||
}
|
||||
|
||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src,
|
||||
size_t *srcLen, const unsigned char *props, size_t propsSize)
|
||||
{
|
||||
ELzmaStatus status;
|
||||
return LzmaDecode(dest, destLen, src, srcLen, props, (unsigned)propsSize, LZMA_FINISH_ANY,
|
||||
&status);
|
||||
}
|
137
depends/lzma/pavlov/LzmaLib.h
Executable file
137
depends/lzma/pavlov/LzmaLib.h
Executable file
@ -0,0 +1,137 @@
|
||||
/* LzmaLib.h -- LZMA library interface
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __LZMALIB_H
|
||||
#define __LZMALIB_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define MY_EXTERN_C extern "C"
|
||||
#else
|
||||
#define MY_EXTERN_C extern
|
||||
#endif
|
||||
|
||||
#define MY_STDAPI MY_EXTERN_C int MY_STD_CALL
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
/*
|
||||
RAM requirements for LZMA:
|
||||
for compression: (dictSize * 11.5 + 6 MB) + state_size
|
||||
for decompression: dictSize + state_size
|
||||
state_size = (4 + (1.5 << (lc + lp))) KB
|
||||
by default (lc=3, lp=0), state_size = 16 KB.
|
||||
|
||||
LZMA properties (5 bytes) format
|
||||
Offset Size Description
|
||||
0 1 lc, lp and pb in encoded form.
|
||||
1 4 dictSize (little endian).
|
||||
*/
|
||||
|
||||
/*
|
||||
LzmaCompress
|
||||
------------
|
||||
|
||||
outPropsSize -
|
||||
In: the pointer to the size of outProps buffer; *outPropsSize = LZMA_PROPS_SIZE = 5.
|
||||
Out: the pointer to the size of written properties in outProps buffer; *outPropsSize =
|
||||
LZMA_PROPS_SIZE = 5.
|
||||
|
||||
LZMA Encoder will use defult values for any parameter, if it is
|
||||
-1 for any from: level, loc, lp, pb, fb, numThreads
|
||||
0 for dictSize
|
||||
|
||||
level - compression level: 0 <= level <= 9;
|
||||
|
||||
level dictSize algo fb
|
||||
0: 16 KB 0 32
|
||||
1: 64 KB 0 32
|
||||
2: 256 KB 0 32
|
||||
3: 1 MB 0 32
|
||||
4: 4 MB 0 32
|
||||
5: 16 MB 1 32
|
||||
6: 32 MB 1 32
|
||||
7+: 64 MB 1 64
|
||||
|
||||
The default value for "level" is 5.
|
||||
|
||||
algo = 0 means fast method
|
||||
algo = 1 means normal method
|
||||
|
||||
dictSize - The dictionary size in bytes. The maximum value is
|
||||
128 MB = (1 << 27) bytes for 32-bit version
|
||||
1 GB = (1 << 30) bytes for 64-bit version
|
||||
The default value is 16 MB = (1 << 24) bytes.
|
||||
It's recommended to use the dictionary that is larger than 4 KB and
|
||||
that can be calculated as (1 << N) or (3 << N) sizes.
|
||||
|
||||
lc - The number of literal context bits (high bits of previous literal).
|
||||
It can be in the range from 0 to 8. The default value is 3.
|
||||
Sometimes lc=4 gives the gain for big files.
|
||||
|
||||
lp - The number of literal pos bits (low bits of current position for literals).
|
||||
It can be in the range from 0 to 4. The default value is 0.
|
||||
The lp switch is intended for periodical data when the period is equal to 2^lp.
|
||||
For example, for 32-bit (4 bytes) periodical data you can use lp=2. Often it's
|
||||
better to set lc=0, if you change lp switch.
|
||||
|
||||
pb - The number of pos bits (low bits of current position).
|
||||
It can be in the range from 0 to 4. The default value is 2.
|
||||
The pb switch is intended for periodical data when the period is equal 2^pb.
|
||||
|
||||
fb - Word size (the number of fast bytes).
|
||||
It can be in the range from 5 to 273. The default value is 32.
|
||||
Usually, a big number gives a little bit better compression ratio and
|
||||
slower compression process.
|
||||
|
||||
numThreads - The number of thereads. 1 or 2. The default value is 2.
|
||||
Fast mode (algo = 0) can use only 1 thread.
|
||||
|
||||
Out:
|
||||
destLen - processed output size
|
||||
Returns:
|
||||
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)
|
||||
*/
|
||||
|
||||
MY_STDAPI LzmaCompress(unsigned char *dest, size_t *destLen, const unsigned char *src,
|
||||
size_t srcLen, unsigned char *outProps,
|
||||
size_t *outPropsSize, /* *outPropsSize must be = 5 */
|
||||
int level, /* 0 <= level <= 9, default = 5 */
|
||||
unsigned dictSize, /* default = (1 << 24) */
|
||||
int lc, /* 0 <= lc <= 8, default = 3 */
|
||||
int lp, /* 0 <= lp <= 4, default = 0 */
|
||||
int pb, /* 0 <= pb <= 4, default = 2 */
|
||||
int fb, /* 5 <= fb <= 273, default = 32 */
|
||||
int numThreads /* 1 or 2, default = 2 */
|
||||
);
|
||||
|
||||
/*
|
||||
LzmaUncompress
|
||||
--------------
|
||||
In:
|
||||
dest - output data
|
||||
destLen - output data size
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
Out:
|
||||
destLen - processed output size
|
||||
srcLen - processed input size
|
||||
Returns:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation arror
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - it needs more bytes in input buffer (src)
|
||||
*/
|
||||
|
||||
MY_STDAPI LzmaUncompress(unsigned char *dest, size_t *destLen, const unsigned char *src,
|
||||
size_t *srcLen, const unsigned char *props, size_t propsSize);
|
||||
|
||||
#endif
|
87
depends/lzma/pavlov/Types.h
Executable file
87
depends/lzma/pavlov/Types.h
Executable file
@ -0,0 +1,87 @@
|
||||
/* Types.h -- Basic types
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
#define SZ_ERROR_MEM 2
|
||||
#define SZ_ERROR_CRC 3
|
||||
#define SZ_ERROR_UNSUPPORTED 4
|
||||
#define SZ_ERROR_PARAM 5
|
||||
#define SZ_ERROR_INPUT_EOF 6
|
||||
#define SZ_ERROR_OUTPUT_EOF 7
|
||||
#define SZ_ERROR_READ 8
|
||||
#define SZ_ERROR_WRITE 9
|
||||
#define SZ_ERROR_PROGRESS 10
|
||||
#define SZ_ERROR_FAIL 11
|
||||
#define SZ_ERROR_THREAD 12
|
||||
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int SRes;
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) \
|
||||
{ \
|
||||
int __result__ = (x); \
|
||||
if (__result__ != 0) \
|
||||
return __result__; \
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef int Bool;
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_STD_CALL __stdcall
|
||||
#define MY_FAST_CALL MY_NO_INLINE __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_CDECL
|
||||
#define MY_STD_CALL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
#endif
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
} ISeqInStream;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
} ISeqOutStream;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Progress)(void *p, uint64_t inSize, uint64_t outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (uint64_t)(int64_t)-1 for size means unknown value. */
|
||||
} ICompressProgress;
|
46
depends/lzma/wrapper/common_internal.c
Normal file
46
depends/lzma/wrapper/common_internal.c
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*/
|
||||
|
||||
#include "common_internal.h"
|
||||
|
||||
static void *elzmaAlloc(void *p, size_t size)
|
||||
{
|
||||
struct elzma_alloc_struct *as = (struct elzma_alloc_struct *)p;
|
||||
if (as->clientMallocFunc)
|
||||
{
|
||||
return as->clientMallocFunc(as->clientMallocContext, size);
|
||||
}
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static void elzmaFree(void *p, void *address)
|
||||
{
|
||||
struct elzma_alloc_struct *as = (struct elzma_alloc_struct *)p;
|
||||
if (as->clientFreeFunc)
|
||||
{
|
||||
as->clientFreeFunc(as->clientMallocContext, address);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(address);
|
||||
}
|
||||
}
|
||||
|
||||
void init_alloc_struct(struct elzma_alloc_struct *as, elzma_malloc clientMallocFunc,
|
||||
void *clientMallocContext, elzma_free clientFreeFunc,
|
||||
void *clientFreeContext)
|
||||
{
|
||||
as->Alloc = elzmaAlloc;
|
||||
as->Free = elzmaFree;
|
||||
as->clientMallocFunc = clientMallocFunc;
|
||||
as->clientMallocContext = clientMallocContext;
|
||||
as->clientFreeFunc = clientFreeFunc;
|
||||
as->clientFreeContext = clientFreeContext;
|
||||
}
|
60
depends/lzma/wrapper/common_internal.h
Normal file
60
depends/lzma/wrapper/common_internal.h
Normal file
@ -0,0 +1,60 @@
|
||||
#ifndef __ELZMA_COMMON_INTERNAL_H__
|
||||
#define __ELZMA_COMMON_INTERNAL_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/** a structure which may be cast and passed into Igor's allocate
|
||||
* routines */
|
||||
struct elzma_alloc_struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
|
||||
elzma_malloc clientMallocFunc;
|
||||
void *clientMallocContext;
|
||||
|
||||
elzma_free clientFreeFunc;
|
||||
void *clientFreeContext;
|
||||
};
|
||||
|
||||
/* initialize an allocation structure, may be called safely multiple
|
||||
* times */
|
||||
void init_alloc_struct(struct elzma_alloc_struct *allocStruct, elzma_malloc clientMallocFunc,
|
||||
void *clientMallocContext, elzma_free clientFreeFunc,
|
||||
void *clientFreeContext);
|
||||
|
||||
/** superset representation of a compressed file header */
|
||||
struct elzma_file_header
|
||||
{
|
||||
unsigned char pb;
|
||||
unsigned char lp;
|
||||
unsigned char lc;
|
||||
unsigned char isStreamed;
|
||||
long long unsigned int uncompressedSize;
|
||||
unsigned int dictSize;
|
||||
};
|
||||
|
||||
/** superset representation of a compressed file footer */
|
||||
struct elzma_file_footer
|
||||
{
|
||||
unsigned int crc32;
|
||||
long long unsigned int uncompressedSize;
|
||||
};
|
||||
|
||||
/** a structure which encapsulates information about the particular
|
||||
* file header and footer in use (lzip vs lzma vs (eventually) xz.
|
||||
* The intention of this structure is to simplify compression and
|
||||
* decompression logic by abstracting the file format details a bit. */
|
||||
struct elzma_format_handler
|
||||
{
|
||||
unsigned int header_size;
|
||||
void (*init_header)(struct elzma_file_header *hdr);
|
||||
int (*parse_header)(const unsigned char *hdrBuf, struct elzma_file_header *hdr);
|
||||
int (*serialize_header)(unsigned char *hdrBuf, const struct elzma_file_header *hdr);
|
||||
|
||||
unsigned int footer_size;
|
||||
int (*serialize_footer)(struct elzma_file_footer *ftr, unsigned char *ftrBuf);
|
||||
int (*parse_footer)(const unsigned char *ftrBuf, struct elzma_file_footer *ftr);
|
||||
};
|
||||
|
||||
#endif
|
297
depends/lzma/wrapper/compress.c
Normal file
297
depends/lzma/wrapper/compress.c
Normal file
@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*/
|
||||
|
||||
#include "compress.h"
|
||||
#include "lzma_header.h"
|
||||
#include "lzip_header.h"
|
||||
#include "common_internal.h"
|
||||
|
||||
#include "pavlov/Types.h"
|
||||
#include "pavlov/LzmaEnc.h"
|
||||
#include "pavlov/7zCrc.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
struct _elzma_compress_handle
|
||||
{
|
||||
CLzmaEncProps props;
|
||||
CLzmaEncHandle encHand;
|
||||
unsigned long long uncompressedSize;
|
||||
elzma_file_format format;
|
||||
struct elzma_alloc_struct allocStruct;
|
||||
struct elzma_format_handler formatHandler;
|
||||
};
|
||||
|
||||
elzma_compress_handle elzma_compress_alloc()
|
||||
{
|
||||
elzma_compress_handle hand = malloc(sizeof(struct _elzma_compress_handle));
|
||||
memset((void *)hand, 0, sizeof(struct _elzma_compress_handle));
|
||||
|
||||
/* "reasonable" defaults for props */
|
||||
LzmaEncProps_Init(&(hand->props));
|
||||
hand->props.lc = 3;
|
||||
hand->props.lp = 0;
|
||||
hand->props.pb = 2;
|
||||
hand->props.level = 5;
|
||||
hand->props.algo = 1;
|
||||
hand->props.fb = 32;
|
||||
hand->props.dictSize = 1 << 24;
|
||||
hand->props.btMode = 1;
|
||||
hand->props.numHashBytes = 4;
|
||||
hand->props.mc = 32;
|
||||
hand->props.numThreads = 1;
|
||||
hand->props.writeEndMark = 1;
|
||||
|
||||
init_alloc_struct(&(hand->allocStruct), NULL, NULL, NULL, NULL);
|
||||
|
||||
/* default format is LZMA-Alone */
|
||||
initializeLZMAFormatHandler(&(hand->formatHandler));
|
||||
|
||||
return hand;
|
||||
}
|
||||
|
||||
void elzma_compress_free(elzma_compress_handle *hand)
|
||||
{
|
||||
if (hand && *hand)
|
||||
{
|
||||
if ((*hand)->encHand)
|
||||
{
|
||||
LzmaEnc_Destroy((*hand)->encHand);
|
||||
}
|
||||
}
|
||||
*hand = NULL;
|
||||
}
|
||||
|
||||
int elzma_compress_config(elzma_compress_handle hand, unsigned char lc, unsigned char lp,
|
||||
unsigned char pb, unsigned char level, unsigned int dictionarySize,
|
||||
elzma_file_format format, unsigned long long uncompressedSize)
|
||||
{
|
||||
/* XXX: validate arguments are in valid ranges */
|
||||
|
||||
hand->props.lc = lc;
|
||||
hand->props.lp = lp;
|
||||
hand->props.pb = pb;
|
||||
hand->props.level = level;
|
||||
hand->props.dictSize = dictionarySize;
|
||||
hand->uncompressedSize = uncompressedSize;
|
||||
hand->format = format;
|
||||
|
||||
/* default of LZMA-Alone is set at alloc time, and there are only
|
||||
* two possible formats */
|
||||
if (format == ELZMA_lzip)
|
||||
{
|
||||
initializeLZIPFormatHandler(&(hand->formatHandler));
|
||||
}
|
||||
|
||||
return ELZMA_E_OK;
|
||||
}
|
||||
|
||||
/* use Igor's stream hooks for compression. */
|
||||
struct elzmaInStream
|
||||
{
|
||||
SRes (*ReadPtr)(void *p, void *buf, size_t *size);
|
||||
elzma_read_callback inputStream;
|
||||
void *inputContext;
|
||||
unsigned int crc32;
|
||||
unsigned int crc32a;
|
||||
unsigned int crc32b;
|
||||
unsigned int crc32c;
|
||||
int calculateCRC;
|
||||
};
|
||||
|
||||
static SRes elzmaReadFunc(void *p, void *buf, size_t *size)
|
||||
{
|
||||
int rv;
|
||||
struct elzmaInStream *is = (struct elzmaInStream *)p;
|
||||
rv = is->inputStream(is->inputContext, buf, size);
|
||||
if (rv == 0 && *size > 0 && is->calculateCRC)
|
||||
{
|
||||
is->crc32 = CrcUpdate(is->crc32, buf, *size);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
struct elzmaOutStream
|
||||
{
|
||||
size_t (*WritePtr)(void *p, const void *buf, size_t size);
|
||||
elzma_write_callback outputStream;
|
||||
void *outputContext;
|
||||
};
|
||||
|
||||
static size_t elzmaWriteFunc(void *p, const void *buf, size_t size)
|
||||
{
|
||||
struct elzmaOutStream *os = (struct elzmaOutStream *)p;
|
||||
return os->outputStream(os->outputContext, buf, size);
|
||||
}
|
||||
|
||||
/* use Igor's stream hooks for compression. */
|
||||
struct elzmaProgressStruct
|
||||
{
|
||||
SRes (*Progress)(void *p, uint64_t inSize, uint64_t outSize);
|
||||
long long unsigned int uncompressedSize;
|
||||
elzma_progress_callback progressCallback;
|
||||
void *progressContext;
|
||||
};
|
||||
|
||||
#include <stdio.h>
|
||||
static SRes elzmaProgress(void *p, uint64_t inSize, uint64_t outSize)
|
||||
{
|
||||
struct elzmaProgressStruct *ps = (struct elzmaProgressStruct *)p;
|
||||
if (ps->progressCallback)
|
||||
{
|
||||
ps->progressCallback(ps->progressContext, inSize, ps->uncompressedSize);
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
void elzma_compress_set_allocation_callbacks(elzma_compress_handle hand,
|
||||
elzma_malloc mallocFunc, void *mallocFuncContext,
|
||||
elzma_free freeFunc, void *freeFuncContext)
|
||||
{
|
||||
if (hand)
|
||||
{
|
||||
init_alloc_struct(&(hand->allocStruct), mallocFunc, mallocFuncContext, freeFunc,
|
||||
freeFuncContext);
|
||||
}
|
||||
}
|
||||
|
||||
int elzma_compress_run(elzma_compress_handle hand, elzma_read_callback inputStream,
|
||||
void *inputContext, elzma_write_callback outputStream,
|
||||
void *outputContext, elzma_progress_callback progressCallback,
|
||||
void *progressContext)
|
||||
{
|
||||
struct elzmaInStream inStreamStruct;
|
||||
struct elzmaOutStream outStreamStruct;
|
||||
struct elzmaProgressStruct progressStruct;
|
||||
SRes r;
|
||||
|
||||
CrcGenerateTable();
|
||||
|
||||
if (hand == NULL || inputStream == NULL)
|
||||
return ELZMA_E_BAD_PARAMS;
|
||||
|
||||
/* initialize stream structrures */
|
||||
inStreamStruct.ReadPtr = elzmaReadFunc;
|
||||
inStreamStruct.inputStream = inputStream;
|
||||
inStreamStruct.inputContext = inputContext;
|
||||
inStreamStruct.crc32 = CRC_INIT_VAL;
|
||||
inStreamStruct.calculateCRC = (hand->formatHandler.serialize_footer != NULL);
|
||||
|
||||
outStreamStruct.WritePtr = elzmaWriteFunc;
|
||||
outStreamStruct.outputStream = outputStream;
|
||||
outStreamStruct.outputContext = outputContext;
|
||||
|
||||
progressStruct.Progress = elzmaProgress;
|
||||
progressStruct.uncompressedSize = hand->uncompressedSize;
|
||||
progressStruct.progressCallback = progressCallback;
|
||||
progressStruct.progressContext = progressContext;
|
||||
|
||||
/* create an encoding object */
|
||||
hand->encHand = LzmaEnc_Create();
|
||||
|
||||
if (hand->encHand == NULL)
|
||||
{
|
||||
return ELZMA_E_COMPRESS_ERROR;
|
||||
}
|
||||
|
||||
/* inintialize with compression parameters */
|
||||
if (SZ_OK != LzmaEnc_SetProps(hand->encHand, &(hand->props)))
|
||||
{
|
||||
return ELZMA_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
/* verify format is sane */
|
||||
if (ELZMA_lzma != hand->format && ELZMA_lzip != hand->format)
|
||||
{
|
||||
return ELZMA_E_UNSUPPORTED_FORMAT;
|
||||
}
|
||||
|
||||
/* now write the compression header header */
|
||||
{
|
||||
unsigned char *hdr =
|
||||
hand->allocStruct.Alloc(&(hand->allocStruct), hand->formatHandler.header_size);
|
||||
|
||||
struct elzma_file_header h;
|
||||
size_t wt;
|
||||
|
||||
hand->formatHandler.init_header(&h);
|
||||
h.pb = (unsigned char)hand->props.pb;
|
||||
h.lp = (unsigned char)hand->props.lp;
|
||||
h.lc = (unsigned char)hand->props.lc;
|
||||
h.dictSize = hand->props.dictSize;
|
||||
h.isStreamed = (unsigned char)(hand->uncompressedSize == 0);
|
||||
h.uncompressedSize = hand->uncompressedSize;
|
||||
|
||||
hand->formatHandler.serialize_header(hdr, &h);
|
||||
|
||||
wt = outputStream(outputContext, (void *)hdr, hand->formatHandler.header_size);
|
||||
|
||||
hand->allocStruct.Free(&(hand->allocStruct), hdr);
|
||||
|
||||
if (wt != hand->formatHandler.header_size)
|
||||
{
|
||||
return ELZMA_E_OUTPUT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* begin LZMA encoding */
|
||||
/* XXX: expose encoding progress */
|
||||
r = LzmaEnc_Encode(hand->encHand, (ISeqOutStream *)&outStreamStruct,
|
||||
(ISeqInStream *)&inStreamStruct, (ICompressProgress *)&progressStruct);
|
||||
|
||||
if (r != SZ_OK)
|
||||
return ELZMA_E_COMPRESS_ERROR;
|
||||
|
||||
/* support a footer! (lzip) */
|
||||
if (hand->formatHandler.serialize_footer != NULL && hand->formatHandler.footer_size > 0)
|
||||
{
|
||||
size_t wt;
|
||||
unsigned char *ftrBuf =
|
||||
hand->allocStruct.Alloc(&(hand->allocStruct), hand->formatHandler.footer_size);
|
||||
struct elzma_file_footer ftr;
|
||||
ftr.crc32 = inStreamStruct.crc32 ^ 0xFFFFFFFF;
|
||||
ftr.uncompressedSize = hand->uncompressedSize;
|
||||
|
||||
hand->formatHandler.serialize_footer(&ftr, ftrBuf);
|
||||
|
||||
wt = outputStream(outputContext, (void *)ftrBuf, hand->formatHandler.footer_size);
|
||||
|
||||
hand->allocStruct.Free(&(hand->allocStruct), ftrBuf);
|
||||
|
||||
if (wt != hand->formatHandler.footer_size)
|
||||
{
|
||||
return ELZMA_E_OUTPUT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ELZMA_E_OK;
|
||||
}
|
||||
|
||||
unsigned int elzma_get_dict_size(unsigned long long size)
|
||||
{
|
||||
int i = 13; /* 16k dict is minimum */
|
||||
|
||||
/* now we'll find the closes power of two with a max at 16< *
|
||||
* if the size is greater than 8m, we'll divide by two, all of this
|
||||
* is based on a quick set of emperical tests on hopefully
|
||||
* representative sample data */
|
||||
if (size > (1 << 23))
|
||||
size >>= 1;
|
||||
|
||||
while (size >> i)
|
||||
i++;
|
||||
|
||||
if (i > 23)
|
||||
return 1 << 23;
|
||||
|
||||
/* now 1 << i is greater than size, let's return either 1<<i or 1<<(i-1),
|
||||
* whichever is closer to size */
|
||||
return 1 << ((((1 << i) - size) > (size - (1 << (i - 1)))) ? i - 1 : i);
|
||||
}
|
263
depends/lzma/wrapper/decompress.c
Normal file
263
depends/lzma/wrapper/decompress.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*/
|
||||
|
||||
#include "include/decompress.h"
|
||||
#include "pavlov/LzmaDec.h"
|
||||
#include "pavlov/7zCrc.h"
|
||||
#include "common_internal.h"
|
||||
#include "lzma_header.h"
|
||||
#include "lzip_header.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define ELZMA_DECOMPRESS_INPUT_BUFSIZE (1024 * 64)
|
||||
#define ELZMA_DECOMPRESS_OUTPUT_BUFSIZE (1024 * 256)
|
||||
|
||||
/** an opaque handle to an lzma decompressor */
|
||||
struct _elzma_decompress_handle
|
||||
{
|
||||
char inbuf[ELZMA_DECOMPRESS_INPUT_BUFSIZE];
|
||||
char outbuf[ELZMA_DECOMPRESS_OUTPUT_BUFSIZE];
|
||||
struct elzma_alloc_struct allocStruct;
|
||||
};
|
||||
|
||||
elzma_decompress_handle elzma_decompress_alloc()
|
||||
{
|
||||
elzma_decompress_handle hand = malloc(sizeof(struct _elzma_decompress_handle));
|
||||
memset((void *)hand, 0, sizeof(struct _elzma_decompress_handle));
|
||||
init_alloc_struct(&(hand->allocStruct), NULL, NULL, NULL, NULL);
|
||||
return hand;
|
||||
}
|
||||
|
||||
void elzma_decompress_set_allocation_callbacks(elzma_decompress_handle hand,
|
||||
elzma_malloc mallocFunc, void *mallocFuncContext,
|
||||
elzma_free freeFunc, void *freeFuncContext)
|
||||
{
|
||||
if (hand)
|
||||
{
|
||||
init_alloc_struct(&(hand->allocStruct), mallocFunc, mallocFuncContext, freeFunc,
|
||||
freeFuncContext);
|
||||
}
|
||||
}
|
||||
|
||||
void elzma_decompress_free(elzma_decompress_handle *hand)
|
||||
{
|
||||
if (*hand)
|
||||
free(*hand);
|
||||
*hand = NULL;
|
||||
}
|
||||
|
||||
int elzma_decompress_run(elzma_decompress_handle hand, elzma_read_callback inputStream,
|
||||
void *inputContext, elzma_write_callback outputStream,
|
||||
void *outputContext, elzma_file_format format)
|
||||
{
|
||||
unsigned long long int totalRead = 0; /* total amount read from stream */
|
||||
unsigned int crc32 = CRC_INIT_VAL; /* running crc32 (lzip case) */
|
||||
CLzmaDec dec;
|
||||
unsigned int errorCode = ELZMA_E_OK;
|
||||
struct elzma_format_handler formatHandler;
|
||||
struct elzma_file_header h;
|
||||
struct elzma_file_footer f;
|
||||
|
||||
/* switch between supported formats */
|
||||
if (format == ELZMA_lzma)
|
||||
{
|
||||
initializeLZMAFormatHandler(&formatHandler);
|
||||
}
|
||||
else if (format == ELZMA_lzip)
|
||||
{
|
||||
CrcGenerateTable();
|
||||
initializeLZIPFormatHandler(&formatHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ELZMA_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
/* initialize footer */
|
||||
f.crc32 = 0;
|
||||
f.uncompressedSize = 0;
|
||||
|
||||
/* initialize decoder memory */
|
||||
memset((void *)&dec, 0, sizeof(dec));
|
||||
LzmaDec_Init(&dec);
|
||||
|
||||
/* decode the header. */
|
||||
{
|
||||
unsigned char *hdr =
|
||||
hand->allocStruct.Alloc(&(hand->allocStruct), formatHandler.header_size);
|
||||
|
||||
size_t sz = formatHandler.header_size;
|
||||
|
||||
formatHandler.init_header(&h);
|
||||
|
||||
if (inputStream(inputContext, hdr, &sz) != 0 || sz != formatHandler.header_size)
|
||||
{
|
||||
hand->allocStruct.Free(&(hand->allocStruct), hdr);
|
||||
return ELZMA_E_INPUT_ERROR;
|
||||
}
|
||||
|
||||
if (0 != formatHandler.parse_header(hdr, &h))
|
||||
{
|
||||
hand->allocStruct.Free(&(hand->allocStruct), hdr);
|
||||
return ELZMA_E_CORRUPT_HEADER;
|
||||
}
|
||||
|
||||
/* the LzmaDec_Allocate call requires 5 bytes which have
|
||||
* compression properties encoded in them. In the case of
|
||||
* lzip, the header format does not already contain what
|
||||
* LzmaDec_Allocate expects, so we must craft it, silly */
|
||||
{
|
||||
unsigned char propsBuf[13];
|
||||
const unsigned char *propsPtr = hdr;
|
||||
|
||||
if (format == ELZMA_lzip)
|
||||
{
|
||||
struct elzma_format_handler lzmaHand;
|
||||
initializeLZMAFormatHandler(&lzmaHand);
|
||||
lzmaHand.serialize_header(propsBuf, &h);
|
||||
propsPtr = propsBuf;
|
||||
}
|
||||
|
||||
/* now we're ready to allocate the decoder */
|
||||
LzmaDec_Allocate(&dec, propsPtr, 5);
|
||||
}
|
||||
|
||||
hand->allocStruct.Free(&(hand->allocStruct), hdr);
|
||||
}
|
||||
|
||||
/* perform the decoding */
|
||||
for (;;)
|
||||
{
|
||||
size_t dstLen = ELZMA_DECOMPRESS_OUTPUT_BUFSIZE;
|
||||
size_t srcLen = ELZMA_DECOMPRESS_INPUT_BUFSIZE;
|
||||
size_t amt = 0;
|
||||
size_t bufOff = 0;
|
||||
ELzmaStatus stat;
|
||||
|
||||
if (0 != inputStream(inputContext, hand->inbuf, &srcLen))
|
||||
{
|
||||
errorCode = ELZMA_E_INPUT_ERROR;
|
||||
goto decompressEnd;
|
||||
}
|
||||
|
||||
/* handle the case where the input prematurely finishes */
|
||||
if (srcLen == 0)
|
||||
{
|
||||
errorCode = ELZMA_E_INSUFFICIENT_INPUT;
|
||||
goto decompressEnd;
|
||||
}
|
||||
|
||||
amt = srcLen;
|
||||
|
||||
/* handle the case where a single read buffer of compressed bytes
|
||||
* will translate into multiple buffers of uncompressed bytes,
|
||||
* with this inner loop */
|
||||
stat = LZMA_STATUS_NOT_SPECIFIED;
|
||||
|
||||
while (bufOff < srcLen)
|
||||
{
|
||||
SRes r = LzmaDec_DecodeToBuf(&dec, (uint8_t *)hand->outbuf, &dstLen,
|
||||
((uint8_t *)hand->inbuf + bufOff), &amt,
|
||||
LZMA_FINISH_ANY, &stat);
|
||||
|
||||
/* XXX deal with result code more granularly*/
|
||||
if (r != SZ_OK)
|
||||
{
|
||||
errorCode = ELZMA_E_DECOMPRESS_ERROR;
|
||||
goto decompressEnd;
|
||||
}
|
||||
|
||||
/* write what we've read */
|
||||
{
|
||||
size_t wt;
|
||||
|
||||
/* if decoding lzip, update our crc32 value */
|
||||
if (format == ELZMA_lzip && dstLen > 0)
|
||||
{
|
||||
crc32 = CrcUpdate(crc32, hand->outbuf, dstLen);
|
||||
}
|
||||
totalRead += dstLen;
|
||||
|
||||
wt = outputStream(outputContext, hand->outbuf, dstLen);
|
||||
if (wt != dstLen)
|
||||
{
|
||||
errorCode = ELZMA_E_OUTPUT_ERROR;
|
||||
goto decompressEnd;
|
||||
}
|
||||
}
|
||||
|
||||
/* do we have more data on the input buffer? */
|
||||
bufOff += amt;
|
||||
assert(bufOff <= srcLen);
|
||||
if (bufOff >= srcLen)
|
||||
break;
|
||||
amt = srcLen - bufOff;
|
||||
|
||||
/* with lzip, we will have the footer left on the buffer! */
|
||||
if (stat == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* now check status */
|
||||
if (stat == LZMA_STATUS_FINISHED_WITH_MARK)
|
||||
{
|
||||
/* read a footer if one is expected and
|
||||
* present */
|
||||
if (formatHandler.footer_size > 0 && amt >= formatHandler.footer_size &&
|
||||
formatHandler.parse_footer != NULL)
|
||||
{
|
||||
formatHandler.parse_footer((unsigned char *)hand->inbuf + bufOff, &f);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
/* for LZMA utils, we don't always have a finished mark */
|
||||
if (!h.isStreamed && totalRead >= h.uncompressedSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* finish the calculated crc32 */
|
||||
crc32 ^= 0xFFFFFFFF;
|
||||
|
||||
/* if we have a footer, check that the calculated crc32 matches
|
||||
* the encoded crc32, and that the sizes match */
|
||||
if (formatHandler.footer_size)
|
||||
{
|
||||
if (f.crc32 != crc32)
|
||||
{
|
||||
errorCode = ELZMA_E_CRC32_MISMATCH;
|
||||
}
|
||||
else if (f.uncompressedSize != totalRead)
|
||||
{
|
||||
errorCode = ELZMA_E_SIZE_MISMATCH;
|
||||
}
|
||||
}
|
||||
else if (!h.isStreamed)
|
||||
{
|
||||
/* if the format does not support a footer and has an uncompressed
|
||||
* size in the header, let's compare that with how much we actually
|
||||
* read */
|
||||
if (h.uncompressedSize != totalRead)
|
||||
{
|
||||
errorCode = ELZMA_E_SIZE_MISMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
decompressEnd:
|
||||
LzmaDec_Free(&dec);
|
||||
|
||||
return errorCode;
|
||||
}
|
96
depends/lzma/wrapper/lzip_header.c
Normal file
96
depends/lzma/wrapper/lzip_header.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "lzip_header.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ELZMA_LZIP_HEADER_SIZE 6
|
||||
#define ELZMA_LZIP_FOOTER_SIZE 12
|
||||
|
||||
static void initLzipHeader(struct elzma_file_header *hdr)
|
||||
{
|
||||
memset((void *)hdr, 0, sizeof(struct elzma_file_header));
|
||||
}
|
||||
|
||||
static int parseLzipHeader(const unsigned char *hdrBuf, struct elzma_file_header *hdr)
|
||||
{
|
||||
if (0 != strncmp("LZIP", (char *)hdrBuf, 4))
|
||||
return 1;
|
||||
/* XXX: ignore version for now */
|
||||
hdr->pb = 2;
|
||||
hdr->lp = 0;
|
||||
hdr->lc = 3;
|
||||
/* unknown at this point */
|
||||
hdr->isStreamed = 1;
|
||||
hdr->uncompressedSize = 0;
|
||||
hdr->dictSize = 1 << (hdrBuf[5] & 0x1F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serializeLzipHeader(unsigned char *hdrBuf, const struct elzma_file_header *hdr)
|
||||
{
|
||||
hdrBuf[0] = 'L';
|
||||
hdrBuf[1] = 'Z';
|
||||
hdrBuf[2] = 'I';
|
||||
hdrBuf[3] = 'P';
|
||||
hdrBuf[4] = 0;
|
||||
{
|
||||
int r = 0;
|
||||
while ((hdr->dictSize >> r) != 0)
|
||||
r++;
|
||||
hdrBuf[5] = (unsigned char)(r - 1) & 0x1F;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serializeLzipFooter(struct elzma_file_footer *ftr, unsigned char *ftrBuf)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
/* first crc32 */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
*(ftrBuf++) = (unsigned char)(ftr->crc32 >> (i * 8));
|
||||
}
|
||||
|
||||
/* next data size */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
*(ftrBuf++) = (unsigned char)(ftr->uncompressedSize >> (i * 8));
|
||||
}
|
||||
|
||||
/* write version 0 files, omit member length for now*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parseLzipFooter(const unsigned char *ftrBuf, struct elzma_file_footer *ftr)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
ftr->crc32 = 0;
|
||||
ftr->uncompressedSize = 0;
|
||||
|
||||
/* first crc32 */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
ftr->crc32 += ((unsigned int)*(ftrBuf++) << (i * 8));
|
||||
}
|
||||
|
||||
/* next data size */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
ftr->uncompressedSize += (unsigned long long)*(ftrBuf++) << (i * 8);
|
||||
}
|
||||
/* read version 0 files, omit member length for now*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initializeLZIPFormatHandler(struct elzma_format_handler *hand)
|
||||
{
|
||||
hand->header_size = ELZMA_LZIP_HEADER_SIZE;
|
||||
hand->init_header = initLzipHeader;
|
||||
hand->parse_header = parseLzipHeader;
|
||||
hand->serialize_header = serializeLzipHeader;
|
||||
hand->footer_size = ELZMA_LZIP_FOOTER_SIZE;
|
||||
hand->serialize_footer = serializeLzipFooter;
|
||||
hand->parse_footer = parseLzipFooter;
|
||||
}
|
11
depends/lzma/wrapper/lzip_header.h
Normal file
11
depends/lzma/wrapper/lzip_header.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef __EASYLZMA_LZIP_HEADER__
|
||||
#define __EASYLZMA_LZIP_HEADER__
|
||||
|
||||
#include "common_internal.h"
|
||||
|
||||
/* lzip file format documented here:
|
||||
* http://download.savannah.gnu.org/releases-noredirect/lzip/manual/ */
|
||||
|
||||
void initializeLZIPFormatHandler(struct elzma_format_handler *hand);
|
||||
|
||||
#endif
|
134
depends/lzma/wrapper/lzma_header.c
Normal file
134
depends/lzma/wrapper/lzma_header.c
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*/
|
||||
|
||||
/* XXX: clean this up, it's mostly lifted from pavel */
|
||||
|
||||
#include "lzma_header.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define ELZMA_LZMA_HEADER_SIZE 13
|
||||
#define ELZMA_LZMA_PROPSBUF_SIZE 5
|
||||
|
||||
/****************
|
||||
Header parsing
|
||||
****************/
|
||||
|
||||
#ifndef UINT64_MAX
|
||||
#define UINT64_MAX ((unsigned long long)-1)
|
||||
#endif
|
||||
|
||||
/* Parse the properties byte */
|
||||
static char lzmadec_header_properties(unsigned char *pb, unsigned char *lp, unsigned char *lc,
|
||||
const unsigned char c)
|
||||
{
|
||||
/* pb, lp and lc are encoded into a single byte. */
|
||||
if (c > (9 * 5 * 5))
|
||||
return -1;
|
||||
*pb = c / (9 * 5); /* 0 <= pb <= 4 */
|
||||
*lp = (c % (9 * 5)) / 9; /* 0 <= lp <= 4 */
|
||||
*lc = c % 9; /* 0 <= lc <= 8 */
|
||||
|
||||
assert(*pb < 5 && *lp < 5 && *lc < 9);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse the dictionary size (4 bytes, little endian) */
|
||||
static char lzmadec_header_dictionary(unsigned int *size, const unsigned char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
*size = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
*size += (unsigned int)(*buffer++) << (i * 8);
|
||||
/* The dictionary size is limited to 256 MiB (checked from
|
||||
* LZMA SDK 4.30) */
|
||||
if (*size > (1 << 28))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Parse the uncompressed size field (8 bytes, little endian) */
|
||||
static void lzmadec_header_uncompressed(unsigned long long *size, unsigned char *is_streamed,
|
||||
const unsigned char *buffer)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Streamed files have all 64 bits set in the size field.
|
||||
* We don't know the uncompressed size beforehand. */
|
||||
*is_streamed = 1; /* Assume streamed. */
|
||||
*size = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
*size += (unsigned long long)buffer[i] << (i * 8);
|
||||
if (buffer[i] != 255)
|
||||
*is_streamed = 0;
|
||||
}
|
||||
assert((*is_streamed == 1 && *size == UINT64_MAX) ||
|
||||
(*is_streamed == 0 && *size < UINT64_MAX));
|
||||
}
|
||||
|
||||
static void initLzmaHeader(struct elzma_file_header *hdr)
|
||||
{
|
||||
memset((void *)hdr, 0, sizeof(struct elzma_file_header));
|
||||
}
|
||||
|
||||
static int parseLzmaHeader(const unsigned char *hdrBuf, struct elzma_file_header *hdr)
|
||||
{
|
||||
if (lzmadec_header_properties(&(hdr->pb), &(hdr->lp), &(hdr->lc), *hdrBuf) ||
|
||||
lzmadec_header_dictionary(&(hdr->dictSize), hdrBuf + 1))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
lzmadec_header_uncompressed(&(hdr->uncompressedSize), &(hdr->isStreamed), hdrBuf + 5);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int serializeLzmaHeader(unsigned char *hdrBuf, const struct elzma_file_header *hdr)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
memset((void *)hdrBuf, 0, ELZMA_LZMA_HEADER_SIZE);
|
||||
|
||||
/* encode lc, pb, and lp */
|
||||
*hdrBuf++ = hdr->lc + (hdr->pb * 45) + (hdr->lp * 45 * 9);
|
||||
|
||||
/* encode dictionary size */
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
*(hdrBuf++) = (unsigned char)(hdr->dictSize >> (i * 8));
|
||||
}
|
||||
|
||||
/* encode uncompressed size */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (hdr->isStreamed)
|
||||
{
|
||||
*(hdrBuf++) = 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(hdrBuf++) = (unsigned char)(hdr->uncompressedSize >> (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void initializeLZMAFormatHandler(struct elzma_format_handler *hand)
|
||||
{
|
||||
hand->header_size = ELZMA_LZMA_HEADER_SIZE;
|
||||
hand->init_header = initLzmaHeader;
|
||||
hand->parse_header = parseLzmaHeader;
|
||||
hand->serialize_header = serializeLzmaHeader;
|
||||
hand->footer_size = 0;
|
||||
hand->serialize_footer = NULL;
|
||||
}
|
10
depends/lzma/wrapper/lzma_header.h
Normal file
10
depends/lzma/wrapper/lzma_header.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef __EASYLZMA_LZMA_HEADER__
|
||||
#define __EASYLZMA_LZMA_HEADER__
|
||||
|
||||
#include "common_internal.h"
|
||||
|
||||
/* LZMA-Alone header format gleaned from reading Igor's code */
|
||||
|
||||
void initializeLZMAFormatHandler(struct elzma_format_handler *hand);
|
||||
|
||||
#endif
|
139
depends/lzma/wrapper/simple.c
Normal file
139
depends/lzma/wrapper/simple.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Written in 2009 by Lloyd Hilaiel
|
||||
*
|
||||
* License
|
||||
*
|
||||
* All the cruft you find here is public domain. You don't have to credit
|
||||
* anyone to use this code, but my personal request is that you mention
|
||||
* Igor Pavlov for his hard, high quality work.
|
||||
*
|
||||
* simple.c - a wrapper around easylzma to compress/decompress to memory
|
||||
*/
|
||||
|
||||
#include "simple.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct dataStream
|
||||
{
|
||||
const unsigned char *inData;
|
||||
size_t inLen;
|
||||
|
||||
unsigned char *outData;
|
||||
size_t outLen;
|
||||
};
|
||||
|
||||
static int inputCallback(void *ctx, void *buf, size_t *size)
|
||||
{
|
||||
size_t rd = 0;
|
||||
struct dataStream *ds = (struct dataStream *)ctx;
|
||||
assert(ds != NULL);
|
||||
|
||||
rd = (ds->inLen < *size) ? ds->inLen : *size;
|
||||
|
||||
if (rd > 0)
|
||||
{
|
||||
memcpy(buf, (void *)ds->inData, rd);
|
||||
ds->inData += rd;
|
||||
ds->inLen -= rd;
|
||||
}
|
||||
|
||||
*size = rd;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t outputCallback(void *ctx, const void *buf, size_t size)
|
||||
{
|
||||
struct dataStream *ds = (struct dataStream *)ctx;
|
||||
assert(ds != NULL);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
ds->outData = realloc(ds->outData, ds->outLen + size);
|
||||
memcpy((void *)(ds->outData + ds->outLen), buf, size);
|
||||
ds->outLen += size;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int simpleCompress(elzma_file_format format, const unsigned char *inData, size_t inLen,
|
||||
unsigned char **outData, size_t *outLen)
|
||||
{
|
||||
int rc;
|
||||
elzma_compress_handle hand;
|
||||
|
||||
/* allocate compression handle */
|
||||
hand = elzma_compress_alloc();
|
||||
assert(hand != NULL);
|
||||
|
||||
rc = elzma_compress_config(hand, ELZMA_LC_DEFAULT, ELZMA_LP_DEFAULT, ELZMA_PB_DEFAULT, 5,
|
||||
(1 << 20) /* 1mb */, format, inLen);
|
||||
|
||||
if (rc != ELZMA_E_OK)
|
||||
{
|
||||
elzma_compress_free(&hand);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* now run the compression */
|
||||
{
|
||||
struct dataStream ds;
|
||||
ds.inData = inData;
|
||||
ds.inLen = inLen;
|
||||
ds.outData = NULL;
|
||||
ds.outLen = 0;
|
||||
|
||||
rc = elzma_compress_run(hand, inputCallback, (void *)&ds, outputCallback, (void *)&ds,
|
||||
NULL, NULL);
|
||||
|
||||
if (rc != ELZMA_E_OK)
|
||||
{
|
||||
if (ds.outData != NULL)
|
||||
free(ds.outData);
|
||||
elzma_compress_free(&hand);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*outData = ds.outData;
|
||||
*outLen = ds.outLen;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int simpleDecompress(elzma_file_format format, const unsigned char *inData, size_t inLen,
|
||||
unsigned char **outData, size_t *outLen)
|
||||
{
|
||||
int rc;
|
||||
elzma_decompress_handle hand;
|
||||
|
||||
hand = elzma_decompress_alloc();
|
||||
|
||||
/* now run the compression */
|
||||
{
|
||||
struct dataStream ds;
|
||||
ds.inData = inData;
|
||||
ds.inLen = inLen;
|
||||
ds.outData = NULL;
|
||||
ds.outLen = 0;
|
||||
|
||||
rc = elzma_decompress_run(hand, inputCallback, (void *)&ds, outputCallback, (void *)&ds,
|
||||
format);
|
||||
|
||||
if (rc != ELZMA_E_OK)
|
||||
{
|
||||
if (ds.outData != NULL)
|
||||
free(ds.outData);
|
||||
elzma_decompress_free(&hand);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*outData = ds.outData;
|
||||
*outLen = ds.outLen;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
43
depends/pack200/CMakeLists.txt
Normal file
43
depends/pack200/CMakeLists.txt
Normal file
@ -0,0 +1,43 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
project(unpack200)
|
||||
|
||||
# Find ZLIB for quazip
|
||||
# Use system zlib on unix and Qt ZLIB on Windows
|
||||
IF(UNIX)
|
||||
find_package(ZLIB REQUIRED)
|
||||
ELSE(UNIX)
|
||||
get_filename_component (ZLIB_FOUND_DIR "${Qt5Core_DIR}/../../../include/QtZlib" ABSOLUTE)
|
||||
SET(ZLIB_INCLUDE_DIRS ${ZLIB_FOUND_DIR} CACHE PATH "Path to ZLIB headers of Qt")
|
||||
SET(ZLIB_LIBRARIES "")
|
||||
IF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
MESSAGE("Please specify a valid zlib include dir")
|
||||
ENDIF(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h")
|
||||
ENDIF(UNIX)
|
||||
|
||||
SET(PACK200_SRC
|
||||
src/bands.cpp
|
||||
src/bands.h
|
||||
src/bytes.cpp
|
||||
src/bytes.h
|
||||
src/coding.cpp
|
||||
src/coding.h
|
||||
src/constants.h
|
||||
src/defines.h
|
||||
src/main.cpp
|
||||
src/unpack.cpp
|
||||
src/unpack.h
|
||||
src/utils.cpp
|
||||
src/utils.h
|
||||
src/zip.cpp
|
||||
src/zip.h
|
||||
)
|
||||
|
||||
add_executable(unpack200 ${PACK200_SRC})
|
||||
|
||||
IF(UNIX)
|
||||
target_link_libraries(unpack200 ${ZLIB_LIBRARIES})
|
||||
ELSE()
|
||||
# zlib is part of Qt on windows. use it.
|
||||
QT5_USE_MODULES(unpack200 Core)
|
||||
ENDIF()
|
1
depends/pack200/include/unpack200.h
Normal file
1
depends/pack200/include/unpack200.h
Normal file
@ -0,0 +1 @@
|
||||
|
451
depends/pack200/src/bands.cpp
Normal file
451
depends/pack200/src/bands.cpp
Normal file
@ -0,0 +1,451 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
// Small program for unpacking specially compressed Java packages.
|
||||
// John R. Rose
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
inline void band::abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
inline bool band::aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
||||
|
||||
void band::readData(int expectedLength)
|
||||
{
|
||||
CHECK;
|
||||
assert(expectedLength >= 0);
|
||||
assert(vs[0].cmk == cmk_ERROR);
|
||||
if (expectedLength != 0)
|
||||
{
|
||||
assert(length == 0);
|
||||
length = expectedLength;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
assert((rplimit = cm.vs0.rp = u->rp) != nullptr);
|
||||
return;
|
||||
}
|
||||
assert(length > 0);
|
||||
|
||||
bool is_BYTE1 = (defc->spec == BYTE1_spec);
|
||||
|
||||
if (is_BYTE1)
|
||||
{
|
||||
// No possibility of coding change. Sizing is exact.
|
||||
u->ensure_input(length);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make a conservatively generous estimate of band size in bytes.
|
||||
// Assume B == 5 everywhere.
|
||||
// Assume awkward pop with all {U} values (2*5 per value)
|
||||
jlong generous = (jlong)length * (B_MAX * 3 + 1) + C_SLOP;
|
||||
u->ensure_input(generous);
|
||||
}
|
||||
|
||||
// Read one value to see what it might be.
|
||||
int XB = _meta_default;
|
||||
int cp1 = 0, cp2 = 0;
|
||||
if (!is_BYTE1)
|
||||
{
|
||||
// must be a variable-length coding
|
||||
assert(defc->B() > 1 && defc->L() > 0);
|
||||
// must have already read from previous band:
|
||||
assert(bn >= BAND_LIMIT || bn <= 0 || bn == e_cp_Utf8_big_chars ||
|
||||
endsWith(name, "_lo") // preceded by _hi conditional band
|
||||
||
|
||||
bn == e_file_options // preceded by conditional band
|
||||
||
|
||||
u->rp == u->all_bands[bn - 1].maxRP() || u->all_bands[bn - 1].defc == nullptr);
|
||||
|
||||
value_stream xvs;
|
||||
coding *valc = defc;
|
||||
if (valc->D() != 0)
|
||||
{
|
||||
valc = coding::findBySpec(defc->B(), defc->H(), defc->S());
|
||||
assert(!valc->isMalloc);
|
||||
}
|
||||
xvs.init(u->rp, u->rplimit, valc);
|
||||
CHECK;
|
||||
int X = xvs.getInt();
|
||||
if (valc->S() != 0)
|
||||
{
|
||||
assert(valc->min <= -256);
|
||||
XB = -1 - X;
|
||||
}
|
||||
else
|
||||
{
|
||||
int L = valc->L();
|
||||
assert(valc->max >= L + 255);
|
||||
XB = X - L;
|
||||
}
|
||||
if (0 <= XB && XB < 256)
|
||||
{
|
||||
// Skip over the escape value.
|
||||
u->rp = xvs.rp;
|
||||
cp1 = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, it's still default.
|
||||
XB = _meta_default;
|
||||
}
|
||||
}
|
||||
|
||||
if (XB <= _meta_canon_max)
|
||||
{
|
||||
byte XB_byte = (byte)XB;
|
||||
byte *XB_ptr = &XB_byte;
|
||||
cm.init(u->rp, u->rplimit, XB_ptr, 0, defc, length, nullptr);
|
||||
CHECK;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(u->meta_rp != nullptr);
|
||||
// Scribble the initial byte onto the band.
|
||||
byte *save_meta_rp = --u->meta_rp;
|
||||
byte save_meta_xb = (*save_meta_rp);
|
||||
(*save_meta_rp) = (byte)XB;
|
||||
cm.init(u->rp, u->rplimit, u->meta_rp, 0, defc, length, nullptr);
|
||||
(*save_meta_rp) = save_meta_xb; // put it back, just to be tidy
|
||||
}
|
||||
rplimit = u->rp;
|
||||
|
||||
rewind();
|
||||
}
|
||||
|
||||
void band::setIndex(cpindex *ix_)
|
||||
{
|
||||
assert(ix_ == nullptr || ixTag == ix_->ixTag);
|
||||
ix = ix_;
|
||||
}
|
||||
void band::setIndexByTag(byte tag)
|
||||
{
|
||||
setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
|
||||
entry *band::getRefCommon(cpindex *ix_, bool nullOKwithCaller)
|
||||
{
|
||||
CHECK_0;
|
||||
assert(ix_->ixTag == ixTag ||
|
||||
(ixTag == CONSTANT_Literal && ix_->ixTag >= CONSTANT_Integer &&
|
||||
ix_->ixTag <= CONSTANT_String));
|
||||
int n = vs[0].getInt() - nullOK;
|
||||
// Note: band-local nullOK means nullptr encodes as 0.
|
||||
// But nullOKwithCaller means caller is willing to tolerate a nullptr.
|
||||
entry *ref = ix_->get(n);
|
||||
if (ref == nullptr && !(nullOKwithCaller && n == -1))
|
||||
abort(n == -1 ? "nullptr ref" : "bad ref");
|
||||
return ref;
|
||||
}
|
||||
|
||||
jlong band::getLong(band &lo_band, bool have_hi)
|
||||
{
|
||||
band &hi_band = (*this);
|
||||
assert(lo_band.bn == hi_band.bn + 1);
|
||||
uint lo = lo_band.getInt();
|
||||
if (!have_hi)
|
||||
{
|
||||
assert(hi_band.length == 0);
|
||||
return makeLong(0, lo);
|
||||
}
|
||||
uint hi = hi_band.getInt();
|
||||
return makeLong(hi, lo);
|
||||
}
|
||||
|
||||
int band::getIntTotal()
|
||||
{
|
||||
CHECK_0;
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (total_memo > 0)
|
||||
return total_memo - 1;
|
||||
int total = getInt();
|
||||
// overflow checks require that none of the addends are <0,
|
||||
// and that the partial sums never overflow (wrap negative)
|
||||
if (total < 0)
|
||||
{
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
for (int k = length - 1; k > 0; k--)
|
||||
{
|
||||
int prev_total = total;
|
||||
total += vs[0].getInt();
|
||||
if (total < prev_total)
|
||||
{
|
||||
abort("overflow detected");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
rewind();
|
||||
total_memo = total + 1;
|
||||
return total;
|
||||
}
|
||||
|
||||
int band::getIntCount(int tag)
|
||||
{
|
||||
CHECK_0;
|
||||
if (length == 0)
|
||||
return 0;
|
||||
if (tag >= HIST0_MIN && tag <= HIST0_MAX)
|
||||
{
|
||||
if (hist0 == nullptr)
|
||||
{
|
||||
// Lazily calculate an approximate histogram.
|
||||
hist0 = U_NEW(int, (HIST0_MAX - HIST0_MIN) + 1);
|
||||
CHECK_0;
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
int x = vs[0].getInt();
|
||||
if (x >= HIST0_MIN && x <= HIST0_MAX)
|
||||
hist0[x - HIST0_MIN] += 1;
|
||||
}
|
||||
rewind();
|
||||
}
|
||||
return hist0[tag - HIST0_MIN];
|
||||
}
|
||||
int total = 0;
|
||||
for (int k = length; k > 0; k--)
|
||||
{
|
||||
total += (vs[0].getInt() == tag) ? 1 : 0;
|
||||
}
|
||||
rewind();
|
||||
return total;
|
||||
}
|
||||
|
||||
#define INDEX_INIT(tag, nullOK, subindex) ((tag) + (subindex) * SUBINDEX_BIT + (nullOK) * 256)
|
||||
|
||||
#define INDEX(tag) INDEX_INIT(tag, 0, 0)
|
||||
#define NULL_OR_INDEX(tag) INDEX_INIT(tag, 1, 0)
|
||||
#define SUB_INDEX(tag) INDEX_INIT(tag, 0, 1)
|
||||
#define NO_INDEX 0
|
||||
|
||||
struct band_init
|
||||
{
|
||||
int defc;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define BAND_INIT(name, cspec, ix) \
|
||||
{ \
|
||||
cspec, ix \
|
||||
}
|
||||
|
||||
const band_init all_band_inits[] =
|
||||
{
|
||||
// BAND_INIT(archive_magic, BYTE1_spec, 0),
|
||||
// BAND_INIT(archive_header, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(band_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(cp_Utf8_prefix, DELTA5_spec, 0), BAND_INIT(cp_Utf8_suffix, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_chars, CHAR3_spec, 0), BAND_INIT(cp_Utf8_big_suffix, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_Utf8_big_chars, DELTA5_spec, 0), BAND_INIT(cp_Int, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Float, UDELTA5_spec, 0), BAND_INIT(cp_Long_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Long_lo, DELTA5_spec, 0), BAND_INIT(cp_Double_hi, UDELTA5_spec, 0),
|
||||
BAND_INIT(cp_Double_lo, DELTA5_spec, 0),
|
||||
BAND_INIT(cp_String, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Class, UDELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_form, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Signature_classes, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Descr_name, DELTA5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(cp_Descr_type, UDELTA5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(cp_Field_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Field_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Method_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Method_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(cp_Imethod_class, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(cp_Imethod_desc, UDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(attr_definition_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(attr_definition_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(attr_definition_layout, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(ic_this_class, UDELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_flags, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(ic_outer_class, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(ic_name, DELTA5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_this, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_super, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_interface_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_interface, DELTA5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_field_count, DELTA5_spec, 0),
|
||||
BAND_INIT(class_method_count, DELTA5_spec, 0),
|
||||
BAND_INIT(field_descr, DELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(field_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(field_ConstantValue_KQ, UNSIGNED5_spec, INDEX(CONSTANT_Literal)),
|
||||
BAND_INIT(field_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(field_metadata_bands, -1, -1), BAND_INIT(field_attr_bands, -1, -1),
|
||||
BAND_INIT(method_descr, MDELTA5_spec, INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(method_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(method_Exceptions_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(method_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(method_metadata_bands, -1, -1), BAND_INIT(method_attr_bands, -1, -1),
|
||||
BAND_INIT(class_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_SourceFile_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_EnclosingMethod_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_EnclosingMethod_RDN, UNSIGNED5_spec,
|
||||
NULL_OR_INDEX(CONSTANT_NameandType)),
|
||||
BAND_INIT(class_Signature_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(class_metadata_bands, -1, -1),
|
||||
BAND_INIT(class_InnerClasses_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_F, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_InnerClasses_outer_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(class_InnerClasses_name_RUN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(class_ClassFile_version_minor_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_ClassFile_version_major_H, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(class_attr_bands, -1, -1), BAND_INIT(code_headers, BYTE1_spec, 0),
|
||||
BAND_INIT(code_max_stack, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_max_na_locals, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_handler_start_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_handler_end_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_catch_PO, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_handler_class_RCN, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_flags_hi, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_flags_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_count, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_indexes, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_calls, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_frame_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_local_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_stack_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_offset, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_T, BYTE1_spec, 0),
|
||||
BAND_INIT(code_StackMapTable_RC, UNSIGNED5_spec, INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(code_StackMapTable_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LineNumberTable_line, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTable_type_RS, UNSIGNED5_spec, INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_N, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_bci_P, BCI5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_span_O, BRANCH5_spec, 0),
|
||||
BAND_INIT(code_LocalVariableTypeTable_name_RU, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_type_RS, UNSIGNED5_spec,
|
||||
INDEX(CONSTANT_Signature)),
|
||||
BAND_INIT(code_LocalVariableTypeTable_slot, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(code_attr_bands, -1, -1), BAND_INIT(bc_codes, BYTE1_spec, 0),
|
||||
BAND_INIT(bc_case_count, UNSIGNED5_spec, 0), BAND_INIT(bc_case_value, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_byte, BYTE1_spec, 0), BAND_INIT(bc_short, DELTA5_spec, 0),
|
||||
BAND_INIT(bc_local, UNSIGNED5_spec, 0), BAND_INIT(bc_label, BRANCH5_spec, 0),
|
||||
BAND_INIT(bc_intref, DELTA5_spec, INDEX(CONSTANT_Integer)),
|
||||
BAND_INIT(bc_floatref, DELTA5_spec, INDEX(CONSTANT_Float)),
|
||||
BAND_INIT(bc_longref, DELTA5_spec, INDEX(CONSTANT_Long)),
|
||||
BAND_INIT(bc_doubleref, DELTA5_spec, INDEX(CONSTANT_Double)),
|
||||
BAND_INIT(bc_stringref, DELTA5_spec, INDEX(CONSTANT_String)),
|
||||
BAND_INIT(bc_classref, UNSIGNED5_spec, NULL_OR_INDEX(CONSTANT_Class)),
|
||||
BAND_INIT(bc_fieldref, DELTA5_spec, INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_methodref, UNSIGNED5_spec, INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_imethodref, DELTA5_spec, INDEX(CONSTANT_InterfaceMethodref)),
|
||||
BAND_INIT(bc_thisfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_superfield, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Fieldref)),
|
||||
BAND_INIT(bc_thismethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_supermethod, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_initref, UNSIGNED5_spec, SUB_INDEX(CONSTANT_Methodref)),
|
||||
BAND_INIT(bc_escref, UNSIGNED5_spec, INDEX(CONSTANT_All)),
|
||||
BAND_INIT(bc_escrefsize, UNSIGNED5_spec, 0), BAND_INIT(bc_escsize, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(bc_escbyte, BYTE1_spec, 0),
|
||||
BAND_INIT(file_name, UNSIGNED5_spec, INDEX(CONSTANT_Utf8)),
|
||||
BAND_INIT(file_size_hi, UNSIGNED5_spec, 0), BAND_INIT(file_size_lo, UNSIGNED5_spec, 0),
|
||||
BAND_INIT(file_modtime, DELTA5_spec, 0), BAND_INIT(file_options, UNSIGNED5_spec, 0),
|
||||
// BAND_INIT(file_bits, BYTE1_spec, 0),
|
||||
{0, 0}};
|
||||
#define NUM_BAND_INITS (sizeof(all_band_inits) / sizeof(all_band_inits[0]))
|
||||
|
||||
band *band::makeBands(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = U_NEW(band, BAND_LIMIT);
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
assert((byte *)&all_band_inits[i + 1] <
|
||||
(byte *)all_band_inits + sizeof(all_band_inits));
|
||||
const band_init &bi = all_band_inits[i];
|
||||
band &b = tmp_all_bands[i];
|
||||
coding *defc = coding::findBySpec(bi.defc);
|
||||
assert((defc == nullptr) == (bi.defc == -1)); // no garbage, please
|
||||
assert(defc == nullptr || !defc->isMalloc);
|
||||
assert(bi.bn == i); // band array consistent w/ band enum
|
||||
b.init(u, i, defc);
|
||||
if (bi.index > 0)
|
||||
{
|
||||
b.nullOK = ((bi.index >> 8) & 1);
|
||||
b.ixTag = (bi.index & 0xFF);
|
||||
}
|
||||
}
|
||||
return tmp_all_bands;
|
||||
}
|
||||
|
||||
void band::initIndexes(unpacker *u)
|
||||
{
|
||||
band *tmp_all_bands = u->all_bands;
|
||||
for (int i = 0; i < BAND_LIMIT; i++)
|
||||
{
|
||||
band *scan = &tmp_all_bands[i];
|
||||
uint tag = scan->ixTag; // Cf. #define INDEX(tag) above
|
||||
if (tag != 0 && tag != CONSTANT_Literal && (tag & SUBINDEX_BIT) == 0)
|
||||
{
|
||||
scan->setIndex(u->cp.getIndex(tag));
|
||||
}
|
||||
}
|
||||
}
|
492
depends/pack200/src/bands.h
Normal file
492
depends/pack200/src/bands.h
Normal file
@ -0,0 +1,492 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// -*- C++ -*-
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct unpacker;
|
||||
|
||||
struct band
|
||||
{
|
||||
int bn; // band_number of this band
|
||||
coding *defc; // default coding method
|
||||
cpindex *ix; // CP entry mapping, if CPRefBand
|
||||
byte ixTag; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
byte nullOK; // 0 or 1; nullptr is coded as (nullOK?0:-1)
|
||||
int length; // expected # values
|
||||
unpacker *u; // back pointer
|
||||
|
||||
value_stream vs[2]; // source of values
|
||||
coding_method cm; // method used for initial state of vs[0]
|
||||
byte *rplimit; // end of band (encoded, transmitted)
|
||||
|
||||
int total_memo; // cached value of getIntTotal, or -1
|
||||
int *hist0; // approximate. histogram
|
||||
enum
|
||||
{
|
||||
HIST0_MIN = 0,
|
||||
HIST0_MAX = 255
|
||||
}; // catches the usual cases
|
||||
|
||||
// properties for attribute layout elements:
|
||||
byte le_kind; // EK_XXX
|
||||
byte le_bci; // 0,EK_BCI,EK_BCD,EK_BCO
|
||||
byte le_back; // ==EF_BACK
|
||||
byte le_len; // 0,1,2,4 (size in classfile), or call addr
|
||||
band **le_body; // body of repl, union, call (nullptr-terminated)
|
||||
// Note: EK_CASE elements use hist0 to record union tags.
|
||||
#define le_casetags hist0
|
||||
|
||||
band &nextBand()
|
||||
{
|
||||
return this[1];
|
||||
}
|
||||
band &prevBand()
|
||||
{
|
||||
return this[-1];
|
||||
}
|
||||
|
||||
void init(unpacker *u_, int bn_, coding *defc_)
|
||||
{
|
||||
u = u_;
|
||||
cm.u = u_;
|
||||
bn = bn_;
|
||||
defc = defc_;
|
||||
}
|
||||
void init(unpacker *u_, int bn_, int defcSpec)
|
||||
{
|
||||
init(u_, bn_, coding::findBySpec(defcSpec));
|
||||
}
|
||||
void initRef(int ixTag_ = 0, bool nullOK_ = false)
|
||||
{
|
||||
ixTag = ixTag_;
|
||||
nullOK = nullOK_;
|
||||
setIndexByTag(ixTag);
|
||||
}
|
||||
|
||||
void expectMoreLength(int l)
|
||||
{
|
||||
assert(length >= 0); // able to accept a length
|
||||
assert((int)l >= 0); // no overflow
|
||||
assert(rplimit == nullptr); // readData not yet called
|
||||
length += l;
|
||||
assert(length >= l); // no overflow
|
||||
}
|
||||
|
||||
void setIndex(cpindex *ix_);
|
||||
void setIndexByTag(byte tag);
|
||||
|
||||
// Parse the band and its meta-coding header.
|
||||
void readData(int expectedLength = 0);
|
||||
|
||||
// Reset the band for another pass (Cf. Java Band.resetForSecondPass.)
|
||||
void rewind()
|
||||
{
|
||||
cm.reset(&vs[0]);
|
||||
}
|
||||
|
||||
byte *&curRP()
|
||||
{
|
||||
return vs[0].rp;
|
||||
}
|
||||
byte *minRP()
|
||||
{
|
||||
return cm.vs0.rp;
|
||||
}
|
||||
byte *maxRP()
|
||||
{
|
||||
return rplimit;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return maxRP() - minRP();
|
||||
}
|
||||
|
||||
int getByte()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getByte();
|
||||
}
|
||||
int getInt()
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return vs[0].getInt();
|
||||
}
|
||||
entry *getRefN()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, true);
|
||||
}
|
||||
entry *getRef()
|
||||
{
|
||||
assert(ix != nullptr);
|
||||
return getRefCommon(ix, false);
|
||||
}
|
||||
entry *getRefUsing(cpindex *ix2)
|
||||
{
|
||||
assert(ix == nullptr);
|
||||
return getRefCommon(ix2, true);
|
||||
}
|
||||
entry *getRefCommon(cpindex *ix, bool nullOK);
|
||||
jlong getLong(band &lo_band, bool have_hi);
|
||||
|
||||
static jlong makeLong(uint hi, uint lo)
|
||||
{
|
||||
return ((julong)hi << 32) + (((julong)lo << 32) >> 32);
|
||||
}
|
||||
|
||||
int getIntTotal();
|
||||
int getIntCount(int tag);
|
||||
|
||||
static band *makeBands(unpacker *u);
|
||||
static void initIndexes(unpacker *u);
|
||||
|
||||
void abort(const char *msg = nullptr); //{ u->abort(msg); }
|
||||
bool aborting(); //{ return u->aborting(); }
|
||||
};
|
||||
|
||||
extern band all_bands[];
|
||||
|
||||
#define BAND_LOCAL /* \
|
||||
band* band_temp = all_bands; \
|
||||
band* all_bands = band_temp */
|
||||
|
||||
// Band schema:
|
||||
enum band_number
|
||||
{
|
||||
// e_archive_magic,
|
||||
// e_archive_header,
|
||||
// e_band_headers,
|
||||
|
||||
// constant pool contents
|
||||
e_cp_Utf8_prefix,
|
||||
e_cp_Utf8_suffix,
|
||||
e_cp_Utf8_chars,
|
||||
e_cp_Utf8_big_suffix,
|
||||
e_cp_Utf8_big_chars,
|
||||
e_cp_Int,
|
||||
e_cp_Float,
|
||||
e_cp_Long_hi,
|
||||
e_cp_Long_lo,
|
||||
e_cp_Double_hi,
|
||||
e_cp_Double_lo,
|
||||
e_cp_String,
|
||||
e_cp_Class,
|
||||
e_cp_Signature_form,
|
||||
e_cp_Signature_classes,
|
||||
e_cp_Descr_name,
|
||||
e_cp_Descr_type,
|
||||
e_cp_Field_class,
|
||||
e_cp_Field_desc,
|
||||
e_cp_Method_class,
|
||||
e_cp_Method_desc,
|
||||
e_cp_Imethod_class,
|
||||
e_cp_Imethod_desc,
|
||||
|
||||
// bands which define transmission of attributes
|
||||
e_attr_definition_headers,
|
||||
e_attr_definition_name,
|
||||
e_attr_definition_layout,
|
||||
|
||||
// band for hardwired InnerClasses attribute (shared across the package)
|
||||
e_ic_this_class,
|
||||
e_ic_flags,
|
||||
// These bands contain data only where flags sets ACC_IC_LONG_FORM:
|
||||
e_ic_outer_class,
|
||||
e_ic_name,
|
||||
|
||||
// bands for carrying class schema information:
|
||||
e_class_this,
|
||||
e_class_super,
|
||||
e_class_interface_count,
|
||||
e_class_interface,
|
||||
|
||||
// bands for class members
|
||||
e_class_field_count,
|
||||
e_class_method_count,
|
||||
e_field_descr,
|
||||
e_field_flags_hi,
|
||||
e_field_flags_lo,
|
||||
e_field_attr_count,
|
||||
e_field_attr_indexes,
|
||||
e_field_attr_calls,
|
||||
e_field_ConstantValue_KQ,
|
||||
e_field_Signature_RS,
|
||||
e_field_metadata_bands,
|
||||
e_field_attr_bands,
|
||||
e_method_descr,
|
||||
e_method_flags_hi,
|
||||
e_method_flags_lo,
|
||||
e_method_attr_count,
|
||||
e_method_attr_indexes,
|
||||
e_method_attr_calls,
|
||||
e_method_Exceptions_N,
|
||||
e_method_Exceptions_RC,
|
||||
e_method_Signature_RS,
|
||||
e_method_metadata_bands,
|
||||
e_method_attr_bands,
|
||||
e_class_flags_hi,
|
||||
e_class_flags_lo,
|
||||
e_class_attr_count,
|
||||
e_class_attr_indexes,
|
||||
e_class_attr_calls,
|
||||
e_class_SourceFile_RUN,
|
||||
e_class_EnclosingMethod_RC,
|
||||
e_class_EnclosingMethod_RDN,
|
||||
e_class_Signature_RS,
|
||||
e_class_metadata_bands,
|
||||
e_class_InnerClasses_N,
|
||||
e_class_InnerClasses_RC,
|
||||
e_class_InnerClasses_F,
|
||||
e_class_InnerClasses_outer_RCN,
|
||||
e_class_InnerClasses_name_RUN,
|
||||
e_class_ClassFile_version_minor_H,
|
||||
e_class_ClassFile_version_major_H,
|
||||
e_class_attr_bands,
|
||||
e_code_headers,
|
||||
e_code_max_stack,
|
||||
e_code_max_na_locals,
|
||||
e_code_handler_count,
|
||||
e_code_handler_start_P,
|
||||
e_code_handler_end_PO,
|
||||
e_code_handler_catch_PO,
|
||||
e_code_handler_class_RCN,
|
||||
|
||||
// code attributes
|
||||
e_code_flags_hi,
|
||||
e_code_flags_lo,
|
||||
e_code_attr_count,
|
||||
e_code_attr_indexes,
|
||||
e_code_attr_calls,
|
||||
e_code_StackMapTable_N,
|
||||
e_code_StackMapTable_frame_T,
|
||||
e_code_StackMapTable_local_N,
|
||||
e_code_StackMapTable_stack_N,
|
||||
e_code_StackMapTable_offset,
|
||||
e_code_StackMapTable_T,
|
||||
e_code_StackMapTable_RC,
|
||||
e_code_StackMapTable_P,
|
||||
e_code_LineNumberTable_N,
|
||||
e_code_LineNumberTable_bci_P,
|
||||
e_code_LineNumberTable_line,
|
||||
e_code_LocalVariableTable_N,
|
||||
e_code_LocalVariableTable_bci_P,
|
||||
e_code_LocalVariableTable_span_O,
|
||||
e_code_LocalVariableTable_name_RU,
|
||||
e_code_LocalVariableTable_type_RS,
|
||||
e_code_LocalVariableTable_slot,
|
||||
e_code_LocalVariableTypeTable_N,
|
||||
e_code_LocalVariableTypeTable_bci_P,
|
||||
e_code_LocalVariableTypeTable_span_O,
|
||||
e_code_LocalVariableTypeTable_name_RU,
|
||||
e_code_LocalVariableTypeTable_type_RS,
|
||||
e_code_LocalVariableTypeTable_slot,
|
||||
e_code_attr_bands,
|
||||
|
||||
// bands for bytecodes
|
||||
e_bc_codes,
|
||||
// remaining bands provide typed opcode fields required by the bc_codes
|
||||
e_bc_case_count,
|
||||
e_bc_case_value,
|
||||
e_bc_byte,
|
||||
e_bc_short,
|
||||
e_bc_local,
|
||||
e_bc_label,
|
||||
|
||||
// ldc* operands:
|
||||
e_bc_intref,
|
||||
e_bc_floatref,
|
||||
e_bc_longref,
|
||||
e_bc_doubleref,
|
||||
e_bc_stringref,
|
||||
e_bc_classref,
|
||||
e_bc_fieldref,
|
||||
e_bc_methodref,
|
||||
e_bc_imethodref,
|
||||
|
||||
// _self_linker_op family
|
||||
e_bc_thisfield,
|
||||
e_bc_superfield,
|
||||
e_bc_thismethod,
|
||||
e_bc_supermethod,
|
||||
|
||||
// bc_invokeinit family:
|
||||
e_bc_initref,
|
||||
|
||||
// bytecode escape sequences
|
||||
e_bc_escref,
|
||||
e_bc_escrefsize,
|
||||
e_bc_escsize,
|
||||
e_bc_escbyte,
|
||||
|
||||
// file attributes and contents
|
||||
e_file_name,
|
||||
e_file_size_hi,
|
||||
e_file_size_lo,
|
||||
e_file_modtime,
|
||||
e_file_options,
|
||||
// e_file_bits, // handled specially as an appendix
|
||||
BAND_LIMIT
|
||||
};
|
||||
|
||||
// Symbolic names for bands, as if in a giant global struct:
|
||||
//#define archive_magic all_bands[e_archive_magic]
|
||||
//#define archive_header all_bands[e_archive_header]
|
||||
//#define band_headers all_bands[e_band_headers]
|
||||
#define cp_Utf8_prefix all_bands[e_cp_Utf8_prefix]
|
||||
#define cp_Utf8_suffix all_bands[e_cp_Utf8_suffix]
|
||||
#define cp_Utf8_chars all_bands[e_cp_Utf8_chars]
|
||||
#define cp_Utf8_big_suffix all_bands[e_cp_Utf8_big_suffix]
|
||||
#define cp_Utf8_big_chars all_bands[e_cp_Utf8_big_chars]
|
||||
#define cp_Int all_bands[e_cp_Int]
|
||||
#define cp_Float all_bands[e_cp_Float]
|
||||
#define cp_Long_hi all_bands[e_cp_Long_hi]
|
||||
#define cp_Long_lo all_bands[e_cp_Long_lo]
|
||||
#define cp_Double_hi all_bands[e_cp_Double_hi]
|
||||
#define cp_Double_lo all_bands[e_cp_Double_lo]
|
||||
#define cp_String all_bands[e_cp_String]
|
||||
#define cp_Class all_bands[e_cp_Class]
|
||||
#define cp_Signature_form all_bands[e_cp_Signature_form]
|
||||
#define cp_Signature_classes all_bands[e_cp_Signature_classes]
|
||||
#define cp_Descr_name all_bands[e_cp_Descr_name]
|
||||
#define cp_Descr_type all_bands[e_cp_Descr_type]
|
||||
#define cp_Field_class all_bands[e_cp_Field_class]
|
||||
#define cp_Field_desc all_bands[e_cp_Field_desc]
|
||||
#define cp_Method_class all_bands[e_cp_Method_class]
|
||||
#define cp_Method_desc all_bands[e_cp_Method_desc]
|
||||
#define cp_Imethod_class all_bands[e_cp_Imethod_class]
|
||||
#define cp_Imethod_desc all_bands[e_cp_Imethod_desc]
|
||||
#define attr_definition_headers all_bands[e_attr_definition_headers]
|
||||
#define attr_definition_name all_bands[e_attr_definition_name]
|
||||
#define attr_definition_layout all_bands[e_attr_definition_layout]
|
||||
#define ic_this_class all_bands[e_ic_this_class]
|
||||
#define ic_flags all_bands[e_ic_flags]
|
||||
#define ic_outer_class all_bands[e_ic_outer_class]
|
||||
#define ic_name all_bands[e_ic_name]
|
||||
#define class_this all_bands[e_class_this]
|
||||
#define class_super all_bands[e_class_super]
|
||||
#define class_interface_count all_bands[e_class_interface_count]
|
||||
#define class_interface all_bands[e_class_interface]
|
||||
#define class_field_count all_bands[e_class_field_count]
|
||||
#define class_method_count all_bands[e_class_method_count]
|
||||
#define field_descr all_bands[e_field_descr]
|
||||
#define field_flags_hi all_bands[e_field_flags_hi]
|
||||
#define field_flags_lo all_bands[e_field_flags_lo]
|
||||
#define field_attr_count all_bands[e_field_attr_count]
|
||||
#define field_attr_indexes all_bands[e_field_attr_indexes]
|
||||
#define field_ConstantValue_KQ all_bands[e_field_ConstantValue_KQ]
|
||||
#define field_Signature_RS all_bands[e_field_Signature_RS]
|
||||
#define field_attr_bands all_bands[e_field_attr_bands]
|
||||
#define method_descr all_bands[e_method_descr]
|
||||
#define method_flags_hi all_bands[e_method_flags_hi]
|
||||
#define method_flags_lo all_bands[e_method_flags_lo]
|
||||
#define method_attr_count all_bands[e_method_attr_count]
|
||||
#define method_attr_indexes all_bands[e_method_attr_indexes]
|
||||
#define method_Exceptions_N all_bands[e_method_Exceptions_N]
|
||||
#define method_Exceptions_RC all_bands[e_method_Exceptions_RC]
|
||||
#define method_Signature_RS all_bands[e_method_Signature_RS]
|
||||
#define method_attr_bands all_bands[e_method_attr_bands]
|
||||
#define class_flags_hi all_bands[e_class_flags_hi]
|
||||
#define class_flags_lo all_bands[e_class_flags_lo]
|
||||
#define class_attr_count all_bands[e_class_attr_count]
|
||||
#define class_attr_indexes all_bands[e_class_attr_indexes]
|
||||
#define class_SourceFile_RUN all_bands[e_class_SourceFile_RUN]
|
||||
#define class_EnclosingMethod_RC all_bands[e_class_EnclosingMethod_RC]
|
||||
#define class_EnclosingMethod_RDN all_bands[e_class_EnclosingMethod_RDN]
|
||||
#define class_Signature_RS all_bands[e_class_Signature_RS]
|
||||
#define class_InnerClasses_N all_bands[e_class_InnerClasses_N]
|
||||
#define class_InnerClasses_RC all_bands[e_class_InnerClasses_RC]
|
||||
#define class_InnerClasses_F all_bands[e_class_InnerClasses_F]
|
||||
#define class_InnerClasses_outer_RCN all_bands[e_class_InnerClasses_outer_RCN]
|
||||
#define class_InnerClasses_name_RUN all_bands[e_class_InnerClasses_name_RUN]
|
||||
#define class_ClassFile_version_minor_H all_bands[e_class_ClassFile_version_minor_H]
|
||||
#define class_ClassFile_version_major_H all_bands[e_class_ClassFile_version_major_H]
|
||||
#define class_attr_bands all_bands[e_class_attr_bands]
|
||||
#define code_headers all_bands[e_code_headers]
|
||||
#define code_max_stack all_bands[e_code_max_stack]
|
||||
#define code_max_na_locals all_bands[e_code_max_na_locals]
|
||||
#define code_handler_count all_bands[e_code_handler_count]
|
||||
#define code_handler_start_P all_bands[e_code_handler_start_P]
|
||||
#define code_handler_end_PO all_bands[e_code_handler_end_PO]
|
||||
#define code_handler_catch_PO all_bands[e_code_handler_catch_PO]
|
||||
#define code_handler_class_RCN all_bands[e_code_handler_class_RCN]
|
||||
#define code_flags_hi all_bands[e_code_flags_hi]
|
||||
#define code_flags_lo all_bands[e_code_flags_lo]
|
||||
#define code_attr_count all_bands[e_code_attr_count]
|
||||
#define code_attr_indexes all_bands[e_code_attr_indexes]
|
||||
#define code_StackMapTable_N all_bands[e_code_StackMapTable_N]
|
||||
#define code_StackMapTable_frame_T all_bands[e_code_StackMapTable_frame_T]
|
||||
#define code_StackMapTable_local_N all_bands[e_code_StackMapTable_local_N]
|
||||
#define code_StackMapTable_stack_N all_bands[e_code_StackMapTable_stack_N]
|
||||
#define code_StackMapTable_offset all_bands[e_code_StackMapTable_offset]
|
||||
#define code_StackMapTable_T all_bands[e_code_StackMapTable_T]
|
||||
#define code_StackMapTable_RC all_bands[e_code_StackMapTable_RC]
|
||||
#define code_StackMapTable_P all_bands[e_code_StackMapTable_P]
|
||||
#define code_LineNumberTable_N all_bands[e_code_LineNumberTable_N]
|
||||
#define code_LineNumberTable_bci_P all_bands[e_code_LineNumberTable_bci_P]
|
||||
#define code_LineNumberTable_line all_bands[e_code_LineNumberTable_line]
|
||||
#define code_LocalVariableTable_N all_bands[e_code_LocalVariableTable_N]
|
||||
#define code_LocalVariableTable_bci_P all_bands[e_code_LocalVariableTable_bci_P]
|
||||
#define code_LocalVariableTable_span_O all_bands[e_code_LocalVariableTable_span_O]
|
||||
#define code_LocalVariableTable_name_RU all_bands[e_code_LocalVariableTable_name_RU]
|
||||
#define code_LocalVariableTable_type_RS all_bands[e_code_LocalVariableTable_type_RS]
|
||||
#define code_LocalVariableTable_slot all_bands[e_code_LocalVariableTable_slot]
|
||||
#define code_LocalVariableTypeTable_N all_bands[e_code_LocalVariableTypeTable_N]
|
||||
#define code_LocalVariableTypeTable_bci_P all_bands[e_code_LocalVariableTypeTable_bci_P]
|
||||
#define code_LocalVariableTypeTable_span_O all_bands[e_code_LocalVariableTypeTable_span_O]
|
||||
#define code_LocalVariableTypeTable_name_RU all_bands[e_code_LocalVariableTypeTable_name_RU]
|
||||
#define code_LocalVariableTypeTable_type_RS all_bands[e_code_LocalVariableTypeTable_type_RS]
|
||||
#define code_LocalVariableTypeTable_slot all_bands[e_code_LocalVariableTypeTable_slot]
|
||||
#define code_attr_bands all_bands[e_code_attr_bands]
|
||||
#define bc_codes all_bands[e_bc_codes]
|
||||
#define bc_case_count all_bands[e_bc_case_count]
|
||||
#define bc_case_value all_bands[e_bc_case_value]
|
||||
#define bc_byte all_bands[e_bc_byte]
|
||||
#define bc_short all_bands[e_bc_short]
|
||||
#define bc_local all_bands[e_bc_local]
|
||||
#define bc_label all_bands[e_bc_label]
|
||||
#define bc_intref all_bands[e_bc_intref]
|
||||
#define bc_floatref all_bands[e_bc_floatref]
|
||||
#define bc_longref all_bands[e_bc_longref]
|
||||
#define bc_doubleref all_bands[e_bc_doubleref]
|
||||
#define bc_stringref all_bands[e_bc_stringref]
|
||||
#define bc_classref all_bands[e_bc_classref]
|
||||
#define bc_fieldref all_bands[e_bc_fieldref]
|
||||
#define bc_methodref all_bands[e_bc_methodref]
|
||||
#define bc_imethodref all_bands[e_bc_imethodref]
|
||||
#define bc_thisfield all_bands[e_bc_thisfield]
|
||||
#define bc_superfield all_bands[e_bc_superfield]
|
||||
#define bc_thismethod all_bands[e_bc_thismethod]
|
||||
#define bc_supermethod all_bands[e_bc_supermethod]
|
||||
#define bc_initref all_bands[e_bc_initref]
|
||||
#define bc_escref all_bands[e_bc_escref]
|
||||
#define bc_escrefsize all_bands[e_bc_escrefsize]
|
||||
#define bc_escsize all_bands[e_bc_escsize]
|
||||
#define bc_escbyte all_bands[e_bc_escbyte]
|
||||
#define file_name all_bands[e_file_name]
|
||||
#define file_size_hi all_bands[e_file_size_hi]
|
||||
#define file_size_lo all_bands[e_file_size_lo]
|
||||
#define file_modtime all_bands[e_file_modtime]
|
||||
#define file_options all_bands[e_file_options]
|
217
depends/pack200/src/bytes.cpp
Normal file
217
depends/pack200/src/bytes.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
static byte dummy[1 << 10];
|
||||
|
||||
bool bytes::inBounds(const void *p)
|
||||
{
|
||||
return p >= ptr && p < limit();
|
||||
}
|
||||
|
||||
void bytes::malloc(size_t len_)
|
||||
{
|
||||
len = len_;
|
||||
ptr = NEW(byte, add_size(len_, 1)); // add trailing zero byte always
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
// set ptr to some victim memory, to ease escape
|
||||
set(dummy, sizeof(dummy) - 1);
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::realloc(size_t len_)
|
||||
{
|
||||
if (len == len_)
|
||||
return; // nothing to do
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
malloc(len_);
|
||||
return;
|
||||
}
|
||||
byte *oldptr = ptr;
|
||||
ptr = (len_ >= PSIZE_MAX) ? nullptr : (byte *)::realloc(ptr, add_size(len_, 1));
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
if (len < len_)
|
||||
memset(ptr + len, 0, len_ - len);
|
||||
ptr[len_] = 0;
|
||||
len = len_;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptr = oldptr; // ease our escape
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
}
|
||||
|
||||
void bytes::free()
|
||||
{
|
||||
if (ptr == dummy)
|
||||
return; // escaping from an error
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
::free(ptr);
|
||||
}
|
||||
len = 0;
|
||||
ptr = 0;
|
||||
}
|
||||
|
||||
int bytes::indexOf(byte c)
|
||||
{
|
||||
byte *p = (byte *)memchr(ptr, c, len);
|
||||
return (p == 0) ? -1 : (int)(p - ptr);
|
||||
}
|
||||
|
||||
byte *bytes::writeTo(byte *bp)
|
||||
{
|
||||
memcpy(bp, ptr, len);
|
||||
return bp + len;
|
||||
}
|
||||
|
||||
int bytes::compareTo(bytes &other)
|
||||
{
|
||||
size_t l1 = len;
|
||||
size_t l2 = other.len;
|
||||
int cmp = memcmp(ptr, other.ptr, (l1 < l2) ? l1 : l2);
|
||||
if (cmp != 0)
|
||||
return cmp;
|
||||
return (l1 < l2) ? -1 : (l1 > l2) ? 1 : 0;
|
||||
}
|
||||
|
||||
void bytes::saveFrom(const void *ptr_, size_t len_)
|
||||
{
|
||||
malloc(len_);
|
||||
// Save as much as possible. (Helps unpacker::abort.)
|
||||
if (len_ > len)
|
||||
{
|
||||
assert(ptr == dummy); // error recovery
|
||||
len_ = len;
|
||||
}
|
||||
copyFrom(ptr_, len_);
|
||||
}
|
||||
|
||||
//#TODO: Need to fix for exception handling
|
||||
void bytes::copyFrom(const void *ptr_, size_t len_, size_t offset)
|
||||
{
|
||||
assert(len_ == 0 || inBounds(ptr + offset));
|
||||
assert(len_ == 0 || inBounds(ptr + offset + len_ - 1));
|
||||
memcpy(ptr + offset, ptr_, len_);
|
||||
}
|
||||
|
||||
// Make sure there are 'o' bytes beyond the fill pointer,
|
||||
// advance the fill pointer, and return the old fill pointer.
|
||||
byte *fillbytes::grow(size_t s)
|
||||
{
|
||||
size_t nlen = add_size(b.len, s);
|
||||
if (nlen <= allocated)
|
||||
{
|
||||
b.len = nlen;
|
||||
return limit() - s;
|
||||
}
|
||||
size_t maxlen = nlen;
|
||||
if (maxlen < 128)
|
||||
maxlen = 128;
|
||||
if (maxlen < allocated * 2)
|
||||
maxlen = allocated * 2;
|
||||
if (allocated == 0)
|
||||
{
|
||||
// Initial buffer was not malloced. Do not reallocate it.
|
||||
bytes old = b;
|
||||
b.malloc(maxlen);
|
||||
if (b.len == maxlen)
|
||||
old.writeTo(b.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
b.realloc(maxlen);
|
||||
}
|
||||
allocated = b.len;
|
||||
if (allocated != maxlen)
|
||||
{
|
||||
assert(unpack_aborting());
|
||||
b.len = nlen - s; // back up
|
||||
return dummy; // scribble during error recov.
|
||||
}
|
||||
// after realloc, recompute pointers
|
||||
b.len = nlen;
|
||||
assert(b.len <= allocated);
|
||||
return limit() - s;
|
||||
}
|
||||
|
||||
void fillbytes::ensureSize(size_t s)
|
||||
{
|
||||
if (allocated >= s)
|
||||
return;
|
||||
size_t len0 = b.len;
|
||||
grow(s - size());
|
||||
b.len = len0; // put it back
|
||||
}
|
||||
|
||||
int ptrlist::indexOf(const void *x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ptrlist::freeAll()
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
void *p = (void *)get(i);
|
||||
if (p != nullptr)
|
||||
{
|
||||
::free(p);
|
||||
}
|
||||
}
|
||||
free();
|
||||
}
|
||||
|
||||
int intlist::indexOf(int x)
|
||||
{
|
||||
int len = length();
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
if (get(i) == x)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
284
depends/pack200/src/bytes.h
Normal file
284
depends/pack200/src/bytes.h
Normal file
@ -0,0 +1,284 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct bytes
|
||||
{
|
||||
int8_t *ptr;
|
||||
size_t len;
|
||||
int8_t *limit()
|
||||
{
|
||||
return ptr + len;
|
||||
}
|
||||
|
||||
void set(int8_t *ptr_, size_t len_)
|
||||
{
|
||||
ptr = ptr_;
|
||||
len = len_;
|
||||
}
|
||||
void set(const char *str)
|
||||
{
|
||||
ptr = (int8_t *)str;
|
||||
len = strlen(str);
|
||||
}
|
||||
bool inBounds(const void *p); // p in [ptr, limit)
|
||||
void malloc(size_t len_);
|
||||
void realloc(size_t len_);
|
||||
void free();
|
||||
void copyFrom(const void *ptr_, size_t len_, size_t offset = 0);
|
||||
void saveFrom(const void *ptr_, size_t len_);
|
||||
void saveFrom(const char *str)
|
||||
{
|
||||
saveFrom(str, strlen(str));
|
||||
}
|
||||
void copyFrom(bytes &other, size_t offset = 0)
|
||||
{
|
||||
copyFrom(other.ptr, other.len, offset);
|
||||
}
|
||||
void saveFrom(bytes &other)
|
||||
{
|
||||
saveFrom(other.ptr, other.len);
|
||||
}
|
||||
void clear(int fill_byte = 0)
|
||||
{
|
||||
memset(ptr, fill_byte, len);
|
||||
}
|
||||
int8_t *writeTo(int8_t *bp);
|
||||
bool equals(bytes &other)
|
||||
{
|
||||
return 0 == compareTo(other);
|
||||
}
|
||||
int compareTo(bytes &other);
|
||||
bool contains(int8_t c)
|
||||
{
|
||||
return indexOf(c) >= 0;
|
||||
}
|
||||
int indexOf(int8_t c);
|
||||
// substrings:
|
||||
static bytes of(int8_t *ptr, size_t len)
|
||||
{
|
||||
bytes res;
|
||||
res.set(ptr, len);
|
||||
return res;
|
||||
}
|
||||
bytes slice(size_t beg, size_t end)
|
||||
{
|
||||
bytes res;
|
||||
res.ptr = ptr + beg;
|
||||
res.len = end - beg;
|
||||
assert(res.len == 0 || inBounds(res.ptr) && inBounds(res.limit() - 1));
|
||||
return res;
|
||||
}
|
||||
// building C strings inside byte buffers:
|
||||
bytes &strcat(const char *str)
|
||||
{
|
||||
::strcat((char *)ptr, str);
|
||||
return *this;
|
||||
}
|
||||
bytes &strcat(bytes &other)
|
||||
{
|
||||
::strncat((char *)ptr, (char *)other.ptr, other.len);
|
||||
return *this;
|
||||
}
|
||||
char *strval()
|
||||
{
|
||||
assert(strlen((char *)ptr) == len);
|
||||
return (char *)ptr;
|
||||
}
|
||||
};
|
||||
#define BYTES_OF(var) (bytes::of((int8_t *)&(var), sizeof(var)))
|
||||
|
||||
struct fillbytes
|
||||
{
|
||||
bytes b;
|
||||
size_t allocated;
|
||||
|
||||
int8_t *base()
|
||||
{
|
||||
return b.ptr;
|
||||
}
|
||||
size_t size()
|
||||
{
|
||||
return b.len;
|
||||
}
|
||||
int8_t *limit()
|
||||
{
|
||||
return b.limit();
|
||||
} // logical limit
|
||||
void setLimit(int8_t *lp)
|
||||
{
|
||||
assert(isAllocated(lp));
|
||||
b.len = lp - b.ptr;
|
||||
}
|
||||
int8_t *end()
|
||||
{
|
||||
return b.ptr + allocated;
|
||||
} // physical limit
|
||||
int8_t *loc(size_t o)
|
||||
{
|
||||
assert(o < b.len);
|
||||
return b.ptr + o;
|
||||
}
|
||||
void init()
|
||||
{
|
||||
allocated = 0;
|
||||
b.set(nullptr, 0);
|
||||
}
|
||||
void init(size_t s)
|
||||
{
|
||||
init();
|
||||
ensureSize(s);
|
||||
}
|
||||
void free()
|
||||
{
|
||||
if (allocated != 0)
|
||||
b.free();
|
||||
allocated = 0;
|
||||
}
|
||||
void empty()
|
||||
{
|
||||
b.len = 0;
|
||||
}
|
||||
int8_t *grow(size_t s); // grow so that limit() += s
|
||||
int getByte(uint i)
|
||||
{
|
||||
return *loc(i) & 0xFF;
|
||||
}
|
||||
void addByte(int8_t x)
|
||||
{
|
||||
*grow(1) = x;
|
||||
}
|
||||
void ensureSize(size_t s); // make sure allocated >= s
|
||||
void trimToSize()
|
||||
{
|
||||
if (allocated > size())
|
||||
b.realloc(allocated = size());
|
||||
}
|
||||
bool canAppend(size_t s)
|
||||
{
|
||||
return allocated > b.len + s;
|
||||
}
|
||||
bool isAllocated(int8_t *p)
|
||||
{
|
||||
return p >= base() && p <= end();
|
||||
} // asserts
|
||||
void set(bytes &src)
|
||||
{
|
||||
set(src.ptr, src.len);
|
||||
}
|
||||
|
||||
void set(int8_t *ptr, size_t len)
|
||||
{
|
||||
b.set(ptr, len);
|
||||
allocated = 0; // mark as not reallocatable
|
||||
}
|
||||
|
||||
// block operations on resizing byte buffer:
|
||||
fillbytes &append(const void *ptr_, size_t len_)
|
||||
{
|
||||
memcpy(grow(len_), ptr_, len_);
|
||||
return (*this);
|
||||
}
|
||||
fillbytes &append(bytes &other)
|
||||
{
|
||||
return append(other.ptr, other.len);
|
||||
}
|
||||
fillbytes &append(const char *str)
|
||||
{
|
||||
return append(str, strlen(str));
|
||||
}
|
||||
};
|
||||
|
||||
struct ptrlist : fillbytes
|
||||
{
|
||||
typedef const void *cvptr;
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(cvptr));
|
||||
}
|
||||
cvptr *base()
|
||||
{
|
||||
return (cvptr *)fillbytes::base();
|
||||
}
|
||||
cvptr &get(int i)
|
||||
{
|
||||
return *(cvptr *)loc(i * sizeof(cvptr));
|
||||
}
|
||||
cvptr *limit()
|
||||
{
|
||||
return (cvptr *)fillbytes::limit();
|
||||
}
|
||||
void add(cvptr x)
|
||||
{
|
||||
*(cvptr *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(cvptr);
|
||||
}
|
||||
int indexOf(cvptr x);
|
||||
bool contains(cvptr x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
void freeAll(); // frees every ptr on the list, plus the list itself
|
||||
};
|
||||
// Use a macro rather than mess with subtle mismatches
|
||||
// between member and non-member function pointers.
|
||||
#define PTRLIST_QSORT(ptrls, fn) ::qsort((ptrls).base(), (ptrls).length(), sizeof(void *), fn)
|
||||
|
||||
struct intlist : fillbytes
|
||||
{
|
||||
int length()
|
||||
{
|
||||
return (int)(size() / sizeof(int));
|
||||
}
|
||||
int *base()
|
||||
{
|
||||
return (int *)fillbytes::base();
|
||||
}
|
||||
int &get(int i)
|
||||
{
|
||||
return *(int *)loc(i * sizeof(int));
|
||||
}
|
||||
int *limit()
|
||||
{
|
||||
return (int *)fillbytes::limit();
|
||||
}
|
||||
void add(int x)
|
||||
{
|
||||
*(int *)grow(sizeof(x)) = x;
|
||||
}
|
||||
void popTo(int l)
|
||||
{
|
||||
assert(l <= length());
|
||||
b.len = l * sizeof(int);
|
||||
}
|
||||
int indexOf(int x);
|
||||
bool contains(int x)
|
||||
{
|
||||
return indexOf(x) >= 0;
|
||||
}
|
||||
};
|
1049
depends/pack200/src/coding.cpp
Normal file
1049
depends/pack200/src/coding.cpp
Normal file
File diff suppressed because it is too large
Load Diff
270
depends/pack200/src/coding.h
Normal file
270
depends/pack200/src/coding.h
Normal file
@ -0,0 +1,270 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
struct unpacker;
|
||||
|
||||
#define INT_MAX_VALUE ((int)0x7FFFFFFF)
|
||||
#define INT_MIN_VALUE ((int)0x80000000)
|
||||
|
||||
#define CODING_SPEC(B, H, S, D) ((B) << 20 | (H) << 8 | (S) << 4 | (D) << 0)
|
||||
#define CODING_B(x) ((x) >> 20 & 0xF)
|
||||
#define CODING_H(x) ((x) >> 8 & 0xFFF)
|
||||
#define CODING_S(x) ((x) >> 4 & 0xF)
|
||||
#define CODING_D(x) ((x) >> 0 & 0xF)
|
||||
|
||||
#define CODING_INIT(B, H, S, D) \
|
||||
{ \
|
||||
CODING_SPEC(B, H, S, D), 0, 0, 0, 0, 0, 0, 0, 0 \
|
||||
}
|
||||
|
||||
// For debugging purposes, some compilers do not like this and will complain.
|
||||
// #define long do_not_use_C_long_types_use_jlong_or_int
|
||||
// Use of the type "long" is problematic, do not use it.
|
||||
|
||||
struct coding
|
||||
{
|
||||
int spec; // B,H,S,D
|
||||
|
||||
// Handy values derived from the spec:
|
||||
int B()
|
||||
{
|
||||
return CODING_B(spec);
|
||||
}
|
||||
int H()
|
||||
{
|
||||
return CODING_H(spec);
|
||||
}
|
||||
int S()
|
||||
{
|
||||
return CODING_S(spec);
|
||||
}
|
||||
int D()
|
||||
{
|
||||
return CODING_D(spec);
|
||||
}
|
||||
int L()
|
||||
{
|
||||
return 256 - CODING_H(spec);
|
||||
}
|
||||
int min, max;
|
||||
int umin, umax;
|
||||
char isSigned, isSubrange, isFullRange, isMalloc;
|
||||
|
||||
coding *init(); // returns self or nullptr if error
|
||||
coding *initFrom(int spec_)
|
||||
{
|
||||
assert(this->spec == 0);
|
||||
this->spec = spec_;
|
||||
return init();
|
||||
}
|
||||
|
||||
static coding *findBySpec(int spec);
|
||||
static coding *findBySpec(int B, int H, int S = 0, int D = 0);
|
||||
static coding *findByIndex(int irregularCodingIndex);
|
||||
|
||||
static uint parse(byte *&rp, int B, int H);
|
||||
static uint parse_lgH(byte *&rp, int B, int H, int lgH);
|
||||
static void parseMultiple(byte *&rp, int N, byte *limit, int B, int H);
|
||||
|
||||
uint parse(byte *&rp)
|
||||
{
|
||||
return parse(rp, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
void parseMultiple(byte *&rp, int N, byte *limit)
|
||||
{
|
||||
parseMultiple(rp, N, limit, CODING_B(spec), CODING_H(spec));
|
||||
}
|
||||
|
||||
bool canRepresent(int x)
|
||||
{
|
||||
return (x >= min && x <= max);
|
||||
}
|
||||
bool canRepresentUnsigned(int x)
|
||||
{
|
||||
return (x >= umin && x <= umax);
|
||||
}
|
||||
|
||||
int sumInUnsignedRange(int x, int y);
|
||||
|
||||
int readFrom(byte *&rpVar, int *dbase);
|
||||
void readArrayFrom(byte *&rpVar, int *dbase, int length, int *values);
|
||||
void skipArrayFrom(byte *&rpVar, int length)
|
||||
{
|
||||
readArrayFrom(rpVar, (int *)NULL, length, (int *)NULL);
|
||||
}
|
||||
|
||||
void free(); // free self if isMalloc
|
||||
|
||||
// error handling
|
||||
static void abort(const char *msg = nullptr)
|
||||
{
|
||||
unpack_abort(msg);
|
||||
}
|
||||
};
|
||||
|
||||
enum coding_method_kind
|
||||
{
|
||||
cmk_ERROR,
|
||||
cmk_BHS,
|
||||
cmk_BHS0,
|
||||
cmk_BHS1,
|
||||
cmk_BHSD1,
|
||||
cmk_BHS1D1full, // isFullRange
|
||||
cmk_BHS1D1sub, // isSubRange
|
||||
|
||||
// special cases hand-optimized (~50% of all decoded values)
|
||||
cmk_BYTE1, //(1,256) 6%
|
||||
cmk_CHAR3, //(3,128) 7%
|
||||
cmk_UNSIGNED5, //(5,64) 13%
|
||||
cmk_DELTA5, //(5,64,1,1) 5%
|
||||
cmk_BCI5, //(5,4) 18%
|
||||
cmk_BRANCH5, //(5,4,2) 4%
|
||||
// cmk_UNSIGNED5H16, //(5,16) 5%
|
||||
// cmk_UNSIGNED2H4, //(2,4) 6%
|
||||
// cmk_DELTA4H8, //(4,8,1,1) 10%
|
||||
// cmk_DELTA3H16, //(3,16,1,1) 9%
|
||||
cmk_BHS_LIMIT,
|
||||
cmk_pop,
|
||||
cmk_pop_BHS0,
|
||||
cmk_pop_BYTE1,
|
||||
cmk_pop_LIMIT,
|
||||
cmk_LIMIT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BYTE1_spec = CODING_SPEC(1, 256, 0, 0),
|
||||
CHAR3_spec = CODING_SPEC(3, 128, 0, 0),
|
||||
UNSIGNED4_spec = CODING_SPEC(4, 256, 0, 0),
|
||||
UNSIGNED5_spec = CODING_SPEC(5, 64, 0, 0),
|
||||
SIGNED5_spec = CODING_SPEC(5, 64, 1, 0),
|
||||
DELTA5_spec = CODING_SPEC(5, 64, 1, 1),
|
||||
UDELTA5_spec = CODING_SPEC(5, 64, 0, 1),
|
||||
MDELTA5_spec = CODING_SPEC(5, 64, 2, 1),
|
||||
BCI5_spec = CODING_SPEC(5, 4, 0, 0),
|
||||
BRANCH5_spec = CODING_SPEC(5, 4, 2, 0)
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
B_MAX = 5,
|
||||
C_SLOP = B_MAX * 10
|
||||
};
|
||||
|
||||
struct coding_method;
|
||||
|
||||
// iterator under the control of a meta-coding
|
||||
struct value_stream
|
||||
{
|
||||
// current coding of values or values
|
||||
coding c; // B,H,S,D,etc.
|
||||
coding_method_kind cmk; // type of decoding needed
|
||||
byte *rp; // read pointer
|
||||
byte *rplimit; // final value of read pointer
|
||||
int sum; // partial sum of all values so far (D=1 only)
|
||||
coding_method *cm; // coding method that defines this stream
|
||||
|
||||
void init(byte *band_rp, byte *band_limit, coding *defc);
|
||||
void init(byte *band_rp, byte *band_limit, int spec)
|
||||
{
|
||||
init(band_rp, band_limit, coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
void setCoding(coding *c);
|
||||
void setCoding(int spec)
|
||||
{
|
||||
setCoding(coding::findBySpec(spec));
|
||||
}
|
||||
|
||||
// Parse and decode a single value.
|
||||
int getInt();
|
||||
|
||||
// Parse and decode a single byte, with no error checks.
|
||||
int getByte()
|
||||
{
|
||||
assert(cmk == cmk_BYTE1);
|
||||
assert(rp < rplimit);
|
||||
return *rp++ & 0xFF;
|
||||
}
|
||||
|
||||
// Used only for asserts.
|
||||
bool hasValue();
|
||||
|
||||
void done()
|
||||
{
|
||||
assert(!hasValue());
|
||||
}
|
||||
|
||||
// Sometimes a value stream has an auxiliary (but there are never two).
|
||||
value_stream *helper()
|
||||
{
|
||||
assert(hasHelper());
|
||||
return this + 1;
|
||||
}
|
||||
bool hasHelper();
|
||||
|
||||
// error handling
|
||||
// inline void abort(const char* msg);
|
||||
// inline void aborting();
|
||||
};
|
||||
|
||||
struct coding_method
|
||||
{
|
||||
value_stream vs0; // initial state snapshot (vs.meta==this)
|
||||
|
||||
coding_method *next; // what to do when we run out of bytes
|
||||
|
||||
// these fields are used for pop codes only:
|
||||
int *fValues; // favored value array
|
||||
int fVlength; // maximum favored value token
|
||||
coding_method *uValues; // unfavored value stream
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Initialize a value stream.
|
||||
void reset(value_stream *state);
|
||||
|
||||
// Parse a band header, size a band, and initialize for further action.
|
||||
// band_rp advances (but not past band_limit), and meta_rp advances.
|
||||
// The mode gives context, such as "inside a pop".
|
||||
// The defc and N are the incoming parameters to a meta-coding.
|
||||
// The value sink is used to collect output values, when desired.
|
||||
void init(byte *&band_rp, byte *band_limit, byte *&meta_rp, int mode, coding *defc, int N,
|
||||
intlist *valueSink);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
||||
|
||||
// inline void value_stream::abort(const char* msg) { cm->abort(msg); }
|
||||
// inline void value_stream::aborting() { cm->aborting(); }
|
442
depends/pack200/src/constants.h
Normal file
442
depends/pack200/src/constants.h
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
Java Class Version numbers history
|
||||
1.0 to 1.3.X 45,3
|
||||
1.4 to 1.4.X 46,0
|
||||
1.5 to 1.5.X 49,0
|
||||
1.6 to 1.5.x 50,0 NOTE Assumed for now
|
||||
*/
|
||||
|
||||
// classfile constants
|
||||
#define JAVA_MAGIC 0xCAFEBABE
|
||||
#define JAVA_MIN_MAJOR_VERSION 45
|
||||
#define JAVA_MIN_MINOR_VERSION 3
|
||||
#define JAVA5_MAX_MAJOR_VERSION 49
|
||||
#define JAVA5_MAX_MINOR_VERSION 0
|
||||
// NOTE: Assume for now
|
||||
#define JAVA6_MAX_MAJOR_VERSION 50
|
||||
#define JAVA6_MAX_MINOR_VERSION 0
|
||||
|
||||
// package file constants
|
||||
#define JAVA_PACKAGE_MAGIC 0xCAFED00D
|
||||
#define JAVA5_PACKAGE_MAJOR_VERSION 150
|
||||
#define JAVA5_PACKAGE_MINOR_VERSION 7
|
||||
|
||||
#define JAVA6_PACKAGE_MAJOR_VERSION 160
|
||||
#define JAVA6_PACKAGE_MINOR_VERSION 1
|
||||
|
||||
// magic number for gzip streams (for processing pack200-gzip data)
|
||||
#define GZIP_MAGIC 0x1F8B0800
|
||||
#define GZIP_MAGIC_MASK 0xFFFFFF00 // last byte is variable "flg" field
|
||||
|
||||
enum
|
||||
{
|
||||
CONSTANT_None,
|
||||
CONSTANT_Utf8,
|
||||
CONSTANT_unused2, /* unused, was Unicode */
|
||||
CONSTANT_Integer,
|
||||
CONSTANT_Float,
|
||||
CONSTANT_Long,
|
||||
CONSTANT_Double,
|
||||
CONSTANT_Class,
|
||||
CONSTANT_String,
|
||||
CONSTANT_Fieldref,
|
||||
CONSTANT_Methodref,
|
||||
CONSTANT_InterfaceMethodref,
|
||||
CONSTANT_NameandType,
|
||||
CONSTANT_Signature = 13,
|
||||
CONSTANT_All = 14,
|
||||
CONSTANT_Limit = 15,
|
||||
CONSTANT_NONE = 0,
|
||||
CONSTANT_Literal = 20, // pseudo-tag for debugging
|
||||
CONSTANT_Member = 21, // pseudo-tag for debugging
|
||||
SUBINDEX_BIT = 64, // combined with CONSTANT_xxx for ixTag
|
||||
ACC_STATIC = 0x0008,
|
||||
ACC_IC_LONG_FORM = (1 << 16), // for ic_flags
|
||||
CLASS_ATTR_SourceFile = 17,
|
||||
CLASS_ATTR_EnclosingMethod = 18,
|
||||
CLASS_ATTR_InnerClasses = 23,
|
||||
CLASS_ATTR_ClassFile_version = 24,
|
||||
FIELD_ATTR_ConstantValue = 17,
|
||||
METHOD_ATTR_Code = 17,
|
||||
METHOD_ATTR_Exceptions = 18,
|
||||
METHOD_ATTR_RuntimeVisibleParameterAnnotations = 23,
|
||||
METHOD_ATTR_RuntimeInvisibleParameterAnnotations = 24,
|
||||
METHOD_ATTR_AnnotationDefault = 25,
|
||||
CODE_ATTR_StackMapTable = 0,
|
||||
CODE_ATTR_LineNumberTable = 1,
|
||||
CODE_ATTR_LocalVariableTable = 2,
|
||||
CODE_ATTR_LocalVariableTypeTable = 3,
|
||||
// X_ATTR_Synthetic = 12, // ACC_SYNTHETIC; not predefined
|
||||
X_ATTR_Signature = 19,
|
||||
X_ATTR_Deprecated = 20,
|
||||
X_ATTR_RuntimeVisibleAnnotations = 21,
|
||||
X_ATTR_RuntimeInvisibleAnnotations = 22,
|
||||
X_ATTR_OVERFLOW = 16,
|
||||
X_ATTR_LIMIT_NO_FLAGS_HI = 32,
|
||||
X_ATTR_LIMIT_FLAGS_HI = 63,
|
||||
|
||||
#define O_ATTR_DO(F) \
|
||||
F(X_ATTR_OVERFLOW, 01) \
|
||||
/*(end)*/
|
||||
#define X_ATTR_DO(F) \
|
||||
O_ATTR_DO(F) F(X_ATTR_Signature, Signature) F(X_ATTR_Deprecated, Deprecated) \
|
||||
F(X_ATTR_RuntimeVisibleAnnotations, RuntimeVisibleAnnotations) \
|
||||
F(X_ATTR_RuntimeInvisibleAnnotations, RuntimeInvisibleAnnotations) \
|
||||
/*F(X_ATTR_Synthetic,Synthetic)*/ \
|
||||
/*(end)*/
|
||||
#define CLASS_ATTR_DO(F) \
|
||||
F(CLASS_ATTR_SourceFile, SourceFile) F(CLASS_ATTR_InnerClasses, InnerClasses) \
|
||||
F(CLASS_ATTR_EnclosingMethod, EnclosingMethod) F(CLASS_ATTR_ClassFile_version, 02) \
|
||||
/*(end)*/
|
||||
#define FIELD_ATTR_DO(F) \
|
||||
F(FIELD_ATTR_ConstantValue, ConstantValue) \
|
||||
/*(end)*/
|
||||
#define METHOD_ATTR_DO(F) \
|
||||
F(METHOD_ATTR_Code, Code) F(METHOD_ATTR_Exceptions, Exceptions) \
|
||||
F(METHOD_ATTR_RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_RuntimeInvisibleParameterAnnotations, \
|
||||
RuntimeInvisibleParameterAnnotations) \
|
||||
F(METHOD_ATTR_AnnotationDefault, AnnotationDefault) \
|
||||
/*(end)*/
|
||||
#define CODE_ATTR_DO(F) \
|
||||
F(CODE_ATTR_StackMapTable, StackMapTable) F(CODE_ATTR_LineNumberTable, LineNumberTable) \
|
||||
F(CODE_ATTR_LocalVariableTable, LocalVariableTable) \
|
||||
F(CODE_ATTR_LocalVariableTypeTable, LocalVariableTypeTable) \
|
||||
/*(end)*/
|
||||
#define ALL_ATTR_DO(F) \
|
||||
X_ATTR_DO(F) CLASS_ATTR_DO(F) FIELD_ATTR_DO(F) METHOD_ATTR_DO(F) CODE_ATTR_DO(F) \
|
||||
/*(end)*/
|
||||
|
||||
// attribute "context types"
|
||||
ATTR_CONTEXT_CLASS = 0,
|
||||
ATTR_CONTEXT_FIELD = 1,
|
||||
ATTR_CONTEXT_METHOD = 2,
|
||||
ATTR_CONTEXT_CODE = 3,
|
||||
ATTR_CONTEXT_LIMIT = 4,
|
||||
|
||||
// constants for parsed layouts (stored in band::le_kind)
|
||||
EK_NONE = 0, // not a layout element
|
||||
EK_INT = 'I', // B H I SH etc., also FH etc.
|
||||
EK_BCI = 'P', // PH etc.
|
||||
EK_BCID = 'Q', // POH etc.
|
||||
EK_BCO = 'O', // OH etc.
|
||||
EK_REPL = 'N', // NH[...] etc.
|
||||
EK_REF = 'R', // RUH, RUNH, KQH, etc.
|
||||
EK_UN = 'T', // TB(...)[...] etc.
|
||||
EK_CASE = 'K', // (...)[...] etc.
|
||||
EK_CALL = '(', // (0), (1), etc.
|
||||
EK_CBLE = '[', // [...][...] etc.
|
||||
NO_BAND_INDEX = -1,
|
||||
|
||||
// File option bits, from LSB in ascending bit position.
|
||||
FO_DEFLATE_HINT = 1 << 0,
|
||||
FO_IS_CLASS_STUB = 1 << 1,
|
||||
|
||||
// Archive option bits, from LSB in ascending bit position:
|
||||
AO_HAVE_SPECIAL_FORMATS = 1 << 0,
|
||||
AO_HAVE_CP_NUMBERS = 1 << 1,
|
||||
AO_HAVE_ALL_CODE_FLAGS = 1 << 2,
|
||||
AO_3_UNUSED_MBZ = 1 << 3,
|
||||
AO_HAVE_FILE_HEADERS = 1 << 4,
|
||||
AO_DEFLATE_HINT = 1 << 5,
|
||||
AO_HAVE_FILE_MODTIME = 1 << 6,
|
||||
AO_HAVE_FILE_OPTIONS = 1 << 7,
|
||||
AO_HAVE_FILE_SIZE_HI = 1 << 8,
|
||||
AO_HAVE_CLASS_FLAGS_HI = 1 << 9,
|
||||
AO_HAVE_FIELD_FLAGS_HI = 1 << 10,
|
||||
AO_HAVE_METHOD_FLAGS_HI = 1 << 11,
|
||||
AO_HAVE_CODE_FLAGS_HI = 1 << 12,
|
||||
#define ARCHIVE_BIT_DO(F) \
|
||||
F(AO_HAVE_SPECIAL_FORMATS) F(AO_HAVE_CP_NUMBERS) F(AO_HAVE_ALL_CODE_FLAGS) \
|
||||
/*F(AO_3_UNUSED_MBZ)*/ \
|
||||
F(AO_HAVE_FILE_HEADERS) F(AO_DEFLATE_HINT) F(AO_HAVE_FILE_MODTIME) \
|
||||
F(AO_HAVE_FILE_OPTIONS) F(AO_HAVE_FILE_SIZE_HI) F(AO_HAVE_CLASS_FLAGS_HI) \
|
||||
F(AO_HAVE_FIELD_FLAGS_HI) F(AO_HAVE_METHOD_FLAGS_HI) F(AO_HAVE_CODE_FLAGS_HI) \
|
||||
/*(end)*/
|
||||
|
||||
// Constants for decoding attribute definition header bytes.
|
||||
ADH_CONTEXT_MASK = 0x3, // (hdr & ADH_CONTEXT_MASK)
|
||||
ADH_BIT_SHIFT = 0x2, // (hdr >> ADH_BIT_SHIFT)
|
||||
ADH_BIT_IS_LSB = 1, // (hdr >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB
|
||||
#define ADH_BYTE(context, index) ((((index) + ADH_BIT_IS_LSB) << ADH_BIT_SHIFT) + (context))
|
||||
#define ADH_BYTE_CONTEXT(adhb) ((adhb) & ADH_CONTEXT_MASK)
|
||||
#define ADH_BYTE_INDEX(adhb) (((adhb) >> ADH_BIT_SHIFT) - ADH_BIT_IS_LSB)
|
||||
NO_MODTIME = 0, // nullptr modtime value
|
||||
|
||||
// meta-coding
|
||||
_meta_default = 0,
|
||||
_meta_canon_min = 1,
|
||||
_meta_canon_max = 115,
|
||||
_meta_arb = 116,
|
||||
_meta_run = 117,
|
||||
_meta_pop = 141,
|
||||
_meta_limit = 189,
|
||||
_meta_error = 255,
|
||||
_xxx_1_end
|
||||
};
|
||||
|
||||
// Bytecodes.
|
||||
|
||||
enum
|
||||
{
|
||||
bc_nop = 0, // 0x00
|
||||
bc_aconst_null = 1, // 0x01
|
||||
bc_iconst_m1 = 2, // 0x02
|
||||
bc_iconst_0 = 3, // 0x03
|
||||
bc_iconst_1 = 4, // 0x04
|
||||
bc_iconst_2 = 5, // 0x05
|
||||
bc_iconst_3 = 6, // 0x06
|
||||
bc_iconst_4 = 7, // 0x07
|
||||
bc_iconst_5 = 8, // 0x08
|
||||
bc_lconst_0 = 9, // 0x09
|
||||
bc_lconst_1 = 10, // 0x0a
|
||||
bc_fconst_0 = 11, // 0x0b
|
||||
bc_fconst_1 = 12, // 0x0c
|
||||
bc_fconst_2 = 13, // 0x0d
|
||||
bc_dconst_0 = 14, // 0x0e
|
||||
bc_dconst_1 = 15, // 0x0f
|
||||
bc_bipush = 16, // 0x10
|
||||
bc_sipush = 17, // 0x11
|
||||
bc_ldc = 18, // 0x12
|
||||
bc_ldc_w = 19, // 0x13
|
||||
bc_ldc2_w = 20, // 0x14
|
||||
bc_iload = 21, // 0x15
|
||||
bc_lload = 22, // 0x16
|
||||
bc_fload = 23, // 0x17
|
||||
bc_dload = 24, // 0x18
|
||||
bc_aload = 25, // 0x19
|
||||
bc_iload_0 = 26, // 0x1a
|
||||
bc_iload_1 = 27, // 0x1b
|
||||
bc_iload_2 = 28, // 0x1c
|
||||
bc_iload_3 = 29, // 0x1d
|
||||
bc_lload_0 = 30, // 0x1e
|
||||
bc_lload_1 = 31, // 0x1f
|
||||
bc_lload_2 = 32, // 0x20
|
||||
bc_lload_3 = 33, // 0x21
|
||||
bc_fload_0 = 34, // 0x22
|
||||
bc_fload_1 = 35, // 0x23
|
||||
bc_fload_2 = 36, // 0x24
|
||||
bc_fload_3 = 37, // 0x25
|
||||
bc_dload_0 = 38, // 0x26
|
||||
bc_dload_1 = 39, // 0x27
|
||||
bc_dload_2 = 40, // 0x28
|
||||
bc_dload_3 = 41, // 0x29
|
||||
bc_aload_0 = 42, // 0x2a
|
||||
bc_aload_1 = 43, // 0x2b
|
||||
bc_aload_2 = 44, // 0x2c
|
||||
bc_aload_3 = 45, // 0x2d
|
||||
bc_iaload = 46, // 0x2e
|
||||
bc_laload = 47, // 0x2f
|
||||
bc_faload = 48, // 0x30
|
||||
bc_daload = 49, // 0x31
|
||||
bc_aaload = 50, // 0x32
|
||||
bc_baload = 51, // 0x33
|
||||
bc_caload = 52, // 0x34
|
||||
bc_saload = 53, // 0x35
|
||||
bc_istore = 54, // 0x36
|
||||
bc_lstore = 55, // 0x37
|
||||
bc_fstore = 56, // 0x38
|
||||
bc_dstore = 57, // 0x39
|
||||
bc_astore = 58, // 0x3a
|
||||
bc_istore_0 = 59, // 0x3b
|
||||
bc_istore_1 = 60, // 0x3c
|
||||
bc_istore_2 = 61, // 0x3d
|
||||
bc_istore_3 = 62, // 0x3e
|
||||
bc_lstore_0 = 63, // 0x3f
|
||||
bc_lstore_1 = 64, // 0x40
|
||||
bc_lstore_2 = 65, // 0x41
|
||||
bc_lstore_3 = 66, // 0x42
|
||||
bc_fstore_0 = 67, // 0x43
|
||||
bc_fstore_1 = 68, // 0x44
|
||||
bc_fstore_2 = 69, // 0x45
|
||||
bc_fstore_3 = 70, // 0x46
|
||||
bc_dstore_0 = 71, // 0x47
|
||||
bc_dstore_1 = 72, // 0x48
|
||||
bc_dstore_2 = 73, // 0x49
|
||||
bc_dstore_3 = 74, // 0x4a
|
||||
bc_astore_0 = 75, // 0x4b
|
||||
bc_astore_1 = 76, // 0x4c
|
||||
bc_astore_2 = 77, // 0x4d
|
||||
bc_astore_3 = 78, // 0x4e
|
||||
bc_iastore = 79, // 0x4f
|
||||
bc_lastore = 80, // 0x50
|
||||
bc_fastore = 81, // 0x51
|
||||
bc_dastore = 82, // 0x52
|
||||
bc_aastore = 83, // 0x53
|
||||
bc_bastore = 84, // 0x54
|
||||
bc_castore = 85, // 0x55
|
||||
bc_sastore = 86, // 0x56
|
||||
bc_pop = 87, // 0x57
|
||||
bc_pop2 = 88, // 0x58
|
||||
bc_dup = 89, // 0x59
|
||||
bc_dup_x1 = 90, // 0x5a
|
||||
bc_dup_x2 = 91, // 0x5b
|
||||
bc_dup2 = 92, // 0x5c
|
||||
bc_dup2_x1 = 93, // 0x5d
|
||||
bc_dup2_x2 = 94, // 0x5e
|
||||
bc_swap = 95, // 0x5f
|
||||
bc_iadd = 96, // 0x60
|
||||
bc_ladd = 97, // 0x61
|
||||
bc_fadd = 98, // 0x62
|
||||
bc_dadd = 99, // 0x63
|
||||
bc_isub = 100, // 0x64
|
||||
bc_lsub = 101, // 0x65
|
||||
bc_fsub = 102, // 0x66
|
||||
bc_dsub = 103, // 0x67
|
||||
bc_imul = 104, // 0x68
|
||||
bc_lmul = 105, // 0x69
|
||||
bc_fmul = 106, // 0x6a
|
||||
bc_dmul = 107, // 0x6b
|
||||
bc_idiv = 108, // 0x6c
|
||||
bc_ldiv = 109, // 0x6d
|
||||
bc_fdiv = 110, // 0x6e
|
||||
bc_ddiv = 111, // 0x6f
|
||||
bc_irem = 112, // 0x70
|
||||
bc_lrem = 113, // 0x71
|
||||
bc_frem = 114, // 0x72
|
||||
bc_drem = 115, // 0x73
|
||||
bc_ineg = 116, // 0x74
|
||||
bc_lneg = 117, // 0x75
|
||||
bc_fneg = 118, // 0x76
|
||||
bc_dneg = 119, // 0x77
|
||||
bc_ishl = 120, // 0x78
|
||||
bc_lshl = 121, // 0x79
|
||||
bc_ishr = 122, // 0x7a
|
||||
bc_lshr = 123, // 0x7b
|
||||
bc_iushr = 124, // 0x7c
|
||||
bc_lushr = 125, // 0x7d
|
||||
bc_iand = 126, // 0x7e
|
||||
bc_land = 127, // 0x7f
|
||||
bc_ior = 128, // 0x80
|
||||
bc_lor = 129, // 0x81
|
||||
bc_ixor = 130, // 0x82
|
||||
bc_lxor = 131, // 0x83
|
||||
bc_iinc = 132, // 0x84
|
||||
bc_i2l = 133, // 0x85
|
||||
bc_i2f = 134, // 0x86
|
||||
bc_i2d = 135, // 0x87
|
||||
bc_l2i = 136, // 0x88
|
||||
bc_l2f = 137, // 0x89
|
||||
bc_l2d = 138, // 0x8a
|
||||
bc_f2i = 139, // 0x8b
|
||||
bc_f2l = 140, // 0x8c
|
||||
bc_f2d = 141, // 0x8d
|
||||
bc_d2i = 142, // 0x8e
|
||||
bc_d2l = 143, // 0x8f
|
||||
bc_d2f = 144, // 0x90
|
||||
bc_i2b = 145, // 0x91
|
||||
bc_i2c = 146, // 0x92
|
||||
bc_i2s = 147, // 0x93
|
||||
bc_lcmp = 148, // 0x94
|
||||
bc_fcmpl = 149, // 0x95
|
||||
bc_fcmpg = 150, // 0x96
|
||||
bc_dcmpl = 151, // 0x97
|
||||
bc_dcmpg = 152, // 0x98
|
||||
bc_ifeq = 153, // 0x99
|
||||
bc_ifne = 154, // 0x9a
|
||||
bc_iflt = 155, // 0x9b
|
||||
bc_ifge = 156, // 0x9c
|
||||
bc_ifgt = 157, // 0x9d
|
||||
bc_ifle = 158, // 0x9e
|
||||
bc_if_icmpeq = 159, // 0x9f
|
||||
bc_if_icmpne = 160, // 0xa0
|
||||
bc_if_icmplt = 161, // 0xa1
|
||||
bc_if_icmpge = 162, // 0xa2
|
||||
bc_if_icmpgt = 163, // 0xa3
|
||||
bc_if_icmple = 164, // 0xa4
|
||||
bc_if_acmpeq = 165, // 0xa5
|
||||
bc_if_acmpne = 166, // 0xa6
|
||||
bc_goto = 167, // 0xa7
|
||||
bc_jsr = 168, // 0xa8
|
||||
bc_ret = 169, // 0xa9
|
||||
bc_tableswitch = 170, // 0xaa
|
||||
bc_lookupswitch = 171, // 0xab
|
||||
bc_ireturn = 172, // 0xac
|
||||
bc_lreturn = 173, // 0xad
|
||||
bc_freturn = 174, // 0xae
|
||||
bc_dreturn = 175, // 0xaf
|
||||
bc_areturn = 176, // 0xb0
|
||||
bc_return = 177, // 0xb1
|
||||
bc_getstatic = 178, // 0xb2
|
||||
bc_putstatic = 179, // 0xb3
|
||||
bc_getfield = 180, // 0xb4
|
||||
bc_putfield = 181, // 0xb5
|
||||
bc_invokevirtual = 182, // 0xb6
|
||||
bc_invokespecial = 183, // 0xb7
|
||||
bc_invokestatic = 184, // 0xb8
|
||||
bc_invokeinterface = 185, // 0xb9
|
||||
bc_xxxunusedxxx = 186, // 0xba
|
||||
bc_new = 187, // 0xbb
|
||||
bc_newarray = 188, // 0xbc
|
||||
bc_anewarray = 189, // 0xbd
|
||||
bc_arraylength = 190, // 0xbe
|
||||
bc_athrow = 191, // 0xbf
|
||||
bc_checkcast = 192, // 0xc0
|
||||
bc_instanceof = 193, // 0xc1
|
||||
bc_monitorenter = 194, // 0xc2
|
||||
bc_monitorexit = 195, // 0xc3
|
||||
bc_wide = 196, // 0xc4
|
||||
bc_multianewarray = 197, // 0xc5
|
||||
bc_ifnull = 198, // 0xc6
|
||||
bc_ifnonnull = 199, // 0xc7
|
||||
bc_goto_w = 200, // 0xc8
|
||||
bc_jsr_w = 201, // 0xc9
|
||||
bc_bytecode_limit = 202 // 0xca
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
bc_end_marker = 255,
|
||||
bc_byte_escape = 254,
|
||||
bc_ref_escape = 253,
|
||||
_first_linker_op = bc_getstatic,
|
||||
_last_linker_op = bc_invokestatic,
|
||||
_num_linker_ops = (_last_linker_op - _first_linker_op) + 1,
|
||||
_self_linker_op = bc_bytecode_limit,
|
||||
_self_linker_aload_flag = 1 * _num_linker_ops,
|
||||
_self_linker_super_flag = 2 * _num_linker_ops,
|
||||
_self_linker_limit = _self_linker_op + 4 * _num_linker_ops,
|
||||
_invokeinit_op = _self_linker_limit,
|
||||
_invokeinit_self_option = 0,
|
||||
_invokeinit_super_option = 1,
|
||||
_invokeinit_new_option = 2,
|
||||
_invokeinit_limit = _invokeinit_op + 3,
|
||||
_xldc_op = _invokeinit_limit,
|
||||
bc_aldc = bc_ldc,
|
||||
bc_cldc = _xldc_op + 0,
|
||||
bc_ildc = _xldc_op + 1,
|
||||
bc_fldc = _xldc_op + 2,
|
||||
bc_aldc_w = bc_ldc_w,
|
||||
bc_cldc_w = _xldc_op + 3,
|
||||
bc_ildc_w = _xldc_op + 4,
|
||||
bc_fldc_w = _xldc_op + 5,
|
||||
bc_lldc2_w = bc_ldc2_w,
|
||||
bc_dldc2_w = _xldc_op + 6,
|
||||
_xldc_limit = _xldc_op + 7,
|
||||
_xxx_3_end
|
||||
};
|
136
depends/pack200/src/defines.h
Normal file
136
depends/pack200/src/defines.h
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2009, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// random definitions
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#include <winuser.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifndef FULL
|
||||
#define FULL 1 /* Adds <500 bytes to the zipped final product. */
|
||||
#endif
|
||||
|
||||
#if FULL // define this if you want debugging and/or compile-time attributes
|
||||
#define IF_FULL(x) x
|
||||
#else
|
||||
#define IF_FULL(x) /*x*/
|
||||
#endif
|
||||
|
||||
// Error messages that we have
|
||||
#define ERROR_ENOMEM "Native allocation failed"
|
||||
#define ERROR_FORMAT "Corrupted pack file"
|
||||
#define ERROR_RESOURCE "Cannot extract resource file"
|
||||
#define ERROR_OVERFLOW "Internal buffer overflow"
|
||||
#define ERROR_INTERNAL "Internal error"
|
||||
|
||||
#define LOGFILE_STDOUT "-"
|
||||
#define LOGFILE_STDERR ""
|
||||
|
||||
#define lengthof(array) (sizeof(array) / sizeof(array[0]))
|
||||
|
||||
#define NEW(T, n) (T *) must_malloc((int)(scale_size(n, sizeof(T))))
|
||||
#define U_NEW(T, n) (T *) u->alloc(scale_size(n, sizeof(T)))
|
||||
#define T_NEW(T, n) (T *) u->temp_alloc(scale_size(n, sizeof(T)))
|
||||
|
||||
// bytes and byte arrays
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef LONGLONG jlong;
|
||||
typedef DWORDLONG julong;
|
||||
#define MKDIR(dir) mkdir(dir)
|
||||
#define getpid() _getpid()
|
||||
#define PATH_MAX MAX_PATH
|
||||
#define dup2(a, b) _dup2(a, b)
|
||||
#define strcasecmp(s1, s2) _stricmp(s1, s2)
|
||||
#define tempname _tempname
|
||||
#define sleep Sleep
|
||||
#else
|
||||
typedef signed char byte;
|
||||
#ifdef _LP64
|
||||
typedef long jlong;
|
||||
typedef long unsigned julong;
|
||||
#else
|
||||
typedef long long jlong;
|
||||
typedef long long unsigned julong;
|
||||
#endif
|
||||
#define MKDIR(dir) mkdir(dir, 0777);
|
||||
#endif
|
||||
|
||||
/* Must cast to void *, then size_t, then int. */
|
||||
#define ptrlowbits(x) ((int)(size_t)(void *)(x))
|
||||
|
||||
/* Back and forth from jlong to pointer */
|
||||
#define ptr2jlong(x) ((jlong)(size_t)(void *)(x))
|
||||
#define jlong2ptr(x) ((void *)(size_t)(x))
|
||||
|
||||
// Keys used by Java:
|
||||
#define UNPACK_DEFLATE_HINT "unpack.deflate.hint"
|
||||
|
||||
#define COM_PREFIX "com.sun.java.util.jar.pack."
|
||||
#define UNPACK_MODIFICATION_TIME COM_PREFIX "unpack.modification.time"
|
||||
#define DEBUG_VERBOSE COM_PREFIX "verbose"
|
||||
|
||||
#define ZIP_ARCHIVE_MARKER_COMMENT "PACK200"
|
||||
|
||||
// The following are not known to the Java classes:
|
||||
#define UNPACK_REMOVE_PACKFILE COM_PREFIX "unpack.remove.packfile"
|
||||
|
||||
// Called from unpacker layers
|
||||
#define _CHECK_DO(t, x) \
|
||||
{ \
|
||||
if (t) \
|
||||
{ \
|
||||
x; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CHECK _CHECK_DO(aborting(), return)
|
||||
#define CHECK_(y) _CHECK_DO(aborting(), return y)
|
||||
#define CHECK_0 _CHECK_DO(aborting(), return 0)
|
||||
|
||||
#define CHECK_NULL(p) _CHECK_DO((p) == nullptr, return)
|
||||
#define CHECK_NULL_(y, p) _CHECK_DO((p) == nullptr, return y)
|
||||
#define CHECK_NULL_0(p) _CHECK_DO((p) == nullptr, return 0)
|
||||
|
||||
#define CHECK_COUNT(t) \
|
||||
if (t < 0) \
|
||||
{ \
|
||||
abort("bad value count"); \
|
||||
} \
|
||||
CHECK
|
||||
|
||||
#define STR_TRUE "true"
|
||||
#define STR_FALSE "false"
|
||||
|
||||
#define STR_TF(x) ((x) ? STR_TRUE : STR_FALSE)
|
||||
#define BOOL_TF(x) (((x) != nullptr &&strcmp((x), STR_TRUE) == 0) ? true : false)
|
||||
|
||||
#define DEFAULT_ARCHIVE_MODTIME 1060000000 // Aug 04, 2003 5:26 PM PDT
|
489
depends/pack200/src/main.cpp
Normal file
489
depends/pack200/src/main.cpp
Normal file
@ -0,0 +1,489 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
#include "coding.h"
|
||||
#include "bands.h"
|
||||
|
||||
#include "constants.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return unpacker::run(argc, argv);
|
||||
}
|
||||
|
||||
unpacker *unpacker::non_mt_current = nullptr;
|
||||
unpacker *unpacker::current()
|
||||
{
|
||||
return non_mt_current;
|
||||
}
|
||||
static void set_current_unpacker(unpacker *u)
|
||||
{
|
||||
unpacker::non_mt_current = u;
|
||||
}
|
||||
|
||||
// Callback for fetching data, Unix style.
|
||||
static jlong read_input_via_stdio(unpacker *u, void *buf, jlong minlen, jlong maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
jlong numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
while (numread < minlen)
|
||||
{
|
||||
// read available input, up to buf.length or maxlen
|
||||
int readlen = (1 << 16);
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
int nr = 0;
|
||||
if (u->infileptr != nullptr)
|
||||
{
|
||||
nr = (int)fread(bufptr, 1, readlen, u->infileptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef WIN32
|
||||
// we prefer unbuffered inputs
|
||||
nr = (int)read(u->infileno, bufptr, readlen);
|
||||
#else
|
||||
nr = (int)fread(bufptr, 1, readlen, stdin);
|
||||
#endif
|
||||
}
|
||||
if (nr <= 0)
|
||||
{
|
||||
if (errno != EINTR)
|
||||
break;
|
||||
nr = 0;
|
||||
}
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
}
|
||||
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d\n",
|
||||
// (int)minlen, (int)maxlen, (int)numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
EOF_MAGIC = 0,
|
||||
BAD_MAGIC = -1
|
||||
};
|
||||
static int read_magic(unpacker *u, char peek[], int peeklen)
|
||||
{
|
||||
assert(peeklen == 4); // magic numbers are always 4 bytes
|
||||
jlong nr = (u->read_input_fn)(u, peek, peeklen, peeklen);
|
||||
if (nr != peeklen)
|
||||
{
|
||||
return (nr == 0) ? EOF_MAGIC : BAD_MAGIC;
|
||||
}
|
||||
int magic = 0;
|
||||
for (int i = 0; i < peeklen; i++)
|
||||
{
|
||||
magic <<= 8;
|
||||
magic += peek[i] & 0xFF;
|
||||
}
|
||||
return magic;
|
||||
}
|
||||
|
||||
static void setup_gzin(unpacker *u)
|
||||
{
|
||||
gunzip *gzin = NEW(gunzip, 1);
|
||||
gzin->init(u);
|
||||
}
|
||||
|
||||
static const char *nbasename(const char *progname)
|
||||
{
|
||||
const char *slash = strrchr(progname, '/');
|
||||
if (slash != nullptr)
|
||||
progname = ++slash;
|
||||
return progname;
|
||||
}
|
||||
|
||||
static const char *usage_lines[] = {
|
||||
"Usage: %s [-opt... | --option=value]... x.pack[.gz] y.jar\n", "\n", "Unpacking Options\n",
|
||||
" -H{h}, --deflate-hint={h} override transmitted deflate hint: true, false, or keep "
|
||||
"(default)\n",
|
||||
" -r, --remove-pack-file remove input file after unpacking\n",
|
||||
" -v, --verbose increase program verbosity\n",
|
||||
" -q, --quiet set verbosity to lowest level\n",
|
||||
" -l{F}, --log-file={F} output to the given log file, or '-' for standard output "
|
||||
"(default)\n",
|
||||
" -?, -h, --help print this message\n",
|
||||
" -J{X} Java VM argument (ignored)\n", nullptr};
|
||||
|
||||
static void usage(unpacker *u, const char *progname, bool full = false)
|
||||
{
|
||||
// WinMain does not set argv[0] to the progrname
|
||||
progname = (progname != nullptr) ? nbasename(progname) : "unpack200";
|
||||
for (int i = 0; usage_lines[i] != nullptr; i++)
|
||||
{
|
||||
fprintf(stderr, usage_lines[i], progname);
|
||||
if (!full)
|
||||
{
|
||||
fprintf(stderr, "(For more information, run %s --help .)\n", progname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// argument parsing
|
||||
static char **init_args(int argc, char **argv, int &envargc)
|
||||
{
|
||||
const char *env = getenv("UNPACK200_FLAGS");
|
||||
ptrlist envargs;
|
||||
envargs.init();
|
||||
if (env != nullptr)
|
||||
{
|
||||
char *buf = (char *)strdup(env);
|
||||
const char *delim = "\n\t ";
|
||||
for (char *p = strtok(buf, delim); p != nullptr; p = strtok(nullptr, delim))
|
||||
{
|
||||
envargs.add(p);
|
||||
}
|
||||
}
|
||||
// allocate extra margin at both head and tail
|
||||
char **argp = NEW(char *, envargs.length() + argc + 1);
|
||||
char **argp0 = argp;
|
||||
int i;
|
||||
for (i = 0; i < envargs.length(); i++)
|
||||
{
|
||||
*argp++ = (char *)envargs.get(i);
|
||||
}
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
// note: skip argv[0] (program name)
|
||||
*argp++ = (char *)strdup(argv[i]); // make a scratch copy
|
||||
}
|
||||
*argp = nullptr; // sentinel
|
||||
envargc = envargs.length(); // report this count to next_arg
|
||||
envargs.free();
|
||||
return argp0;
|
||||
}
|
||||
|
||||
static int strpcmp(const char *str, const char *pfx)
|
||||
{
|
||||
return strncmp(str, pfx, strlen(pfx));
|
||||
}
|
||||
|
||||
static const char flag_opts[] = "vqrVh?";
|
||||
static const char string_opts[] = "HlJ";
|
||||
|
||||
static int next_arg(char **&argp)
|
||||
{
|
||||
char *arg = *argp;
|
||||
if (arg == nullptr || arg[0] != '-')
|
||||
{ // end of option list
|
||||
return 0;
|
||||
}
|
||||
// printf("opt: %s\n", arg);
|
||||
char ach = arg[1];
|
||||
if (ach == '\0')
|
||||
{
|
||||
// ++argp; // do not pop this arg
|
||||
return 0; // bare "-" is stdin/stdout
|
||||
}
|
||||
else if (arg[1] == '-')
|
||||
{ // --foo option
|
||||
static const char *keys[] = {"Hdeflate-hint=", "vverbose", "qquiet",
|
||||
"rremove-pack-file", "llog-file=", "Vversion",
|
||||
"hhelp", nullptr};
|
||||
if (arg[2] == '\0')
|
||||
{ // end of option list
|
||||
++argp; // pop the "--"
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; keys[i] != nullptr; i++)
|
||||
{
|
||||
const char *key = keys[i];
|
||||
char kch = *key++;
|
||||
if (strchr(key, '=') == nullptr)
|
||||
{
|
||||
if (!strcmp(arg + 2, key))
|
||||
{
|
||||
++argp; // pop option arg
|
||||
return kch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!strpcmp(arg + 2, key))
|
||||
{
|
||||
*argp += 2 + strlen(key); // remove "--"+key from arg
|
||||
return kch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (strchr(flag_opts, ach) != nullptr)
|
||||
{ // plain option
|
||||
if (arg[2] == '\0')
|
||||
{
|
||||
++argp;
|
||||
}
|
||||
else
|
||||
{
|
||||
// in-place edit of "-vxyz" to "-xyz"
|
||||
arg += 1; // skip original '-'
|
||||
arg[0] = '-';
|
||||
*argp = arg;
|
||||
}
|
||||
// printf(" key => %c\n", ach);
|
||||
return ach;
|
||||
}
|
||||
else if (strchr(string_opts, ach) != nullptr)
|
||||
{ // argument-bearing option
|
||||
if (arg[2] == '\0')
|
||||
{
|
||||
if (argp[1] == nullptr)
|
||||
return -1; // no next arg
|
||||
++argp; // leave the argument in place
|
||||
}
|
||||
else
|
||||
{
|
||||
// in-place edit of "-Hxyz" to "xyz"
|
||||
arg += 2; // skip original '-H'
|
||||
*argp = arg;
|
||||
}
|
||||
// printf(" key => %c\n", ach);
|
||||
return ach;
|
||||
}
|
||||
return -1; // bad argument
|
||||
}
|
||||
|
||||
static const char sccsver[] = "1.30, 07/05/05";
|
||||
|
||||
// Usage: unpackage input.pack output.jar
|
||||
int unpacker::run(int argc, char **argv)
|
||||
{
|
||||
unpacker u;
|
||||
u.init(read_input_via_stdio);
|
||||
set_current_unpacker(&u);
|
||||
|
||||
jar jarout;
|
||||
jarout.init(&u);
|
||||
|
||||
int envargc = 0;
|
||||
char **argbuf = init_args(argc, argv, envargc);
|
||||
char **arg0 = argbuf + envargc;
|
||||
char **argp = argbuf;
|
||||
|
||||
int verbose = 0;
|
||||
char *logfile = nullptr;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char *arg = (*argp == nullptr) ? "" : u.saveStr(*argp);
|
||||
bool isenvarg = (argp < arg0);
|
||||
int ach = next_arg(argp);
|
||||
bool hasoptarg = (ach != 0 && strchr(string_opts, ach) != nullptr);
|
||||
if (ach == 0 && argp >= arg0)
|
||||
break;
|
||||
if (isenvarg && argp == arg0 && hasoptarg)
|
||||
ach = 0; // don't pull from cmdline
|
||||
switch (ach)
|
||||
{
|
||||
case 'H':
|
||||
u.set_option(UNPACK_DEFLATE_HINT, *argp++);
|
||||
break;
|
||||
case 'v':
|
||||
++verbose;
|
||||
break;
|
||||
case 'q':
|
||||
verbose = 0;
|
||||
break;
|
||||
case 'r':
|
||||
u.set_option(UNPACK_REMOVE_PACKFILE, "1");
|
||||
break;
|
||||
case 'l':
|
||||
logfile = *argp++;
|
||||
break;
|
||||
case 'J':
|
||||
argp += 1;
|
||||
break; // skip ignored -Jxxx parameter
|
||||
|
||||
case 'h':
|
||||
case '?':
|
||||
usage(&u, argv[0], true);
|
||||
exit(1);
|
||||
|
||||
default:
|
||||
const char *inenv = isenvarg ? " in ${UNPACK200_FLAGS}" : "";
|
||||
if (hasoptarg)
|
||||
fprintf(stderr, "Missing option string%s: %s\n", inenv, arg);
|
||||
else
|
||||
fprintf(stderr, "Unrecognized argument%s: %s\n", inenv, arg);
|
||||
usage(&u, argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
u.set_option(DEBUG_VERBOSE, u.saveIntStr(verbose));
|
||||
}
|
||||
|
||||
const char *source_file = *argp++;
|
||||
const char *destination_file = *argp++;
|
||||
|
||||
if (source_file == nullptr || destination_file == nullptr || *argp != nullptr)
|
||||
{
|
||||
usage(&u, argv[0]);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
fprintf(stderr, "Unpacking from %s to %s\n", source_file, destination_file);
|
||||
}
|
||||
bool &remove_source = u.remove_packfile;
|
||||
|
||||
if (strcmp(source_file, "-") == 0)
|
||||
{
|
||||
remove_source = false;
|
||||
u.infileno = fileno(stdin);
|
||||
}
|
||||
else
|
||||
{
|
||||
u.infileptr = fopen(source_file, "rb");
|
||||
if (u.infileptr == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open input file: %s\n", source_file);
|
||||
exit(3); // Called only from the native standalone unpacker
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(destination_file, "-") == 0)
|
||||
{
|
||||
jarout.jarfp = stdout;
|
||||
}
|
||||
else
|
||||
{
|
||||
jarout.openJarFile(destination_file);
|
||||
assert(jarout.jarfp != nullptr);
|
||||
}
|
||||
|
||||
if (verbose != 0)
|
||||
u.dump_options();
|
||||
|
||||
char peek[4];
|
||||
int magic;
|
||||
|
||||
// check for GZIP input
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if ((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC)
|
||||
{
|
||||
// Oops; must slap an input filter on this data.
|
||||
setup_gzin(&u);
|
||||
u.gzin->start(magic);
|
||||
if (!u.aborting())
|
||||
{
|
||||
u.start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
// Note: The checks to u.aborting() are necessary to gracefully
|
||||
// terminate processing when the first segment throws an error.
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (u.aborting())
|
||||
break;
|
||||
|
||||
// Each trip through this loop unpacks one segment
|
||||
// and then resets the unpacker.
|
||||
for (unpacker::file *filep; (filep = u.get_next_file()) != nullptr;)
|
||||
{
|
||||
if (u.aborting())
|
||||
break;
|
||||
u.write_file_to_jar(filep);
|
||||
}
|
||||
if (u.aborting())
|
||||
break;
|
||||
|
||||
// Peek ahead for more data.
|
||||
magic = read_magic(&u, peek, (int)sizeof(peek));
|
||||
if (magic != (int)JAVA_PACKAGE_MAGIC)
|
||||
{
|
||||
if (magic != EOF_MAGIC)
|
||||
u.abort("garbage after end of pack archive");
|
||||
break; // all done
|
||||
}
|
||||
|
||||
// Release all storage from parsing the old segment.
|
||||
u.reset();
|
||||
|
||||
// Restart, beginning with the peek-ahead.
|
||||
u.start(peek, sizeof(peek));
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
if (u.aborting())
|
||||
{
|
||||
fprintf(stderr, "Error: %s\n", u.get_abort_message());
|
||||
status = 1;
|
||||
}
|
||||
|
||||
if (u.infileptr != nullptr)
|
||||
{
|
||||
fclose(u.infileptr);
|
||||
u.infileptr = nullptr;
|
||||
}
|
||||
|
||||
if (!u.aborting() && remove_source)
|
||||
remove(source_file);
|
||||
|
||||
if (verbose != 0)
|
||||
{
|
||||
fprintf(stderr, "unpacker completed with status=%d\n", status);
|
||||
}
|
||||
|
||||
u.finish();
|
||||
|
||||
u.free(); // tidy up malloc blocks
|
||||
set_current_unpacker(nullptr); // clean up global pointer
|
||||
|
||||
return status;
|
||||
}
|
5105
depends/pack200/src/unpack.cpp
Normal file
5105
depends/pack200/src/unpack.cpp
Normal file
File diff suppressed because it is too large
Load Diff
585
depends/pack200/src/unpack.h
Normal file
585
depends/pack200/src/unpack.h
Normal file
@ -0,0 +1,585 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Global Structures
|
||||
struct jar;
|
||||
struct gunzip;
|
||||
struct band;
|
||||
struct cpool;
|
||||
struct entry;
|
||||
struct cpindex;
|
||||
struct inner_class;
|
||||
struct value_stream;
|
||||
|
||||
struct cpindex
|
||||
{
|
||||
uint len;
|
||||
entry *base1; // base of primary index
|
||||
entry **base2; // base of secondary index
|
||||
byte ixTag; // type of entries (!= CONSTANT_None), plus 64 if sub-index
|
||||
enum
|
||||
{
|
||||
SUB_TAG = 64
|
||||
};
|
||||
|
||||
entry *get(uint i);
|
||||
|
||||
void init(int len_, entry *base1_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = base1_;
|
||||
base2 = nullptr;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
void init(int len_, entry **base2_, int ixTag_)
|
||||
{
|
||||
len = len_;
|
||||
base1 = nullptr;
|
||||
base2 = base2_;
|
||||
ixTag = ixTag_;
|
||||
}
|
||||
};
|
||||
|
||||
struct cpool
|
||||
{
|
||||
uint nentries;
|
||||
entry *entries;
|
||||
entry *first_extra_entry;
|
||||
uint maxentries; // total allocated size of entries
|
||||
|
||||
// Position and size of each homogeneous subrange:
|
||||
int tag_count[CONSTANT_Limit];
|
||||
int tag_base[CONSTANT_Limit];
|
||||
cpindex tag_index[CONSTANT_Limit];
|
||||
ptrlist tag_extras[CONSTANT_Limit];
|
||||
|
||||
cpindex *member_indexes; // indexed by 2*CONSTANT_Class.inord
|
||||
cpindex *getFieldIndex(entry *classRef);
|
||||
cpindex *getMethodIndex(entry *classRef);
|
||||
|
||||
inner_class **ic_index;
|
||||
inner_class **ic_child_index;
|
||||
inner_class *getIC(entry *inner);
|
||||
inner_class *getFirstChildIC(entry *outer);
|
||||
inner_class *getNextChildIC(inner_class *child);
|
||||
|
||||
int outputIndexLimit; // index limit after renumbering
|
||||
ptrlist outputEntries; // list of entry* needing output idx assigned
|
||||
|
||||
entry **hashTab;
|
||||
uint hashTabLength;
|
||||
entry *&hashTabRef(byte tag, bytes &b);
|
||||
entry *ensureUtf8(bytes &b);
|
||||
entry *ensureClass(bytes &b);
|
||||
|
||||
// Well-known Utf8 symbols.
|
||||
enum
|
||||
{
|
||||
#define SNAME(n, s) s_##s,
|
||||
ALL_ATTR_DO(SNAME)
|
||||
#undef SNAME
|
||||
s_lt_init_gt, // <init>
|
||||
s_LIMIT
|
||||
};
|
||||
entry *sym[s_LIMIT];
|
||||
|
||||
// read counts from hdr, allocate main arrays
|
||||
enum
|
||||
{
|
||||
NUM_COUNTS = 12
|
||||
};
|
||||
void init(unpacker *u, int counts[NUM_COUNTS]);
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
int getCount(byte tag)
|
||||
{
|
||||
assert((uint)tag < CONSTANT_Limit);
|
||||
return tag_count[tag];
|
||||
}
|
||||
cpindex *getIndex(byte tag)
|
||||
{
|
||||
assert((uint)tag < CONSTANT_Limit);
|
||||
return &tag_index[tag];
|
||||
}
|
||||
cpindex *getKQIndex(); // uses cur_descr
|
||||
|
||||
void expandSignatures();
|
||||
void initMemberIndexes();
|
||||
|
||||
void computeOutputOrder();
|
||||
void computeOutputIndexes();
|
||||
void resetOutputIndexes();
|
||||
|
||||
// error handling
|
||||
inline void abort(const char *msg);
|
||||
inline bool aborting();
|
||||
};
|
||||
|
||||
/*
|
||||
* The unpacker provides the entry points to the unpack engine,
|
||||
* as well as maintains the state of the engine.
|
||||
*/
|
||||
struct unpacker
|
||||
{
|
||||
// One element of the resulting JAR.
|
||||
struct file
|
||||
{
|
||||
const char *name;
|
||||
julong size;
|
||||
int modtime;
|
||||
int options;
|
||||
bytes data[2];
|
||||
// Note: If Sum(data[*].len) < size,
|
||||
// remaining bytes must be read directly from the input stream.
|
||||
bool deflate_hint()
|
||||
{
|
||||
return ((options & FO_DEFLATE_HINT) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
// global pointer to self, if not running under JNI (not multi-thread safe)
|
||||
static unpacker *non_mt_current;
|
||||
|
||||
// if running Unix-style, here are the inputs and outputs
|
||||
FILE *infileptr; // buffered
|
||||
int infileno; // unbuffered
|
||||
bytes inbytes; // direct
|
||||
gunzip *gzin; // gunzip filter, if any
|
||||
jar *jarout; // output JAR file
|
||||
|
||||
// pointer to self, for U_NEW macro
|
||||
unpacker *u;
|
||||
|
||||
// private abort message string, allocated to PATH_MAX*2
|
||||
const char *abort_message;
|
||||
ptrlist mallocs; // list of guys to free when we are all done
|
||||
ptrlist tmallocs; // list of guys to free on next client request
|
||||
fillbytes smallbuf; // supplies small alloc requests
|
||||
fillbytes tsmallbuf; // supplies temporary small alloc requests
|
||||
|
||||
// option management members
|
||||
int verbose; // verbose level, 0 means no output
|
||||
bool strip_compile;
|
||||
bool strip_debug;
|
||||
bool strip_jcov;
|
||||
bool remove_packfile;
|
||||
int deflate_hint_or_zero; // ==0 means not set, otherwise -1 or 1
|
||||
int modification_time_or_zero;
|
||||
|
||||
// input stream
|
||||
fillbytes input; // the whole block (size is predicted, has slop too)
|
||||
bool live_input; // is the data in this block live?
|
||||
bool free_input; // must the input buffer be freed?
|
||||
byte *rp; // read pointer (< rplimit <= input.limit())
|
||||
byte *rplimit; // how much of the input block has been read?
|
||||
julong bytes_read;
|
||||
int unsized_bytes_read;
|
||||
|
||||
// callback to read at least one byte, up to available input
|
||||
typedef jlong (*read_input_fn_t)(unpacker *self, void *buf, jlong minlen, jlong maxlen);
|
||||
read_input_fn_t read_input_fn;
|
||||
|
||||
// archive header fields
|
||||
int magic, minver, majver;
|
||||
size_t archive_size;
|
||||
int archive_next_count, archive_options, archive_modtime;
|
||||
int band_headers_size;
|
||||
int file_count, attr_definition_count, ic_count, class_count;
|
||||
int default_class_minver, default_class_majver;
|
||||
int default_file_options, suppress_file_options; // not header fields
|
||||
int default_archive_modtime, default_file_modtime; // not header fields
|
||||
int code_count; // not a header field
|
||||
int files_remaining; // not a header field
|
||||
|
||||
// engine state
|
||||
band *all_bands; // indexed by band_number
|
||||
byte *meta_rp; // read-pointer into (copy of) band_headers
|
||||
cpool cp; // all constant pool information
|
||||
inner_class *ics; // InnerClasses
|
||||
|
||||
// output stream
|
||||
bytes output; // output block (either classfile head or tail)
|
||||
byte *wp; // write pointer (< wplimit == output.limit())
|
||||
byte *wpbase; // write pointer starting address (<= wp)
|
||||
byte *wplimit; // how much of the output block has been written?
|
||||
|
||||
// output state
|
||||
file cur_file;
|
||||
entry *cur_class; // CONSTANT_Class entry
|
||||
entry *cur_super; // CONSTANT_Class entry or nullptr
|
||||
entry *cur_descr; // CONSTANT_NameandType entry
|
||||
int cur_descr_flags; // flags corresponding to cur_descr
|
||||
int cur_class_minver, cur_class_majver;
|
||||
bool cur_class_has_local_ics;
|
||||
fillbytes cur_classfile_head;
|
||||
fillbytes cur_classfile_tail;
|
||||
int files_written; // also tells which file we're working on
|
||||
int classes_written; // also tells which class we're working on
|
||||
julong bytes_written;
|
||||
intlist bcimap;
|
||||
fillbytes class_fixup_type;
|
||||
intlist class_fixup_offset;
|
||||
ptrlist class_fixup_ref;
|
||||
fillbytes code_fixup_type; // which format of branch operand?
|
||||
intlist code_fixup_offset; // location of operand needing fixup
|
||||
intlist code_fixup_source; // encoded ID of branch insn
|
||||
ptrlist requested_ics; // which ics need output?
|
||||
|
||||
// stats pertaining to multiple segments (updated on reset)
|
||||
julong bytes_read_before_reset;
|
||||
julong bytes_written_before_reset;
|
||||
int files_written_before_reset;
|
||||
int classes_written_before_reset;
|
||||
int segments_read_before_reset;
|
||||
|
||||
// attribute state
|
||||
struct layout_definition
|
||||
{
|
||||
uint idx; // index (0..31...) which identifies this layout
|
||||
const char *name; // name of layout
|
||||
entry *nameEntry;
|
||||
const char *layout; // string of layout (not yet parsed)
|
||||
band **elems; // array of top-level layout elems (or callables)
|
||||
|
||||
bool hasCallables()
|
||||
{
|
||||
return layout[0] == '[';
|
||||
}
|
||||
band **bands()
|
||||
{
|
||||
assert(elems != nullptr);
|
||||
return elems;
|
||||
}
|
||||
};
|
||||
struct attr_definitions
|
||||
{
|
||||
unpacker *u; // pointer to self, for U_NEW macro
|
||||
int xxx_flags_hi_bn; // locator for flags, count, indexes, calls bands
|
||||
int attrc; // ATTR_CONTEXT_CLASS, etc.
|
||||
uint flag_limit; // 32 or 63, depending on archive_options bit
|
||||
julong predef; // mask of built-in definitions
|
||||
julong redef; // mask of local flag definitions or redefinitions
|
||||
ptrlist layouts; // local (compressor-defined) defs, in index order
|
||||
int flag_count[X_ATTR_LIMIT_FLAGS_HI];
|
||||
intlist overflow_count;
|
||||
ptrlist strip_names; // what attribute names are being stripped?
|
||||
ptrlist band_stack; // Temp., used during layout parsing.
|
||||
ptrlist calls_to_link; // (ditto)
|
||||
int bands_made; // (ditto)
|
||||
|
||||
void free()
|
||||
{
|
||||
layouts.free();
|
||||
overflow_count.free();
|
||||
strip_names.free();
|
||||
band_stack.free();
|
||||
calls_to_link.free();
|
||||
}
|
||||
|
||||
// Locate the five fixed bands.
|
||||
band &xxx_flags_hi();
|
||||
band &xxx_flags_lo();
|
||||
band &xxx_attr_count();
|
||||
band &xxx_attr_indexes();
|
||||
band &xxx_attr_calls();
|
||||
band &fixed_band(int e_class_xxx);
|
||||
|
||||
// Register a new layout, and make bands for it.
|
||||
layout_definition *defineLayout(int idx, const char *name, const char *layout);
|
||||
layout_definition *defineLayout(int idx, entry *nameEntry, const char *layout);
|
||||
band **buildBands(layout_definition *lo);
|
||||
|
||||
// Parse a layout string or part of one, recursively if necessary.
|
||||
const char *parseLayout(const char *lp, band **&res, int curCble);
|
||||
const char *parseNumeral(const char *lp, int &res);
|
||||
const char *parseIntLayout(const char *lp, band *&res, byte le_kind,
|
||||
bool can_be_signed = false);
|
||||
band **popBody(int band_stack_base); // pops a body off band_stack
|
||||
|
||||
// Read data into the bands of the idx-th layout.
|
||||
void readBandData(int idx); // parse layout, make bands, read data
|
||||
void readBandData(band **body, uint count); // recursive helper
|
||||
|
||||
layout_definition *getLayout(uint idx)
|
||||
{
|
||||
if (idx >= (uint)layouts.length())
|
||||
return nullptr;
|
||||
return (layout_definition *)layouts.get(idx);
|
||||
}
|
||||
|
||||
void setHaveLongFlags(bool z)
|
||||
{
|
||||
assert(flag_limit == 0); // not set up yet
|
||||
flag_limit = (z ? X_ATTR_LIMIT_FLAGS_HI : X_ATTR_LIMIT_NO_FLAGS_HI);
|
||||
}
|
||||
bool haveLongFlags()
|
||||
{
|
||||
assert(flag_limit == X_ATTR_LIMIT_NO_FLAGS_HI ||
|
||||
flag_limit == X_ATTR_LIMIT_FLAGS_HI);
|
||||
return flag_limit == X_ATTR_LIMIT_FLAGS_HI;
|
||||
}
|
||||
|
||||
// Return flag_count if idx is predef and not redef, else zero.
|
||||
int predefCount(uint idx);
|
||||
|
||||
bool isRedefined(uint idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)((redef >> idx) & 1);
|
||||
}
|
||||
bool isPredefined(uint idx)
|
||||
{
|
||||
if (idx >= flag_limit)
|
||||
return false;
|
||||
return (bool)(((predef & ~redef) >> idx) & 1);
|
||||
}
|
||||
julong flagIndexMask()
|
||||
{
|
||||
return (predef | redef);
|
||||
}
|
||||
bool isIndex(uint idx)
|
||||
{
|
||||
assert(flag_limit != 0); // must be set up already
|
||||
if (idx < flag_limit)
|
||||
return (bool)(((predef | redef) >> idx) & 1);
|
||||
else
|
||||
return (idx - flag_limit < (uint)overflow_count.length());
|
||||
}
|
||||
int &getCount(uint idx)
|
||||
{
|
||||
assert(isIndex(idx));
|
||||
if (idx < flag_limit)
|
||||
return flag_count[idx];
|
||||
else
|
||||
return overflow_count.get(idx - flag_limit);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
||||
void abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
};
|
||||
|
||||
attr_definitions attr_defs[ATTR_CONTEXT_LIMIT];
|
||||
|
||||
// Initialization
|
||||
void init(read_input_fn_t input_fn = nullptr);
|
||||
// Resets to a known sane state
|
||||
void reset();
|
||||
// Deallocates all storage.
|
||||
void free();
|
||||
// Deallocates temporary storage (volatile after next client call).
|
||||
void free_temps()
|
||||
{
|
||||
tsmallbuf.init();
|
||||
tmallocs.freeAll();
|
||||
}
|
||||
|
||||
// Option management methods
|
||||
bool set_option(const char *option, const char *value);
|
||||
const char *get_option(const char *option);
|
||||
|
||||
void dump_options();
|
||||
|
||||
// Fetching input.
|
||||
bool ensure_input(jlong more);
|
||||
byte *input_scan()
|
||||
{
|
||||
return rp;
|
||||
}
|
||||
size_t input_remaining()
|
||||
{
|
||||
return rplimit - rp;
|
||||
}
|
||||
size_t input_consumed()
|
||||
{
|
||||
return rp - input.base();
|
||||
}
|
||||
|
||||
// Entry points to the unpack engine
|
||||
static int run(int argc, char **argv); // Unix-style entry point.
|
||||
void check_options();
|
||||
void start(void *packptr = nullptr, size_t len = 0);
|
||||
void write_file_to_jar(file *f);
|
||||
void finish();
|
||||
|
||||
// Public post unpack methods
|
||||
int get_files_remaining()
|
||||
{
|
||||
return files_remaining;
|
||||
}
|
||||
int get_segments_remaining()
|
||||
{
|
||||
return archive_next_count;
|
||||
}
|
||||
file *get_next_file(); // returns nullptr on last file
|
||||
|
||||
// General purpose methods
|
||||
void *alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true);
|
||||
}
|
||||
void *temp_alloc(size_t size)
|
||||
{
|
||||
return alloc_heap(size, true, true);
|
||||
}
|
||||
void *alloc_heap(size_t size, bool smallOK = false, bool temp = false);
|
||||
void saveTo(bytes &b, const char *str)
|
||||
{
|
||||
saveTo(b, (byte *)str, strlen(str));
|
||||
}
|
||||
void saveTo(bytes &b, bytes &data)
|
||||
{
|
||||
saveTo(b, data.ptr, data.len);
|
||||
}
|
||||
void saveTo(bytes &b, byte *ptr, size_t len); //{ b.ptr = U_NEW...}
|
||||
const char *saveStr(const char *str)
|
||||
{
|
||||
bytes buf;
|
||||
saveTo(buf, str);
|
||||
return buf.strval();
|
||||
}
|
||||
const char *saveIntStr(int num)
|
||||
{
|
||||
char buf[30];
|
||||
sprintf(buf, "%d", num);
|
||||
return saveStr(buf);
|
||||
}
|
||||
const char *get_abort_message();
|
||||
void abort(const char *s = nullptr);
|
||||
bool aborting()
|
||||
{
|
||||
return abort_message != nullptr;
|
||||
}
|
||||
static unpacker *current(); // find current instance
|
||||
|
||||
// Output management
|
||||
void set_output(fillbytes *which)
|
||||
{
|
||||
assert(wp == nullptr);
|
||||
which->ensureSize(1 << 12); // covers the average classfile
|
||||
wpbase = which->base();
|
||||
wp = which->limit();
|
||||
wplimit = which->end();
|
||||
}
|
||||
fillbytes *close_output(fillbytes *which = nullptr); // inverse of set_output
|
||||
|
||||
// These take an implicit parameter of wp/wplimit, and resize as necessary:
|
||||
byte *put_space(size_t len); // allocates space at wp, returns pointer
|
||||
size_t put_empty(size_t s)
|
||||
{
|
||||
byte *p = put_space(s);
|
||||
return p - wpbase;
|
||||
}
|
||||
void ensure_put_space(size_t len);
|
||||
void put_bytes(bytes &b)
|
||||
{
|
||||
b.writeTo(put_space(b.len));
|
||||
}
|
||||
void putu1(int n)
|
||||
{
|
||||
putu1_at(put_space(1), n);
|
||||
}
|
||||
void putu1_fast(int n)
|
||||
{
|
||||
putu1_at(wp++, n);
|
||||
}
|
||||
void putu2(int n); // { putu2_at(put_space(2), n); }
|
||||
void putu4(int n); // { putu4_at(put_space(4), n); }
|
||||
void putu8(jlong n); // { putu8_at(put_space(8), n); }
|
||||
void putref(entry *e); // { putu2_at(put_space(2), putref_index(e, 2)); }
|
||||
void putu1ref(entry *e); // { putu1_at(put_space(1), putref_index(e, 1)); }
|
||||
int putref_index(entry *e, int size); // size in [1..2]
|
||||
void put_label(int curIP, int size); // size in {2,4}
|
||||
void putlayout(band **body);
|
||||
void put_stackmap_type();
|
||||
|
||||
size_t wpoffset()
|
||||
{
|
||||
return (size_t)(wp - wpbase);
|
||||
} // (unvariant across overflow)
|
||||
byte *wp_at(size_t offset)
|
||||
{
|
||||
return wpbase + offset;
|
||||
}
|
||||
uint to_bci(uint bii);
|
||||
void get_code_header(int &max_stack, int &max_na_locals, int &handler_count, int &cflags);
|
||||
band *ref_band_for_self_op(int bc, bool &isAloadVar, int &origBCVar);
|
||||
band *ref_band_for_op(int bc);
|
||||
|
||||
// Definitions of standard classfile int formats:
|
||||
static void putu1_at(byte *wp, int n)
|
||||
{
|
||||
assert(n == (n & 0xFF));
|
||||
wp[0] = n;
|
||||
}
|
||||
static void putu2_at(byte *wp, int n);
|
||||
static void putu4_at(byte *wp, int n);
|
||||
static void putu8_at(byte *wp, jlong n);
|
||||
|
||||
// Private stuff
|
||||
void reset_cur_classfile();
|
||||
void write_classfile_tail();
|
||||
void write_classfile_head();
|
||||
void write_code();
|
||||
void write_bc_ops();
|
||||
void write_members(int num, int attrc); // attrc=ATTR_CONTEXT_FIELD/METHOD
|
||||
int write_attrs(int attrc, julong indexBits);
|
||||
|
||||
// The readers
|
||||
void read_bands();
|
||||
void read_file_header();
|
||||
void read_cp();
|
||||
void read_cp_counts(value_stream &hdr);
|
||||
void read_attr_defs();
|
||||
void read_ics();
|
||||
void read_attrs(int attrc, int obj_count);
|
||||
void read_classes();
|
||||
void read_code_headers();
|
||||
void read_bcs();
|
||||
void read_bc_ops();
|
||||
void read_files();
|
||||
void read_Utf8_values(entry *cpMap, int len);
|
||||
void read_single_words(band &cp_band, entry *cpMap, int len);
|
||||
void read_double_words(band &cp_bands, entry *cpMap, int len);
|
||||
void read_single_refs(band &cp_band, byte refTag, entry *cpMap, int len);
|
||||
void read_double_refs(band &cp_band, byte ref1Tag, byte ref2Tag, entry *cpMap, int len);
|
||||
void read_signature_values(entry *cpMap, int len);
|
||||
};
|
||||
|
||||
inline void cpool::abort(const char *msg)
|
||||
{
|
||||
u->abort(msg);
|
||||
}
|
||||
inline bool cpool::aborting()
|
||||
{
|
||||
return u->aborting();
|
||||
}
|
91
depends/pack200/src/utils.cpp
Normal file
91
depends/pack200/src/utils.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "constants.h"
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "unpack.h"
|
||||
|
||||
void *must_malloc(size_t size)
|
||||
{
|
||||
size_t msize = size;
|
||||
void *ptr = (msize > PSIZE_MAX) ? nullptr : malloc(msize);
|
||||
if (ptr != nullptr)
|
||||
{
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
unpack_abort(ERROR_ENOMEM);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void unpack_abort(const char *msg, unpacker *u)
|
||||
{
|
||||
if (msg == nullptr)
|
||||
msg = "corrupt pack file or internal error";
|
||||
if (u == nullptr)
|
||||
u = unpacker::current();
|
||||
if (u == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: unpacker: %s\n", msg);
|
||||
::abort();
|
||||
return;
|
||||
}
|
||||
u->abort(msg);
|
||||
}
|
||||
|
||||
bool unpack_aborting(unpacker *u)
|
||||
{
|
||||
if (u == nullptr)
|
||||
u = unpacker::current();
|
||||
if (u == nullptr)
|
||||
{
|
||||
fprintf(stderr, "Error: unpacker: no current instance\n");
|
||||
::abort();
|
||||
return true;
|
||||
}
|
||||
return u->aborting();
|
||||
}
|
54
depends/pack200/src/utils.h
Normal file
54
depends/pack200/src/utils.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// Definitions of our util functions
|
||||
|
||||
void *must_malloc(size_t size);
|
||||
|
||||
// overflow management
|
||||
#define OVERFLOW ((size_t) - 1)
|
||||
#define PSIZE_MAX (OVERFLOW / 2) /* normal size limit */
|
||||
|
||||
inline size_t scale_size(size_t size, size_t scale)
|
||||
{
|
||||
return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2)
|
||||
{
|
||||
return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX) ? OVERFLOW : size1 + size2;
|
||||
}
|
||||
|
||||
inline size_t add_size(size_t size1, size_t size2, int size3)
|
||||
{
|
||||
return add_size(add_size(size1, size2), size3);
|
||||
}
|
||||
|
||||
// These may be expensive, because they have to go via Java TSD,
|
||||
// if the optional u argument is missing.
|
||||
struct unpacker;
|
||||
extern void unpack_abort(const char *msg, unpacker *u = nullptr);
|
||||
extern bool unpack_aborting(unpacker *u = nullptr);
|
||||
|
610
depends/pack200/src/zip.cpp
Normal file
610
depends/pack200/src/zip.cpp
Normal file
@ -0,0 +1,610 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Note: Lifted from uncrunch.c from jdk sources
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "defines.h"
|
||||
#include "bytes.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include "constants.h"
|
||||
#include "unpack.h"
|
||||
|
||||
#include "zip.h"
|
||||
|
||||
#ifdef NO_ZLIB
|
||||
|
||||
inline bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#define Z_NULL NULL
|
||||
|
||||
#else // Have ZLIB
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
inline uint jar::get_crc32(uint c, uchar *ptr, uint len)
|
||||
{
|
||||
return crc32(c, ptr, len);
|
||||
}
|
||||
|
||||
#endif // End of ZLIB
|
||||
|
||||
#ifdef sparc
|
||||
#define SWAP_BYTES(a) ((((a) << 8) & 0xff00) | 0x00ff) & (((a) >> 8) | 0xff00)
|
||||
#else
|
||||
#define SWAP_BYTES(a) (a)
|
||||
#endif
|
||||
|
||||
#define GET_INT_LO(a) SWAP_BYTES(a & 0xFFFF)
|
||||
|
||||
#define GET_INT_HI(a) SWAP_BYTES((a >> 16) & 0xFFFF);
|
||||
|
||||
void jar::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
u->jarout = this;
|
||||
}
|
||||
|
||||
// Write data to the ZIP output stream.
|
||||
void jar::write_data(void *buff, int len)
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
int rc = (int)fwrite(buff, 1, len, jarfp);
|
||||
if (rc <= 0)
|
||||
{
|
||||
fprintf(stderr, "Error: write on output file failed err=%d\n", errno);
|
||||
exit(1); // Called only from the native standalone unpacker
|
||||
}
|
||||
output_file_offset += rc;
|
||||
buff = ((char *)buff) + rc;
|
||||
len -= rc;
|
||||
}
|
||||
}
|
||||
|
||||
void jar::add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc)
|
||||
{
|
||||
uint fname_length = (uint)strlen(fname);
|
||||
ushort header[23];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0201);
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// required version
|
||||
header[3] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method 8=deflate.
|
||||
header[5] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[6] = (ushort)GET_INT_LO(dostime);
|
||||
header[7] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[8] = (ushort)GET_INT_LO(crc);
|
||||
header[9] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[10] = (ushort)GET_INT_LO(clen);
|
||||
header[11] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[12] = (ushort)GET_INT_LO(len);
|
||||
header[13] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[14] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[15] = 0;
|
||||
// So called "comment" length.
|
||||
header[16] = 0;
|
||||
// Disk number start
|
||||
header[17] = 0;
|
||||
// File flags => binary
|
||||
header[18] = 0;
|
||||
// More file flags
|
||||
header[19] = 0;
|
||||
header[20] = 0;
|
||||
// Offset within ZIP file.
|
||||
header[21] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[22] = (ushort)GET_INT_HI(output_file_offset);
|
||||
|
||||
// Copy the whole thing into the central directory.
|
||||
central_directory.append(header, sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
central_directory.append(fname, fname_length);
|
||||
|
||||
central_directory_count++;
|
||||
}
|
||||
|
||||
void jar::write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint crc)
|
||||
{
|
||||
uint fname_length = (uint)strlen(fname);
|
||||
ushort header[15];
|
||||
if (modtime == 0)
|
||||
modtime = default_modtime;
|
||||
uint32_t dostime = get_dostime(modtime);
|
||||
|
||||
// ZIP LOC magic.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0403);
|
||||
|
||||
// Version
|
||||
header[2] = (ushort)SWAP_BYTES(0xA);
|
||||
|
||||
// flags 02 = maximum sub-compression flag
|
||||
header[3] = (store) ? 0x0 : SWAP_BYTES(0x2);
|
||||
|
||||
// Compression method = deflate
|
||||
header[4] = (store) ? 0x0 : SWAP_BYTES(0x08);
|
||||
|
||||
// Last modified date and time.
|
||||
header[5] = (ushort)GET_INT_LO(dostime);
|
||||
header[6] = (ushort)GET_INT_HI(dostime);
|
||||
|
||||
// CRC
|
||||
header[7] = (ushort)GET_INT_LO(crc);
|
||||
header[8] = (ushort)GET_INT_HI(crc);
|
||||
|
||||
// Compressed length:
|
||||
header[9] = (ushort)GET_INT_LO(clen);
|
||||
header[10] = (ushort)GET_INT_HI(clen);
|
||||
|
||||
// Uncompressed length.
|
||||
header[11] = (ushort)GET_INT_LO(len);
|
||||
header[12] = (ushort)GET_INT_HI(len);
|
||||
|
||||
// Filename length
|
||||
header[13] = (ushort)SWAP_BYTES(fname_length);
|
||||
// So called "extra field" length.
|
||||
header[14] = 0;
|
||||
|
||||
// Write the LOC header to the output file.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Copy the fname to the header.
|
||||
write_data((char *)fname, (int)fname_length);
|
||||
}
|
||||
|
||||
static const char marker_comment[] = ZIP_ARCHIVE_MARKER_COMMENT;
|
||||
|
||||
void jar::write_central_directory()
|
||||
{
|
||||
bytes mc;
|
||||
mc.set(marker_comment);
|
||||
|
||||
ushort header[11];
|
||||
|
||||
// Create the End of Central Directory structure.
|
||||
header[0] = (ushort)SWAP_BYTES(0x4B50);
|
||||
header[1] = (ushort)SWAP_BYTES(0x0605);
|
||||
// disk numbers
|
||||
header[2] = 0;
|
||||
header[3] = 0;
|
||||
// Number of entries in central directory.
|
||||
header[4] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
header[5] = (ushort)SWAP_BYTES(central_directory_count);
|
||||
// Size of the central directory}
|
||||
header[6] = (ushort)GET_INT_LO((int)central_directory.size());
|
||||
header[7] = (ushort)GET_INT_HI((int)central_directory.size());
|
||||
// Offset of central directory within disk.
|
||||
header[8] = (ushort)GET_INT_LO(output_file_offset);
|
||||
header[9] = (ushort)GET_INT_HI(output_file_offset);
|
||||
// zipfile comment length;
|
||||
header[10] = (ushort)SWAP_BYTES((int)mc.len);
|
||||
|
||||
// Write the central directory.
|
||||
write_data(central_directory.b);
|
||||
|
||||
// Write the End of Central Directory structure.
|
||||
write_data(header, (int)sizeof(header));
|
||||
|
||||
// Write the comment.
|
||||
write_data(mc);
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
// Open a Jar file and initialize.
|
||||
void jar::openJarFile(const char *fname)
|
||||
{
|
||||
if (!jarfp)
|
||||
{
|
||||
jarfp = fopen(fname, "wb");
|
||||
if (!jarfp)
|
||||
{
|
||||
fprintf(stderr, "Error: Could not open jar file: %s\n", fname);
|
||||
exit(3); // Called only from the native standalone unpacker
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry and copy the file data
|
||||
void jar::addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
int clen = 0;
|
||||
|
||||
uint crc = get_crc32(0, Z_NULL, 0);
|
||||
if (head.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)head.ptr, (uint)head.len);
|
||||
if (tail.len != 0)
|
||||
crc = get_crc32(crc, (uchar *)tail.ptr, (uint)tail.len);
|
||||
|
||||
bool deflate = (deflate_hint && len > 0);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
if (deflate_bytes(head, tail) == false)
|
||||
{
|
||||
deflate = false;
|
||||
}
|
||||
}
|
||||
clen = (int)((deflate) ? deflated.size() : len);
|
||||
add_to_jar_directory(fname, !deflate, modtime, len, clen, crc);
|
||||
write_jar_header(fname, !deflate, modtime, len, clen, crc);
|
||||
|
||||
if (deflate)
|
||||
{
|
||||
write_data(deflated.b);
|
||||
}
|
||||
else
|
||||
{
|
||||
write_data(head);
|
||||
write_data(tail);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a ZIP entry for a directory name no data
|
||||
void jar::addDirectoryToJarFile(const char *dir_name)
|
||||
{
|
||||
bool store = true;
|
||||
add_to_jar_directory((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
write_jar_header((const char *)dir_name, store, default_modtime, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Write out the central directory and close the jar file.
|
||||
void jar::closeJarFile(bool central)
|
||||
{
|
||||
if (jarfp)
|
||||
{
|
||||
fflush(jarfp);
|
||||
if (central)
|
||||
write_central_directory();
|
||||
fflush(jarfp);
|
||||
fclose(jarfp);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
|
||||
* time (date in high two bytes, time in low two bytes allowing magnitude
|
||||
* comparison).
|
||||
*/
|
||||
inline uint32_t jar::dostime(int y, int n, int d, int h, int m, int s)
|
||||
{
|
||||
return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0)
|
||||
: (((uint32_t)y - 1980) << 25) | ((uint32_t)n << 21) | ((uint32_t)d << 16) |
|
||||
((uint32_t)h << 11) | ((uint32_t)m << 5) | ((uint32_t)s >> 1);
|
||||
}
|
||||
|
||||
#ifdef _REENTRANT // solaris
|
||||
extern "C" struct tm *gmtime_r(const time_t *, struct tm *);
|
||||
#else
|
||||
#define gmtime_r(t, s) gmtime(t)
|
||||
#endif
|
||||
/*
|
||||
* Return the Unix time in DOS format
|
||||
*/
|
||||
uint32_t jar::get_dostime(int modtime)
|
||||
{
|
||||
// see defines.h
|
||||
if (modtime != 0 && modtime == modtime_cache)
|
||||
return dostime_cache;
|
||||
if (modtime != 0 && default_modtime == 0)
|
||||
default_modtime = modtime; // catch a reasonable default
|
||||
time_t t = modtime;
|
||||
struct tm sbuf;
|
||||
(void)memset((void *)&sbuf, 0, sizeof(sbuf));
|
||||
struct tm *s = gmtime_r(&t, &sbuf);
|
||||
modtime_cache = modtime;
|
||||
dostime_cache =
|
||||
dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday, s->tm_hour, s->tm_min, s->tm_sec);
|
||||
// printf("modtime %d => %d\n", modtime_cache, dostime_cache);
|
||||
return dostime_cache;
|
||||
}
|
||||
|
||||
/* Returns true on success, and will set the clen to the compressed
|
||||
length, the caller should verify if true and clen less than the
|
||||
input data
|
||||
*/
|
||||
bool jar::deflate_bytes(bytes &head, bytes &tail)
|
||||
{
|
||||
int len = (int)(head.len + tail.len);
|
||||
|
||||
z_stream zs;
|
||||
BYTES_OF(zs).clear();
|
||||
|
||||
// NOTE: the window size should always be -MAX_WBITS normally -15.
|
||||
// unzip/zipup.c and java/Deflater.c
|
||||
|
||||
int error =
|
||||
deflateInit2(&zs, Z_BEST_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
/*
|
||||
switch (error)
|
||||
{
|
||||
case Z_MEM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Out of memory \n"));
|
||||
break;
|
||||
case Z_STREAM_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid compression level \n"));
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
PRINTCR((2, "Error: deflate error : Invalid version\n"));
|
||||
break;
|
||||
default:
|
||||
PRINTCR((2, "Error: Internal deflate error error = %d\n", error));
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
deflated.empty();
|
||||
zs.next_out = (uchar *)deflated.grow(len + (len / 2));
|
||||
zs.avail_out = (int)deflated.size();
|
||||
|
||||
zs.next_in = (uchar *)head.ptr;
|
||||
zs.avail_in = (int)head.len;
|
||||
|
||||
bytes *first = &head;
|
||||
bytes *last = &tail;
|
||||
if (last->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
last = &head;
|
||||
}
|
||||
else if (first->len == 0)
|
||||
{
|
||||
first = nullptr;
|
||||
}
|
||||
|
||||
if (first != nullptr && error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)first->ptr;
|
||||
zs.avail_in = (int)first->len;
|
||||
error = deflate(&zs, Z_NO_FLUSH);
|
||||
}
|
||||
if (error == Z_OK)
|
||||
{
|
||||
zs.next_in = (uchar *)last->ptr;
|
||||
zs.avail_in = (int)last->len;
|
||||
error = deflate(&zs, Z_FINISH);
|
||||
}
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
if (len > (int)zs.total_out)
|
||||
{
|
||||
deflated.b.len = zs.total_out;
|
||||
deflateEnd(&zs);
|
||||
return true;
|
||||
}
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
deflateEnd(&zs);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Callback for fetching data from a GZIP input stream
|
||||
static jlong read_input_via_gzip(unpacker *u, void *buf, jlong minlen, jlong maxlen)
|
||||
{
|
||||
assert(minlen <= maxlen); // don't talk nonsense
|
||||
jlong numread = 0;
|
||||
char *bufptr = (char *)buf;
|
||||
char *inbuf = u->gzin->inbuf;
|
||||
size_t inbuflen = sizeof(u->gzin->inbuf);
|
||||
unpacker::read_input_fn_t read_gzin_fn = (unpacker::read_input_fn_t)u->gzin->read_input_fn;
|
||||
z_stream &zs = *(z_stream *)u->gzin->zstream;
|
||||
while (numread < minlen)
|
||||
{
|
||||
int readlen = (1 << 16); // pretty arbitrary
|
||||
if (readlen > (maxlen - numread))
|
||||
readlen = (int)(maxlen - numread);
|
||||
zs.next_out = (uchar *)bufptr;
|
||||
zs.avail_out = readlen;
|
||||
if (zs.avail_in == 0)
|
||||
{
|
||||
zs.avail_in = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.next_in = (uchar *)inbuf;
|
||||
}
|
||||
int error = inflate(&zs, Z_NO_FLUSH);
|
||||
if (error != Z_OK && error != Z_STREAM_END)
|
||||
{
|
||||
u->abort("error inflating input");
|
||||
break;
|
||||
}
|
||||
int nr = readlen - zs.avail_out;
|
||||
numread += nr;
|
||||
bufptr += nr;
|
||||
assert(numread <= maxlen);
|
||||
if (error == Z_STREAM_END)
|
||||
{
|
||||
enum
|
||||
{
|
||||
TRAILER_LEN = 8
|
||||
};
|
||||
// skip 8-byte trailer
|
||||
if (zs.avail_in >= TRAILER_LEN)
|
||||
{
|
||||
zs.avail_in -= TRAILER_LEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bug: 5023768,we read past the TRAILER_LEN to see if there is
|
||||
// any extraneous data, as we dont support concatenated .gz
|
||||
// files just yet.
|
||||
int extra = (int)read_gzin_fn(u, inbuf, 1, inbuflen);
|
||||
zs.avail_in += extra - TRAILER_LEN;
|
||||
}
|
||||
// %%% should check final CRC and length here
|
||||
// %%% should check for concatenated *.gz files here
|
||||
if (zs.avail_in > 0)
|
||||
u->abort("garbage after end of deflated input stream");
|
||||
// pop this filter off:
|
||||
u->gzin->free();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fprintf(u->errstrm, "readInputFn(%d,%d) => %d (gunzip)\n",
|
||||
// (int)minlen, (int)maxlen, (int)numread);
|
||||
return numread;
|
||||
}
|
||||
|
||||
void gunzip::init(unpacker *u_)
|
||||
{
|
||||
BYTES_OF(*this).clear();
|
||||
u = u_;
|
||||
assert(u->gzin == nullptr); // once only, please
|
||||
read_input_fn = (void *)u->read_input_fn;
|
||||
zstream = NEW(z_stream, 1);
|
||||
u->gzin = this;
|
||||
u->read_input_fn = read_input_via_gzip;
|
||||
}
|
||||
|
||||
void gunzip::start(int magic)
|
||||
{
|
||||
assert((magic & GZIP_MAGIC_MASK) == GZIP_MAGIC);
|
||||
int gz_flg = (magic & 0xFF); // keep "flg", discard other 3 bytes
|
||||
enum
|
||||
{
|
||||
FHCRC = (1 << 1),
|
||||
FEXTRA = (1 << 2),
|
||||
FNAME = (1 << 3),
|
||||
FCOMMENT = (1 << 4)
|
||||
};
|
||||
char gz_mtime[4];
|
||||
char gz_xfl[1];
|
||||
char gz_os[1];
|
||||
char gz_extra_len[2];
|
||||
char gz_hcrc[2];
|
||||
char gz_ignore;
|
||||
// do not save extra, name, comment
|
||||
read_fixed_field(gz_mtime, sizeof(gz_mtime));
|
||||
read_fixed_field(gz_xfl, sizeof(gz_xfl));
|
||||
read_fixed_field(gz_os, sizeof(gz_os));
|
||||
if (gz_flg & FEXTRA)
|
||||
{
|
||||
read_fixed_field(gz_extra_len, sizeof(gz_extra_len));
|
||||
int extra_len = gz_extra_len[0] & 0xFF;
|
||||
extra_len += (gz_extra_len[1] & 0xFF) << 8;
|
||||
for (; extra_len > 0; extra_len--)
|
||||
{
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
}
|
||||
}
|
||||
int null_terms = 0;
|
||||
if (gz_flg & FNAME)
|
||||
null_terms++;
|
||||
if (gz_flg & FCOMMENT)
|
||||
null_terms++;
|
||||
for (; null_terms; null_terms--)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
gz_ignore = 0;
|
||||
read_fixed_field(&gz_ignore, 1);
|
||||
if (gz_ignore == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (gz_flg & FHCRC)
|
||||
read_fixed_field(gz_hcrc, sizeof(gz_hcrc));
|
||||
|
||||
if (aborting())
|
||||
return;
|
||||
|
||||
// now the input stream is ready to read into the inflater
|
||||
int error = inflateInit2((z_stream *)zstream, -MAX_WBITS);
|
||||
if (error != Z_OK)
|
||||
{
|
||||
abort("cannot create input");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void gunzip::free()
|
||||
{
|
||||
assert(u->gzin == this);
|
||||
u->gzin = nullptr;
|
||||
u->read_input_fn = (unpacker::read_input_fn_t) this->read_input_fn;
|
||||
inflateEnd((z_stream *)zstream);
|
||||
::free(zstream);
|
||||
zstream = nullptr;
|
||||
::free(this);
|
||||
}
|
||||
|
||||
void gunzip::read_fixed_field(char *buf, size_t buflen)
|
||||
{
|
||||
if (aborting())
|
||||
return;
|
||||
jlong nr = ((unpacker::read_input_fn_t)read_input_fn)(u, buf, buflen, buflen);
|
||||
if ((size_t)nr != buflen)
|
||||
u->abort("short stream header");
|
||||
}
|
130
depends/pack200/src/zip.h
Normal file
130
depends/pack200/src/zip.h
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
struct unpacker;
|
||||
|
||||
struct jar
|
||||
{
|
||||
// JAR file writer
|
||||
FILE *jarfp;
|
||||
int default_modtime;
|
||||
|
||||
// Used by unix2dostime:
|
||||
int modtime_cache;
|
||||
uint32_t dostime_cache;
|
||||
|
||||
// Private members
|
||||
fillbytes central_directory;
|
||||
ushort central_directory_count;
|
||||
uint output_file_offset;
|
||||
fillbytes deflated; // temporary buffer
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
// Public Methods
|
||||
void openJarFile(const char *fname);
|
||||
void addJarEntry(const char *fname, bool deflate_hint, int modtime, bytes &head,
|
||||
bytes &tail);
|
||||
void addDirectoryToJarFile(const char *dir_name);
|
||||
void closeJarFile(bool central);
|
||||
|
||||
void init(unpacker *u_);
|
||||
|
||||
void free()
|
||||
{
|
||||
central_directory.free();
|
||||
deflated.free();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
free();
|
||||
init(u);
|
||||
}
|
||||
|
||||
// Private Methods
|
||||
void write_data(void *ptr, int len);
|
||||
void write_data(bytes &b)
|
||||
{
|
||||
write_data(b.ptr, (int)b.len);
|
||||
}
|
||||
void add_to_jar_directory(const char *fname, bool store, int modtime, int len, int clen,
|
||||
uint32_t crc);
|
||||
void write_jar_header(const char *fname, bool store, int modtime, int len, int clen,
|
||||
unsigned int crc);
|
||||
void write_central_directory();
|
||||
uint32_t dostime(int y, int n, int d, int h, int m, int s);
|
||||
uint32_t get_dostime(int modtime);
|
||||
|
||||
// The definitions of these depend on the NO_ZLIB option:
|
||||
bool deflate_bytes(bytes &head, bytes &tail);
|
||||
static uint get_crc32(uint c, unsigned char *ptr, uint len);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
||||
|
||||
struct gunzip
|
||||
{
|
||||
// optional gzip input stream control block
|
||||
|
||||
// pointer to outer unpacker, for error checks etc.
|
||||
unpacker *u;
|
||||
|
||||
void *read_input_fn; // underlying byte stream
|
||||
void *zstream; // inflater state
|
||||
char inbuf[1 << 14]; // input buffer
|
||||
|
||||
void init(unpacker *u_); // pushes new value on u->read_input_fn
|
||||
|
||||
void free();
|
||||
|
||||
void start(int magic);
|
||||
|
||||
// private stuff
|
||||
void read_fixed_field(char *buf, size_t buflen);
|
||||
|
||||
// error handling
|
||||
void abort(const char *msg)
|
||||
{
|
||||
unpack_abort(msg, u);
|
||||
}
|
||||
bool aborting()
|
||||
{
|
||||
return unpack_aborting(u);
|
||||
}
|
||||
};
|
@ -189,5 +189,8 @@ void OneSixUpdate::jarlibFinished()
|
||||
|
||||
void OneSixUpdate::jarlibFailed()
|
||||
{
|
||||
emitFailed("Failed to download the binary garbage. Try again. Maybe. IF YOU DARE");
|
||||
QStringList failed = jarlibDownloadJob->getFailedFiles();
|
||||
QString failed_all = failed.join("\n");
|
||||
emitFailed("Failed to download the following files:\n" + failed_all +
|
||||
"\n\nPlease try again.");
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ void MCVListLoadTask::executeTask()
|
||||
|
||||
void MCVListLoadTask::list_downloaded()
|
||||
{
|
||||
if(vlistReply->error() != QNetworkReply::QNetworkReply::NoError)
|
||||
if(vlistReply->error() != QNetworkReply::NoError)
|
||||
{
|
||||
vlistReply->deleteLater();
|
||||
emitFailed("Failed to load Minecraft main version list" + vlistReply->errorString());
|
||||
|
@ -31,7 +31,7 @@ void ByteArrayDownload::downloadProgress ( qint64 bytesReceived, qint64 bytesTot
|
||||
void ByteArrayDownload::downloadError ( QNetworkReply::NetworkError error )
|
||||
{
|
||||
// error happened during download.
|
||||
// TODO: log the reason why
|
||||
qDebug() << "URL:" << m_url.toString().toLocal8Bit() << "Network error: " << error;
|
||||
m_status = Job_Failed;
|
||||
}
|
||||
|
||||
|
@ -7,47 +7,48 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
ByteArrayDownloadPtr DownloadJob::add ( QUrl url )
|
||||
ByteArrayDownloadPtr DownloadJob::add(QUrl url)
|
||||
{
|
||||
ByteArrayDownloadPtr ptr (new ByteArrayDownload(url));
|
||||
ByteArrayDownloadPtr ptr(new ByteArrayDownload(url));
|
||||
ptr->index_within_job = downloads.size();
|
||||
downloads.append(ptr);
|
||||
parts_progress.append(QPair<qint64, qint64>(0,1));
|
||||
parts_progress.append(part_info());
|
||||
total_progress++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
FileDownloadPtr DownloadJob::add ( QUrl url, QString rel_target_path)
|
||||
FileDownloadPtr DownloadJob::add(QUrl url, QString rel_target_path)
|
||||
{
|
||||
FileDownloadPtr ptr (new FileDownload(url, rel_target_path));
|
||||
FileDownloadPtr ptr(new FileDownload(url, rel_target_path));
|
||||
ptr->index_within_job = downloads.size();
|
||||
downloads.append(ptr);
|
||||
parts_progress.append(QPair<qint64, qint64>(0,1));
|
||||
parts_progress.append(part_info());
|
||||
total_progress++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
CacheDownloadPtr DownloadJob::add ( QUrl url, MetaEntryPtr entry)
|
||||
CacheDownloadPtr DownloadJob::add(QUrl url, MetaEntryPtr entry)
|
||||
{
|
||||
CacheDownloadPtr ptr (new CacheDownload(url, entry));
|
||||
CacheDownloadPtr ptr(new CacheDownload(url, entry));
|
||||
ptr->index_within_job = downloads.size();
|
||||
downloads.append(ptr);
|
||||
parts_progress.append(QPair<qint64, qint64>(0,1));
|
||||
parts_progress.append(part_info());
|
||||
total_progress++;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void DownloadJob::partSucceeded ( int index )
|
||||
void DownloadJob::partSucceeded(int index)
|
||||
{
|
||||
// do progress. all slots are 1 in size at least
|
||||
auto & slot = parts_progress[index];
|
||||
partProgress ( index, slot.second , slot.second );
|
||||
auto &slot = parts_progress[index];
|
||||
partProgress(index, slot.total_progress, slot.total_progress);
|
||||
|
||||
num_succeeded++;
|
||||
qDebug() << m_job_name.toLocal8Bit() << " progress: " << num_succeeded << "/" << downloads.size();
|
||||
if(num_failed + num_succeeded == downloads.size())
|
||||
qDebug() << m_job_name.toLocal8Bit() << " progress: " << num_succeeded << "/"
|
||||
<< downloads.size();
|
||||
if (num_failed + num_succeeded == downloads.size())
|
||||
{
|
||||
if(num_failed)
|
||||
if (num_failed)
|
||||
{
|
||||
qDebug() << m_job_name.toLocal8Bit() << " failed.";
|
||||
emit failed();
|
||||
@ -60,39 +61,65 @@ void DownloadJob::partSucceeded ( int index )
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadJob::partFailed ( int index )
|
||||
void DownloadJob::partFailed(int index)
|
||||
{
|
||||
auto &slot = parts_progress[index];
|
||||
if (slot.failures == 3)
|
||||
{
|
||||
qDebug() << "Part " << index << " failed 3 times (" << downloads[index]->m_url << ")";
|
||||
num_failed++;
|
||||
if(num_failed + num_succeeded == downloads.size())
|
||||
if (num_failed + num_succeeded == downloads.size())
|
||||
{
|
||||
qDebug() << m_job_name.toLocal8Bit() << " failed.";
|
||||
emit failed();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Part " << index << " failed, restarting (" << downloads[index]->m_url
|
||||
<< ")";
|
||||
// restart the job
|
||||
slot.failures++;
|
||||
downloads[index]->start();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadJob::partProgress ( int index, qint64 bytesReceived, qint64 bytesTotal )
|
||||
void DownloadJob::partProgress(int index, qint64 bytesReceived, qint64 bytesTotal)
|
||||
{
|
||||
auto & slot = parts_progress[index];
|
||||
auto &slot = parts_progress[index];
|
||||
|
||||
current_progress -= slot.first;
|
||||
slot.first = bytesReceived;
|
||||
current_progress += slot.first;
|
||||
current_progress -= slot.current_progress;
|
||||
slot.current_progress = bytesReceived;
|
||||
current_progress += slot.current_progress;
|
||||
|
||||
total_progress -= slot.second;
|
||||
slot.second = bytesTotal;
|
||||
total_progress += slot.second;
|
||||
total_progress -= slot.total_progress;
|
||||
slot.total_progress = bytesTotal;
|
||||
total_progress += slot.total_progress;
|
||||
emit progress(current_progress, total_progress);
|
||||
}
|
||||
|
||||
|
||||
void DownloadJob::start()
|
||||
{
|
||||
qDebug() << m_job_name.toLocal8Bit() << " started.";
|
||||
for(auto iter: downloads)
|
||||
for (auto iter : downloads)
|
||||
{
|
||||
connect(iter.data(), SIGNAL(succeeded(int)), SLOT(partSucceeded(int)));
|
||||
connect(iter.data(), SIGNAL(failed(int)), SLOT(partFailed(int)));
|
||||
connect(iter.data(), SIGNAL(progress(int,qint64,qint64)), SLOT(partProgress(int,qint64,qint64)));
|
||||
connect(iter.data(), SIGNAL(progress(int, qint64, qint64)),
|
||||
SLOT(partProgress(int, qint64, qint64)));
|
||||
iter->start();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DownloadJob::getFailedFiles()
|
||||
{
|
||||
QStringList failed;
|
||||
for (auto download : downloads)
|
||||
{
|
||||
if (download->m_status == Job_Failed)
|
||||
{
|
||||
failed.push_back(download->m_url.toString());
|
||||
}
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ public:
|
||||
{
|
||||
return m_running;
|
||||
};
|
||||
QStringList getFailedFiles();
|
||||
signals:
|
||||
void started();
|
||||
void progress(qint64 current, qint64 total);
|
||||
@ -63,9 +64,15 @@ private slots:
|
||||
void partSucceeded(int index);
|
||||
void partFailed(int index);
|
||||
private:
|
||||
struct part_info
|
||||
{
|
||||
qint64 current_progress = 0;
|
||||
qint64 total_progress = 1;
|
||||
int failures = 0;
|
||||
};
|
||||
QString m_job_name;
|
||||
QList<DownloadPtr> downloads;
|
||||
QList<QPair<qint64, qint64>> parts_progress;
|
||||
QList<part_info> parts_progress;
|
||||
qint64 current_progress = 0;
|
||||
qint64 total_progress = 0;
|
||||
int num_succeeded = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user