public int LZ4_loadDict(LZ4_stream_t *LZ4_dict, byte *dictionary, int dictSize) { const int HASH_UNIT = ALGORITHM_ARCH; var dict = LZ4_dict; const tableType_t tableType = tableType_t.byU32; var p = dictionary; var dictEnd = p + dictSize; LZ4_initStream(LZ4_dict); dict->currentOffset += 64 * KB; if (dictSize < HASH_UNIT) { return(0); } if (dictEnd - p > 64 * KB) { p = dictEnd - 64 * KB; } var @base = dictEnd - dict->currentOffset; dict->dictionary = p; dict->dictSize = (uint)(dictEnd - p); dict->tableType = tableType; while (p <= dictEnd - HASH_UNIT) { LZ4_putPosition(p, dict->hashTable, tableType, @base); p += 3; } return((int)dict->dictSize); }
private static uint LZ4_hashPosition(void *p, tableType_t tableType) { if (tableType != tableType_t.byU16) { return(LZ4_hash5(LZ4_read_ARCH(p), tableType)); } return(LZ4_hash4(LZ4Mem.Peek32(p), tableType)); }
private static uint LZ4_hashPosition(void *p, tableType_t tableType) { #if !BIT32 if (tableType != tableType_t.byU16) { return(LZ4_hash5(LZ4_read_ARCH(p), tableType)); } #endif return(LZ4_hash4(LZ4_read32(p), tableType)); }
protected static uint LZ4_hashPosition(void *p, tableType_t tableType) { #if !BIT32 if (tableType != tableType_t.byU16) { return(LZ4_hash5(Mem.PeekW(p), tableType)); } #endif return(LZ4_hash4(Mem.Peek4(p), tableType)); }
protected static byte *LZ4_getPositionOnHash( uint h, void *tableBase, tableType_t tableType, byte *srcBase) { switch (tableType) { case tableType_t.byPtr: return(((byte **)tableBase)[h]); case tableType_t.byU32: return(((uint *)tableBase)[h] + srcBase); default: return(((ushort *)tableBase)[h] + srcBase); } }
protected static uint LZ4_getIndexOnHash(uint h, void *tableBase, tableType_t tableType) { Assert(LZ4_MEMORY_USAGE > 2); switch (tableType) { case tableType_t.byU32: Assert(h < (1U << (LZ4_MEMORY_USAGE - 2))); return(((uint *)tableBase)[h]); case tableType_t.byU16: Assert(h < (1U << (LZ4_MEMORY_USAGE - 1))); return(((ushort *)tableBase)[h]); default: Assert(false); return(0); } }
protected static void LZ4_putPositionOnHash( byte *p, uint h, void *tableBase, tableType_t tableType, byte *srcBase) { switch (tableType) { case tableType_t.byPtr: ((byte **)tableBase)[h] = p; return; case tableType_t.byU32: ((uint *)tableBase)[h] = (uint)(p - srcBase); return; default: ((ushort *)tableBase)[h] = (ushort)(p - srcBase); return; } }
protected static void LZ4_putIndexOnHash( uint idx, uint h, void *tableBase, tableType_t tableType) { switch (tableType) { case tableType_t.byU32: ((uint *)tableBase)[h] = idx; return; case tableType_t.byU16: Assert(idx < 65536); ((ushort *)tableBase)[h] = (ushort)idx; return; default: Assert(false); return; } }
protected static void LZ4_clearHash(uint h, void *tableBase, tableType_t tableType) { switch (tableType) { case tableType_t.byPtr: ((byte **)tableBase)[h] = null; return; case tableType_t.byU32: ((uint *)tableBase)[h] = 0; return; case tableType_t.byU16: ((ushort *)tableBase)[h] = 0; return; default: Assert(false); return; } }
protected static uint LZ4_hash5(ulong sequence, tableType_t tableType) { var hashLog = tableType == tableType_t.byU16 ? LZ4_HASHLOG + 1 : LZ4_HASHLOG; return((uint)(((sequence << 24) * 889523592379ul) >> (64 - hashLog))); }
protected static uint LZ4_hash4(uint sequence, tableType_t tableType) { var hashLog = tableType == tableType_t.byU16 ? LZ4_HASHLOG + 1 : LZ4_HASHLOG; return((sequence * 2654435761u) >> (MINMATCH * 8 - hashLog)); }
public static int LZ4_compress_fast_continue( LZ4_stream_t *LZ4_stream, byte *source, byte *dest, int inputSize, int maxOutputSize, int acceleration) { const tableType_t tableType = tableType_t.byU32; var streamPtr = LZ4_stream; var dictEnd = streamPtr->dictionary + streamPtr->dictSize; if (streamPtr->dirty) { return(0); } LZ4_renormDictT(streamPtr, inputSize); if (acceleration < 1) { acceleration = ACCELERATION_DEFAULT; } if (streamPtr->dictSize - 1 < 4 - 1 && dictEnd != source) { streamPtr->dictSize = 0; streamPtr->dictionary = source; dictEnd = source; } { 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; } } if (dictEnd == source) { if (streamPtr->dictSize < 64 * KB && streamPtr->dictSize < streamPtr->currentOffset) { return(LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.withPrefix64k, dictIssue_directive.dictSmall, acceleration)); } else { return(LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.withPrefix64k, dictIssue_directive.noDictIssue, acceleration)); } } { int result; if (streamPtr->dictCtx != null) { if (inputSize > 4 * KB) { Mem.Copy((byte *)streamPtr, (byte *)streamPtr->dictCtx, sizeof(LZ4_stream_t)); result = LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.usingExtDict, dictIssue_directive.noDictIssue, acceleration); } else { result = LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.usingDictCtx, dictIssue_directive.noDictIssue, acceleration); } } else { if ((streamPtr->dictSize < 64 * KB) && (streamPtr->dictSize < streamPtr->currentOffset)) { result = LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.usingExtDict, dictIssue_directive.dictSmall, acceleration); } else { result = LZ4_compress_generic( streamPtr, source, dest, inputSize, null, maxOutputSize, limitedOutput_directive.limitedOutput, tableType, dict_directive.usingExtDict, dictIssue_directive.noDictIssue, acceleration); } } streamPtr->dictionary = source; streamPtr->dictSize = (uint)inputSize; return(result); } }
protected static int LZ4_compress_generic( LZ4_stream_t *cctx, byte *source, byte *dest, int inputSize, int *inputConsumed, /* only written when outputDirective == fillOutput */ int maxOutputSize, limitedOutput_directive outputDirective, tableType_t tableType, dict_directive dictDirective, dictIssue_directive dictIssue, int acceleration) { int result; byte *ip = (byte *)source; uint startIndex = cctx->currentOffset; byte * @base = (byte *)source - startIndex; byte * lowLimit; LZ4_stream_t *dictCtx = (LZ4_stream_t *)cctx->dictCtx; byte * dictionary = dictDirective == dict_directive.usingDictCtx ? dictCtx->dictionary : cctx->dictionary; uint dictSize = dictDirective == dict_directive.usingDictCtx ? dictCtx->dictSize : cctx->dictSize; uint dictDelta = (dictDirective == dict_directive.usingDictCtx) ? startIndex - dictCtx->currentOffset : 0; bool maybe_extMem = (dictDirective == dict_directive.usingExtDict) || (dictDirective == dict_directive.usingDictCtx); uint prefixIdxLimit = startIndex - dictSize; byte *dictEnd = dictionary + dictSize; byte *anchor = (byte *)source; byte *iend = ip + inputSize; byte *mflimitPlusOne = iend - MFLIMIT + 1; byte *matchlimit = iend - LASTLITERALS; /* the dictCtx currentOffset is indexed on the start of the dictionary, * while a dictionary in the current context precedes the currentOffset */ byte *dictBase = (dictDirective == dict_directive.usingDictCtx) ? dictionary + dictSize - dictCtx->currentOffset : dictionary + dictSize - startIndex; byte *op = (byte *)dest; byte *olimit = op + maxOutputSize; uint offset = 0; uint forwardH; if (outputDirective == limitedOutput_directive.fillOutput && maxOutputSize < 1) { return(0); } if ((uint)inputSize > (uint)LZ4_MAX_INPUT_SIZE) { return(0); } if ((tableType == tableType_t.byU16) && (inputSize >= LZ4_64Klimit)) { return(0); } if (tableType == tableType_t.byPtr) { Assert(dictDirective == dict_directive.noDict); } Assert(acceleration >= 1); lowLimit = (byte *)source - (dictDirective == dict_directive.withPrefix64k ? dictSize : 0); /* Update context state */ if (dictDirective == dict_directive.usingDictCtx) { /* Subsequent linked blocks can't use the dictionary. */ /* Instead, they use the block we just compressed. */ cctx->dictCtx = null; cctx->dictSize = (uint)inputSize; } else { cctx->dictSize += (uint)inputSize; } cctx->currentOffset += (uint)inputSize; cctx->tableType = tableType; if (inputSize < LZ4_minLength) { goto _last_literals; } /* First Byte */ LZ4_putPosition(ip, cctx->hashTable, tableType, @base); ip++; forwardH = LZ4_hashPosition(ip, tableType); /* Main Loop */ for (;;) { byte *match; byte *token; byte *filledIp; /* Find a match */ if (tableType == tableType_t.byPtr) { byte *forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { uint h = forwardH; ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if ((forwardIp > mflimitPlusOne)) { goto _last_literals; } Assert(ip < mflimitPlusOne); match = LZ4_getPositionOnHash(h, cctx->hashTable, tableType, @base); forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putPositionOnHash(ip, h, cctx->hashTable, tableType, @base); }while ((match + LZ4_DISTANCE_MAX < ip) || (Mem.Peek4(match) != Mem.Peek4(ip))); } else { /* byU32, byU16 */ byte *forwardIp = ip; int step = 1; int searchMatchNb = acceleration << LZ4_skipTrigger; do { uint h = forwardH; uint current = (uint)(forwardIp - @base); uint matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); Assert(matchIndex <= current); Assert(forwardIp - @base < (2 * GB - 1)); ip = forwardIp; forwardIp += step; step = (searchMatchNb++ >> LZ4_skipTrigger); if ((forwardIp > mflimitPlusOne)) { goto _last_literals; } Assert(ip < mflimitPlusOne); if (dictDirective == dict_directive.usingDictCtx) { if (matchIndex < startIndex) { Assert(tableType == tableType_t.byU32); matchIndex = LZ4_getIndexOnHash( h, dictCtx->hashTable, tableType_t.byU32); match = dictBase + matchIndex; matchIndex += dictDelta; lowLimit = dictionary; } else { match = @base + matchIndex; lowLimit = (byte *)source; } } else if (dictDirective == dict_directive.usingExtDict) { if (matchIndex < startIndex) { Assert(startIndex - matchIndex >= MINMATCH); match = dictBase + matchIndex; lowLimit = dictionary; } else { match = @base + matchIndex; lowLimit = (byte *)source; } } else { match = @base + matchIndex; } forwardH = LZ4_hashPosition(forwardIp, tableType); LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); if ((dictIssue == dictIssue_directive.dictSmall) && (matchIndex < prefixIdxLimit)) { continue; } Assert(matchIndex < current); if (((tableType != tableType_t.byU16) || (LZ4_DISTANCE_MAX < LZ4_DISTANCE_ABSOLUTE_MAX)) && (matchIndex + LZ4_DISTANCE_MAX < current)) { continue; } Assert((current - matchIndex) <= LZ4_DISTANCE_MAX); if (Mem.Peek4(match) == Mem.Peek4(ip)) { if (maybe_extMem) { offset = current - matchIndex; } break; } }while (true); } filledIp = ip; while (((ip > anchor) & (match > lowLimit)) && ((ip[-1] == match[-1]))) { ip--; match--; } { var litLength = (uint)(ip - anchor); token = op++; if ((outputDirective == limitedOutput_directive.limitedOutput) && ((op + litLength + (2 + 1 + LASTLITERALS) + (litLength / 255) > olimit))) { return(0); } if ((outputDirective == limitedOutput_directive.fillOutput) && ((op + (litLength + 240) / 255 + litLength + 2 + 1 + MFLIMIT - MINMATCH > olimit))) { op--; goto _last_literals; } if (litLength >= RUN_MASK) { int 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.WildCopy8(op, anchor, op + litLength); op += litLength; } _next_match: /* at this stage, the following variables must be correctly set : * - ip : at start of LZ operation * - match : at start of previous pattern occurence; can be within current prefix, or within extDict * - offset : if maybe_ext_memSegment==1 (constant) * - lowLimit : must be == dictionary to mean "match is within extDict"; must be == source otherwise * - token and *token : position to write 4-bits for match length; higher 4-bits for literal length supposed already written */ if ((outputDirective == limitedOutput_directive.fillOutput) && (op + 2 + 1 + MFLIMIT - MINMATCH > olimit)) { /* the match was too close to the end, rewind and go to last literals */ op = token; goto _last_literals; } /* Encode Offset */ if (maybe_extMem) { /* static test */ Assert(offset <= LZ4_DISTANCE_MAX && offset > 0); Mem.Poke2(op, (ushort)offset); op += 2; } else { Assert(ip - match <= LZ4_DISTANCE_MAX); Mem.Poke2(op, (ushort)(ip - match)); op += 2; } /* Encode MatchLength */ { uint matchCode; if ((dictDirective == dict_directive.usingExtDict || dictDirective == dict_directive.usingDictCtx) && (lowLimit == dictionary) /* match within extDict */) { byte *limit = ip + (dictEnd - match); Assert(dictEnd > match); if (limit > matchlimit) { limit = matchlimit; } matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, limit); ip += (uint)matchCode + MINMATCH; if (ip == limit) { uint more = LZ4_count(limit, (byte *)source, matchlimit); matchCode += more; ip += more; } } else { matchCode = LZ4_count(ip + MINMATCH, match + MINMATCH, matchlimit); ip += (uint)matchCode + MINMATCH; } if ((outputDirective != 0) && ((op + (1 + LASTLITERALS) + (matchCode + 240) / 255 > olimit))) { if (outputDirective == limitedOutput_directive.fillOutput) { /* Match description too long : reduce it */ uint newMatchCode = 15 - 1 + ((uint)(olimit - op) - 1 - LASTLITERALS) * 255; ip -= matchCode - newMatchCode; Assert(newMatchCode < matchCode); matchCode = newMatchCode; if ((ip <= filledIp)) { /* We have already filled up to filledIp so if ip ends up less than filledIp * we have positions in the hash table beyond the current position. This is * a problem if we reuse the hash table. So we have to remove these positions * from the hash table. */ byte *ptr; for (ptr = ip; ptr <= filledIp; ++ptr) { uint h = LZ4_hashPosition(ptr, tableType); LZ4_clearHash(h, cctx->hashTable, tableType); } } } else { Assert(outputDirective == limitedOutput_directive.limitedOutput); return(0); } } if (matchCode >= ML_MASK) { *token += (byte)ML_MASK; //!!! matchCode -= ML_MASK; Mem.Poke4(op, 0xFFFFFFFF); while (matchCode >= 4 * 255) { op += 4; Mem.Poke4(op, 0xFFFFFFFF); matchCode -= 4 * 255; } op += matchCode / 255; *op++ = (byte)(matchCode % 255); } else { *token += (byte)(matchCode); } } /* Ensure we have enough space for the last literals. */ Assert( !(outputDirective == limitedOutput_directive.fillOutput && op + 1 + LASTLITERALS > olimit)); anchor = ip; /* Test end of chunk */ if (ip >= mflimitPlusOne) { break; } /* Fill table */ LZ4_putPosition(ip - 2, cctx->hashTable, tableType, @base); /* Test next position */ if (tableType == tableType_t.byPtr) { match = LZ4_getPosition(ip, cctx->hashTable, tableType, @base); LZ4_putPosition(ip, cctx->hashTable, tableType, @base); if ((match + LZ4_DISTANCE_MAX >= ip) && (Mem.Peek4(match) == Mem.Peek4(ip))) { token = op++; *token = 0; goto _next_match; } } else { /* byU32, byU16 */ uint h = LZ4_hashPosition(ip, tableType); uint current = (uint)(ip - @base); uint matchIndex = LZ4_getIndexOnHash(h, cctx->hashTable, tableType); Assert(matchIndex < current); if (dictDirective == dict_directive.usingDictCtx) { if (matchIndex < startIndex) { matchIndex = LZ4_getIndexOnHash( h, dictCtx->hashTable, tableType_t.byU32); match = dictBase + matchIndex; lowLimit = dictionary; matchIndex += dictDelta; } else { match = @base + matchIndex; lowLimit = (byte *)source; } } else if (dictDirective == dict_directive.usingExtDict) { if (matchIndex < startIndex) { match = dictBase + matchIndex; lowLimit = dictionary; } else { match = @base + matchIndex; lowLimit = (byte *)source; } } else { match = @base + matchIndex; } LZ4_putIndexOnHash(current, h, cctx->hashTable, tableType); Assert(matchIndex < current); if (((dictIssue != dictIssue_directive.dictSmall) || (matchIndex >= prefixIdxLimit)) && (((tableType == tableType_t.byU16) && (LZ4_DISTANCE_MAX == LZ4_DISTANCE_ABSOLUTE_MAX)) || (matchIndex + LZ4_DISTANCE_MAX >= current)) && (Mem.Peek4(match) == Mem.Peek4(ip))) { token = op++; *token = 0; if (maybe_extMem) { offset = current - matchIndex; } goto _next_match; } } forwardH = LZ4_hashPosition(++ip, tableType); } _last_literals: { var lastRun = (size_t)(iend - anchor); if ((outputDirective != 0) && (op + lastRun + 1 + ((lastRun + 255 - RUN_MASK) / 255) > olimit)) { if (outputDirective == limitedOutput_directive.fillOutput) { Assert(olimit >= op); lastRun = (size_t)(olimit - op) - 1; lastRun -= (lastRun + 240) / 255; } else { Assert(outputDirective == limitedOutput_directive.limitedOutput); return(0); } } if (lastRun >= RUN_MASK) { var accumulator = (size_t)(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, (int)lastRun); ip = anchor + lastRun; op += lastRun; } if (outputDirective == limitedOutput_directive.fillOutput) { *inputConsumed = (int)(((byte *)ip) - source); } result = (int)(((byte *)op) - dest); Assert(result > 0); return(result); }
private 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 || LZ4Mem.Peek32(match) != LZ4Mem.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); } LZ4Mem.WildCopy(op, anchor, op + litLength); op += litLength; } _next_match: LZ4Mem.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 && LZ4Mem.Peek32(match) == LZ4Mem.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); } LZ4Mem.Copy(op, anchor, lastRunSize); op += lastRunSize; } *srcSizePtr = (int)(ip - src); return((int)(op - dst)); }
private static byte *LZ4_getPosition(byte *p, void *tableBase, tableType_t tableType, byte *srcBase) => LZ4_getPositionOnHash(LZ4_hashPosition(p, tableType), tableBase, tableType, srcBase);
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 || LZ4Mem.Peek32(match + refDelta) != LZ4Mem.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); } LZ4Mem.WildCopy(op, anchor, op + litLength); op += litLength; } _next_match: LZ4Mem.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; LZ4Mem.Poke32(op, 0xFFFFFFFF); while (matchCode >= 4 * 255) { op += 4; LZ4Mem.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 && LZ4Mem.Peek32(match + refDelta) == LZ4Mem.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); } LZ4Mem.Copy(op, anchor, lastRun); op += lastRun; } return((int)(op - dest)); }
protected static void LZ4_putPosition( byte *p, void *tableBase, tableType_t tableType, byte *srcBase) => LZ4_putPositionOnHash(p, LZ4_hashPosition(p, tableType), tableBase, tableType, srcBase);