diff options
author | Yann Collet <cyan@fb.com> | 2017-11-07 18:53:29 (GMT) |
---|---|---|
committer | Yann Collet <cyan@fb.com> | 2017-11-07 18:53:29 (GMT) |
commit | a004c1fbee4e5a8793f9dfc1deeafea1d59be486 (patch) | |
tree | b1b878a8aefcba68f39d39b3566f8bb7b707bca8 /lib/lz4hc.c | |
parent | aa99163752079890c8d75461d2b5c1fd7c426c3b (diff) | |
download | lz4-a004c1fbee4e5a8793f9dfc1deeafea1d59be486.zip lz4-a004c1fbee4e5a8793f9dfc1deeafea1d59be486.tar.gz lz4-a004c1fbee4e5a8793f9dfc1deeafea1d59be486.tar.bz2 |
fixed LZ4HC_countPattern()
- works with byte values other than `0`
- works for any repetitive pattern of length 1, 2 or 4 (but not 3!)
- works for little and big endian systems
- preserve speed of previous implementation
Diffstat (limited to 'lib/lz4hc.c')
-rw-r--r-- | lib/lz4hc.c | 24 |
1 files changed, 19 insertions, 5 deletions
diff --git a/lib/lz4hc.c b/lib/lz4hc.c index 0cda77c..fbcec98 100644 --- a/lib/lz4hc.c +++ b/lib/lz4hc.c @@ -130,20 +130,34 @@ static int LZ4HC_countBack(const BYTE* const ip, const BYTE* const match, return back; } -static unsigned LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, reg_t pattern) +/* LZ4HC_countPattern() : + * pattern32 must be a sample of repetitive pattern of length 1, 2 or 4 (but not 3!) */ +static unsigned LZ4HC_countPattern(const BYTE* ip, const BYTE* const iEnd, U32 const pattern32) { const BYTE* const iStart = ip; + reg_t const pattern = (sizeof(pattern)==8) ? (reg_t)pattern32 + (((reg_t)pattern32) << 32) : pattern32; - while (likely(ip<iEnd-(sizeof(pattern)-1))) { + while (likely(ip < iEnd-(sizeof(pattern)-1))) { reg_t const diff = LZ4_read_ARCH(ip) ^ pattern; if (!diff) { ip+=sizeof(pattern); continue; } ip += LZ4_NbCommonBytes(diff); return (unsigned)(ip - iStart); } - if ((sizeof(pattern)==8) && (ip<(iEnd-3)) && (LZ4_read32(ip)==(U32)pattern)) { ip+=4; } - if ((ip<(iEnd-1)) && (LZ4_read16(ip)==(U16)pattern)) { ip+=2; } - if ((ip<iEnd) && (*ip == (BYTE)pattern)) ip++; + if (LZ4_isLittleEndian()) { + reg_t patternByte = pattern; + while ((ip<iEnd) && (*ip == (BYTE)patternByte)) { + ip++; patternByte >>= 8; + } + } else { /* big endian */ + U32 bitOffset = (sizeof(pattern)*8) - 8; + while (ip < iEnd) { + BYTE const byte = (BYTE)(pattern >> bitOffset); + if (*ip != byte) break; + ip ++; bitOffset -= 8; + } + } + return (unsigned)(ip - iStart); } |