private static void LZ4_resetStream(LZ4_stream_t *state) => Mem.Zero((byte *)state, sizeof(LZ4_stream_t));
private static int LZ4_compress_fast_continue <TEndian, TArch>(LZ4_stream_t *stream, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration = 1) where TEndian : struct, IEndian where TArch : unmanaged, IArch { var dictEnd = stream->dictionary + stream->dictSize; Debug.WriteLine($"LZ4_compress_fast_continue (inputSize={inputSize})"); if (stream->initCheck != 0) { return(0); /* Uninitialized structure detected */ } LZ4_renormDictT(stream, inputSize); /* avoid index overflow */ acceleration = Math.Max(acceleration, 1); /* invalidate tiny dictionaries */ if (stream->dictSize - 1 < 4 && /* intentional underflow */ dictEnd != source) { Debug.WriteLine($"LZ4_compress_fast_continue: dictSize({stream->dictSize}) at addr:{(ulong)stream->dictionary} is too small"); stream->dictSize = 0; stream->dictionary = source; dictEnd = source; } /* Check overlapping input/dictionary space */ { var sourceEnd = source + inputSize; if ((sourceEnd > stream->dictionary) && (sourceEnd < dictEnd)) { stream->dictSize = (uint)(dictEnd - sourceEnd); if (stream->dictSize > _64KB) { stream->dictSize = _64KB; } if (stream->dictSize < 4) { stream->dictSize = 0; } stream->dictionary = dictEnd - stream->dictSize; } } /* prefix mode : source data follows dictionary */ if (dictEnd == source) { var _ = 0; if (stream->dictSize < _64KB && stream->dictSize < stream->currentOffset) { return(LZ4_compress_generic <LimitedOutput, ByU32, WithPrefix64K, DictSmall, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration)); } return(LZ4_compress_generic <LimitedOutput, ByU32, WithPrefix64K, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration)); } /* external dictionary mode */ { int result; var _ = 0; if (stream->dictCtx != null) { /* We depend here on the fact that dictCtx'es (produced by * LZ4_loadDict) guarantee that their tables contain no references * to offsets between dictCtx->currentOffset - 64 KB and * dictCtx->currentOffset - dictCtx->dictSize. This makes it safe * to use noDictIssue even when the dict isn't a full 64 KB. */ if (inputSize > _4KB) { /* For compressing large blobs, it is faster to pay the setup * cost to copy the dictionary's tables into the active context, * so that the compression loop is only looking into one table. */ Unsafe.CopyBlock(stream, stream->dictCtx, (uint)sizeof(LZ4_stream_t)); result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration); } else { result = LZ4_compress_generic <LimitedOutput, ByU32, UsingDictCtx, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration); } } else { if ((stream->dictSize < _64KB) && (stream->dictSize < stream->currentOffset)) { result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, DictSmall, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration); } else { result = LZ4_compress_generic <LimitedOutput, ByU32, UsingExtDict, NoDictIssue, TEndian, TArch>(stream, source, dest, inputSize, ref _, maxOutputSize, acceleration); } } stream->dictionary = source; stream->dictSize = (uint)inputSize; return(result); } }
static int LZ4_compress_destSize_generic( LZ4_stream_t *ctx, byte *src, byte *dst, int *srcSizePtr, int targetDstSize, tableType_t tableType) { var ip = src; var base_ = src; var lowLimit = src; var anchor = ip; var iend = ip + *srcSizePtr; var mflimit = iend - MFLIMIT; var matchlimit = iend - LASTLITERALS; var op = dst; var oend = op + targetDstSize; var oMaxLit = op + targetDstSize - 2 - 8 - 1; var oMaxMatch = op + targetDstSize - (LASTLITERALS + 1); var oMaxSeq = oMaxLit - 1; if (targetDstSize < 1) { return(0); } if (*srcSizePtr > LZ4_MAX_INPUT_SIZE) { return(0); } if (tableType == tableType_t.byU16 && *srcSizePtr >= LZ4_64Klimit) { return(0); } if (*srcSizePtr < LZ4_minLength) { goto _last_literals; /* Input too small, no compression (all literals) */ } *srcSizePtr = 0; LZ4_putPosition(ip, ctx->hashTable, tableType, base_); ip++; var forwardH = LZ4_hashPosition(ip, tableType); for (;;) { byte *match; byte *token; { var forwardIp = ip; var step = 1u; var searchMatchNb = 1u << LZ4_skipTrigger; do { var h = forwardH; ip = forwardIp; forwardIp += step; step = searchMatchNb++ >> LZ4_skipTrigger; if (forwardIp > mflimit) { goto _last_literals; } match = LZ4_getPositionOnHash(h, ctx->hashTable, tableType, base_); forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putPositionOnHash(ip, h, ctx->hashTable, tableType, base_); }while ( tableType != tableType_t.byU16 && match + MAX_DISTANCE < ip || Mem.Peek32(match) != Mem.Peek32(ip)); } while (ip > anchor && match > lowLimit && ip[-1] == match[-1]) { ip--; match--; } { var litLength = (uint)(ip - anchor); token = op++; if (op + (litLength + 240) / 255 + litLength > oMaxLit) { op--; goto _last_literals; } if (litLength >= RUN_MASK) { var len = litLength - RUN_MASK; *token = (byte)(RUN_MASK << ML_BITS); for (; len >= 255; len -= 255) { *op++ = 255; } *op++ = (byte)len; } else { *token = (byte)(litLength << ML_BITS); } Mem.WildCopy(op, anchor, op + litLength); op += litLength; } _next_match: Mem.Poke16(op, (ushort)(ip - match)); op += 2; { var matchLength = (int)LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); if (op + (matchLength + 240) / 255 > oMaxMatch) { matchLength = (int)(15 - 1 + (oMaxMatch - op) * 255); } ip += MINMATCH + matchLength; if (matchLength >= ML_MASK) { *token += (byte)ML_MASK; matchLength -= (int)ML_MASK; while (matchLength >= 255) { matchLength -= 255; *op++ = 255; } *op++ = (byte)matchLength; } else { *token += (byte)matchLength; } } anchor = ip; if (ip > mflimit) { break; } if (op > oMaxSeq) { break; } LZ4_putPosition(ip - 2, ctx->hashTable, tableType, base_); match = LZ4_getPosition(ip, ctx->hashTable, tableType, base_); LZ4_putPosition(ip, ctx->hashTable, tableType, base_); if (match + MAX_DISTANCE >= ip && Mem.Peek32(match) == Mem.Peek32(ip)) { token = op++; *token = 0; goto _next_match; } forwardH = LZ4_hashPosition(++ip, tableType); } _last_literals: { var lastRunSize = (int)(iend - anchor); if (op + 1 + (lastRunSize + 240) / 255 + lastRunSize > oend) { lastRunSize = (int)(oend - op) - 1; lastRunSize -= (lastRunSize + 240) / 255; } ip = anchor + lastRunSize; if (lastRunSize >= RUN_MASK) { var accumulator = lastRunSize - RUN_MASK; *op++ = (byte)(RUN_MASK << ML_BITS); for (; accumulator >= 255; accumulator -= 255) { *op++ = 255; } *op++ = (byte)accumulator; } else { *op++ = (byte)(lastRunSize << ML_BITS); } Mem.Copy(op, anchor, lastRunSize); op += lastRunSize; } *srcSizePtr = (int)(ip - src); return((int)(op - dst)); }
public static int LZ4_compress_fast_continue( LZ4_stream_t *streamPtr, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration) { var dictEnd = streamPtr->dictionary + streamPtr->dictSize; var smallest = source; if (streamPtr->initCheck != 0) { return(0); /* Uninitialized structure detected */ } if (streamPtr->dictSize > 0 && smallest > dictEnd) { smallest = dictEnd; } LZ4_renormDictT(streamPtr, smallest); if (acceleration < 1) { acceleration = ACCELERATION_DEFAULT; } /* Check overlapping input/dictionary space */ { var sourceEnd = source + inputSize; if (sourceEnd > streamPtr->dictionary && sourceEnd < dictEnd) { streamPtr->dictSize = (uint)(dictEnd - sourceEnd); if (streamPtr->dictSize > 64 * KB) { streamPtr->dictSize = 64 * KB; } if (streamPtr->dictSize < 4) { streamPtr->dictSize = 0; } streamPtr->dictionary = dictEnd - streamPtr->dictSize; } } var dictIssue = streamPtr->dictSize < 64 * KB && streamPtr->dictSize < streamPtr->currentOffset ? dictIssue_directive.dictSmall : dictIssue_directive.noDictIssue; var dictMode = dictEnd == source ? dict_directive.withPrefix64k : dict_directive.usingExtDict; var result = LZ4_compress_generic( streamPtr, source, dest, inputSize, maxOutputSize, limitedOutput_directive.limitedOutput, tableType_t.byU32, dictMode, dictIssue, (uint)acceleration); if (dictMode == dict_directive.withPrefix64k) { /* prefix mode : source data follows dictionary */ streamPtr->dictSize += (uint)inputSize; streamPtr->currentOffset += (uint)inputSize; } else { /* external dictionary mode */ streamPtr->dictionary = source; streamPtr->dictSize = (uint)inputSize; streamPtr->currentOffset += (uint)inputSize; } return(result); }
public static int LZ4_compress_generic( LZ4_stream_t *cctx, byte *source, byte *dest, int inputSize, int maxOutputSize, limitedOutput_directive outputLimited, tableType_t tableType, dict_directive dict, dictIssue_directive dictIssue, uint acceleration) { var ip = source; byte *ibase; byte *lowLimit; var lowRefLimit = ip - cctx->dictSize; var dictionary = cctx->dictionary; var dictEnd = dictionary + cctx->dictSize; var dictDelta = dictEnd - source; var anchor = source; var iend = ip + inputSize; var mflimit = iend - MFLIMIT; var matchlimit = iend - LASTLITERALS; var op = dest; var olimit = op + maxOutputSize; if (inputSize > LZ4_MAX_INPUT_SIZE) { return(0); } switch (dict) { case dict_directive.withPrefix64k: ibase = source - cctx->currentOffset; lowLimit = source - cctx->dictSize; break; case dict_directive.usingExtDict: ibase = source - cctx->currentOffset; lowLimit = source; break; default: ibase = source; lowLimit = source; break; } if (tableType == tableType_t.byU16 && inputSize >= LZ4_64Klimit) { return(0); } if (inputSize < LZ4_minLength) { goto _last_literals; } LZ4_putPosition(ip, cctx->hashTable, tableType, ibase); ip++; var forwardH = LZ4_hashPosition(ip, tableType); for (;;) { var refDelta = 0L; byte *match; byte *token; { var forwardIp = ip; var step = 1u; var searchMatchNb = acceleration << LZ4_skipTrigger; do { var h = forwardH; ip = forwardIp; forwardIp += step; step = searchMatchNb++ >> LZ4_skipTrigger; if (forwardIp > mflimit) { goto _last_literals; } match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, ibase); if (dict == dict_directive.usingExtDict) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, ibase); }while ( dictIssue == dictIssue_directive.dictSmall && match < lowRefLimit || tableType != tableType_t.byU16 && match + MAX_DISTANCE < ip || Mem.Peek32(match + refDelta) != Mem.Peek32(ip)); } while (ip > anchor && match + refDelta > lowLimit && ip[-1] == match[refDelta - 1]) { ip--; match--; } { var litLength = (uint)(ip - anchor); token = op++; if (outputLimited == limitedOutput_directive.limitedOutput && op + litLength + (2 + 1 + LASTLITERALS) + litLength / 255 > olimit) { return(0); } if (litLength >= RUN_MASK) { var len = (int)(litLength - RUN_MASK); *token = (byte)(RUN_MASK << ML_BITS); for (; len >= 255; len -= 255) { *op++ = 255; } *op++ = (byte)len; } else { *token = (byte)(litLength << ML_BITS); } Mem.WildCopy(op, anchor, op + litLength); op += litLength; } _next_match: Mem.Poke16(op, (ushort)(ip - match)); op += 2; { uint matchCode; if (dict == dict_directive.usingExtDict && lowLimit == dictionary) { match += refDelta; var limit = ip + (dictEnd - match); if (limit > matchlimit) { limit = matchlimit; } matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, limit); ip += MINMATCH + matchCode; if (ip == limit) { var more = LZ4_count(ip, source, matchlimit); matchCode += more; ip += more; } } else { matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); ip += MINMATCH + matchCode; } if (outputLimited == limitedOutput_directive.limitedOutput && op + (1 + LASTLITERALS) + (matchCode >> 8) > olimit) { return(0); } if (matchCode >= ML_MASK) { *token += (byte)ML_MASK; matchCode -= ML_MASK; Mem.Poke32(op, 0xFFFFFFFF); while (matchCode >= 4 * 255) { op += 4; Mem.Poke32(op, 0xFFFFFFFF); matchCode -= 4 * 255; } op += matchCode / 255; *op++ = (byte)(matchCode % 255); } else { *token += (byte)matchCode; } } anchor = ip; if (ip > mflimit) { break; } LZ4_putPosition(ip - 2, cctx->hashTable, tableType, ibase); match = LZ4_getPosition(ip, cctx->hashTable, tableType, ibase); if (dict == dict_directive.usingExtDict) { if (match < source) { refDelta = dictDelta; lowLimit = dictionary; } else { refDelta = 0; lowLimit = source; } } LZ4_putPosition(ip, cctx->hashTable, tableType, ibase); if ((dictIssue != dictIssue_directive.dictSmall || match >= lowRefLimit) && match + MAX_DISTANCE >= ip && Mem.Peek32(match + refDelta) == Mem.Peek32(ip)) { token = op++; *token = 0; goto _next_match; } forwardH = LZ4_hashPosition(++ip, tableType); } _last_literals: { var lastRun = (int)(iend - anchor); if (outputLimited == limitedOutput_directive.limitedOutput && op - dest + lastRun + 1 + (lastRun + 255 - RUN_MASK) / 255 > (uint)maxOutputSize) { return(0); } if (lastRun >= RUN_MASK) { var accumulator = (int)(lastRun - RUN_MASK); *op++ = (byte)(RUN_MASK << ML_BITS); for (; accumulator >= 255; accumulator -= 255) { *op++ = 255; } *op++ = (byte)accumulator; } else { *op++ = (byte)(lastRun << ML_BITS); } Mem.Copy(op, anchor, lastRun); op += lastRun; } return((int)(op - dest)); }