コード例 #1
0
ファイル: LZ4Engine64HC.cs プロジェクト: standardfx/standard
        private static uint ReverseCountPattern(byte *ip, byte *iLow, uint pattern)
        {
            byte *iStart = ip;

            while (ip >= iLow + 4)
            {
                if (LZ4MemoryHelper.Peek32(ip - 4) != pattern)
                {
                    break;
                }

                ip -= 4;
            }

            {
                // works for any endianess
                byte *bytePtr = (byte *)&pattern + 3;
                while (ip > iLow)
                {
                    if (ip[-1] != *bytePtr)
                    {
                        break;
                    }

                    ip--;
                    bytePtr--;
                }
            }

            return((uint)(iStart - ip));
        }
コード例 #2
0
ファイル: LZ4Engine64.cs プロジェクト: standardfx/standard
        private static uint HashPosition(void *p, TableTypeT tableType)
        {
#if !BIT32
            if (tableType != TableTypeT.ByU16)
            {
                return(Hash5(ReadArch(p), tableType));
            }
#endif
            return(Hash4(LZ4MemoryHelper.Peek32(p), tableType));
        }
コード例 #3
0
ファイル: LZ4Engine64.cs プロジェクト: standardfx/standard
        protected static uint Count(byte *pIn, byte *pMatch, byte *pInLimit)
        {
            byte *pStart = pIn;

            if (pIn < pInLimit - (StepSize - 1))
            {
                ulong diff = ReadArch(pMatch) ^ ReadArch(pIn);
                if (diff != 0)
                {
                    return(NbCommonBytes(diff));
                }

                pIn    += StepSize;
                pMatch += StepSize;
            }

            while (pIn < pInLimit - (StepSize - 1))
            {
                ulong diff = ReadArch(pMatch) ^ ReadArch(pIn);
                if (diff != 0)
                {
                    return((uint)(pIn + NbCommonBytes(diff) - pStart));
                }

                pIn    += StepSize;
                pMatch += StepSize;
            }

#if !BIT32
            if ((pIn < pInLimit - 3) && (LZ4MemoryHelper.Peek32(pMatch) == LZ4MemoryHelper.Peek32(pIn)))
            {
                pIn    += 4;
                pMatch += 4;
            }
#endif

            if ((pIn < pInLimit - 1) && (LZ4MemoryHelper.Peek16(pMatch) == LZ4MemoryHelper.Peek16(pIn)))
            {
                pIn    += 2;
                pMatch += 2;
            }

            if ((pIn < pInLimit) && (*pMatch == *pIn))
            {
                pIn++;
            }

            return((uint)(pIn - pStart));
        }
