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

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