Exemple #1
0
        public int Decompress(
            byte *compressedBuffer,
            byte *decompressedBuffer,
            int compressedSize,
            int maxDecompressedSize)
        {
            fixed(sbyte *dec = m_DecArray)
            {
                // Local Variables
                byte *ip   = (byte *)compressedBuffer;
                byte *iend = ip + compressedSize;
                byte *r;

                byte *op   = (byte *)decompressedBuffer;
                byte *oend = op + maxDecompressedSize;
                byte *cpy;

                byte token;
                int  len, length;


                // Main Loop
                while (ip < iend)
                {
                    // get runLength
                    token = *ip++;
                    if ((length = (token >> LZ4Util.ML_BITS)) == LZ4Util.RUN_MASK)
                    {
                        int s = 255; while ((ip < iend) && (s == 255))
                        {
                            s = *ip++; length += s;
                        }
                    }

                    // copy literals
                    cpy = op + length;
                    if ((cpy > oend - LZ4Util.COPYLENGTH) || (ip + length > iend - LZ4Util.COPYLENGTH))
                    {
                        if (cpy > oend)
                        {
                            goto _output_error;             // Error : request to write beyond destination buffer
                        }
                        if (ip + length > iend)
                        {
                            goto _output_error;                     // Error : request to read beyond source buffer
                        }
                        LZ4Util.CopyMemory(op, ip, length);
                        op += length;
                        ip += length;
                        if (ip < iend)
                        {
                            goto _output_error; // Error : LZ4 format violation
                        }
                        break;                  //Necessarily EOF
                    }

                    do
                    {
                        *(uint *)op = *(uint *)ip; op += 4; ip += 4;; *(uint *)op = *(uint *)ip; op += 4; ip += 4;;
                    } while (op < cpy);; ip -= (op - cpy); op = cpy;

                    // get offset
                    { r = (cpy) - *(ushort *)ip; }; ip += 2;
                    if (r < decompressedBuffer)
                    {
                        goto _output_error;
                    }

                    // get matchlength
                    if ((length = (int)(token & LZ4Util.ML_MASK)) == LZ4Util.ML_MASK)
                    {
                        while (ip < iend)
                        {
                            int s = *ip++; length += s; if (s == 255)
                            {
                                continue;
                            }
                            break;
                        }
                    }

                    // copy repeated sequence
                    if (op - r < STEPSIZE)
                    {
                        const int dec2 = 0;


                        *op++ = *r++;
                        *op++ = *r++;
                        *op++ = *r++;
                        *op++ = *r++;
                        r          -= dec[op - r];
                        *(uint *)op = *(uint *)r; op += STEPSIZE - 4;
                        r          -= dec2;
                    }
                    else
                    {
                        *(uint *)op = *(uint *)r; op += 4; r += 4;;
                    }
                    cpy = op + length - (STEPSIZE - 4);
                    if (cpy > oend - LZ4Util.COPYLENGTH)
                    {
                        if (cpy > oend)
                        {
                            goto _output_error;
                        }

                        do
                        {
                            *(uint *)op = *(uint *)r; op += 4; r += 4;; *(uint *)op = *(uint *)r; op += 4; r += 4;;
                        } while (op < (oend - LZ4Util.COPYLENGTH));;
                        while (op < cpy)
                        {
                            *op++ = *r++;
                        }
                        op = cpy;
                        if (op == oend)
                        {
                            goto _output_error;             // Check EOF (should never happen, since last 5 bytes are supposed to be literals)
                        }
                        continue;
                    }
                    do
                    {
                        *(uint *)op = *(uint *)r; op += 4; r += 4;; *(uint *)op = *(uint *)r; op += 4; r += 4;;
                    } while (op < cpy);;
                    op = cpy; // correction
                }


                return((int)(((byte *)op) - decompressedBuffer));


_output_error:
                return((int)(-(((byte *)ip) - compressedBuffer)));
            }
        }
