Compression algo dependencies, still need hackery...

This commit is contained in:
Petr Mrázek 2013-09-26 02:58:09 +02:00
parent af234f3502
commit 2c8dc0b855
52 changed files with 17769 additions and 40 deletions

View File

@ -43,6 +43,10 @@ include_directories(${Qt5Widgets_INCLUDE_DIRS})
add_subdirectory(depends/quazip) add_subdirectory(depends/quazip)
include_directories(depends/quazip) include_directories(depends/quazip)
# Add lzma
add_subdirectory(depends/lzma)
include_directories(depends/lzma/include)
# Add the java launcher # Add the java launcher
add_subdirectory(depends/launcher) add_subdirectory(depends/launcher)
@ -60,6 +64,8 @@ include_directories(${LIBSETTINGS_INCLUDE_DIR})
add_subdirectory(depends/groupview) add_subdirectory(depends/groupview)
include_directories(${LIBGROUPVIEW_INCLUDE_DIR}) include_directories(${LIBGROUPVIEW_INCLUDE_DIR})
#pack 200
add_subdirectory(depends/pack200)
################################ SET UP BUILD OPTIONS ################################ ################################ SET UP BUILD OPTIONS ################################
@ -345,8 +351,9 @@ ADD_EXECUTABLE(MultiMC MACOSX_BUNDLE WIN32
# Link # Link
QT5_USE_MODULES(MultiMC Widgets Network Xml) QT5_USE_MODULES(MultiMC Widgets Network Xml)
TARGET_LINK_LIBRARIES(MultiMC quazip libUtil libSettings libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS}) TARGET_LINK_LIBRARIES(MultiMC quazip lzma libUtil libSettings libGroupView
ADD_DEPENDENCIES(MultiMC MultiMCLauncher 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) option(BUILD_KEYRING_TEST "Build the simple keyring test binary" OFF)

View 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
View 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.
#

View 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
View 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);
}

View 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

View 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

View 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

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

File diff suppressed because it is too large Load Diff

220
depends/lzma/pavlov/LzmaDec.h Executable file
View 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

File diff suppressed because it is too large Load Diff

71
depends/lzma/pavlov/LzmaEnc.h Executable file
View 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
View 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
View 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
View 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;

View 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;
}

View 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

View 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);
}

View 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;
}

View 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;
}

View 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

View 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;
}

View 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

View 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;
}

View 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()

View File

@ -0,0 +1 @@

View 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
View 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]

View 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
View 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;
}
};

File diff suppressed because it is too large Load Diff

View 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(); }

View 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
};

View 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

View 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;
}

File diff suppressed because it is too large Load Diff

View 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();
}

View 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();
}

View 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
View 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
View 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);
}
};

View File

@ -189,5 +189,8 @@ void OneSixUpdate::jarlibFinished()
void OneSixUpdate::jarlibFailed() 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.");
} }

View File

