From fb79d319cb44ea631a7f8240fdea7c7009d5b235 Mon Sep 17 00:00:00 2001 From: emmanuel-marty Date: Sat, 20 Apr 2019 10:27:24 +0200 Subject: [PATCH] Speed up portable decompressor a bit --- src/expand.c | 183 ++++++++++++++++++++++++++++----------------------- 1 file changed, 100 insertions(+), 83 deletions(-) diff --git a/src/expand.c b/src/expand.c index 68b2687..48e9f7d 100755 --- a/src/expand.c +++ b/src/expand.c @@ -32,37 +32,50 @@ #define FORCE_INLINE __attribute__((always_inline)) #endif /* _MSC_VER */ -static inline FORCE_INLINE int lzsa_expand_literals_slow(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, int nLiterals, unsigned char **ppCurOutData, const unsigned char *pOutDataEnd) { +static inline FORCE_INLINE int lzsa_expand_literals_slow(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, unsigned int nLiterals, unsigned char **ppCurOutData, const unsigned char *pOutDataEnd) { const unsigned char *pInBlock = *ppInBlock; unsigned char *pCurOutData = *ppCurOutData; if (nLiterals == LITERALS_RUN_LEN) { unsigned char nByte; - if (pInBlock >= pInBlockEnd) return -1; - nByte = *pInBlock++; - nLiterals += (int)((unsigned int)nByte); + if (pInBlock < pInBlockEnd) { + nByte = *pInBlock++; + nLiterals += ((unsigned int)nByte); - if (nByte == 254) { - if (pInBlock >= pInBlockEnd) return -1; - nLiterals += (int)((unsigned int)*pInBlock++); + if (nByte == 254) { + if (pInBlock < pInBlockEnd) { + nLiterals += ((unsigned int)*pInBlock++); + } + else { + return -1; + } + } + else if (nByte == 255) { + if ((pInBlock + 1) < pInBlockEnd) { + nLiterals = ((unsigned int)*pInBlock++); + nLiterals |= (((unsigned int)*pInBlock++) << 8); + } + else { + return -1; + } + } } - else if (nByte == 255) { - if ((pInBlock + 1) >= pInBlockEnd) return -1; - nLiterals = ((unsigned int)*pInBlock++); - nLiterals |= (((unsigned int)*pInBlock++) << 8); + else { + return -1; } } if (nLiterals != 0) { - if ((pInBlock + nLiterals) > pInBlockEnd || - (pCurOutData + nLiterals) > pOutDataEnd) { + if ((pInBlock + nLiterals) <= pInBlockEnd && + (pCurOutData + nLiterals) <= pOutDataEnd) { + memcpy(pCurOutData, pInBlock, nLiterals); + pInBlock += nLiterals; + pCurOutData += nLiterals; + } + else { return -1; } - - memcpy(pCurOutData, pInBlock, nLiterals); - pInBlock += nLiterals; - pCurOutData += nLiterals; } *ppInBlock = pInBlock; @@ -70,76 +83,76 @@ static inline FORCE_INLINE int lzsa_expand_literals_slow(const unsigned char **p return 0; } -static inline FORCE_INLINE int lzsa_expand_match_slow(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, const unsigned char *pSrc, int nMatchLen, unsigned char **ppCurOutData, const unsigned char *pOutDataEnd, const unsigned char *pOutDataFastEnd) { +static inline FORCE_INLINE int lzsa_expand_match_slow(const unsigned char **ppInBlock, const unsigned char *pInBlockEnd, const unsigned char *pSrc, unsigned int nMatchLen, unsigned char **ppCurOutData, const unsigned char *pOutDataEnd, const unsigned char *pOutDataFastEnd) { const unsigned char *pInBlock = *ppInBlock; unsigned char *pCurOutData = *ppCurOutData; if (nMatchLen == MATCH_RUN_LEN) { unsigned char nByte; - if (pInBlock >= pInBlockEnd) return -1; - nByte = *pInBlock++; - nMatchLen += (int)((unsigned int)nByte); + if (pInBlock < pInBlockEnd) { + nByte = *pInBlock++; + nMatchLen += ((unsigned int)nByte); - if (nByte == 254) { - if (pInBlock >= pInBlockEnd) return -1; - nMatchLen += (int)((unsigned int)*pInBlock++); + if (nByte == 254) { + if (pInBlock < pInBlockEnd) { + nMatchLen += ((unsigned int)*pInBlock++); + } + else { + return -1; + } + } + else if (nByte == 255) { + if ((pInBlock + 1) < pInBlockEnd) { + nMatchLen = ((unsigned int)*pInBlock++); + nMatchLen |= (((unsigned int)*pInBlock++) << 8); + } + else { + return -1; + } + } } - else if (nByte == 255) { - if ((pInBlock + 1) >= pInBlockEnd) return -1; - nMatchLen = ((unsigned int)*pInBlock++); - nMatchLen |= (((unsigned int)*pInBlock++) << 8); + else { + return -1; } } nMatchLen += MIN_MATCH_SIZE; - if ((pCurOutData + nMatchLen) > pOutDataEnd) { - return -1; - } - - if ((pSrc + 1) == pCurOutData && nMatchLen >= 16) { - /* One-byte RLE */ - memset(pCurOutData, *pSrc, nMatchLen); - pCurOutData += nMatchLen; - } - else { + if ((pCurOutData + nMatchLen) <= pOutDataEnd) { /* Do a deterministic, left to right byte copy instead of memcpy() so as to handle overlaps */ - int nMaxFast = nMatchLen; - if (nMaxFast > (pCurOutData - pSrc)) - nMaxFast = (int)(pCurOutData - pSrc); - if ((pCurOutData + nMaxFast) > (pOutDataFastEnd - 15)) - nMaxFast = (int)(pOutDataFastEnd - 15 - pCurOutData); - - if (nMaxFast > 0) { + if ((pCurOutData - pSrc) >= 8 && (pCurOutData + nMatchLen) < (pOutDataFastEnd - 15)) { const unsigned char *pCopySrc = pSrc; unsigned char *pCopyDst = pCurOutData; - const unsigned char *pCopyEndDst = pCurOutData + nMaxFast; + const unsigned char *pCopyEndDst = pCurOutData + nMatchLen; do { - memcpy(pCopyDst, pCopySrc, 16); + memcpy(pCopyDst, pCopySrc, 8); + memcpy(pCopyDst + 8, pCopySrc + 8, 8); pCopySrc += 16; pCopyDst += 16; } while (pCopyDst < pCopyEndDst); - pCurOutData += nMaxFast; - pSrc += nMaxFast; - nMatchLen -= nMaxFast; + pCurOutData += nMatchLen; } - - while (nMatchLen >= 4) { - *pCurOutData++ = *pSrc++; - *pCurOutData++ = *pSrc++; - *pCurOutData++ = *pSrc++; - *pCurOutData++ = *pSrc++; - nMatchLen -= 4; - } - while (nMatchLen > 0) { - *pCurOutData++ = *pSrc++; - nMatchLen--; + else { + while (nMatchLen >= 4) { + *pCurOutData++ = *pSrc++; + *pCurOutData++ = *pSrc++; + *pCurOutData++ = *pSrc++; + *pCurOutData++ = *pSrc++; + nMatchLen -= 4; + } + while (nMatchLen) { + *pCurOutData++ = *pSrc++; + nMatchLen--; + } } } + else { + return -1; + } *ppInBlock = pInBlock; *ppCurOutData = pCurOutData; @@ -159,16 +172,16 @@ static inline FORCE_INLINE int lzsa_expand_match_slow(const unsigned char **ppIn */ int lzsa_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned char *pOutData, int nOutDataOffset, int nBlockMaxSize) { const unsigned char *pInBlockEnd = pInBlock + nBlockSize; - const unsigned char *pInBlockFastEnd = pInBlock + nBlockSize - 16; + const unsigned char *pInBlockFastEnd = pInBlock + nBlockSize - 8; unsigned char *pCurOutData = pOutData + nOutDataOffset; const unsigned char *pOutDataEnd = pCurOutData + nBlockMaxSize; - const unsigned char *pOutDataFastEnd = pOutDataEnd - 16; + const unsigned char *pOutDataFastEnd = pOutDataEnd - 20; /* Fast loop */ while (pInBlock < pInBlockFastEnd && pCurOutData < pOutDataFastEnd) { const unsigned char token = *pInBlock++; - int nLiterals = (int)((unsigned int)((token & 0x70) >> 4)); + unsigned int nLiterals = (unsigned int)((token & 0x70) >> 4); if (nLiterals < LITERALS_RUN_LEN) { memcpy(pCurOutData, pInBlock, 8); @@ -180,28 +193,31 @@ int lzsa_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned ch return -1; } - if (pInBlock < pInBlockEnd) { /* The last token in the block does not include match information */ + if ((pInBlock + 1) < pInBlockEnd) { /* The last token in the block does not include match information */ int nMatchOffset; nMatchOffset = ((unsigned int)*pInBlock++); if (token & 0x80) { - if (pInBlock >= pInBlockEnd) return -1; nMatchOffset |= (((unsigned int)*pInBlock++) << 8); } nMatchOffset++; const unsigned char *pSrc = pCurOutData - nMatchOffset; - if (pSrc < pOutData) - return -1; - - int nMatchLen = (int)((unsigned int)(token & 0x0f)); - if (nMatchLen < (16 - MIN_MATCH_SIZE + 1) && (pSrc + MIN_MATCH_SIZE + nMatchLen) < pCurOutData && pCurOutData < pOutDataFastEnd) { - memcpy(pCurOutData, pSrc, 16); - pCurOutData += (MIN_MATCH_SIZE + nMatchLen); + if (pSrc >= pOutData) { + unsigned int nMatchLen = (unsigned int)(token & 0x0f); + if (nMatchLen < MATCH_RUN_LEN && nMatchOffset >= 8 && pCurOutData < pOutDataFastEnd) { + memcpy(pCurOutData, pSrc, 8); + memcpy(pCurOutData + 8, pSrc + 8, 8); + memcpy(pCurOutData + 16, pSrc + 16, 4); + pCurOutData += (MIN_MATCH_SIZE + nMatchLen); + } + else { + if (lzsa_expand_match_slow(&pInBlock, pInBlockEnd, pSrc, nMatchLen, &pCurOutData, pOutDataEnd, pOutDataFastEnd)) + return -1; + } } else { - if (lzsa_expand_match_slow(&pInBlock, pInBlockEnd, pSrc, nMatchLen, &pCurOutData, pOutDataEnd, pOutDataFastEnd)) - return -1; + return -1; } } } @@ -210,28 +226,29 @@ int lzsa_expand_block(const unsigned char *pInBlock, int nBlockSize, unsigned ch while (pInBlock < pInBlockEnd) { const unsigned char token = *pInBlock++; - int nLiterals = (int)((unsigned int)((token & 0x70) >> 4)); + unsigned int nLiterals = (unsigned int)((token & 0x70) >> 4); if (lzsa_expand_literals_slow(&pInBlock, pInBlockEnd, nLiterals, &pCurOutData, pOutDataEnd)) return -1; - if (pInBlock < pInBlockEnd) { /* The last token in the block does not include match information */ + if ((pInBlock + 1) < pInBlockEnd) { /* The last token in the block does not include match information */ int nMatchOffset; nMatchOffset = ((unsigned int)*pInBlock++); if (token & 0x80) { - if (pInBlock >= pInBlockEnd) return -1; nMatchOffset |= (((unsigned int)*pInBlock++) << 8); } nMatchOffset++; const unsigned char *pSrc = pCurOutData - nMatchOffset; - if (pSrc < pOutData) - return -1; - - int nMatchLen = (int)((unsigned int)(token & 0x0f)); - if (lzsa_expand_match_slow(&pInBlock, pInBlockEnd, pSrc, nMatchLen, &pCurOutData, pOutDataEnd, pOutDataFastEnd)) + if (pSrc >= pOutData) { + unsigned int nMatchLen = (unsigned int)(token & 0x0f); + if (lzsa_expand_match_slow(&pInBlock, pInBlockEnd, pSrc, nMatchLen, &pCurOutData, pOutDataEnd, pOutDataFastEnd)) + return -1; + } + else { return -1; + } } }