public static int LZ4_decompress_generic( byte *src, byte *dst, int srcSize, int outputSize, endCondition_directive endOnInput, earlyEnd_directive partialDecoding, int targetOutputSize, dict_directive dict, byte *lowPrefix, byte *dictStart, int dictSize) { var ip = src; var iend = ip + srcSize; var op = dst; var oend = op + outputSize; var oexit = op + targetOutputSize; var dictEnd = dictStart + dictSize; var safeDecode = endOnInput == endCondition_directive.endOnInputSize; var checkOffset = safeDecode && dictSize < 64 * KB; if (partialDecoding != earlyEnd_directive.full && oexit > oend - MFLIMIT) { oexit = oend - MFLIMIT; } if (endOnInput == endCondition_directive.endOnInputSize && outputSize == 0) { return(srcSize == 1 && *ip == 0 ? 0 : -1); } if (endOnInput != endCondition_directive.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 << ML_BITS && (token & ML_MASK) != 15) { var ll = (int)(token >> ML_BITS); int off = Mem.Peek16(ip + ll); var matchPtr = op + ll - off; if (off >= 18 && matchPtr >= lowPrefix) { var ml = (int)((token & ML_MASK) + MINMATCH); Mem.Copy16(op, ip); op += ll; ip += ll + 2; Mem.Copy18(op, matchPtr); op += ml; continue; } } if ((length = (int)(token >> ML_BITS)) == RUN_MASK) { uint s; do { s = *ip++; length += (int)s; }while ( (endOnInput != endCondition_directive.endOnInputSize || ip < iend - RUN_MASK) && s == 255); if (safeDecode && op + length < op) { goto _output_error; } if (safeDecode && ip + length < ip) { goto _output_error; } } var cpy = op + length; if (endOnInput == endCondition_directive.endOnInputSize && ( cpy > (partialDecoding == earlyEnd_directive.partial ? oexit : oend - MFLIMIT) || ip + length > iend - (2 + 1 + LASTLITERALS) ) || endOnInput != endCondition_directive.endOnInputSize && cpy > oend - WILDCOPYLENGTH) { if (partialDecoding == earlyEnd_directive.partial) { if (cpy > oend) { goto _output_error; } if (endOnInput == endCondition_directive.endOnInputSize && ip + length > iend) { goto _output_error; } } else { if (endOnInput != endCondition_directive.endOnInputSize && cpy != oend) { goto _output_error; } if (endOnInput == endCondition_directive.endOnInputSize && (ip + length != iend || cpy > oend)) { goto _output_error; } } Mem.Copy(op, ip, length); ip += length; op += length; break; } Mem.WildCopy(op, ip, cpy); ip += length; op = cpy; int offset = Mem.Peek16(ip); ip += 2; var match = op - offset; if (checkOffset && match + dictSize < lowPrefix) { goto _output_error; } Mem.Poke32(op, (uint)offset); length = (int)(token & ML_MASK); if (length == ML_MASK) { uint s; do { s = *ip++; if ((endOnInput == endCondition_directive.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 == dict_directive.usingExtDict && match < lowPrefix) { if (op + length > oend - LASTLITERALS) { goto _output_error; } if (length <= lowPrefix - match) { Mem.Move(op, dictEnd - (lowPrefix - match), length); op += length; } else { var copySize = (int)(lowPrefix - match); var restSize = length - copySize; Mem.Copy(op, dictEnd - copySize, copySize); op += copySize; if (restSize > (int)(op - lowPrefix)) { var endOfMatch = op + restSize; var copyFrom = lowPrefix; while (op < endOfMatch) { *op++ = *copyFrom++; } } else { Mem.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]; Mem.Copy(op + 4, match, 4); match -= dec64table[offset]; } else { Mem.Copy8(op, match); match += 8; } op += 8; if (cpy > oend - 12) { var oCopyLimit = oend - (WILDCOPYLENGTH - 1); if (cpy > oend - LASTLITERALS) { goto _output_error; } if (op < oCopyLimit) { Mem.WildCopy(op, match, oCopyLimit); match += oCopyLimit - op; op = oCopyLimit; } while (op < cpy) { *op++ = *match++; } } else { Mem.Copy8(op, match); if (length > 16) { Mem.WildCopy(op + 8, match + 8, cpy); } } op = cpy; /* correction */ } /* end of decoding */ if (endOnInput == endCondition_directive.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); }