mirror of
https://github.com/emmanuel-marty/lzsa.git
synced 2024-11-28 14:50:44 +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;
|
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;
|
int nMatchOffset;
|
||||||
|
|
||||||
nMatchOffset = ((unsigned int)*pInBlock++);
|
nMatchOffset = ((unsigned int)*pInBlock++);
|
||||||
if (token & 0x80)
|
if (token & 0x80) {
|
||||||
|
if (pInBlock >= pInBlockEnd) return -1;
|
||||||
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
||||||
|
}
|
||||||
|
if (nMatchOffset == 0xffff) break;
|
||||||
nMatchOffset++;
|
nMatchOffset++;
|
||||||
|
|
||||||
const unsigned char *pSrc = pCurOutData - 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))
|
if (lzsa_expand_literals_slow(&pInBlock, pInBlockEnd, nLiterals, &pCurOutData, pOutDataEnd))
|
||||||
return -1;
|
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;
|
int nMatchOffset;
|
||||||
|
|
||||||
nMatchOffset = ((unsigned int)*pInBlock++);
|
nMatchOffset = ((unsigned int)*pInBlock++);
|
||||||
if (token & 0x80)
|
if (token & 0x80) {
|
||||||
|
if (pInBlock >= pInBlockEnd) return -1;
|
||||||
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
nMatchOffset |= (((unsigned int)*pInBlock++) << 8);
|
||||||
|
}
|
||||||
|
if (nMatchOffset == 0xffff) break;
|
||||||
nMatchOffset++;
|
nMatchOffset++;
|
||||||
|
|
||||||
const unsigned char *pSrc = pCurOutData - nMatchOffset;
|
const unsigned char *pSrc = pCurOutData - nMatchOffset;
|
||||||
|
324
src/main.c
324
src/main.c
@ -34,6 +34,8 @@
|
|||||||
#include "expand.h"
|
#include "expand.h"
|
||||||
|
|
||||||
#define BLOCK_SIZE 65536
|
#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;
|
FILE *f_in, *f_out;
|
||||||
unsigned char *pInData, *pOutData;
|
unsigned char *pInData, *pOutData;
|
||||||
lsza_compressor compressor;
|
lsza_compressor compressor;
|
||||||
long long nStartTime = 0LL, nEndTime = 0LL;
|
long long nStartTime = 0LL, nEndTime = 0LL;
|
||||||
long long nOriginalSize = 0LL, nCompressedSize = 0LL;
|
long long nOriginalSize = 0LL, nCompressedSize = 0LL;
|
||||||
int nResult;
|
int nResult;
|
||||||
bool bError;
|
bool bError = false;
|
||||||
|
|
||||||
f_in = fopen(pszInFilename, "rb");
|
f_in = fopen(pszInFilename, "rb");
|
||||||
if (!f_in) {
|
if (!f_in) {
|
||||||
@ -124,16 +126,18 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char cHeader[3];
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
|
unsigned char cHeader[3];
|
||||||
|
|
||||||
cHeader[0] = 0x7b; /* Magic number: 0x9e7b */
|
cHeader[0] = 0x7b; /* Magic number: 0x9e7b */
|
||||||
cHeader[1] = 0x9e;
|
cHeader[1] = 0x9e;
|
||||||
cHeader[2] = 0; /* Format version 1 */
|
cHeader[2] = 0; /* Format version 1 */
|
||||||
|
|
||||||
bError = fwrite(cHeader, 1, 3, f_out) != 3;
|
bError = fwrite(cHeader, 1, 3, f_out) != 3;
|
||||||
nCompressedSize += 3LL;
|
nCompressedSize += 3LL;
|
||||||
|
}
|
||||||
|
|
||||||
if (nVerbosity > 0) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = lzsa_get_time();
|
nStartTime = lzsa_get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,22 +152,31 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
|||||||
|
|
||||||
nInDataSize = (int)fread(pInData + BLOCK_SIZE, 1, BLOCK_SIZE, f_in);
|
nInDataSize = (int)fread(pInData + BLOCK_SIZE, 1, BLOCK_SIZE, f_in);
|
||||||
if (nInDataSize > 0) {
|
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;
|
int nOutDataSize;
|
||||||
|
|
||||||
nOutDataSize = lzsa_shrink_block(&compressor, pInData + BLOCK_SIZE - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutData, (nInDataSize >= BLOCK_SIZE) ? BLOCK_SIZE : nInDataSize);
|
nOutDataSize = lzsa_shrink_block(&compressor, pInData + BLOCK_SIZE - nPreviousBlockSize, nPreviousBlockSize, nInDataSize, pOutData, (nInDataSize >= BLOCK_SIZE) ? BLOCK_SIZE : nInDataSize);
|
||||||
if (nOutDataSize >= 0) {
|
if (nOutDataSize >= 0) {
|
||||||
/* Write compressed block */
|
/* Write compressed block */
|
||||||
|
|
||||||
unsigned char cBlockSize[3];
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
|
unsigned char cBlockSize[3];
|
||||||
|
|
||||||
cBlockSize[0] = nOutDataSize & 0xff;
|
cBlockSize[0] = nOutDataSize & 0xff;
|
||||||
cBlockSize[1] = (nOutDataSize >> 8) & 0xff;
|
cBlockSize[1] = (nOutDataSize >> 8) & 0xff;
|
||||||
cBlockSize[2] = (nOutDataSize >> 16) & 0xff;
|
cBlockSize[2] = (nOutDataSize >> 16) & 0xff;
|
||||||
|
|
||||||
if (fwrite(cBlockSize, 1, 3, f_out) != (size_t)3) {
|
if (fwrite(cBlockSize, 1, 3, f_out) != (size_t)3) {
|
||||||
bError = true;
|
bError = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
if (!bError) {
|
||||||
if (fwrite(pOutData, 1, (size_t)nOutDataSize, f_out) != (size_t)nOutDataSize) {
|
if (fwrite(pOutData, 1, (size_t)nOutDataSize, f_out) != (size_t)nOutDataSize) {
|
||||||
bError = true;
|
bError = true;
|
||||||
}
|
}
|
||||||
@ -176,6 +189,12 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
|||||||
else {
|
else {
|
||||||
/* Write uncompressible, literal block */
|
/* 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];
|
unsigned char cBlockSize[3];
|
||||||
|
|
||||||
cBlockSize[0] = nInDataSize & 0xff;
|
cBlockSize[0] = nInDataSize & 0xff;
|
||||||
@ -206,7 +225,7 @@ static int lzsa_compress(const char *pszInFilename, const char *pszOutFilename,
|
|||||||
|
|
||||||
unsigned char cFooter[3];
|
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[1] = 0xFF;
|
||||||
cFooter[2] = 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;
|
bError = fwrite(cFooter, 1, 3, f_out) != 3;
|
||||||
nCompressedSize += 3LL;
|
nCompressedSize += 3LL;
|
||||||
|
|
||||||
if (!bError && nVerbosity > 0) {
|
if (!bError && (nOptions & OPT_VERBOSE)) {
|
||||||
nEndTime = lzsa_get_time();
|
nEndTime = lzsa_get_time();
|
||||||
|
|
||||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
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 nStartTime = 0LL, nEndTime = 0LL;
|
||||||
long long nOriginalSize = 0LL;
|
long long nOriginalSize = 0LL;
|
||||||
|
unsigned int nFileSize = 0;
|
||||||
|
|
||||||
FILE *pInFile = fopen(pszInFilename, "rb");
|
FILE *pInFile = fopen(pszInFilename, "rb");
|
||||||
if (!pInFile) {
|
if (!pInFile) {
|
||||||
@ -258,24 +278,38 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char cHeader[3];
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
|
unsigned char cHeader[3];
|
||||||
|
|
||||||
memset(cHeader, 0, 3);
|
memset(cHeader, 0, 3);
|
||||||
|
|
||||||
if (fread(cHeader, 1, 3, pInFile) != 3) {
|
if (fread(cHeader, 1, 3, pInFile) != 3) {
|
||||||
fclose(pInFile);
|
fclose(pInFile);
|
||||||
pInFile = NULL;
|
pInFile = NULL;
|
||||||
fprintf(stderr, "error reading header in input file\n");
|
fprintf(stderr, "error reading header in input file\n");
|
||||||
return 100;
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cHeader[0] != 0x7b ||
|
||||||
|
cHeader[1] != 0x9e ||
|
||||||
|
cHeader[2] != 0) {
|
||||||
|
fclose(pInFile);
|
||||||
|
pInFile = NULL;
|
||||||
|
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 (cHeader[0] != 0x7b ||
|
if (nFileSize < 3) {
|
||||||
cHeader[1] != 0x9e ||
|
fclose(pInFile);
|
||||||
cHeader[2] != 0) {
|
pInFile = NULL;
|
||||||
fclose(pInFile);
|
fprintf(stderr, "invalid file size for raw block mode\n");
|
||||||
pInFile = NULL;
|
return 100;
|
||||||
fprintf(stderr, "invalid magic number or format version in input file\n");
|
}
|
||||||
return 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *pOutFile = fopen(pszOutFilename, "wb");
|
FILE *pOutFile = fopen(pszOutFilename, "wb");
|
||||||
@ -314,7 +348,7 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nVerbosity > 0) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = lzsa_get_time();
|
nStartTime = lzsa_get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,51 +357,62 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
|||||||
|
|
||||||
while (!feof(pInFile) && !nDecompressionError) {
|
while (!feof(pInFile) && !nDecompressionError) {
|
||||||
unsigned char cBlockSize[3];
|
unsigned char cBlockSize[3];
|
||||||
|
unsigned int nBlockSize = 0;
|
||||||
|
|
||||||
if (nPrevDecompressedSize != 0) {
|
if (nPrevDecompressedSize != 0) {
|
||||||
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
unsigned int nBlockSize = ((unsigned int)cBlockSize[0]) |
|
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
||||||
(((unsigned int)cBlockSize[1]) << 8) |
|
nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||||
(((unsigned int)cBlockSize[2]) << 16);
|
(((unsigned int)cBlockSize[1]) << 8) |
|
||||||
if ((nBlockSize & 0x400000) == 0) {
|
(((unsigned int)cBlockSize[2]) << 16);
|
||||||
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
}
|
||||||
int nDecompressedSize = 0;
|
else {
|
||||||
|
nBlockSize = 0xffffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nBlockSize = nFileSize - 3;
|
||||||
|
nFileSize = 0xffffff;
|
||||||
|
}
|
||||||
|
|
||||||
nBlockSize &= 0x7fffff;
|
if ((nBlockSize & 0x400000) == 0) {
|
||||||
if (fread(pInBlock, 1, nBlockSize, pInFile) == nBlockSize) {
|
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
||||||
if (bIsUncompressed) {
|
int nDecompressedSize = 0;
|
||||||
memcpy(pOutData + BLOCK_SIZE, pInBlock, nBlockSize);
|
|
||||||
nDecompressedSize = nBlockSize;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
unsigned int nBlockOffs = 0;
|
|
||||||
|
|
||||||
nDecompressedSize = lzsa_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE);
|
nBlockSize &= 0x7fffff;
|
||||||
if (nDecompressedSize < 0) {
|
if (fread(pInBlock, 1, nBlockSize, pInFile) == nBlockSize) {
|
||||||
nDecompressionError = nDecompressedSize;
|
if (bIsUncompressed) {
|
||||||
break;
|
memcpy(pOutData + BLOCK_SIZE, pInBlock, nBlockSize);
|
||||||
}
|
nDecompressedSize = nBlockSize;
|
||||||
}
|
|
||||||
|
|
||||||
if (nDecompressedSize != 0) {
|
|
||||||
nOriginalSize += (long long)nDecompressedSize;
|
|
||||||
|
|
||||||
fwrite(pOutData + BLOCK_SIZE, 1, nDecompressedSize, pOutFile);
|
|
||||||
nPrevDecompressedSize = nDecompressedSize;
|
|
||||||
nDecompressedSize = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break;
|
unsigned int nBlockOffs = 0;
|
||||||
|
|
||||||
|
nDecompressedSize = lzsa_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE);
|
||||||
|
if (nDecompressedSize < 0) {
|
||||||
|
nDecompressionError = nDecompressedSize;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nDecompressedSize != 0) {
|
||||||
|
nOriginalSize += (long long)nDecompressedSize;
|
||||||
|
|
||||||
|
fwrite(pOutData + BLOCK_SIZE, 1, nDecompressedSize, pOutFile);
|
||||||
|
nPrevDecompressedSize = nDecompressedSize;
|
||||||
|
nDecompressedSize = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pOutData);
|
free(pOutData);
|
||||||
@ -387,7 +432,7 @@ static int lzsa_decompress(const char *pszInFilename, const char *pszOutFilename
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (nVerbosity > 0) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nEndTime = lzsa_get_time();
|
nEndTime = lzsa_get_time();
|
||||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
||||||
double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
|
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 nStartTime = 0LL, nEndTime = 0LL;
|
||||||
long long nOriginalSize = 0LL;
|
long long nOriginalSize = 0LL;
|
||||||
long long nKnownGoodSize = 0LL;
|
long long nKnownGoodSize = 0LL;
|
||||||
|
unsigned int nFileSize = 0;
|
||||||
|
|
||||||
FILE *pInFile = fopen(pszInFilename, "rb");
|
FILE *pInFile = fopen(pszInFilename, "rb");
|
||||||
if (!pInFile) {
|
if (!pInFile) {
|
||||||
@ -410,24 +456,38 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char cHeader[3];
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
|
unsigned char cHeader[3];
|
||||||
|
|
||||||
memset(cHeader, 0, 3);
|
memset(cHeader, 0, 3);
|
||||||
|
|
||||||
if (fread(cHeader, 1, 3, pInFile) != 3) {
|
if (fread(cHeader, 1, 3, pInFile) != 3) {
|
||||||
fclose(pInFile);
|
fclose(pInFile);
|
||||||
pInFile = NULL;
|
pInFile = NULL;
|
||||||
fprintf(stderr, "error reading header in compressed input file\n");
|
fprintf(stderr, "error reading header in compressed input file\n");
|
||||||
return 100;
|
return 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cHeader[0] != 0x7b ||
|
||||||
|
cHeader[1] != 0x9e ||
|
||||||
|
cHeader[2] != 0) {
|
||||||
|
fclose(pInFile);
|
||||||
|
pInFile = NULL;
|
||||||
|
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 (cHeader[0] != 0x7b ||
|
if (nFileSize < 3) {
|
||||||
cHeader[1] != 0x9e ||
|
fclose(pInFile);
|
||||||
cHeader[2] != 0) {
|
pInFile = NULL;
|
||||||
fclose(pInFile);
|
fprintf(stderr, "invalid file size for raw block mode\n");
|
||||||
pInFile = NULL;
|
return 100;
|
||||||
fprintf(stderr, "invalid magic number or format version in input file\n");
|
}
|
||||||
return 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *pOutFile = fopen(pszOutFilename, "rb");
|
FILE *pOutFile = fopen(pszOutFilename, "rb");
|
||||||
@ -484,7 +544,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nVerbosity > 0) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nStartTime = lzsa_get_time();
|
nStartTime = lzsa_get_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,7 +553,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
int nPrevDecompressedSize = 0;
|
int nPrevDecompressedSize = 0;
|
||||||
|
|
||||||
while (!feof(pInFile) && !nDecompressionError && !bComparisonError) {
|
while (!feof(pInFile) && !nDecompressionError && !bComparisonError) {
|
||||||
unsigned char cBlockSize[3];
|
unsigned int nBlockSize = 0;
|
||||||
|
|
||||||
if (nPrevDecompressedSize != 0) {
|
if (nPrevDecompressedSize != 0) {
|
||||||
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
memcpy(pOutData + BLOCK_SIZE - nPrevDecompressedSize, pOutData + BLOCK_SIZE, nPrevDecompressedSize);
|
||||||
@ -501,46 +561,55 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
|
|
||||||
int nBytesToCompare = (int)fread(pCompareData, 1, BLOCK_SIZE, pOutFile);
|
int nBytesToCompare = (int)fread(pCompareData, 1, BLOCK_SIZE, pOutFile);
|
||||||
|
|
||||||
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
unsigned int nBlockSize = ((unsigned int)cBlockSize[0]) |
|
unsigned char cBlockSize[3];
|
||||||
(((unsigned int)cBlockSize[1]) << 8) |
|
|
||||||
(((unsigned int)cBlockSize[2]) << 16);
|
|
||||||
if ((nBlockSize & 0x400000) == 0) {
|
|
||||||
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
|
||||||
int nDecompressedSize = 0;
|
|
||||||
|
|
||||||
nBlockSize &= 0x7fffff;
|
if (fread(cBlockSize, 1, 3, pInFile) == 3) {
|
||||||
if (fread(pInBlock, 1, nBlockSize, pInFile) == nBlockSize) {
|
nBlockSize = ((unsigned int)cBlockSize[0]) |
|
||||||
if (bIsUncompressed) {
|
(((unsigned int)cBlockSize[1]) << 8) |
|
||||||
memcpy(pOutData + BLOCK_SIZE, pInBlock, nBlockSize);
|
(((unsigned int)cBlockSize[2]) << 16);
|
||||||
nDecompressedSize = nBlockSize;
|
}
|
||||||
}
|
else {
|
||||||
else {
|
nBlockSize = 0xffffff;
|
||||||
unsigned int nBlockOffs = 0;
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nBlockSize = nFileSize - 3;
|
||||||
|
nFileSize = 0xffffff;
|
||||||
|
}
|
||||||
|
|
||||||
nDecompressedSize = lzsa_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE);
|
if ((nBlockSize & 0x400000) == 0) {
|
||||||
if (nDecompressedSize < 0) {
|
bool bIsUncompressed = (nBlockSize & 0x800000) != 0;
|
||||||
nDecompressionError = nDecompressedSize;
|
int nDecompressedSize = 0;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nDecompressedSize == nBytesToCompare) {
|
nBlockSize &= 0x7fffff;
|
||||||
nKnownGoodSize = nOriginalSize;
|
if (fread(pInBlock, 1, nBlockSize, pInFile) == nBlockSize) {
|
||||||
|
if (bIsUncompressed) {
|
||||||
|
memcpy(pOutData + BLOCK_SIZE, pInBlock, nBlockSize);
|
||||||
|
nDecompressedSize = nBlockSize;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
unsigned int nBlockOffs = 0;
|
||||||
|
|
||||||
nOriginalSize += (long long)nDecompressedSize;
|
nDecompressedSize = lzsa_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE);
|
||||||
|
if (nDecompressedSize < 0) {
|
||||||
if (memcmp(pOutData + BLOCK_SIZE, pCompareData, nBytesToCompare))
|
nDecompressionError = nDecompressedSize;
|
||||||
bComparisonError = true;
|
|
||||||
nPrevDecompressedSize = nDecompressedSize;
|
|
||||||
nDecompressedSize = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bComparisonError = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nDecompressedSize == nBytesToCompare) {
|
||||||
|
nKnownGoodSize = nOriginalSize;
|
||||||
|
|
||||||
|
nOriginalSize += (long long)nDecompressedSize;
|
||||||
|
|
||||||
|
if (memcmp(pOutData + BLOCK_SIZE, pCompareData, nBytesToCompare))
|
||||||
|
bComparisonError = true;
|
||||||
|
nPrevDecompressedSize = nDecompressedSize;
|
||||||
|
nDecompressedSize = 0;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
|
bComparisonError = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -548,6 +617,9 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pCompareData);
|
free(pCompareData);
|
||||||
@ -574,7 +646,7 @@ static int lzsa_compare(const char *pszInFilename, const char *pszOutFilename, i
|
|||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (nVerbosity > 0) {
|
if (nOptions & OPT_VERBOSE) {
|
||||||
nEndTime = lzsa_get_time();
|
nEndTime = lzsa_get_time();
|
||||||
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
double fDelta = ((double)(nEndTime - nStartTime)) / 1000000.0;
|
||||||
double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
|
double fSpeed = ((double)nOriginalSize / 1048576.0) / fDelta;
|
||||||
@ -596,7 +668,7 @@ int main(int argc, char **argv) {
|
|||||||
bool bCommandDefined = false;
|
bool bCommandDefined = false;
|
||||||
bool bVerifyCompression = false;
|
bool bVerifyCompression = false;
|
||||||
char cCommand = 'z';
|
char cCommand = 'z';
|
||||||
int nVerbosity = 0;
|
unsigned int nOptions = 0;
|
||||||
|
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (!strcmp(argv[i], "-d")) {
|
if (!strcmp(argv[i], "-d")) {
|
||||||
@ -623,8 +695,15 @@ int main(int argc, char **argv) {
|
|||||||
bArgsError = true;
|
bArgsError = true;
|
||||||
}
|
}
|
||||||
else if (!strcmp(argv[i], "-v")) {
|
else if (!strcmp(argv[i], "-v")) {
|
||||||
if (nVerbosity == 0) {
|
if ((nOptions & OPT_VERBOSE) == 0) {
|
||||||
nVerbosity = 1;
|
nOptions |= OPT_VERBOSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
bArgsError = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(argv[i], "-r")) {
|
||||||
|
if ((nOptions & OPT_RAW) == 0) {
|
||||||
|
nOptions |= OPT_RAW;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
bArgsError = true;
|
bArgsError = true;
|
||||||
@ -642,21 +721,22 @@ int main(int argc, char **argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (bArgsError || !pszInFilename || !pszOutFilename) {
|
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, " -c: check resulting stream after compressing\n");
|
||||||
fprintf(stderr, " -d: decompress (default: compress)\n");
|
fprintf(stderr, " -d: decompress (default: compress)\n");
|
||||||
fprintf(stderr, " -v: be verbose\n");
|
fprintf(stderr, " -v: be verbose\n");
|
||||||
|
fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n");
|
||||||
return 100;
|
return 100;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cCommand == 'z') {
|
if (cCommand == 'z') {
|
||||||
int nResult = lzsa_compress(pszInFilename, pszOutFilename, nVerbosity);
|
int nResult = lzsa_compress(pszInFilename, pszOutFilename, nOptions);
|
||||||
if (nResult == 0 && bVerifyCompression) {
|
if (nResult == 0 && bVerifyCompression) {
|
||||||
nResult = lzsa_compare(pszOutFilename, pszInFilename, nVerbosity);
|
nResult = lzsa_compare(pszOutFilename, pszInFilename, nOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cCommand == 'd') {
|
else if (cCommand == 'd') {
|
||||||
return lzsa_decompress(pszInFilename, pszOutFilename, nVerbosity);
|
return lzsa_decompress(pszInFilename, pszOutFilename, nOptions);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 100;
|
return 100;
|
||||||
|
Loading…
Reference in New Issue
Block a user