コード例 #4
0
ファイル: LZ4Engine64.cs プロジェクト: standardfx/standard
        private static int CompressDestSizeGeneric(StreamT *ctx, byte *src, byte *dst, int *srcSizePtr, int targetDstSize, TableTypeT tableType)
        {
            byte *ip         = src;
            byte *srcBase    = src;
            byte *lowLimit   = src;
            byte *anchor     = ip;
            byte *iend       = ip + *srcSizePtr;
            byte *mflimit    = iend - MFLimit;
            byte *matchlimit = iend - LastLiterals;

            byte *op        = dst;
            byte *oend      = op + targetDstSize;
            byte *oMaxLit   = op + targetDstSize - 2 - 8 - 1;
            byte *oMaxMatch = op + targetDstSize - (LastLiterals + 1);
            byte *oMaxSeq   = oMaxLit - 1;

            if (targetDstSize < 1)
            {
                return(0);
            }
            if (*srcSizePtr > MaxInputSize)
            {
                return(0);
            }
            if ((tableType == TableTypeT.ByU16) && (*srcSizePtr >= Limit64k))
            {
                return(0);
            }

            if (*srcSizePtr < LZ4MinLength)
            {
                goto _last_literals; // Input too small, no compression (all literals)
            }
            *srcSizePtr = 0;
            PutPosition(ip, ctx->HashTable, tableType, srcBase);
            ip++;
            uint forwardH = HashPosition(ip, tableType);

            for (; ;)
            {
                byte *match;
                byte *token;

                {
                    byte *forwardIp     = ip;
                    uint  step          = 1u;
                    uint  searchMatchNb = 1u << SkipTrigger;

                    do
                    {
                        uint h = forwardH;
                        ip         = forwardIp;
                        forwardIp += step;
                        step       = searchMatchNb++ >> SkipTrigger;

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        match    = GetPositionOnHash(h, ctx->HashTable, tableType, srcBase);
                        forwardH = HashPosition(forwardIp, tableType);
                        PutPositionOnHash(ip, h, ctx->HashTable, tableType, srcBase);
                    }while ((tableType != TableTypeT.ByU16) && (match + MaxDistance < ip) ||
                            (LZ4MemoryHelper.Peek32(match) != LZ4MemoryHelper.Peek32(ip)));
                }

                while ((ip > anchor) && (match > lowLimit) && (ip[-1] == match[-1]))
                {
                    ip--;
                    match--;
                }

                {
                    uint litLength = (uint)(ip - anchor);
                    token = op++;
                    if (op + (litLength + 240) / 255 + litLength > oMaxLit)
                    {
                        op--;
                        goto _last_literals;
                    }

                    if (litLength >= RunMask)
                    {
                        uint len = litLength - RunMask;

                        *token = (byte)(RunMask << MLBits);
                        for (; len >= 255; len -= 255)
                        {
                            *op++ = 255;
                        }

                        *op++ = (byte)len;
                    }
                    else
                    {
                        *token = (byte)(litLength << MLBits);
                    }

                    LZ4MemoryHelper.WildCopy(op, anchor, op + litLength);
                    op += litLength;
                }

_next_match:
                LZ4MemoryHelper.Poke16(op, (ushort)(ip - match));
                op += 2;

                {
                    int matchLength = (int)Count(ip + MinMatch, match + MinMatch, matchlimit);

                    if (op + (matchLength + 240) / 255 > oMaxMatch)
                    {
                        matchLength = (int)(15 - 1 + (oMaxMatch - op) * 255);
                    }

                    ip += MinMatch + matchLength;

                    if (matchLength >= MLMask)
                    {
                        *token += (byte)MLMask;
                        matchLength -= (int)MLMask;
                        while (matchLength >= 255)
                        {
                            matchLength -= 255;
                            *op++ = 255;
                        }

                        *op++ = (byte)matchLength;
                    }
                    else
                    {
                        *token += (byte)matchLength;
                    }
                }

                anchor = ip;

                if (ip > mflimit)
                {
                    break;
                }
                if (op > oMaxSeq)
                {
                    break;
                }

                PutPosition(ip - 2, ctx->HashTable, tableType, srcBase);

                match = GetPosition(ip, ctx->HashTable, tableType, srcBase);
                PutPosition(ip, ctx->HashTable, tableType, srcBase);
                if ((match + MaxDistance >= ip) && (LZ4MemoryHelper.Peek32(match) == LZ4MemoryHelper.Peek32(ip)))
                {
                    token = op++;
                    *token = 0;
                    goto _next_match;
                }

                forwardH = HashPosition(++ip, tableType);
            }

_last_literals:
            {
                int lastRunSize = (int)(iend - anchor);
                if (op + 1 + (lastRunSize + 240) / 255 + lastRunSize > oend)
                {
                    lastRunSize  = (int)(oend - op) - 1;
                    lastRunSize -= (lastRunSize + 240) / 255;
                }

                ip = anchor + lastRunSize;

                if (lastRunSize >= RunMask)
                {
                    long accumulator = lastRunSize - RunMask;

                    *op++ = (byte)(RunMask << MLBits);
                    for (; accumulator >= 255; accumulator -= 255)
                    {
                        *op++ = 255;
                    }

                    *op++ = (byte)accumulator;
                }
                else
                {
                    *op++ = (byte)(lastRunSize << MLBits);
                }

                LZ4MemoryHelper.Copy(op, anchor, lastRunSize);
                op += lastRunSize;
            }

            *srcSizePtr = (int)(ip - src);
            return((int)(op - dst));
        }
