Esempio n. 1
0
        private static void LZ4_putPosition <TTableType>(byte *p, Lz4StreamTInternal *ctx, byte *srcBase)
            where TTableType : ITableTypeDirective
        {
            int h = LZ4_hashPosition <TTableType>(p);

            LZ4_putPositionOnHash <TTableType>(p, h, ctx, srcBase);
        }
Esempio n. 2
0
        private static byte *LZ4_getPosition <TTableType>(byte *p, Lz4StreamTInternal *ctx, byte *srcBase)
            where TTableType : ITableTypeDirective
        {
            int h = LZ4_hashPosition <TTableType>(p);

            return(LZ4_getPositionOnHash <TTableType>(h, ctx, srcBase));
        }
Esempio n. 3
0
        private static byte *LZ4_getPositionOnHash <TTableType>(int h, Lz4StreamTInternal *ctx, byte *srcBase)
            where TTableType : ITableTypeDirective
        {
            if (typeof(TTableType) == typeof(ByU32))
            {
                return(srcBase + ctx->hashTable[h]);
            }
            else if (typeof(TTableType) == typeof(ByU16))
            {
                return(srcBase + ((ushort *)ctx->hashTable)[h]);
            }

            ThrowException(new NotSupportedException("TTableType directive is not supported."));
            return(default(byte *));
        }
Esempio n. 4
0
 private static void LZ4_putPositionOnHash <TTableType>(byte *p, int h, Lz4StreamTInternal *ctx, byte *srcBase)
     where TTableType : ITableTypeDirective
 {
     if (typeof(TTableType) == typeof(ByU32))
     {
         ctx->hashTable[h] = (int)(p - srcBase);
     }
     else if (typeof(TTableType) == typeof(ByU16))
     {
         ((ushort *)ctx->hashTable)[h] = (ushort)(p - srcBase);
     }
     else
     {
         ThrowException(new NotSupportedException("TTableType directive is not supported."));
     }
 }