Exemple #2
0
        public int DecompressKnownSize(byte *compressed, byte *decompressedBuffer, int decompressedSize)
        {
            fixed(sbyte *dec = m_DecArray)
            {
                // Local Variables
                byte *ip = (byte *)compressed;
                byte *r;

                byte *op   = (byte *)decompressedBuffer;
                byte *oend = op + decompressedSize;
                byte *cpy;

                byte token;
                int  len, length;


                // Main Loop
                while (true)
                {
                    // get runLength
                    token = *ip++;
                    if ((length = (token >> LZ4Util.ML_BITS)) == LZ4Util.RUN_MASK)
                    {
                        for (; (len = *ip++) == 255; length += 255)
                        {
                        }
                        length += len;
                    }


                    cpy = op + length;
                    if (cpy > oend - LZ4Util.COPYLENGTH)
                    {
                        if (cpy > oend)
                        {
                            goto _output_error;
                        }
                        LZ4Util.CopyMemory(op, ip, length);
                        ip += length;
                        break;
                    }

                    do
                    {
                        *(uint *)op = *(uint *)ip; op += 4; ip += 4;; *(uint *)op = *(uint *)ip; op += 4; ip += 4;;
                    } while (op < cpy);; ip -= (op - cpy); op = cpy;


                    // get offset
                    { r = (cpy) - *(ushort *)ip; }; ip += 2;
                    if (r < decompressedBuffer)
                    {
                        goto _output_error;
                    }

                    // get matchLength
                    if ((length = (int)(token & LZ4Util.ML_MASK)) == LZ4Util.ML_MASK)
                    {
                        for (; *ip == 255; length += 255)
                        {
                            ip++;
                        }
                        length += *ip++;
                    }

                    // copy repeated sequence
                    if (op - r < STEPSIZE)
                    {
                        const int dec2 = 0;



                        *op++ = *r++;
                        *op++ = *r++;
                        *op++ = *r++;
                        *op++ = *r++;
                        r          -= dec[op - r];
                        *(uint *)op = *(uint *)r; op += STEPSIZE - 4;
                        r          -= dec2;
                    }
                    else
                    {
                        *(uint *)op = *(uint *)r; op += 4; r += 4;;
                    }
                    cpy = op + length - (STEPSIZE - 4);
                    if (cpy > oend - LZ4Util.COPYLENGTH)
                    {
                        if (cpy > oend)
                        {
                            goto _output_error;
                        }

                        do
                        {
                            *(uint *)op = *(uint *)r; op += 4; r += 4;; *(uint *)op = *(uint *)r; op += 4; r += 4;;
                        } while (op < (oend - LZ4Util.COPYLENGTH));;
                        while (op < cpy)
                        {
                            *op++ = *r++;
                        }
                        op = cpy;
                        if (op == oend)
                        {
                            break;
                        }
                        continue;
                    }

                    do
                    {
                        *(uint *)op = *(uint *)r; op += 4; r += 4;; *(uint *)op = *(uint *)r; op += 4; r += 4;;
                    } while (op < cpy);;
                    op = cpy; // correction
                }

                // end of decoding
                return((int)(((byte *)ip) - compressed));

                // write overflow error detected
_output_error:
                return((int)(-(((byte *)ip) - compressed)));
            }
        }
        // Note : this function is valid only if isize < LZ4_64KLIMIT



        int Compress64K(byte *source, byte *dest, int isize, int maxOutputSize)
        {
            fixed(byte *hashTablePtr = m_HashTable)
            fixed(byte *deBruijnBytePos = DeBruijnBytePos)
            {
                Clear(hashTablePtr, sizeof(ushort) * HASHTABLESIZE * 2);
                ushort *hashTable = (ushort *)hashTablePtr;

                byte *ip         = (byte *)source;
                byte *anchor     = ip;
                byte *basep      = ip;
                byte *iend       = ip + isize;
                byte *mflimit    = iend - MFLIMIT;
                byte *matchlimit = (iend - LASTLITERALS);
                byte *op         = (byte *)dest;
                byte *oend       = dest + maxOutputSize;

                int       len, length;
                const int skipStrength = SKIPSTRENGTH;
                uint      forwardH;

                // Init
                if (isize < MINLENGTH)
                {
                    goto _last_literals;
                }

                // First Byte
                ip++; forwardH = (((*(uint *)ip) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)));

                // Main Loop
                for (; ;)
                {
                    int   findMatchAttempts = (int)(1U << skipStrength) + 3;
                    byte *forwardIp         = ip;
                    byte *r;
                    byte *token;

                    // Find a match
                    do
                    {
                        uint h    = forwardH;
                        int  step = findMatchAttempts++ >> skipStrength;
                        ip        = forwardIp;
                        forwardIp = ip + step;

                        if (forwardIp > mflimit)
                        {
                            goto _last_literals;
                        }

                        forwardH     = (((*(uint *)forwardIp) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)));
                        r            = basep + hashTable[h];
                        hashTable[h] = (ushort)(ip - basep);
                    } while (*(uint *)r != *(uint *)ip);

                    // Catch up
                    while ((ip > anchor) && (r > (byte *)source) && (ip[-1] == r[-1]))
                    {
                        ip--; r--;
                    }

                    // Encode Literal Length
                    length = (int)(ip - anchor);
                    token  = op++;
                    if (op + length + (2 + 1 + LASTLITERALS) + (length >> 8) >= oend)
                    {
                        return(0);                                                              // Check output limit
                    }
                    if (length >= (int)LZ4Util.RUN_MASK)
                    {
                        *token = (byte)(LZ4Util.RUN_MASK << LZ4Util.ML_BITS); len = (int)(length - LZ4Util.RUN_MASK); for (; len > 254; len -= 255)
                        {
                            *op++ = 255;
                        }
                        *op++ = (byte)len;
                    }
                    else
                    {
                        *token = (byte)(length << LZ4Util.ML_BITS);
                    }

                    // Copy Literals
                    { byte *e = (op) + length; do
                      {
                          *(ulong *)op = *(ulong *)anchor; op += 8; anchor += 8;
                      } while (op < e);; op = e; };


_next_match:
                    // Encode Offset
                    *(ushort *)op = (ushort)(ip - r); op += 2;

                    // Start Counting
                    ip    += MINMATCH; r += MINMATCH; // MinMatch verified
                    anchor = ip;
                    //					while (ip<matchlimit-3)
                    //					{
                    //						if (*(uint *)r == *(uint *)ip) { ip+=4; r+=4; continue; }
                    //						if (*(ushort *)r == *(ushort *)ip) { ip+=2; r+=2; }
                    //						if (*r == *ip) ip++;

                    while (ip < matchlimit - (STEPSIZE - 1))
                    {
                        long diff = (long)(*(long *)(r) ^ *(long *)(ip));
                        if (diff == 0)
                        {
                            ip += STEPSIZE; r += STEPSIZE; continue;
                        }
                        ip += DeBruijnBytePos[((ulong)((diff & -diff) * 0x0218A392CDABBD3F)) >> 58];;
                        goto _endCount;
                    }

                    if ((ip < (matchlimit - 3)) && (*(uint *)r == *(uint *)ip))
                    {
                        ip += 4; r += 4;
                    }

                    if ((ip < (matchlimit - 1)) && (*(ushort *)r == *(ushort *)ip))
                    {
                        ip += 2; r += 2;
                    }
                    if ((ip < matchlimit) && (*r == *ip))
                    {
                        ip++;
                    }
_endCount:
                    len = (int)(ip - anchor);

                    //Encode MatchLength
                    if (len >= (int)LZ4Util.ML_MASK)
                    {
                        *token = (byte)(*token + LZ4Util.ML_MASK); len = (int)(len - LZ4Util.ML_MASK); for (; len > 509; len -= 510)
                        {
                            *op++ = 255; *op++ = 255;
                        }
                        if (len > 254)
                        {
                            len -= 255; *op++ = 255;
                        }
                        *op++ = (byte)len;
                    }
                    else
                    {
                        *token = (byte)(*token + len);
                    }

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

                    // Fill table
                    hashTable[(((*(uint *)ip - 2) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)))] = (ushort)(ip - 2 - basep);

                    // Test next position
                    r = basep + hashTable[(((*(uint *)ip) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)))];
                    hashTable[(((*(uint *)ip) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)))] = (ushort)(ip - basep);
                    if (*(uint *)r == *(uint *)ip)
                    {
                        token = op++; *token = 0; goto _next_match;
                    }

                    // Prepare next loop
                    anchor   = ip++;
                    forwardH = (((*(uint *)ip) * 2654435761U) >> ((MINMATCH * 8) - (HASH_LOG + 1)));
                }

_last_literals:
                {
                    int lastRun = (int)(iend - anchor);
                    if (((byte *)op - dest) + lastRun + 1 + ((lastRun) >> 8) >= maxOutputSize)
                    {
                        return(0);
                    }
                    if (lastRun >= (int)LZ4Util.RUN_MASK)
                    {
                        *op++ = (byte)(LZ4Util.RUN_MASK << LZ4Util.ML_BITS); lastRun -= (byte)LZ4Util.RUN_MASK; for (; lastRun > 254; lastRun -= 255)
                        {
                            *op++ = 255;
                        }
                        *op++ = (byte)lastRun;
                    }
                    else
                    {
                        *op++ = (byte)(lastRun << LZ4Util.ML_BITS);
                    }
                    LZ4Util.CopyMemory(op, anchor, iend - anchor);
                    op += iend - anchor;
                }


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