コード例 #1
0
ファイル: LZ4.cs プロジェクト: mpvyard/Minotaur
 private static void LZ4_resetStream(LZ4_stream_t *state) => Mem.Zero((byte *)state, sizeof(LZ4_stream_t));
コード例 #2
0
ファイル: LZ4.cs プロジェクト: mpvyard/Minotaur
        private static int LZ4_compress_fast_continue <TEndian, TArch>(LZ4_stream_t *stream, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration = 1)
            where TEndian : struct, IEndian
            where TArch : unmanaged, IArch
        {
            var dictEnd = stream->dictionary + stream->dictSize;

            Debug.WriteLine($"LZ4_compress_fast_continue (inputSize={inputSize})");
            if (stream->initCheck != 0)
            {
                return(0);                        /* Uninitialized structure detected */
            }
            LZ4_renormDictT(stream, inputSize);   /* avoid index overflow */
            acceleration = Math.Max(acceleration, 1);

            /* invalidate tiny dictionaries */
            if (stream->dictSize - 1 < 4 && /* intentional underflow */
                dictEnd != source)
            {
                Debug.WriteLine($"LZ4_compress_fast_continue: dictSize({stream->dictSize}) at addr:{(ulong)stream->dictionary} is too small");
                stream->dictSize   = 0;
                stream->dictionary = source;
                dictEnd            = source;
            }

            /* Check overlapping input/dictionary space */
            {
                var sourceEnd = source + inputSize;
                if ((sourceEnd > stream->dictionary) && (sourceEnd < dictEnd))
                {
                    stream->dictSize = (uint)(dictEnd - sourceEnd);
                    if (stream->dictSize > _64KB)
                    {
                        stream->dictSize = _64KB;
                    }
                    if (stream->dictSize < 4)
                    {
                        stream->dictSize = 0;
                    }
                    stream->dictionary = dictEnd - stream->dictSize;
                }
            }

            /* prefix mode : source data follows dictionary */
            if (dictEnd == source)
            {
                var _ = 0;
                if (stream->dictSize < _64KB && stream->dictSize < stream->currentOffset)
                {
                    return(LZ4_compress_generic <LimitedOutput, ByU32, WithPrefix64K, DictSmall, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration));
                }
                return(LZ4_compress_generic <LimitedOutput, ByU32, WithPrefix64K, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration));
            }

            /* external dictionary mode */
            {
                int result;
                var _ = 0;
                if (stream->dictCtx != null)
                {
                    /* We depend here on the fact that dictCtx'es (produced by
                     * LZ4_loadDict) guarantee that their tables contain no references
                     * to offsets between dictCtx->currentOffset - 64 KB and
                     * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe
                     * to use noDictIssue even when the dict isn't a full 64 KB.
                     */
                    if (inputSize > _4KB)
                    {
                        /* For compressing large blobs, it is faster to pay the setup
                         * cost to copy the dictionary's tables into the active context,
                         * so that the compression loop is only looking into one table.
                         */
                        Unsafe.CopyBlock(stream, stream->dictCtx, (uint)sizeof(LZ4_stream_t));
                        result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration);
                    }
                    else
                    {
                        result = LZ4_compress_generic <LimitedOutput, ByU32, UsingDictCtx, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration);
                    }
                }
                else
                {
                    if ((stream->dictSize < _64KB) && (stream->dictSize < stream->currentOffset))
                    {
                        result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, DictSmall, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration);
                    }
                    else
                    {
                        result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration);
                    }
                }
                stream->dictionary = source;
                stream->dictSize   = (uint)inputSize;
                return(result);
            }
        }
