Exemplo n.º 1
0
            private void MakeWriteable(Partition partition)
            {
                if (partition.Writeable)
                {
                    return;
                }

                // we can safely pass the raw pointer here and dispose DirectAdd scope immediately because
                // filter's content will be written to an overflow

                Debug.Assert(_tree.ShouldGoToOverflowPage(_ptrSize));

                using (_tree.DirectAdd(partition.Key, Partition.PartitionSize, out byte *ptr))
                {
                    if (partition.IsEmpty == false)
                    {
                        UnmanagedMemory.Copy(ptr, partition.Ptr, Partition.PartitionSize);
                    }

                    partition.Writeable = true;
                    partition.IsEmpty   = false;
                    partition.Ptr       = ptr;
                }

                Writeable = true;
            }
            private void MakeWriteable()
            {
                if (Writeable)
                {
                    return;
                }

                var ptr = _tree.DirectAdd(_key, PtrSize);

                UnmanagedMemory.Copy(ptr, _basePtr, PtrSize);

                Initialize(ptr);

                Writeable = true;
            }
Exemplo n.º 3
0
        private static int LZ4_decompress_generic <TEndCondition, TEarlyEnd, TDictionaryType>(byte *source, byte *dest, int inputSize, int outputSize, int targetOutputSize, byte *lowPrefix, byte *dictStart, int dictSize)
            where TEndCondition : IEndConditionDirective
            where TEarlyEnd : IEarlyEndDirective
            where TDictionaryType : IDictionaryTypeDirective
        {
            /* Local Variables */
            byte *ip   = source;
            byte *iend = ip + inputSize;

            byte *op   = dest;
            byte *oend = op + outputSize;

            byte *oexit    = op + targetOutputSize;
            byte *lowLimit = lowPrefix - dictSize;

            byte *dictEnd = dictStart + dictSize;

            bool checkOffset = ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (dictSize < 64 * Constants.Size.Kilobyte));

            // Special Cases
            if ((typeof(TEarlyEnd) == typeof(Partial)) && (oexit > oend - MFLIMIT))
            {
                oexit = oend - MFLIMIT;                                                                                              // targetOutputSize too high => decode everything
            }
            if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (outputSize == 0))
            {
                return(((inputSize == 1) && (*ip == 0)) ? 0 : -1);  // Empty output buffer
            }
            if ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (outputSize == 0))
            {
                return(*ip == 0 ? 1 : -1);
            }

            // Main Loop
            while (true)
            {
                int length;

                /* get literal length */
                byte token = *ip++;
                if ((length = (token >> ML_BITS)) == RUN_MASK)
                {
                    byte s;
                    do
                    {
                        s       = *ip++;
                        length += s;
                    }while (((typeof(TEndCondition) == typeof(EndOnInputSize)) ? ip < iend - RUN_MASK : true) && (s == 255));

                    if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (op + length) < op)
                    {
                        goto _output_error;                                                                            /* overflow detection */
                    }
                    if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip + length) < ip)
                    {
                        goto _output_error;                                                                            /* overflow detection */
                    }
                }

                // copy literals
                byte *cpy = op + length;
                if (((typeof(TEndCondition) == typeof(EndOnInputSize)) && ((cpy > (typeof(TEarlyEnd) == typeof(Partial) ? oexit : oend - MFLIMIT)) || (ip + length > iend - (2 + 1 + LASTLITERALS)))) ||
                    ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (cpy > oend - COPYLENGTH)))
                {
                    if (typeof(TEarlyEnd) == typeof(Partial))
                    {
                        if (cpy > oend)
                        {
                            goto _output_error;                           /* Error : write attempt beyond end of output buffer */
                        }
                        if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip + length > iend))
                        {
                            goto _output_error;   /* Error : read attempt beyond end of input buffer */
                        }
                    }
                    else
                    {
                        if ((typeof(TEndCondition) == typeof(EndOnOutputSize)) && (cpy != oend))
                        {
                            goto _output_error;       /* Error : block decoding must stop exactly there */
                        }
                        if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && ((ip + length != iend) || (cpy > oend)))
                        {
                            goto _output_error;   /* Error : input must be consumed */
                        }
                    }

                    UnmanagedMemory.Copy(op, ip, length);
                    ip += length;
                    op += length;
                    break;     /* Necessarily EOF, due to parsing restrictions */
                }

                WildCopy(op, ip, cpy);
                ip += length; op = cpy;

                /* get offset */
                byte *match = cpy - *((ushort *)ip); ip += sizeof(ushort);
                if ((checkOffset) && (match < lowLimit))
                {
                    goto _output_error;   /* Error : offset outside destination buffer */
                }
                /* get matchlength */
                if ((length = (token & ML_MASK)) == ML_MASK)
                {
                    byte s;
                    do
                    {
                        if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (ip > iend - LASTLITERALS))
                        {
                            goto _output_error;
                        }

                        s       = *ip++;
                        length += s;
                    }while (s == 255);

                    if ((typeof(TEndCondition) == typeof(EndOnInputSize)) && (op + length) < op)
                    {
                        goto _output_error;   /* overflow detection */
                    }
                }

                length += MINMATCH;

                /* check external dictionary */
                if ((typeof(TDictionaryType) == typeof(UsingExtDict)) && (match < lowPrefix))
                {
                    if (op + length > oend - LASTLITERALS)
                    {
                        goto _output_error;   /* doesn't respect parsing restriction */
                    }
                    if (length <= (int)(lowPrefix - match))
                    {
                        /* match can be copied as a single segment from external dictionary */
                        match = dictEnd - (lowPrefix - match);
                        UnmanagedMemory.Move(op, match, length); // TODO: Check if move is required.
                        op += length;
                    }
                    else
                    {
                        /* match encompass external dictionary and current segment */
                        int copySize = (int)(lowPrefix - match);
                        UnmanagedMemory.Copy(op, dictEnd - copySize, copySize);
                        op += copySize;

                        copySize = length - copySize;
                        if (copySize > (int)(op - lowPrefix))   /* overlap within current segment */
                        {
                            byte *endOfMatch = op + copySize;
                            byte *copyFrom   = lowPrefix;
                            while (op < endOfMatch)
                            {
                                *op++ = *copyFrom++;
                            }
                        }
                        else
                        {
                            UnmanagedMemory.Copy(op, lowPrefix, copySize);
                            op += copySize;
                        }
                    }
                    continue;
                }

                /* copy repeated sequence */
                cpy = op + length;
                if ((op - match) < 8)
                {
                    int dec64 = dec64table[op - match];
                    op[0] = match[0];
                    op[1] = match[1];
                    op[2] = match[2];
                    op[3] = match[3];

                    match += dec32table[op - match];
                    *((uint *)(op + 4)) = *(uint *)match;
                    op    += 8;
                    match -= dec64;
                }
                else
                {
                    *((ulong *)op) = *(ulong *)match;
                    op            += sizeof(ulong);
                    match         += sizeof(ulong);
                }

                if (cpy > oend - 12)
                {
                    if (cpy > oend - LASTLITERALS)
                    {
                        goto _output_error;    /* Error : last LASTLITERALS bytes must be literals */
                    }
                    if (op < oend - 8)
                    {
                        WildCopy(op, match, (oend - 8));
                        match += (oend - 8) - op;
                        op     = oend - 8;
                    }

                    while (op < cpy)
                    {
                        *op++ = *match++;
                    }
                }
                else
                {
                    WildCopy(op, match, cpy);
                }

                op = cpy;   /* correction */
            }

            /* end of decoding */
            if (typeof(TEndCondition) == typeof(EndOnInputSize))
            {
                return((int)(op - dest));     /* Nb of output bytes decoded */
            }
            else
            {
                return((int)(ip - source));   /* Nb of input bytes read */
            }
            /* Overflow error detected */