@ -152,7 +152,7 @@ void MCVListLoadTask::executeTask()
void MCVListLoadTask::list_downloaded() void MCVListLoadTask::list_downloaded()
{ {
if(vlistReply->error() != QNetworkReply::QNetworkReply::NoError) if(vlistReply->error() != QNetworkReply::NoError)
{ {
vlistReply->deleteLater(); vlistReply->deleteLater();
emitFailed("Failed to load Minecraft main version list" + vlistReply->errorString()); emitFailed("Failed to load Minecraft main version list" + vlistReply->errorString());

View File

@ -31,7 +31,7 @@ void ByteArrayDownload::downloadProgress ( qint64 bytesReceived, qint64 bytesTot
void ByteArrayDownload::downloadError ( QNetworkReply::NetworkError error ) void ByteArrayDownload::downloadError ( QNetworkReply::NetworkError error )
{ {
// error happened during download. // error happened during download.
// TODO: log the reason why qDebug() << "URL:" << m_url.toString().toLocal8Bit() << "Network error: " << error;
m_status = Job_Failed; m_status = Job_Failed;
} }

View File

@ -7,47 +7,48 @@
#include <QDebug> #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(); ptr->index_within_job = downloads.size();
downloads.append(ptr); downloads.append(ptr);
parts_progress.append(QPair<qint64, qint64>(0,1)); parts_progress.append(part_info());
total_progress++; total_progress++;
return ptr; 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(); ptr->index_within_job = downloads.size();
downloads.append(ptr); downloads.append(ptr);
parts_progress.append(QPair<qint64, qint64>(0,1)); parts_progress.append(part_info());
total_progress++; total_progress++;
return ptr; 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(); ptr->index_within_job = downloads.size();
downloads.append(ptr); downloads.append(ptr);
parts_progress.append(QPair<qint64, qint64>(0,1)); parts_progress.append(part_info());
total_progress++; total_progress++;
return ptr; return ptr;
} }
void DownloadJob::partSucceeded ( int index ) void DownloadJob::partSucceeded(int index)
{ {
// do progress. all slots are 1 in size at least // do progress. all slots are 1 in size at least
auto & slot = parts_progress[index]; auto &slot = parts_progress[index];
partProgress ( index, slot.second , slot.second ); partProgress(index, slot.total_progress, slot.total_progress);
num_succeeded++; num_succeeded++;
qDebug() << m_job_name.toLocal8Bit() << " progress: " << num_succeeded << "/" << downloads.size(); qDebug() << m_job_name.toLocal8Bit() << " progress: " << num_succeeded << "/"
if(num_failed + num_succeeded == downloads.size()) << downloads.size();
if (num_failed + num_succeeded == downloads.size())
{ {
if(num_failed) if (num_failed)
{ {
qDebug() << m_job_name.toLocal8Bit() << " failed."; qDebug() << m_job_name.toLocal8Bit() << " failed.";
emit 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++; num_failed++;
if(num_failed + num_succeeded == downloads.size()) if (num_failed + num_succeeded == downloads.size())
{ {
qDebug() << m_job_name.toLocal8Bit() << " failed."; qDebug() << m_job_name.toLocal8Bit() << " failed.";
emit 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; current_progress -= slot.current_progress;
slot.first = bytesReceived; slot.current_progress = bytesReceived;
current_progress += slot.first; current_progress += slot.current_progress;
total_progress -= slot.second; total_progress -= slot.total_progress;
slot.second = bytesTotal; slot.total_progress = bytesTotal;
total_progress += slot.second; total_progress += slot.total_progress;
emit progress(current_progress, total_progress); emit progress(current_progress, total_progress);
} }
void DownloadJob::start() void DownloadJob::start()
{ {
qDebug() << m_job_name.toLocal8Bit() << " started."; 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(succeeded(int)), SLOT(partSucceeded(int)));
connect(iter.data(), SIGNAL(failed(int)), SLOT(partFailed(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(); 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;
}

View File

@ -51,6 +51,7 @@ public:
{ {
return m_running; return m_running;
}; };
QStringList getFailedFiles();
signals: signals:
void started(); void started();
void progress(qint64 current, qint64 total); void progress(qint64 current, qint64 total);
@ -63,9 +64,15 @@ private slots:
void partSucceeded(int index); void partSucceeded(int index);
void partFailed(int index); void partFailed(int index);
private: private:
struct part_info
{
qint64 current_progress = 0;
qint64 total_progress = 1;
int failures = 0;
};
QString m_job_name; QString m_job_name;
QList<DownloadPtr> downloads; QList<DownloadPtr> downloads;
QList<QPair<qint64, qint64>> parts_progress; QList<part_info> parts_progress;
qint64 current_progress = 0; qint64 current_progress = 0;
qint64 total_progress = 0; qint64 total_progress = 0;
int num_succeeded = 0; int num_succeeded = 0;