Esempio n. 5
0
        private static int LZ4_compress_generic <TLimited, TTableType, TDictionaryType, TDictionaryIssue>(Lz4StreamTInternal *dictPtr, ref byte *source, ref byte *dest, int inputSize, int maxOutputSize, int acceleration)
            where TLimited : ILimitedOutputDirective
            where TTableType : ITableTypeDirective
            where TDictionaryType : IDictionaryTypeDirective
            where TDictionaryIssue : IDictionaryIssueDirective
        {
            Lz4StreamTInternal *ctx = dictPtr;

            byte *op     = dest;
            byte *ip     = source;
            byte *anchor = source;

            byte *dictionary  = ctx->dictionary;
            byte *dictEnd     = dictionary + ctx->dictSize;
            byte *lowRefLimit = ip - ctx->dictSize;

            long dictDelta = (long)dictEnd - (long)source;

            byte *iend       = ip + inputSize;
            byte *mflimit    = iend - MFLIMIT;
            byte *matchlimit = iend - LASTLITERALS;

            byte *olimit = op + maxOutputSize;

            // Init conditions
            if (typeof(TLimited) == typeof(LimitedDestSize) && maxOutputSize < 1)
            {
                return(0);                                                                  /* Impossible to store anything */
            }
            if (inputSize > LZ4_MAX_INPUT_SIZE)
            {
                return(0);                                  // Unsupported input size, too large (or negative)
            }
            byte * @base;
            byte * lowLimit;

            if (typeof(TDictionaryType) == typeof(NoDict))
            {
                @base    = source;
                lowLimit = source;
            }
            else if (typeof(TDictionaryType) == typeof(WithPrefix64K))
            {
                @base    = source - ctx->currentOffset;
                lowLimit = source - ctx->dictSize;
            }
            else if (typeof(TDictionaryType) == typeof(UsingExtDict))
            {
                @base    = source - ctx->currentOffset;
                lowLimit = source;
            }
            else
            {
                throw new NotSupportedException("Unsupported IDictionaryTypeDirective.");
            }

            if ((typeof(TTableType) == typeof(ByU16)) && (inputSize >= LZ4_64_KLIMIT)) // Size too large (not within 64K limit)
            {
                return(0);
            }

            if (inputSize < LZ4_MIN_LENGTH) // Input too small, no compression (all literals)
            {
                goto _last_literals;
            }

            // First Byte
            LZ4_putPosition <TTableType>(ip, ctx, @base);
            ip++;
            int forwardH = LZ4_hashPosition <TTableType>(ip);

            // Main Loop
            long refDelta = 0;

            for (;;)
            {
                byte *match;
                {
                    byte *forwardIp = ip;

                    int step          = 1;
                    int searchMatchNb = acceleration << LZ4_SKIP_TRIGGER;

                    do
                    {
                        int h = forwardH;
                        ip         = forwardIp;
                        forwardIp += step;
                        step       = (searchMatchNb++ >> LZ4_SKIP_TRIGGER);

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        match = LZ4_getPositionOnHash <TTableType>(h, ctx, @base);
                        if (typeof(TDictionaryType) == typeof(UsingExtDict))
                        {
                            if (match < source)
                            {
                                refDelta = dictDelta;
                                lowLimit = dictionary;
                            }
                            else
                            {
                                refDelta = 0;
                                lowLimit = source;
                            }
                        }

                        if (typeof(TTableType) == typeof(ByU16))
                        {
                            ulong value = *((ulong *)forwardIp) * PRIME5_BYTES >> (40 - BY_U16_HASH_LOG);
                            forwardH = (int)(value & BY_U16_HASH_MASK);
                            ((ushort *)ctx->hashTable)[h] = (ushort)(ip - @base);
                        }
                        else if (typeof(TTableType) == typeof(ByU32))
                        {
                            ulong value = (*((ulong *)forwardIp) * PRIME5_BYTES >> (40 - BY_U32_HASH_LOG));
                            forwardH          = (int)(value & BY_U32_HASH_MASK);
                            ctx->hashTable[h] = (int)(ip - @base);
                        }
                        else
                        {
                            throw new NotSupportedException("TTableType directive is not supported.");
                        }
                    }while (((typeof(TDictionaryType) == typeof(DictSmall)) ? (match < lowRefLimit) : false) ||
                            ((typeof(TTableType) == typeof(ByU16)) ? false : (match + MAX_DISTANCE < ip)) ||
                            (*(uint *)(match + refDelta) != *((uint *)ip)));
                }

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


                // Encode Literal length
                byte *token;
                {
                    int litLength = (int)(ip - anchor);
                    token = op++;

                    /* Check output limit */
                    if ((typeof(TLimited) == typeof(LimitedOutput)) &&
                        (op + litLength + (litLength / 255) + sizeof(ushort) > olimit))
                    {
                        op = token;
                        ip = anchor;
                        goto _skip_last_literals;
                    }

                    if (litLength >= RUN_MASK)
                    {
                        int len   = litLength - RUN_MASK;
                        *   token = RUN_MASK << ML_BITS;

                        for (; len >= 255; len -= 255)
                        {
                            *op++ = 255;
                        }

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

                    /* Copy Literals */
                    WildCopy(op, anchor, (op + litLength));
                    op += litLength;
                }

_next_match:

                // Encode Offset
                *((ushort *)op) = (ushort)(ip - match);
                op += sizeof(ushort);

                // Encode MatchLength
                {
                    int matchLength;

                    if ((typeof(TDictionaryType) == typeof(UsingExtDict)) && (lowLimit == dictionary))
                    {
                        match += refDelta;

                        byte *limit = ip + (dictEnd - match);
                        if (limit > matchlimit)
                        {
                            limit = matchlimit;
                        }
                        matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, limit);
                        ip         += MINMATCH + matchLength;
                        if (ip == limit)
                        {
                            int more = LZ4_count(ip, source, matchlimit);
                            matchLength += more;
                            ip          += more;
                        }
                    }
                    else
                    {
                        matchLength = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit);
                        ip         += MINMATCH + matchLength;
                    }

                    if ((typeof(TLimited) == typeof(LimitedOutput)) && ((op + (1 + LASTLITERALS) + (matchLength >> 8)) > olimit))
                    {
                        return(0);    /* Check output limit */
                    }
                    if (matchLength >= ML_MASK)
                    {
                        *token += ML_MASK;
                        matchLength -= ML_MASK;

                        for (; matchLength >= 510; matchLength -= 510)
                        {
                            *(ushort *)op = (255 << 8 | 255);
                            op           += sizeof(ushort);
                        }

                        if (matchLength >= 255)
                        {
                            matchLength -= 255;
                            *op++ = 255;
                        }

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


                anchor = ip;

                // Test end of chunk
                if (ip > mflimit)
                {
                    break;
                }

                // Fill table
                LZ4_putPosition <TTableType>(ip - 2, ctx, @base);

                /* Test next position */
                match = LZ4_getPosition <TTableType>(ip, ctx, @base);
                if (typeof(TDictionaryType) == typeof(UsingExtDict))
                {
                    if (match < source)
                    {
                        refDelta = dictDelta;
                        lowLimit = dictionary;
                    }
                    else
                    {
                        refDelta = 0;
                        lowLimit = source;
                    }
                }

                LZ4_putPosition <TTableType>(ip, ctx, @base);
                if (((typeof(TDictionaryType) == typeof(DictSmall)) ? (match >= lowRefLimit) : true) && (match + MAX_DISTANCE >= ip) && (*(uint *)(match + refDelta) == *(uint *)(ip)))
                {
                    token = op++; *token = 0;
                    goto _next_match;
                }

                /* Prepare next loop */
                forwardH = LZ4_hashPosition <TTableType>(++ip);
            }

_last_literals:

            /* Encode Last Literals */
            {
                int lastRun = typeof(TLimited) == typeof(LimitedOutput) ? maxOutputSize - (int)(op - dest) - 1 : (int)(iend - anchor);

                if (lastRun >= RUN_MASK)
                {
                    int accumulator = lastRun - RUN_MASK;
                    *   op++        = RUN_MASK << ML_BITS;

                    for (; accumulator >= 255; accumulator -= 255)
                    {
                        *op++ = 255;
                    }

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

                Unsafe.CopyBlock(op, anchor, (uint)lastRun);
                op += lastRun;
                ip += lastRun;
            }

_skip_last_literals:

            {
                var result = (int)(op - dest);
                source = ip;
                dest   = op;
                return(result);
            }
        }