_output_error:
            return((int)(-(ip - source)) - 1);
        }
Exemplo n.º 4
0
        private static int LZ4_compress_generic <TLimited, TTableType, TDictionaryType, TDictionaryIssue>(LZ4_stream_t_internal *dictPtr, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration)
            where TLimited : ILimitedOutputDirective
            where TTableType : ITableTypeDirective
            where TDictionaryType : IDictionaryTypeDirective
            where TDictionaryIssue : IDictionaryIssueDirective
        {
            LZ4_stream_t_internal *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 (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_64Klimit)) // Size too large (not within 64K limit)
            {
                return(0);
            }

            if (inputSize < LZ4_minLength) // 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_skipTrigger;

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

                        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) * prime5bytes >> (40 - ByU16HashLog);
                            forwardH = (int)(value & ByU16HashMask);
                            ((ushort *)ctx->hashTable)[h] = (ushort)(ip - @base);
                        }
                        else if (typeof(TTableType) == typeof(ByU32))
                        {
                            ulong value = (*((ulong *)forwardIp) * prime5bytes >> (40 - ByU32HashLog));
                            forwardH          = (int)(value & ByU32HashMask);
                            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++;

                    if ((typeof(TLimited) == typeof(LimitedOutput)) && (op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit))
                    {
                        return(0);   /* Check output limit */
                    }
                    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)
                        {
                            *op++ = 255;
                            *op++ = 255;
                        }

                        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 = (int)(iend - anchor);
                if ((typeof(TLimited) == typeof(LimitedOutput)) && ((op - dest) + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > maxOutputSize))
                {
                    return(0);   // Check output limit;
                }
                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);
                }

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

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