コード例 #3
0
        static int LZ4_compress_destSize_generic(
            LZ4_stream_t *ctx, byte *src, byte *dst, int *srcSizePtr, int targetDstSize,
            tableType_t tableType)
        {
            var ip         = src;
            var base_      = src;
            var lowLimit   = src;
            var anchor     = ip;
            var iend       = ip + *srcSizePtr;
            var mflimit    = iend - MFLIMIT;
            var matchlimit = iend - LASTLITERALS;

            var op        = dst;
            var oend      = op + targetDstSize;
            var oMaxLit   = op + targetDstSize - 2 - 8 - 1;
            var oMaxMatch = op + targetDstSize - (LASTLITERALS + 1);
            var oMaxSeq   = oMaxLit - 1;

            if (targetDstSize < 1)
            {
                return(0);
            }
            if (*srcSizePtr > LZ4_MAX_INPUT_SIZE)
            {
                return(0);
            }
            if (tableType == tableType_t.byU16 && *srcSizePtr >= LZ4_64Klimit)
            {
                return(0);
            }

            if (*srcSizePtr < LZ4_minLength)
            {
                goto _last_literals;                 /* Input too small, no compression (all literals) */
            }
            *srcSizePtr = 0;
            LZ4_putPosition(ip, ctx->hashTable, tableType, base_);
            ip++;
            var forwardH = LZ4_hashPosition(ip, tableType);

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

                {
                    var forwardIp     = ip;
                    var step          = 1u;
                    var searchMatchNb = 1u << LZ4_skipTrigger;

                    do
                    {
                        var h = forwardH;
                        ip         = forwardIp;
                        forwardIp += step;
                        step       = searchMatchNb++ >> LZ4_skipTrigger;

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        match    = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base_);
                        forwardH = LZ4_hashPosition(forwardIp, tableType);
                        LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base_);
                    }while (
                        tableType != tableType_t.byU16 && match + MAX_DISTANCE < ip ||
                        Mem.Peek32(match) != Mem.Peek32(ip));
                }

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

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

                    if (litLength >= RUN_MASK)
                    {
                        var len = litLength - RUN_MASK;

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

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

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

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

                {
                    var matchLength = (int)LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);

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

                    ip += MINMATCH + matchLength;

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

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

                anchor = ip;

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

                LZ4_putPosition(ip - 2, ctx->hashTable, tableType, base_);

                match = LZ4_getPosition(ip, ctx->hashTable, tableType, base_);
                LZ4_putPosition(ip, ctx->hashTable, tableType, base_);
                if (match + MAX_DISTANCE >= ip && Mem.Peek32(match) == Mem.Peek32(ip))
                {
                    token = op++;
                    *token = 0;
                    goto _next_match;
                }

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

_last_literals:
            {
                var 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 >= RUN_MASK)
                {
                    var accumulator = lastRunSize - RUN_MASK;

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

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

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

            *srcSizePtr = (int)(ip - src);
            return((int)(op - dst));
        }
コード例 #4
0
        public static int LZ4_compress_fast_continue(
            LZ4_stream_t *streamPtr, byte *source, byte *dest, int inputSize, int maxOutputSize,
            int acceleration)
        {
            var dictEnd = streamPtr->dictionary + streamPtr->dictSize;

            var smallest = source;

            if (streamPtr->initCheck != 0)
            {
                return(0);                                       /* Uninitialized structure detected */
            }
            if (streamPtr->dictSize > 0 && smallest > dictEnd)
            {
                smallest = dictEnd;
            }
            LZ4_renormDictT(streamPtr, smallest);
            if (acceleration < 1)
            {
                acceleration = ACCELERATION_DEFAULT;
            }

            /* Check overlapping input/dictionary space */
            {
                var 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;
                }
            }

            var dictIssue =
                streamPtr->dictSize < 64 * KB && streamPtr->dictSize < streamPtr->currentOffset
                                        ? dictIssue_directive.dictSmall
                                        : dictIssue_directive.noDictIssue;
            var dictMode =
                dictEnd == source
                                        ? dict_directive.withPrefix64k
                                        : dict_directive.usingExtDict;

            var result = LZ4_compress_generic(
                streamPtr,
                source,
                dest,
                inputSize,
                maxOutputSize,
                limitedOutput_directive.limitedOutput,
                tableType_t.byU32,
                dictMode,
                dictIssue,
                (uint)acceleration);

            if (dictMode == dict_directive.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);
        }
