public static int DecompressGeneric(byte *src, byte *dst, int srcSize, int outputSize, EndConditionDirective endOnInput, EarlyEndDirective partialDecoding, int targetOutputSize, DictDirective dict, byte *lowPrefix, byte *dictStart, int dictSize) { byte *ip = src; byte *iend = ip + srcSize; byte *op = dst; byte *oend = op + outputSize; byte *oexit = op + targetOutputSize; byte *dictEnd = dictStart + dictSize; bool safeDecode = endOnInput == EndConditionDirective.EndOnInputSize; bool checkOffset = safeDecode && dictSize < 64 * KB; if ((partialDecoding != EarlyEndDirective.Full) && (oexit > oend - MFLimit)) { oexit = oend - MFLimit; } if ((endOnInput == EndConditionDirective.EndOnInputSize) && (outputSize == 0)) { return(srcSize == 1 && *ip == 0 ? 0 : -1); } if ((endOnInput != EndConditionDirective.EndOnInputSize) && (outputSize == 0)) { return(*ip == 0 ? 1 : -1); } for (; ;) { int length; uint token = *ip++; if ((ip + 14 + 2 <= iend) && (op + 14 + 18 <= oend) && (token < 15 << MLBits) && ((token & MLMask) != 15)) { int ll = (int)(token >> MLBits); int off = LZ4MemoryHelper.Peek16(ip + ll); byte *matchPtr = op + ll - off; if (off >= 18 && matchPtr >= lowPrefix) { int ml = (int)((token & MLMask) + MinMatch); LZ4MemoryHelper.Copy16(op, ip); op += ll; ip += ll + 2; LZ4MemoryHelper.Copy18(op, matchPtr); op += ml; continue; } } if ((length = (int)(token >> MLBits)) == RunMask) { uint s; do { s = *ip++; length += (int)s; }while ( (endOnInput != EndConditionDirective.EndOnInputSize || ip < iend - RunMask) && (s == 255)); if (safeDecode && op + length < op) { goto _output_error; } if (safeDecode && ip + length < ip) { goto _output_error; } } byte *cpy = op + length; if ((endOnInput == EndConditionDirective.EndOnInputSize) && ((cpy > (partialDecoding == EarlyEndDirective.Partial ? oexit : oend - MFLimit)) || (ip + length > iend - (2 + 1 + LastLiterals))) || (endOnInput != EndConditionDirective.EndOnInputSize) && (cpy > oend - WildCopyLength)) { if (partialDecoding == EarlyEndDirective.Partial) { if (cpy > oend) { goto _output_error; } if ((endOnInput == EndConditionDirective.EndOnInputSize) && (ip + length > iend)) { goto _output_error; } } else { if ((endOnInput != EndConditionDirective.EndOnInputSize) && (cpy != oend)) { goto _output_error; } if ((endOnInput == EndConditionDirective.EndOnInputSize) && (ip + length != iend || cpy > oend)) { goto _output_error; } } LZ4MemoryHelper.Copy(op, ip, length); ip += length; op += length; break; } LZ4MemoryHelper.WildCopy(op, ip, cpy); ip += length; op = cpy; int offset = LZ4MemoryHelper.Peek16(ip); ip += 2; byte *match = op - offset; if (checkOffset && match + dictSize < lowPrefix) { goto _output_error; } LZ4MemoryHelper.Poke32(op, (uint)offset); length = (int)(token & MLMask); if (length == MLMask) { uint s; do { s = *ip++; if ((endOnInput == EndConditionDirective.EndOnInputSize) && (ip > iend - LastLiterals)) { goto _output_error; } length += (int)s; }while (s == 255); if (safeDecode && (op + length < op)) { goto _output_error; } } length += MinMatch; if ((dict == DictDirective.UsingExtDict) && (match < lowPrefix)) { if (op + length > oend - LastLiterals) { goto _output_error; } if (length <= lowPrefix - match) { LZ4MemoryHelper.Move(op, dictEnd - (lowPrefix - match), length); op += length; } else { int copySize = (int)(lowPrefix - match); int restSize = length - copySize; LZ4MemoryHelper.Copy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (int)(op - lowPrefix)) { byte *endOfMatch = op + restSize; byte *copyFrom = lowPrefix; while (op < endOfMatch) { *op++ = *copyFrom++; } } else { LZ4MemoryHelper.Copy(op, lowPrefix, restSize); op += restSize; } } continue; } cpy = op + length; if (offset < 8) { op[0] = match[0]; op[1] = match[1]; op[2] = match[2]; op[3] = match[3]; match += _inc32table[offset]; LZ4MemoryHelper.Copy(op + 4, match, 4); match -= _dec64table[offset]; } else { LZ4MemoryHelper.Copy8(op, match); match += 8; } op += 8; if (cpy > oend - 12) { byte *oCopyLimit = oend - (WildCopyLength - 1); if (cpy > oend - LastLiterals) { goto _output_error; } if (op < oCopyLimit) { LZ4MemoryHelper.WildCopy(op, match, oCopyLimit); match += oCopyLimit - op; op = oCopyLimit; } while (op < cpy) { *op++ = *match++; } } else { LZ4MemoryHelper.Copy8(op, match); if (length > 16) { LZ4MemoryHelper.WildCopy(op + 8, match + 8, cpy); } } op = cpy; // correction } // end of decoding if (endOnInput == EndConditionDirective.EndOnInputSize) { return((int)(op - dst)); // Nb of output bytes decoded } return((int)(ip - src)); // Nb of input bytes read // Overflow error detected _output_error: return((int)-(ip - src) - 1); }