示例#1
0
        public static int CompressFastContinue(StreamT *streamPtr, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration)
        {
            byte *dictEnd = streamPtr->Dictionary + streamPtr->DictSize;

            byte *smallest = source;

            if (streamPtr->InitCheck != 0)
            {
                return(0); // Uninitialized structure detected
            }
            if (streamPtr->DictSize > 0 && smallest > dictEnd)
            {
                smallest = dictEnd;
            }

            RenormDictT(streamPtr, smallest);

            if (acceleration < 1)
            {
                acceleration = AccelerationDefault;
            }

            // Check overlapping input/dictionary space
            {
                byte *sourceEnd = source + inputSize;
                if (sourceEnd > streamPtr->Dictionary && sourceEnd < dictEnd)
                {
                    streamPtr->DictSize = (uint)(dictEnd - sourceEnd);
                    if (streamPtr->DictSize > 64 * KB)
                    {
                        streamPtr->DictSize = 64 * KB;
                    }

                    if (streamPtr->DictSize < 4)
                    {
                        streamPtr->DictSize = 0;
                    }

                    streamPtr->Dictionary = dictEnd - streamPtr->DictSize;
                }
            }

            DictIssueDirective dictIssue = (streamPtr->DictSize < 64 * KB) && (streamPtr->DictSize < streamPtr->CurrentOffset)
                ? DictIssueDirective.DictSmall
                : DictIssueDirective.NoDictIssue;

            DictDirective dictMode = dictEnd == source
                ? DictDirective.WithPrefix64k
                : DictDirective.UsingExtDict;

            int result = CompressGeneric(
                streamPtr,
                source,
                dest,
                inputSize,
                maxOutputSize,
                LimitedOutputDirective.LimitedOutput,
                TableTypeT.ByU32,
                dictMode,
                dictIssue,
                (uint)acceleration);

            if (dictMode == DictDirective.WithPrefix64k)
            {
                // prefix mode : source data follows dictionary
                streamPtr->DictSize      += (uint)inputSize;
                streamPtr->CurrentOffset += (uint)inputSize;
            }
            else
            {
                // external dictionary mode
                streamPtr->Dictionary     = source;
                streamPtr->DictSize       = (uint)inputSize;
                streamPtr->CurrentOffset += (uint)inputSize;
            }

            return(result);
        }
示例#2
0
        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));
        }