コード例 #5
0
        public static int LZ4_compress_generic(
            LZ4_stream_t *cctx,
            byte *source,
            byte *dest,
            int inputSize,
            int maxOutputSize,
            limitedOutput_directive outputLimited,
            tableType_t tableType,
            dict_directive dict,
            dictIssue_directive dictIssue,
            uint acceleration)
        {
            var   ip = source;
            byte *ibase;
            byte *lowLimit;
            var   lowRefLimit = ip - cctx->dictSize;
            var   dictionary  = cctx->dictionary;
            var   dictEnd     = dictionary + cctx->dictSize;
            var   dictDelta   = dictEnd - source;
            var   anchor      = source;
            var   iend        = ip + inputSize;
            var   mflimit     = iend - MFLIMIT;
            var   matchlimit  = iend - LASTLITERALS;

            var op     = dest;
            var olimit = op + maxOutputSize;

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

            switch (dict)
            {
            case dict_directive.withPrefix64k:
                ibase    = source - cctx->currentOffset;
                lowLimit = source - cctx->dictSize;
                break;

            case dict_directive.usingExtDict:
                ibase    = source - cctx->currentOffset;
                lowLimit = source;
                break;

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

            if (tableType == tableType_t.byU16 && inputSize >= LZ4_64Klimit)
            {
                return(0);
            }

            if (inputSize < LZ4_minLength)
            {
                goto _last_literals;
            }

            LZ4_putPosition(ip, cctx->hashTable, tableType, ibase);
            ip++;
            var forwardH = LZ4_hashPosition(ip, tableType);

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

                {
                    var forwardIp     = ip;
                    var step          = 1u;
                    var searchMatchNb = acceleration << LZ4_skipTrigger;
                    do
                    {
                        var h = forwardH;
                        ip         = forwardIp;
                        forwardIp += step;
                        step       = searchMatchNb++ >> LZ4_skipTrigger;

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, ibase);
                        if (dict == dict_directive.usingExtDict)
                        {
                            if (match < source)
                            {
                                refDelta = dictDelta;
                                lowLimit = dictionary;
                            }
                            else
                            {
                                refDelta = 0;
                                lowLimit = source;
                            }
                        }

                        forwardH = LZ4_hashPosition(forwardIp, tableType);
                        LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, ibase);
                    }while (
                        dictIssue == dictIssue_directive.dictSmall && match < lowRefLimit ||
                        tableType != tableType_t.byU16 && match + MAX_DISTANCE < ip ||
                        Mem.Peek32(match + refDelta) != Mem.Peek32(ip));
                }

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

                {
                    var litLength = (uint)(ip - anchor);
                    token = op++;
                    if (outputLimited == limitedOutput_directive.limitedOutput &&
                        op + litLength + (2 + 1 + LASTLITERALS) + litLength / 255 > olimit)
                    {
                        return(0);
                    }

                    if (litLength >= RUN_MASK)
                    {
                        var len = (int)(litLength - RUN_MASK);

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

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

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

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

                {
                    uint matchCode;

                    if (dict == dict_directive.usingExtDict && lowLimit == dictionary)
                    {
                        match += refDelta;
                        var limit = ip + (dictEnd - match);
                        if (limit > matchlimit)
                        {
                            limit = matchlimit;
                        }
                        matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, limit);
                        ip       += MINMATCH + matchCode;
                        if (ip == limit)
                        {
                            var more = LZ4_count(ip, source, matchlimit);
                            matchCode += more;
                            ip        += more;
                        }
                    }
                    else
                    {
                        matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
                        ip       += MINMATCH + matchCode;
                    }

                    if (outputLimited == limitedOutput_directive.limitedOutput &&
                        op + (1 + LASTLITERALS) + (matchCode >> 8) > olimit)
                    {
                        return(0);
                    }

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

                        op += matchCode / 255;

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

                anchor = ip;

                if (ip > mflimit)
                {
                    break;
                }

                LZ4_putPosition(ip - 2, cctx->hashTable, tableType, ibase);

                match = LZ4_getPosition(ip, cctx->hashTable, tableType, ibase);
                if (dict == dict_directive.usingExtDict)
                {
                    if (match < source)
                    {
                        refDelta = dictDelta;
                        lowLimit = dictionary;
                    }
                    else
                    {
                        refDelta = 0;
                        lowLimit = source;
                    }
                }

                LZ4_putPosition(ip, cctx->hashTable, tableType, ibase);
                if ((dictIssue != dictIssue_directive.dictSmall || match >= lowRefLimit) &&
                    match + MAX_DISTANCE >= ip &&
                    Mem.Peek32(match + refDelta) == Mem.Peek32(ip))
                {
                    token = op++;
                    *token = 0;
                    goto _next_match;
                }

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

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

                if (lastRun >= RUN_MASK)
                {
                    var accumulator = (int)(lastRun - RUN_MASK);

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

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

            return((int)(op - dest));
        }