From 4835e4c26c4429c80932d204f03b6cc6c9ee8389 Mon Sep 17 00:00:00 2001 From: Emmanuel Marty Date: Wed, 24 Jul 2019 20:08:23 +0200 Subject: [PATCH] Support backward decompression --- asm/6502/decompress_v1.asm | 98 +++++++++++++++++++++++++++++++++++++- asm/6502/decompress_v2.asm | 94 +++++++++++++++++++++++++++++++++++- src/expand_context.c | 26 ++++++++-- src/expand_context.h | 3 +- src/expand_inmem.c | 8 ++-- src/expand_inmem.h | 2 +- src/expand_streaming.c | 2 +- src/lib.h | 18 +++++++ src/lzsa.c | 34 +++++++++++-- src/shrink_context.c | 47 +++++++++++++----- src/shrink_context.h | 2 +- src/shrink_inmem.c | 2 +- src/shrink_inmem.h | 2 +- 13 files changed, 305 insertions(+), 33 deletions(-) diff --git a/asm/6502/decompress_v1.asm b/asm/6502/decompress_v1.asm index be84e88..eec59f3 100755 --- a/asm/6502/decompress_v1.asm +++ b/asm/6502/decompress_v1.asm @@ -7,6 +7,18 @@ ; ; out: ; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1 +; +; ----------------------------------------------------------------------------- +; Backward decompression is also supported, use lzsa -r -b +; To use it, also define BACKWARD_DECOMPRESS=1 before including this code! +; +; in: +; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data +; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer +; +; out: +; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1 +; ; ----------------------------------------------------------------------------- ; ; Copyright (C) 2019 Emmanuel Marty @@ -96,11 +108,29 @@ PREPARE_COPY_MATCH_Y COPY_MATCH_LOOP LDA $AAAA ; get one byte of backreference + JSR PUTDST ; copy to destination + +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- put backreference bytes backward + + LDA COPY_MATCH_LOOP+1 + BNE GETMATCH_DONE + DEC COPY_MATCH_LOOP+2 +GETMATCH_DONE + DEC COPY_MATCH_LOOP+1 + +else + + ; Forward decompression -- put backreference bytes forward + INC COPY_MATCH_LOOP+1 BNE GETMATCH_DONE INC COPY_MATCH_LOOP+2 GETMATCH_DONE - JSR PUTDST ; copy to destination + +endif + DEX BNE COPY_MATCH_LOOP DEY @@ -111,6 +141,29 @@ GET_LONG_OFFSET ; handle 16 bit offset: JSR GETLARGESRC ; grab low 8 bits in X, high 8 bits in A GOT_OFFSET + +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression - substract match offset + + STA OFFSHI ; store high 8 bits of offset + STX OFFSLO + + SEC ; substract dest - match offset + LDA PUTDST+1 +OFFSLO = *+1 + SBC #$AA ; low 8 bits + STA COPY_MATCH_LOOP+1 ; store back reference address + LDA PUTDST+2 +OFFSHI = *+1 + SBC #$AA ; high 8 bits + STA COPY_MATCH_LOOP+2 ; store high 8 bits of address + SEC + +else + + ; Forward decompression - add match offset + STA OFFSHI ; store high 8 bits of offset TXA @@ -123,6 +176,8 @@ OFFSHI = *+1 ADC PUTDST+2 STA COPY_MATCH_LOOP+2 ; store high 8 bits of address +endif + PLA ; retrieve token from stack again AND #$0F ; isolate match len (MMMM) ADC #$02 ; plus carry which is always set by the high ADC @@ -145,6 +200,45 @@ OFFSHI = *+1 DECOMPRESSION_DONE RTS +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- get and put bytes backward + +GETPUT + JSR GETSRC +PUTDST +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + STA $AAAA + LDA PUTDST+1 + BNE PUTDST_DONE + DEC PUTDST+2 +PUTDST_DONE + DEC PUTDST+1 + RTS + +GETLARGESRC + JSR GETSRC ; grab low 8 bits + TAX ; move to X + ; fall through grab high 8 bits + +GETSRC +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + LDA $AAAA + PHA + LDA GETSRC+1 + BNE GETSRC_DONE + DEC GETSRC+2 +GETSRC_DONE + DEC GETSRC+1 + PLA + RTS + +else + + ; Forward decompression -- get and put bytes forward + GETPUT JSR GETSRC PUTDST @@ -171,3 +265,5 @@ LZSA_SRC_HI = *+2 INC GETSRC+2 GETSRC_DONE RTS + +endif diff --git a/asm/6502/decompress_v2.asm b/asm/6502/decompress_v2.asm index 9bd7942..46f2a58 100755 --- a/asm/6502/decompress_v2.asm +++ b/asm/6502/decompress_v2.asm @@ -8,6 +8,18 @@ ; ; out: ; * LZSA_DST_LO and LZSA_DST_HI contain the last decompressed byte address, +1 +; +; ----------------------------------------------------------------------------- +; Backward decompression is also supported, use lzsa -r -b -f2 +; To use it, also define BACKWARD_DECOMPRESS=1 before including this code! +; +; in: +; * LZSA_SRC_LO/LZSA_SRC_HI must contain the address of the last byte of compressed data +; * LZSA_DST_LO/LZSA_DST_HI must contain the address of the last byte of the destination buffer +; +; out: +; * LZSA_DST_LO/LZSA_DST_HI contain the last decompressed byte address, -1 +; ; ----------------------------------------------------------------------------- ; ; Copyright (C) 2019 Emmanuel Marty @@ -130,6 +142,25 @@ GOT_OFFSET_LO STX OFFSHI ; store high byte of match offset REP_MATCH +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression - substract match offset + + SEC ; add dest + match offset + LDA PUTDST+1 ; low 8 bits +OFFSLO = *+1 + SBC #$AA + STA COPY_MATCH_LOOP+1 ; store back reference address + LDA PUTDST+2 +OFFSHI = *+1 + SBC #$AA ; high 8 bits + STA COPY_MATCH_LOOP+2 ; store high 8 bits of address + SEC + +else + + ; Forward decompression - add match offset + CLC ; add dest + match offset LDA PUTDST+1 ; low 8 bits OFFSLO = *+1 @@ -140,6 +171,8 @@ OFFSHI = *+1 ADC PUTDST+2 STA COPY_MATCH_LOOP+2 ; store high 8 bits of address +endif + PLA ; retrieve token from stack again AND #$07 ; isolate match len (MMM) ADC #$01 ; add MIN_MATCH_SIZE_V2 and carry @@ -173,11 +206,29 @@ PREPARE_COPY_MATCH_Y COPY_MATCH_LOOP LDA $AAAA ; get one byte of backreference + JSR PUTDST ; copy to destination + +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- put backreference bytes backward + + LDA COPY_MATCH_LOOP+1 + BNE GETMATCH_DONE + DEC COPY_MATCH_LOOP+2 +GETMATCH_DONE + DEC COPY_MATCH_LOOP+1 + +else + + ; Forward decompression -- put backreference bytes forward + INC COPY_MATCH_LOOP+1 BNE GETMATCH_DONE INC COPY_MATCH_LOOP+2 GETMATCH_DONE - JSR PUTDST ; copy to destination + +endif + DEX BNE COPY_MATCH_LOOP DEY @@ -215,6 +266,45 @@ HAS_NIBBLES AND #$0F ; isolate low 4 bits of nibble RTS +ifdef BACKWARD_DECOMPRESS + + ; Backward decompression -- get and put bytes backward + +GETPUT + JSR GETSRC +PUTDST +LZSA_DST_LO = *+1 +LZSA_DST_HI = *+2 + STA $AAAA + LDA PUTDST+1 + BNE PUTDST_DONE + DEC PUTDST+2 +PUTDST_DONE + DEC PUTDST+1 + RTS + +GETLARGESRC + JSR GETSRC ; grab low 8 bits + TAX ; move to X + ; fall through grab high 8 bits + +GETSRC +LZSA_SRC_LO = *+1 +LZSA_SRC_HI = *+2 + LDA $AAAA + PHA + LDA GETSRC+1 + BNE GETSRC_DONE + DEC GETSRC+2 +GETSRC_DONE + DEC GETSRC+1 + PLA + RTS + +else + + ; Forward decompression -- get and put bytes forward + GETPUT JSR GETSRC PUTDST @@ -241,3 +331,5 @@ LZSA_SRC_HI = *+2 INC GETSRC+2 GETSRC_DONE RTS + +endif diff --git a/src/expand_context.c b/src/expand_context.c index 3178111..b02620d 100644 --- a/src/expand_context.c +++ b/src/expand_context.c @@ -35,6 +35,7 @@ #include "expand_context.h" #include "expand_block_v1.h" #include "expand_block_v2.h" +#include "lib.h" /** * Decompress one data block @@ -45,14 +46,31 @@ * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes) * @param nBlockMaxSize total size of output decompression buffer, in bytes * @param nFormatVersion version of format to use (1-2) + * @param nFlags compression flags (LZSA_FLAG_xxx) * * @return size of decompressed data in bytes, or -1 for error */ -int lzsa_decompressor_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion) { +int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags) { + int nDecompressedSize; + + if (nFlags & LZSA_FLAG_RAW_BACKWARD) { + lzsa_reverse_buffer(pInBlock, nBlockSize); + } + if (nFormatVersion == 1) - return lzsa_decompressor_expand_block_v1(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize); + nDecompressedSize = lzsa_decompressor_expand_block_v1(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize); else if (nFormatVersion == 2) - return lzsa_decompressor_expand_block_v2(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize); + nDecompressedSize = lzsa_decompressor_expand_block_v2(pInBlock, nBlockSize, pOutData, nOutDataOffset, nBlockMaxSize); else - return -1; + nDecompressedSize = -1; + + if (nDecompressedSize != -1 && (nFlags & LZSA_FLAG_RAW_BACKWARD)) { + lzsa_reverse_buffer(pOutData + nOutDataOffset, nDecompressedSize); + } + + if (nFlags & LZSA_FLAG_RAW_BACKWARD) { + lzsa_reverse_buffer(pInBlock, nBlockSize); + } + + return nDecompressedSize; } diff --git a/src/expand_context.h b/src/expand_context.h index 9b60c6f..698e039 100644 --- a/src/expand_context.h +++ b/src/expand_context.h @@ -48,10 +48,11 @@ extern "C" { * @param nOutDataOffset starting index of where to store decompressed bytes in output buffer (and size of previously decompressed bytes) * @param nBlockMaxSize total size of output decompression buffer, in bytes * @param nFormatVersion version of format to use (1-2) + * @param nFlags compression flags (LZSA_FLAG_xxx) * * @return size of decompressed data in bytes, or -1 for error */ -int lzsa_decompressor_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion); +int lzsa_decompressor_expand_block(unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize, const int nFormatVersion, const int nFlags); #ifdef __cplusplus } diff --git a/src/expand_inmem.c b/src/expand_inmem.c index 501ec37..050bdbc 100644 --- a/src/expand_inmem.c +++ b/src/expand_inmem.c @@ -98,8 +98,8 @@ size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size * * @return actual decompressed size, or -1 for error */ -size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion) { - const unsigned char *pCurFileData = pFileData; +size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion) { + unsigned char *pCurFileData = pFileData; const unsigned char *pEndFileData = pCurFileData + nFileSize; unsigned char *pCurOutBuffer = pOutBuffer; const unsigned char *pEndOutBuffer = pCurOutBuffer + nMaxOutBufferSize; @@ -107,7 +107,7 @@ size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOut const int nHeaderSize = lzsa_get_header_size(); if (nFlags & LZSA_FLAG_RAW_BLOCK) { - return (size_t)lzsa_decompressor_expand_block(pFileData, (int)nFileSize, pOutBuffer, 0, (int)nMaxOutBufferSize, *pFormatVersion); + return (size_t)lzsa_decompressor_expand_block(pFileData, (int)nFileSize, pOutBuffer, 0, (int)nMaxOutBufferSize, *pFormatVersion, nFlags); } /* Check header */ @@ -139,7 +139,7 @@ size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOut if ((pCurFileData + nBlockDataSize) > pEndFileData) return -1; - nDecompressedSize = lzsa_decompressor_expand_block(pCurFileData, nBlockDataSize, pCurOutBuffer - nPreviousBlockSize, nPreviousBlockSize, (int)(pEndOutBuffer - pCurOutBuffer + nPreviousBlockSize), *pFormatVersion); + nDecompressedSize = lzsa_decompressor_expand_block(pCurFileData, nBlockDataSize, pCurOutBuffer - nPreviousBlockSize, nPreviousBlockSize, (int)(pEndOutBuffer - pCurOutBuffer + nPreviousBlockSize), *pFormatVersion, nFlags); if (nDecompressedSize < 0) return -1; diff --git a/src/expand_inmem.h b/src/expand_inmem.h index bd95ff0..b52ee68 100644 --- a/src/expand_inmem.h +++ b/src/expand_inmem.h @@ -61,7 +61,7 @@ size_t lzsa_get_max_decompressed_size_inmem(const unsigned char *pFileData, size * * @return actual decompressed size, or -1 for error */ -size_t lzsa_decompress_inmem(const unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion); +size_t lzsa_decompress_inmem(unsigned char *pFileData, unsigned char *pOutBuffer, size_t nFileSize, size_t nMaxOutBufferSize, const unsigned int nFlags, int *pFormatVersion); #ifdef __cplusplus } diff --git a/src/expand_streaming.c b/src/expand_streaming.c index d981778..b241c68 100644 --- a/src/expand_streaming.c +++ b/src/expand_streaming.c @@ -196,7 +196,7 @@ lzsa_status_t lzsa_decompress_stream(lzsa_stream_t *pInStream, lzsa_stream_t *pO nDecompressedSize = nBlockSize; } else { - nDecompressedSize = lzsa_decompressor_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE, nFormatVersion); + nDecompressedSize = lzsa_decompressor_expand_block(pInBlock, nBlockSize, pOutData, BLOCK_SIZE, BLOCK_SIZE, nFormatVersion, nFlags); if (nDecompressedSize < 0) { nDecompressionError = LZSA_ERROR_DECOMPRESSION; break; diff --git a/src/lib.h b/src/lib.h index 141469c..5556d2a 100755 --- a/src/lib.h +++ b/src/lib.h @@ -69,6 +69,24 @@ typedef enum _lzsa_status_t { /* Compression flags */ #define LZSA_FLAG_FAVOR_RATIO (1<<0) /**< 1 to compress with the best ratio, 0 to trade some compression ratio for extra decompression speed */ #define LZSA_FLAG_RAW_BLOCK (1<<1) /**< 1 to emit raw block */ +#define LZSA_FLAG_RAW_BACKWARD (1<<2) /**< 1 to compress or decompress raw block backward */ + +/** + * Reverse bytes in the specified buffer + * + * @param pBuffer pointer to buffer whose contents are to be reversed + * @param nBufferSize size of buffer in bytes + */ +static inline void lzsa_reverse_buffer(unsigned char *pBuffer, const int nBufferSize) { + int nMidPoint = nBufferSize / 2; + int i, j; + + for (i = 0, j = nBufferSize - 1; i < nMidPoint; i++, j--) { + unsigned char c = pBuffer[i]; + pBuffer[i] = pBuffer[j]; + pBuffer[j] = c; + } +} #ifdef __cplusplus } diff --git a/src/lzsa.c b/src/lzsa.c index ff2e684..4fdf773 100755 --- a/src/lzsa.c +++ b/src/lzsa.c @@ -42,11 +42,12 @@ #endif #include "lib.h" -#define OPT_VERBOSE 1 -#define OPT_RAW 2 -#define OPT_FAVOR_RATIO 4 +#define OPT_VERBOSE 1 +#define OPT_RAW 2 +#define OPT_FAVOR_RATIO 4 +#define OPT_RAW_BACKWARD 8 -#define TOOL_VERSION "1.0.4" +#define TOOL_VERSION "1.0.5" /*---------------------------------------------------------------------------*/ @@ -109,6 +110,8 @@ static int do_compress(const char *pszInFilename, const char *pszOutFilename, co nFlags |= LZSA_FLAG_FAVOR_RATIO; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; if (nOptions & OPT_VERBOSE) { nStartTime = do_get_time(); @@ -160,6 +163,8 @@ static int do_decompress(const char *pszInFilename, const char *pszOutFilename, nFlags = 0; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; if (nOptions & OPT_VERBOSE) { nStartTime = do_get_time(); @@ -308,6 +313,8 @@ static int do_compare(const char *pszInFilename, const char *pszOutFilename, con nFlags = 0; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; if (nOptions & OPT_VERBOSE) { nStartTime = do_get_time(); @@ -419,6 +426,8 @@ static int do_self_test(const unsigned int nOptions, const int nMinMatchSize, in nFlags |= LZSA_FLAG_FAVOR_RATIO; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; pGeneratedData = (unsigned char*)malloc(4 * BLOCK_SIZE); if (!pGeneratedData) { @@ -590,6 +599,8 @@ static int do_compr_benchmark(const char *pszInFilename, const char *pszOutFilen nFlags |= LZSA_FLAG_FAVOR_RATIO; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; if (pszDictionaryFilename) { fprintf(stderr, "in-memory benchmarking does not support dictionaries\n"); @@ -720,6 +731,8 @@ static int do_dec_benchmark(const char *pszInFilename, const char *pszOutFilenam nFlags = 0; if (nOptions & OPT_RAW) nFlags |= LZSA_FLAG_RAW_BLOCK; + if (nOptions & OPT_RAW_BACKWARD) + nFlags |= LZSA_FLAG_RAW_BACKWARD; if (pszDictionaryFilename) { fprintf(stderr, "in-memory benchmarking does not support dictionaries\n"); @@ -987,6 +1000,13 @@ int main(int argc, char **argv) { else bArgsError = true; } + else if (!strcmp(argv[i], "-b")) { + if ((nOptions & OPT_RAW_BACKWARD) == 0) { + nOptions |= OPT_RAW_BACKWARD; + } + else + bArgsError = true; + } else { if (!pszInFilename) pszInFilename = argv[i]; @@ -999,6 +1019,11 @@ int main(int argc, char **argv) { } } + if (!bArgsError && (nOptions & OPT_RAW_BACKWARD) && !(nOptions & OPT_RAW)) { + fprintf(stderr, "error: -b (compress backwards) requires -r (raw block format)\n"); + return 100; + } + if (!bArgsError && cCommand == 't') { return do_self_test(nOptions, nMinMatchSize, nFormatVersion); } @@ -1014,6 +1039,7 @@ int main(int argc, char **argv) { fprintf(stderr, " -v: be verbose\n"); fprintf(stderr, " -f : LZSA compression format (1-2)\n"); fprintf(stderr, " -r: raw block format (max. 64 Kb files)\n"); + fprintf(stderr, " -b: compress backward (requires -r and a backward decompressor)\n"); fprintf(stderr, " -D : use dictionary file\n"); fprintf(stderr, " -m : minimum match size (3-5) (default: 3)\n"); fprintf(stderr, " --prefer-ratio: favor compression ratio (default)\n"); diff --git a/src/shrink_context.c b/src/shrink_context.c index 26a5d04..c27bf63 100644 --- a/src/shrink_context.c +++ b/src/shrink_context.c @@ -37,6 +37,7 @@ #include "shrink_block_v2.h" #include "format.h" #include "matchfinder.h" +#include "lib.h" /** * Initialize compression context @@ -188,23 +189,43 @@ void lzsa_compressor_destroy(lzsa_compressor *pCompressor) { * * @return size of compressed data in output buffer, or -1 if the data is uncompressible */ -int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) { - if (lzsa_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize)) - return -1; - if (nPreviousBlockSize) { - lzsa_skip_matches(pCompressor, 0, nPreviousBlockSize); - } - lzsa_find_all_matches(pCompressor, nPreviousBlockSize, nPreviousBlockSize + nInDataSize); +int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize) { + int nCompressedSize; - if (pCompressor->format_version == 1) { - return lzsa_optimize_and_write_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize); - } - else if (pCompressor->format_version == 2) { - return lzsa_optimize_and_write_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize); + if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) { + lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize); } + + if (lzsa_build_suffix_array(pCompressor, pInWindow, nPreviousBlockSize + nInDataSize)) + nCompressedSize = -1; else { - return -1; + if (nPreviousBlockSize) { + lzsa_skip_matches(pCompressor, 0, nPreviousBlockSize); + } + lzsa_find_all_matches(pCompressor, nPreviousBlockSize, nPreviousBlockSize + nInDataSize); + + if (pCompressor->format_version == 1) { + nCompressedSize = lzsa_optimize_and_write_block_v1(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize); + if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) { + lzsa_reverse_buffer(pOutData, nCompressedSize); + } + } + else if (pCompressor->format_version == 2) { + nCompressedSize = lzsa_optimize_and_write_block_v2(pCompressor, pInWindow, nPreviousBlockSize, nInDataSize, pOutData, nMaxOutDataSize); + if (nCompressedSize != -1 && (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD)) { + lzsa_reverse_buffer(pOutData, nCompressedSize); + } + } + else { + nCompressedSize = -1; + } } + + if (pCompressor->flags & LZSA_FLAG_RAW_BACKWARD) { + lzsa_reverse_buffer(pInWindow + nPreviousBlockSize, nInDataSize); + } + + return nCompressedSize; } /** diff --git a/src/shrink_context.h b/src/shrink_context.h index 4bbf6ec..cf9b1c5 100644 --- a/src/shrink_context.h +++ b/src/shrink_context.h @@ -123,7 +123,7 @@ void lzsa_compressor_destroy(lzsa_compressor *pCompressor); * * @return size of compressed data in output buffer, or -1 if the data is uncompressible */ -int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, const unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize); +int lzsa_compressor_shrink_block(lzsa_compressor *pCompressor, unsigned char *pInWindow, const int nPreviousBlockSize, const int nInDataSize, unsigned char *pOutData, const int nMaxOutDataSize); /** * Get the number of compression commands issued in compressed data blocks diff --git a/src/shrink_inmem.c b/src/shrink_inmem.c index 32a727b..c3596b7 100644 --- a/src/shrink_inmem.c +++ b/src/shrink_inmem.c @@ -62,7 +62,7 @@ size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize) { * * @return actual compressed size, or -1 for error */ -size_t lzsa_compress_inmem(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize, +size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize, const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion) { lzsa_compressor compressor; size_t nOriginalSize = 0; diff --git a/src/shrink_inmem.h b/src/shrink_inmem.h index 2c9c89f..2bd8f27 100644 --- a/src/shrink_inmem.h +++ b/src/shrink_inmem.h @@ -61,7 +61,7 @@ size_t lzsa_get_max_compressed_size_inmem(size_t nInputSize); * * @return actual compressed size, or -1 for error */ -size_t lzsa_compress_inmem(const unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize, +size_t lzsa_compress_inmem(unsigned char *pInputData, unsigned char *pOutBuffer, size_t nInputSize, size_t nMaxOutBufferSize, const unsigned int nFlags, const int nMinMatchSize, const int nFormatVersion); #ifdef __cplusplus