コード例 #5
0
ファイル: LZ4Engine64.cs プロジェクト: standardfx/standard
        public static int CompressGeneric(StreamT *cctx, byte *source, byte *dest, int inputSize, int maxOutputSize,
                                          LimitedOutputDirective outputLimited, TableTypeT tableType,
                                          DictDirective dict, DictIssueDirective dictIssue, uint acceleration)
        {
            byte *ip = source;
            byte *ibase;
            byte *lowLimit;
            byte *lowRefLimit = ip - cctx->DictSize;
            byte *dictionary  = cctx->Dictionary;
            byte *dictEnd     = dictionary + cctx->DictSize;
            long  dictDelta   = dictEnd - source;
            byte *anchor      = source;
            byte *iend        = ip + inputSize;
            byte *mflimit     = iend - MFLimit;
            byte *matchlimit  = iend - LastLiterals;

            byte *op     = dest;
            byte *olimit = op + maxOutputSize;

            if (inputSize > MaxInputSize)
            {
                return(0);
            }

            switch (dict)
            {
            case DictDirective.WithPrefix64k:
                ibase    = source - cctx->CurrentOffset;
                lowLimit = source - cctx->DictSize;
                break;

            case DictDirective.UsingExtDict:
                ibase    = source - cctx->CurrentOffset;
                lowLimit = source;
                break;

            default:
                ibase    = source;
                lowLimit = source;
                break;
            }

            if ((tableType == TableTypeT.ByU16) && (inputSize >= Limit64k))
            {
                return(0);
            }

            if (inputSize < LZ4MinLength)
            {
                goto _last_literals;
            }

            PutPosition(ip, cctx->HashTable, tableType, ibase);
            ip++;
            uint forwardH = HashPosition(ip, tableType);

            for (; ;)
            {
                long  refDelta = 0L;
                byte *match;
                byte *token;

                {
                    byte *forwardIp     = ip;
                    uint  step          = 1u;
                    uint  searchMatchNb = acceleration << SkipTrigger;
                    do
                    {
                        uint h = forwardH;
                        ip         = forwardIp;
                        forwardIp += step;
                        step       = searchMatchNb++ >> SkipTrigger;

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        match = GetPositionOnHash(h, cctx->HashTable, tableType, ibase);
                        if (dict == DictDirective.UsingExtDict)
                        {
                            if (match < source)
                            {
                                refDelta = dictDelta;
                                lowLimit = dictionary;
                            }
                            else
                            {
                                refDelta = 0;
                                lowLimit = source;
                            }
                        }

                        forwardH = HashPosition(forwardIp, tableType);
                        PutPositionOnHash(ip, h, cctx->HashTable, tableType, ibase);
                    }while ((dictIssue == DictIssueDirective.DictSmall) && (match < lowRefLimit) ||
                            (tableType != TableTypeT.ByU16) && (match + MaxDistance < ip) ||
                            (LZ4MemoryHelper.Peek32(match + refDelta) != LZ4MemoryHelper.Peek32(ip)));
                }

                while ((ip > anchor) && (match + refDelta > lowLimit) && (ip[-1] == match[refDelta - 1]))
                {
                    ip--;
                    match--;
                }

                {
                    uint litLength = (uint)(ip - anchor);
                    token = op++;
                    if ((outputLimited == LimitedOutputDirective.LimitedOutput) &&
                        (op + litLength + (2 + 1 + LastLiterals) + litLength / 255 > olimit))
                    {
                        return(0);
                    }

                    if (litLength >= RunMask)
                    {
                        int len = (int)(litLength - RunMask);

                        *token = (byte)(RunMask << MLBits);
                        for (; len >= 255; len -= 255)
                        {
                            *op++ = 255;
                        }

                        *op++ = (byte)len;
                    }
                    else
                    {
                        *token = (byte)(litLength << MLBits);
                    }

                    LZ4MemoryHelper.WildCopy(op, anchor, op + litLength);
                    op += litLength;
                }

_next_match:
                LZ4MemoryHelper.Poke16(op, (ushort)(ip - match));
                op += 2;

                {
                    uint matchCode;

                    if ((dict == DictDirective.UsingExtDict) && (lowLimit == dictionary))
                    {
                        match += refDelta;
                        byte *limit = ip + (dictEnd - match);
                        if (limit > matchlimit)
                        {
                            limit = matchlimit;
                        }
                        matchCode = Count(ip + MinMatch, match + MinMatch, limit);
                        ip       += MinMatch + matchCode;
                        if (ip == limit)
                        {
                            uint more = Count(ip, source, matchlimit);
                            matchCode += more;
                            ip        += more;
                        }
                    }
                    else
                    {
                        matchCode = Count(ip + MinMatch, match + MinMatch, matchlimit);
                        ip       += MinMatch + matchCode;
                    }

                    if ((outputLimited == LimitedOutputDirective.LimitedOutput) &&
                        (op + (1 + LastLiterals) + (matchCode >> 8) > olimit))
                    {
                        return(0);
                    }

                    if (matchCode >= MLMask)
                    {
                        *token += (byte)MLMask;
                        matchCode -= MLMask;
                        LZ4MemoryHelper.Poke32(op, 0xFFFFFFFF);
                        while (matchCode >= 4 * 255)
                        {
                            op += 4;
                            LZ4MemoryHelper.Poke32(op, 0xFFFFFFFF);
                            matchCode -= 4 * 255;
                        }

                        op += matchCode / 255;

                        *op++ = (byte)(matchCode % 255);
                    }
                    else
                    {
                        *token += (byte)matchCode;
                    }
                }

                anchor = ip;

                if (ip > mflimit)
                {
                    break;
                }

                PutPosition(ip - 2, cctx->HashTable, tableType, ibase);

                match = GetPosition(ip, cctx->HashTable, tableType, ibase);
                if (dict == DictDirective.UsingExtDict)
                {
                    if (match < source)
                    {
                        refDelta = dictDelta;
                        lowLimit = dictionary;
                    }
                    else
                    {
                        refDelta = 0;
                        lowLimit = source;
                    }
                }

                PutPosition(ip, cctx->HashTable, tableType, ibase);
                if ((dictIssue != DictIssueDirective.DictSmall || match >= lowRefLimit) &&
                    (match + MaxDistance >= ip) &&
                    (LZ4MemoryHelper.Peek32(match + refDelta) == LZ4MemoryHelper.Peek32(ip)))
                {
                    token = op++;
                    *token = 0;
                    goto _next_match;
                }

                forwardH = HashPosition(++ip, tableType);
            }

_last_literals:
            {
                int lastRun = (int)(iend - anchor);
                if ((outputLimited == LimitedOutputDirective.LimitedOutput) &&
                    (op - dest + lastRun + 1 + (lastRun + 255 - RunMask) / 255 > (uint)maxOutputSize))
                {
                    return(0);
                }

                if (lastRun >= RunMask)
                {
                    int accumulator = (int)(lastRun - RunMask);

                    *op++ = (byte)(RunMask << MLBits);
                    for (; accumulator >= 255; accumulator -= 255)
                    {
                        *op++ = 255;
                    }
                    *op++ = (byte)accumulator;
                }
                else
                {
                    *op++ = (byte)(lastRun << MLBits);
                }

                LZ4MemoryHelper.Copy(op, anchor, lastRun);
                op += lastRun;
            }

            return((int)(op - dest));
        }
