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 { *(uint *)op = *(uint *)anchor; op += 4; anchor += 4;; *(uint *)op = *(uint *)anchor; op += 4; anchor += 4;; } 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)) { int diff = (int)(*(int *)(r) ^ *(int *)(ip)); if (diff == 0) { ip += STEPSIZE; r += STEPSIZE; continue; } ip += DeBruijnBytePos[((uint)((diff & -diff) * 0x077CB531U)) >> 27];; goto _endCount; } 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)); } }
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 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))); } }