mirror of
https://github.com/emmanuel-marty/lzsa.git
synced 2024-11-24 19:32:16 +00:00
Implement raw block mode
This commit is contained in:
parent
11d1ff8cd7
commit
18fc4da994
14
src/expand.c
14
src/expand.c
@ -186,12 +186,15 @@ int lzsa_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned ch
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((pInBlock + 2) <= pInBlockEnd) { /* The last token in the block does not include match information */
|
||||
if (pInBlock < pInBlockEnd) { /* The last token in the block does not include match information */
|
||||
int nMatchOffset;
|
||||
|
||||
nMatchOffset = ((unsigned int)*pInBlock++);
|
||||
if (token & 0x80)
|
||||
if (token & 0x80) {
|
||||
if (pInBlock >= pInBlockEnd) return -1;
|
||||
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
||||
}
|
||||
if (nMatchOffset == 0xffff) break;
|
||||
nMatchOffset++;
|
||||
|
||||
const unsigned char *pSrc = pCurOutData - nMatchOffset;
|
||||
@ -219,12 +222,15 @@ int lzsa_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned ch
|
||||
if (lzsa_expand_literals_slow(&pInBlock, pInBlockEnd, nLiterals, &pCurOutData, pOutDataEnd))
|
||||
return -1;
|
||||
|
||||
if ((pInBlock + 2) <= pInBlockEnd) { /* The last token in the block does not include match information */
|
||||
if (pInBlock < pInBlockEnd) { /* The last token in the block does not include match information */
|
||||
int nMatchOffset;
|
||||
|
||||
nMatchOffset = ((unsigned int)*pInBlock++);
|
||||
if (token & 0x80)
|
||||
if (token & 0x80) {
|
||||
if (pInBlock >= pInBlockEnd) return -1;
|
||||
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
||||
}
|
||||
if (nMatchOffset == 0xffff) break;
|
||||
nMatchOffset++;
|
||||
|
||||
const unsigned char *pSrc = pCurOutData - nMatchOffset;
|
||||
|
128
src/main.c
128
src/main.c
@ -34,6 +34,8 @@
|
||||
#include "expand.h"
|
||||
|
||||
#define BLOCK_SIZE 65536
|
||||
#define OPT_VERBOSE 1
|
||||
#define OPT_RAW 2
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
@ -56,14 +58,14 @@ static long long lzsa_get_time() {
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename, int nVerbosity) {
|
||||
static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename, const unsigned int nOptions) {
|
||||
FILE *f_in, *f_out;
|
||||
unsigned char *pInData, *pOutData;
|
||||
lsza_compressor compressor;
|
||||
long long nStartTime = 0LL, nEndTime = 0LL;
|
||||
long long nOriginalSize = 0LL, nCompressedSize = 0LL;
|
||||
int nResult;
|
||||
bool bError;
|
||||
bool bError = false;
|
||||
|
||||
f_in = fopen(pszInFilename, "rb");
|
||||
if (!f_in) {
|
||||
@ -124,6 +126,7 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
return 100;
|
||||
}
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
unsigned char cHeader[3];
|
||||
|
||||
cHeader[0] = 0x7b; /* Magic number: 0x9e7b */
|
||||
@ -132,8 +135,9 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
|
||||
bError = fwrite(cHeader, 1, 3, f_out) != 3;
|
||||
nCompressedSize += 3LL;
|
||||
}
|
||||
|
||||
if (nVerbosity > 0) {
|
||||
if (nOptions & OPT_VERBOSE) {
|
||||
nStartTime = lzsa_get_time();
|
||||
}
|
||||
|
||||
@ -148,12 +152,19 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
|
||||
nInDataSize = (int)fread(pInData + BLOCK_SIZE, 1, BLOCK_SIZE, f_in);
|
||||
if (nInDataSize > 0) {
|
||||
if (nPreviousBlockSize && (nOptions & OPT_RAW) != 0) {
|
||||
fprintf(stderr, "error: raw blocks can only be used with files <= 64 Kb\n");
|
||||
bError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
int nOutDataSize;
|
||||
|
||||
nOutDataSize = lzsa_shrink_block(&compressor, pInData + BLOCK_SIZE - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutData, (nInDataSize >= BLOCK_SIZE) ? BLOCK_SIZE : nInDataSize);
|
||||
if (nOutDataSize >= 0) {
|
||||
/* Write compressed block */
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
unsigned char cBlockSize[3];
|
||||
|
||||
cBlockSize[0] = nOutDataSize & 0xff;
|
||||
@ -163,7 +174,9 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
if (fwrite(cBlockSize, 1, 3, f_out) != (size_t)3) {
|
||||
bError = true;
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
if (!bError) {
|
||||
if (fwrite(pOutData, 1, (size_t)nOutDataSize, f_out) != (size_t)nOutDataSize) {
|
||||
bError = true;
|
||||
}
|
||||
@ -176,6 +189,12 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
else {
|
||||
/* Write uncompressible, literal block */
|
||||
|
||||
if ((nOptions & OPT_RAW) != 0) {
|
||||
fprintf(stderr, "error: data is incompressible, raw blocks only support compressed data\n");
|
||||
bError = true;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned char cBlockSize[3];
|
||||
|
||||
cBlockSize[0] = nInDataSize & 0xff;
|
||||
@ -206,7 +225,7 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
|
||||
unsigned char cFooter[3];
|
||||
|
||||
cFooter[0] = 0xFF; /* EOD frame */
|
||||
cFooter[0] = 0xFF; /* EOD frame (written even in raw mode, so that the end of the data can be detected) */
|
||||
cFooter[1] = 0xFF;
|
||||
cFooter[2] = 0xFF;
|
||||
|
||||
@ -214,7 +233,7 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
bError = fwrite(cFooter, 1, 3, f_out) != 3;
|
||||
nCompressedSize += 3LL;
|
||||
|
||||
if (!bError && nVerbosity > 0) {
|
||||
if (!bError && (nOptions & OPT_VERBOSE)) {
|
||||
nEndTime = lzsa_get_time();
|
||||
|
||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
||||
@ -248,9 +267,10 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename, int nVerbosity) {
|
||||
static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename, const unsigned int nOptions) {
|
||||
long long nStartTime = 0LL, nEndTime = 0LL;
|
||||
long long nOriginalSize = 0LL;
|
||||
unsigned int nFileSize = 0;
|
||||
|
||||
FILE *pInFile = fopen(pszInFilename, "rb");
|
||||
if (!pInFile) {
|
||||
@ -258,6 +278,7 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
return 100;
|
||||
}
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
unsigned char cHeader[3];
|
||||
|
||||
memset(cHeader, 0, 3);
|
||||
@ -277,6 +298,19 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
fprintf(stderr, "invalid magic number or format version in input file\n");
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fseek(pInFile, 0, SEEK_END);
|
||||
nFileSize = (unsigned int)ftell(pInFile);
|
||||
fseek(pInFile, 0, SEEK_SET);
|
||||
|
||||
if (nFileSize < 3) {
|
||||
fclose(pInFile);
|
||||
pInFile = NULL;
|
||||
fprintf(stderr, "invalid file size for raw block mode\n");
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *pOutFile = fopen(pszOutFilename, "wb");
|
||||
if (!pOutFile) {
|
||||
@ -314,7 +348,7 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (nVerbosity > 0) {
|
||||
if (nOptions & OPT_VERBOSE) {
|
||||
nStartTime = lzsa_get_time();
|
||||
}
|
||||
|
||||
@ -323,15 +357,27 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
|
||||
while (!feof(pInFile) && !nDecompressionError) {
|
||||
unsigned char cBlockSize[3];
|
||||
unsigned int nBlockSize = 0;
|
||||
|
||||
if (nPrevDecompressedSize != 0) {
|
||||
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
||||
}
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
||||
unsigned int nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||
nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||
(((unsigned int)cBlockSize[1]) << 8) |
|
||||
(((unsigned int)cBlockSize[2]) << 16);
|
||||
}
|
||||
else {
|
||||
nBlockSize = 0xffffff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nBlockSize = nFileSize - 3;
|
||||
nFileSize = 0xffffff;
|
||||
}
|
||||
|
||||
if ((nBlockSize & 0x400000) == 0) {
|
||||
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
||||
int nDecompressedSize = 0;
|
||||
@ -368,7 +414,6 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(pOutData);
|
||||
pOutData = NULL;
|
||||
@ -387,7 +432,7 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
return 100;
|
||||
}
|
||||
else {
|
||||
if (nVerbosity > 0) {
|
||||
if (nOptions & OPT_VERBOSE) {
|
||||
nEndTime = lzsa_get_time();
|
||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
||||
double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
|
||||
@ -399,10 +444,11 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
||||
}
|
||||
}
|
||||
|
||||
static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, int nVerbosity) {
|
||||
static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, const unsigned int nOptions) {
|
||||
long long nStartTime = 0LL, nEndTime = 0LL;
|
||||
long long nOriginalSize = 0LL;
|
||||
long long nKnownGoodSize = 0LL;
|
||||
unsigned int nFileSize = 0;
|
||||
|
||||
FILE *pInFile = fopen(pszInFilename, "rb");
|
||||
if (!pInFile) {
|
||||
@ -410,6 +456,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
return 100;
|
||||
}
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
unsigned char cHeader[3];
|
||||
|
||||
memset(cHeader, 0, 3);
|
||||
@ -429,6 +476,19 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
fprintf(stderr, "invalid magic number or format version in input file\n");
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fseek(pInFile, 0, SEEK_END);
|
||||
nFileSize = (unsigned int)ftell(pInFile);
|
||||
fseek(pInFile, 0, SEEK_SET);
|
||||
|
||||
if (nFileSize < 3) {
|
||||
fclose(pInFile);
|
||||
pInFile = NULL;
|
||||
fprintf(stderr, "invalid file size for raw block mode\n");
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *pOutFile = fopen(pszOutFilename, "rb");
|
||||
if (!pOutFile) {
|
||||
@ -484,7 +544,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (nVerbosity > 0) {
|
||||
if (nOptions & OPT_VERBOSE) {
|
||||
nStartTime = lzsa_get_time();
|
||||
}
|
||||
|
||||
@ -493,7 +553,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
int nPrevDecompressedSize = 0;
|
||||
|
||||
while (!feof(pInFile) && !nDecompressionError && !bComparisonError) {
|
||||
unsigned char cBlockSize[3];
|
||||
unsigned int nBlockSize = 0;
|
||||
|
||||
if (nPrevDecompressedSize != 0) {
|
||||
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
||||
@ -501,10 +561,23 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
|
||||
int nBytesToCompare = (int)fread(pCompareData, 1, BLOCK_SIZE, pOutFile);
|
||||
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
unsigned char cBlockSize[3];
|
||||
|
||||
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
||||
unsigned int nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||
nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||
(((unsigned int)cBlockSize[1]) << 8) |
|
||||
(((unsigned int)cBlockSize[2]) << 16);
|
||||
}
|
||||
else {
|
||||
nBlockSize = 0xffffff;
|
||||
}
|
||||
}
|
||||
else {
|
||||
nBlockSize = nFileSize - 3;
|
||||
nFileSize = 0xffffff;
|
||||
}
|
||||
|
||||
if ((nBlockSize & 0x400000) == 0) {
|
||||
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
||||
int nDecompressedSize = 0;
|
||||
@ -548,7 +621,6 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(pCompareData);
|
||||
pCompareData = NULL;
|
||||
@ -574,7 +646,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
||||
return 100;
|
||||
}
|
||||
else {
|
||||
if (nVerbosity > 0) {
|
||||
if (nOptions & OPT_VERBOSE) {
|
||||
nEndTime = lzsa_get_time();
|
||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
||||
double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
|
||||
@ -596,7 +668,7 @@ int main(int argc, char **argv) {
|
||||
bool bCommandDefined = false;
|
||||
bool bVerifyCompression = false;
|
||||
char cCommand = 'z';
|
||||
int nVerbosity = 0;
|
||||
unsigned int nOptions = 0;
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-d")) {
|
||||
@ -623,8 +695,15 @@ int main(int argc, char **argv) {
|
||||
bArgsError = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-v")) {
|
||||
if (nVerbosity == 0) {
|
||||
nVerbosity = 1;
|
||||
if ((nOptions & OPT_VERBOSE) == 0) {
|
||||
nOptions |= OPT_VERBOSE;
|
||||
}
|
||||
else
|
||||
bArgsError = true;
|
||||
}
|
||||
else if (!strcmp(argv[i], "-r")) {
|
||||
if ((nOptions & OPT_RAW) == 0) {
|
||||
nOptions |= OPT_RAW;
|
||||
}
|
||||
else
|
||||
bArgsError = true;
|
||||
@ -642,21 +721,22 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
|
||||
if (bArgsError || !pszInFilename || !pszOutFilename) {
|
||||
fprintf(stderr, "usage: %s [-c] [-d] [-v] <infile> <outfile>\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s [-c] [-d] [-v] [-r] <infile> <outfile>\n", argv[0]);
|
||||
fprintf(stderr, " -c: check resulting stream after compressing\n");
|
||||
fprintf(stderr, " -d: decompress (default: compress)\n");
|
||||
fprintf(stderr, " -v: be verbose\n");
|
||||
fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n");
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (cCommand == 'z') {
|
||||
int nResult = lzsa_compress(pszInFilename, pszOutFilename, nVerbosity);
|
||||
int nResult = lzsa_compress(pszInFilename, pszOutFilename, nOptions);
|
||||
if (nResult == 0 && bVerifyCompression) {
|
||||
nResult = lzsa_compare(pszOutFilename, pszInFilename, nVerbosity);
|
||||
nResult = lzsa_compare(pszOutFilename, pszInFilename, nOptions);
|
||||
}
|
||||
}
|
||||
else if (cCommand == 'd') {
|
||||
return lzsa_decompress(pszInFilename, pszOutFilename, nVerbosity);
|
||||
return lzsa_decompress(pszInFilename, pszOutFilename, nOptions);
|
||||
}
|
||||
else {
|
||||
return 100;
|
||||
|
Loading…
Reference in New Issue
Block a user