コード例 #6
0
ファイル: LZ4Engine64HC.cs プロジェクト: standardfx/standard
        private static int InsertAndGetWiderMatch(CCtxT *hc4, byte *ip, byte *iLowLimit, byte *iHighLimit, int longest,
                                                  byte **matchpos, byte **startpos, int maxNbAttempts, int patternAnalysis)
        {
            ushort *chainTable   = hc4->ChainTable;
            uint *  hashTable    = hc4->HashTable;
            byte *  basep        = hc4->BaseP;
            uint    dictLimit    = hc4->DictLimit;
            byte *  lowPrefixPtr = basep + dictLimit;
            uint    lowLimit     = hc4->LowLimit + 64 * KB > (uint)(ip - basep)
                ? hc4->LowLimit
                : (uint)(ip - basep) - MaxDistance;
            byte *       dictBase         = hc4->DictBase;
            int          delta            = (int)(ip - iLowLimit);
            int          nbAttempts       = maxNbAttempts;
            uint         pattern          = LZ4MemoryHelper.Peek32(ip);
            RepeatStateE repeat           = RepeatStateE.RepUntested;
            int          srcPatternLength = 0;

            // First Match
            Insert(hc4, ip);
            uint matchIndex = hashTable[HashPtr(ip)];

            while ((matchIndex >= lowLimit) && (nbAttempts != 0))
            {
                nbAttempts--;
                if (matchIndex >= dictLimit)
                {
                    byte *matchPtr = basep + matchIndex;
                    if (*(iLowLimit + longest) == *(matchPtr - delta + longest))
                    {
                        if (LZ4MemoryHelper.Peek32(matchPtr) == pattern)
                        {
                            int mlt  = MinMatch + (int)Count(ip + MinMatch, matchPtr + MinMatch, iHighLimit);
                            int back = 0;
                            while ((ip + back > iLowLimit) &&
                                   (matchPtr + back > lowPrefixPtr) &&
                                   (ip[back - 1] == matchPtr[back - 1]))
                            {
                                back--;
                            }

                            mlt -= back;

                            if (mlt > longest)
                            {
                                longest = mlt;
                                *matchpos = matchPtr + back;
                                *startpos = ip + back;
                            }
                        }
                    }
                }
                else
                {
                    byte *matchPtr = dictBase + matchIndex;
                    if (LZ4MemoryHelper.Peek32(matchPtr) == pattern)
                    {
                        int   back   = 0;
                        byte *vLimit = ip + (dictLimit - matchIndex);
                        if (vLimit > iHighLimit)
                        {
                            vLimit = iHighLimit;
                        }
                        int mlt = MinMatch + (int)Count(ip + MinMatch, matchPtr + MinMatch, vLimit);
                        if ((ip + mlt == vLimit) && (vLimit < iHighLimit))
                        {
                            mlt += (int)Count(ip + mlt, basep + dictLimit, iHighLimit);
                        }

                        while ((ip + back > iLowLimit) &&
                               (matchIndex + back > lowLimit) &&
                               (ip[back - 1] == matchPtr[back - 1]))
                        {
                            back--;
                        }

                        mlt -= back;
                        if (mlt > longest)
                        {
                            longest = mlt;
                            *matchpos = basep + matchIndex + back;
                            *startpos = ip + back;
                        }
                    }
                }

                {
                    ushort nextOffset = DeltaNextU16(chainTable, (ushort)matchIndex);
                    matchIndex -= nextOffset;
                    if ((patternAnalysis != 0) && (nextOffset == 1))
                    {
                        // may be a repeated pattern
                        if (repeat == RepeatStateE.RepUntested)
                        {
                            if (((pattern & 0xFFFF) == pattern >> 16) &
                                ((pattern & 0xFF) == pattern >> 24))
                            {
                                repeat           = RepeatStateE.RepConfirmed;
                                srcPatternLength = (int)CountPattern(ip + 4, iHighLimit, pattern) + 4;
                            }
                            else
                            {
                                repeat = RepeatStateE.RepNot;
                            }
                        }

                        if ((repeat == RepeatStateE.RepConfirmed) && (matchIndex >= dictLimit))
                        {
                            byte *matchPtr = basep + matchIndex;
                            if (LZ4MemoryHelper.Peek32(matchPtr) == pattern)
                            {
                                int   forwardPatternLength = (int)CountPattern(matchPtr + sizeof(uint), iHighLimit, pattern) + sizeof(uint);
                                byte *maxLowPtr            = lowPrefixPtr + MaxDistance >= ip
                                    ? lowPrefixPtr
                                    : ip - MaxDistance;
                                int backLength           = (int)ReverseCountPattern(matchPtr, maxLowPtr, pattern);
                                int currentSegmentLength = backLength + forwardPatternLength;

                                if ((currentSegmentLength >= srcPatternLength) &&
                                    (forwardPatternLength <= srcPatternLength))
                                {
                                    matchIndex += (uint)(forwardPatternLength - srcPatternLength);
                                }
                                else
                                {
                                    matchIndex -= (uint)backLength;
                                }
                            }
                        }
                    }
                }
            }

            return(longest);
        }
コード例 #7
0
ファイル: LZ4Engine64HC.cs プロジェクト: standardfx/standard
 private static uint HashPtr(void *ptr)
 {
     return((LZ4MemoryHelper.Peek32(ptr) * 2654435761U) >> (MinMatch * 8 - HashLogHC));
 }