/** ZSTD_ldm_adjustParameters() : * If the params->hashRateLog is not set, set it to its default value based on * windowLog and params->hashLog. * * Ensures that params->bucketSizeLog is <= params->hashLog (setting it to * params->hashLog if it is not). * * Ensures that the minMatchLength >= targetLength during optimal parsing. */ public static void ZSTD_ldm_adjustParameters(ldmParams_t * @params, ZSTD_compressionParameters *cParams) { @params->windowLog = cParams->windowLog; if (@params->bucketSizeLog == 0) { @params->bucketSizeLog = 3; } if (@params->minMatchLength == 0) { @params->minMatchLength = 64; } if (@params->hashLog == 0) { @params->hashLog = (uint)((6) > (@params->windowLog - 7) ? (6) : (@params->windowLog - 7)); assert(@params->hashLog <= (uint)(((((int)((nuint)(sizeof(nuint)) == 4 ? 30 : 31)) < 30) ? ((int)((nuint)(sizeof(nuint)) == 4 ? 30 : 31)) : 30))); } if (@params->hashRateLog == 0) { @params->hashRateLog = (uint)(@params->windowLog < @params->hashLog ? 0 : @params->windowLog - @params->hashLog); } @params->bucketSizeLog = ((@params->bucketSizeLog) < (@params->hashLog) ? (@params->bucketSizeLog) : (@params->hashLog)); }
/** * ZSTD_ldm_blockCompress(): * * Compresses a block using the predefined sequences, along with a secondary * block compressor. The literals section of every sequence is passed to the * secondary block compressor, and those sequences are interspersed with the * predefined sequences. Returns the length of the last literals. * Updates `rawSeqStore.pos` to indicate how many sequences have been consumed. * `rawSeqStore.seq` may also be updated to split the last sequence between two * blocks. * @return The length of the last literals. * * NOTE: The source must be at most the maximum block size, but the predefined * sequences can be any size, and may be longer than the block. In the case that * they are longer than the block, the last sequences may need to be split into * two. We handle that case correctly, and update `rawSeqStore` appropriately. * NOTE: This function does not return any errors. */ public static nuint ZSTD_ldm_blockCompress(rawSeqStore_t *rawSeqStore, ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize) { ZSTD_compressionParameters *cParams = &ms->cParams; uint minMatch = cParams->minMatch; ZSTD_blockCompressor blockCompressor = ZSTD_selectBlockCompressor(cParams->strategy, ZSTD_matchState_dictMode(ms)); byte *istart = (byte *)(src); byte *iend = istart + srcSize; byte *ip = istart; if (cParams->strategy >= ZSTD_strategy.ZSTD_btopt) { nuint lastLLSize; ms->ldmSeqStore = rawSeqStore; lastLLSize = blockCompressor(ms, seqStore, rep, src, srcSize); ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore, srcSize); return(lastLLSize); } assert(rawSeqStore->pos <= rawSeqStore->size); assert(rawSeqStore->size <= rawSeqStore->capacity); while (rawSeqStore->pos < rawSeqStore->size && ip < iend) { rawSeq sequence = maybeSplitSequence(rawSeqStore, (uint)(iend - ip), minMatch); int i; if (sequence.offset == 0) { break; } assert(ip + sequence.litLength + sequence.matchLength <= iend); ZSTD_ldm_limitTableUpdate(ms, ip); ZSTD_ldm_fillFastTables(ms, (void *)ip); { nuint newLitLength = blockCompressor(ms, seqStore, rep, (void *)ip, sequence.litLength); ip += sequence.litLength; for (i = 3 - 1; i > 0; i--) { rep[i] = rep[i - 1]; } rep[0] = sequence.offset; ZSTD_storeSeq(seqStore, newLitLength, ip - newLitLength, iend, sequence.offset + (uint)((3 - 1)), sequence.matchLength - 3); ip += sequence.matchLength; } } ZSTD_ldm_limitTableUpdate(ms, ip); ZSTD_ldm_fillFastTables(ms, (void *)ip); return(blockCompressor(ms, seqStore, rep, (void *)ip, (nuint)(iend - ip))); }
public static void ZSTD_fillDoubleHashTable(ZSTD_matchState_t *ms, void *end, ZSTD_dictTableLoadMethod_e dtlm) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashLarge = ms->hashTable; uint hBitsL = cParams->hashLog; uint mls = cParams->minMatch; uint * hashSmall = ms->chainTable; uint hBitsS = cParams->chainLog; byte * @base = ms->window.@base; byte * ip = @base + ms->nextToUpdate; byte * iend = ((byte *)(end)) - 8; uint fastHashFillStep = 3; for (; ip + fastHashFillStep - 1 <= iend; ip += fastHashFillStep) { uint curr = (uint)(ip - @base); uint i; for (i = 0; i < fastHashFillStep; ++i) { nuint smHash = ZSTD_hashPtr((void *)(ip + i), hBitsS, mls); nuint lgHash = ZSTD_hashPtr((void *)(ip + i), hBitsL, 8); if (i == 0) { hashSmall[smHash] = curr + i; } if (i == 0 || hashLarge[lgHash] == 0) { hashLarge[lgHash] = curr + i; } if (dtlm == ZSTD_dictTableLoadMethod_e.ZSTD_dtlm_fast) { break; } } } }
public static void ZSTD_fillHashTable(ZSTD_matchState_t *ms, void *end, ZSTD_dictTableLoadMethod_e dtlm) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashTable = ms->hashTable; uint hBits = cParams->hashLog; uint mls = cParams->minMatch; byte * @base = ms->window.@base; byte * ip = @base + ms->nextToUpdate; byte * iend = ((byte *)(end)) - 8; uint fastHashFillStep = 3; for (; ip + fastHashFillStep < iend + 2; ip += fastHashFillStep) { uint curr = (uint)(ip - @base); nuint hash0 = ZSTD_hashPtr((void *)ip, hBits, mls); hashTable[hash0] = curr; if (dtlm == ZSTD_dictTableLoadMethod_e.ZSTD_dtlm_fast) { continue; } { uint p; for (p = 1; p < fastHashFillStep; ++p) { nuint hash = ZSTD_hashPtr((void *)(ip + p), hBits, mls); if (hashTable[hash] == 0) { hashTable[hash] = curr + p; } } } } }
private static nuint ZSTD_compressBlock_fast_generic(ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize, uint mls) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashTable = ms->hashTable; uint hlog = cParams->hashLog; nuint stepSize = cParams->targetLength + (uint)((cParams->targetLength) == 0 ? 1 : 0) + 1; byte * @base = ms->window.@base; byte * istart = (byte *)(src); byte * ip0 = istart; byte * ip1; byte * anchor = istart; uint endIndex = (uint)((nuint)(istart - @base) + srcSize); uint prefixStartIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); byte * prefixStart = @base + prefixStartIndex; byte * iend = istart + srcSize; byte * ilimit = iend - 8; uint offset_1 = rep[0], offset_2 = rep[1]; uint offsetSaved = 0; ip0 += ((ip0 == prefixStart) ? 1 : 0); ip1 = ip0 + 1; { uint curr = (uint)(ip0 - @base); uint windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); uint maxRep = curr - windowLow; if (offset_2 > maxRep) { offsetSaved = offset_2; offset_2 = 0; } if (offset_1 > maxRep) { offsetSaved = offset_1; offset_1 = 0; } } while (ip1 < ilimit) { byte *match0; byte *match1; uint current0; { nuint h0 = ZSTD_hashPtr((void *)ip0, hlog, mls); nuint h1 = ZSTD_hashPtr((void *)ip1, hlog, mls); match0 = @base + hashTable[h0]; match1 = @base + hashTable[h1]; current0 = (uint)(ip0 - @base); hashTable[h0] = current0; hashTable[h1] = (uint)(ip1 - @base); } uint offcode; nuint mLength; assert(ip0 + 1 == ip1); { byte *ip2 = ip0 + 2; byte *repMatch = ip2 - offset_1; if (((offset_1 > 0) && (MEM_read32((void *)repMatch) == MEM_read32((void *)ip2)))) { mLength = (nuint)((ip2[-1] == repMatch[-1]) ? 1 : 0); ip0 = ip2 - mLength; match0 = repMatch - mLength; mLength += 4; offcode = 0; goto _match; } } if ((match0 > prefixStart) && MEM_read32((void *)match0) == MEM_read32((void *)ip0)) { goto _offset; } if ((match1 > prefixStart) && MEM_read32((void *)match1) == MEM_read32((void *)ip1)) { ip0 = ip1; match0 = match1; goto _offset; } { nuint step = ((nuint)(ip0 - anchor) >> (8 - 1)) + stepSize; assert(step >= 2); ip0 += step; ip1 += step; continue; } _offset: offset_2 = offset_1; offset_1 = (uint)(ip0 - match0); offcode = offset_1 + (uint)((3 - 1)); mLength = 4; while ((((ip0 > anchor) && (match0 > prefixStart))) && (ip0[-1] == match0[-1])) { ip0--; match0--; mLength++; } _match: mLength += ZSTD_count(ip0 + mLength, match0 + mLength, iend); ZSTD_storeSeq(seqStore, (nuint)(ip0 - anchor), anchor, iend, offcode, mLength - 3); ip0 += mLength; anchor = ip0; if (ip0 <= ilimit) { assert(@base + current0 + 2 > istart); hashTable[ZSTD_hashPtr((void *)(@base + current0 + 2), hlog, mls)] = current0 + 2; hashTable[ZSTD_hashPtr((void *)(ip0 - 2), hlog, mls)] = (uint)(ip0 - 2 - @base); if (offset_2 > 0) { while ((ip0 <= ilimit) && (MEM_read32((void *)ip0) == MEM_read32((void *)(ip0 - offset_2)))) { nuint rLength = ZSTD_count(ip0 + 4, ip0 + 4 - offset_2, iend) + 4; { uint tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; } hashTable[ZSTD_hashPtr((void *)ip0, hlog, mls)] = (uint)(ip0 - @base); ip0 += rLength; ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength - 3); anchor = ip0; continue; } } } ip1 = ip0 + 1; } rep[0] = offset_1 != 0 ? offset_1 : offsetSaved; rep[1] = offset_2 != 0 ? offset_2 : offsetSaved; return((nuint)(iend - anchor)); }
private static nuint ZSTD_compressBlock_fast_extDict_generic(ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize, uint mls) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashTable = ms->hashTable; uint hlog = cParams->hashLog; uint stepSize = cParams->targetLength + (uint)((cParams->targetLength) == 0 ? 1 : 0); byte * @base = ms->window.@base; byte * dictBase = ms->window.dictBase; byte * istart = (byte *)(src); byte * ip = istart; byte * anchor = istart; uint endIndex = (uint)((nuint)(istart - @base) + srcSize); uint lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); uint dictStartIndex = lowLimit; byte * dictStart = dictBase + dictStartIndex; uint dictLimit = ms->window.dictLimit; uint prefixStartIndex = dictLimit < lowLimit ? lowLimit : dictLimit; byte * prefixStart = @base + prefixStartIndex; byte * dictEnd = dictBase + prefixStartIndex; byte * iend = istart + srcSize; byte * ilimit = iend - 8; uint offset_1 = rep[0], offset_2 = rep[1]; if (prefixStartIndex == dictStartIndex) { return(ZSTD_compressBlock_fast_generic(ms, seqStore, rep, src, srcSize, mls)); } while (ip < ilimit) { nuint h = ZSTD_hashPtr((void *)ip, hlog, mls); uint matchIndex = hashTable[h]; byte *matchBase = matchIndex < prefixStartIndex ? dictBase : @base; byte *match = matchBase + matchIndex; uint curr = (uint)(ip - @base); uint repIndex = curr + 1 - offset_1; byte *repBase = repIndex < prefixStartIndex ? dictBase : @base; byte *repMatch = repBase + repIndex; hashTable[h] = curr; assert(offset_1 <= curr + 1); if (((((uint)((prefixStartIndex - 1) - repIndex) >= 3) && (repIndex > dictStartIndex))) && (MEM_read32((void *)repMatch) == MEM_read32((void *)(ip + 1)))) { byte *repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; nuint rLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; ip++; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, 0, rLength - 3); ip += rLength; anchor = ip; } else { if ((matchIndex < dictStartIndex) || (MEM_read32((void *)match) != MEM_read32((void *)ip))) { assert(stepSize >= 1); ip += (ulong)((ip - anchor) >> 8) + stepSize; continue; } { byte *matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; byte *lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; uint offset = curr - matchIndex; nuint mLength = ZSTD_count_2segments(ip + 4, match + 4, iend, matchEnd, prefixStart) + 4; while ((((ip > anchor) && (match > lowMatchPtr))) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); ip += mLength; anchor = ip; } } if (ip <= ilimit) { hashTable[ZSTD_hashPtr((void *)(@base + curr + 2), hlog, mls)] = curr + 2; hashTable[ZSTD_hashPtr((void *)(ip - 2), hlog, mls)] = (uint)(ip - 2 - @base); while (ip <= ilimit) { uint current2 = (uint)(ip - @base); uint repIndex2 = current2 - offset_2; byte *repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : @base + repIndex2; if (((((uint)((prefixStartIndex - 1) - repIndex2) >= 3) && (repIndex2 > dictStartIndex))) && (MEM_read32((void *)repMatch2) == MEM_read32((void *)ip))) { byte *repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; nuint repLength2 = ZSTD_count_2segments(ip + 4, repMatch2 + 4, iend, repEnd2, prefixStart) + 4; { uint tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; } ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2 - 3); hashTable[ZSTD_hashPtr((void *)ip, hlog, mls)] = current2; ip += repLength2; anchor = ip; continue; } break; } } } rep[0] = offset_1; rep[1] = offset_2; return((nuint)(iend - anchor)); }
private static nuint ZSTD_compressBlock_fast_dictMatchState_generic(ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize, uint mls) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashTable = ms->hashTable; uint hlog = cParams->hashLog; uint stepSize = cParams->targetLength + (uint)((cParams->targetLength) == 0 ? 1 : 0); byte * @base = ms->window.@base; byte * istart = (byte *)(src); byte * ip = istart; byte * anchor = istart; uint prefixStartIndex = ms->window.dictLimit; byte * prefixStart = @base + prefixStartIndex; byte * iend = istart + srcSize; byte * ilimit = iend - 8; uint offset_1 = rep[0], offset_2 = rep[1]; uint offsetSaved = 0; ZSTD_matchState_t * dms = ms->dictMatchState; ZSTD_compressionParameters *dictCParams = &dms->cParams; uint * dictHashTable = dms->hashTable; uint dictStartIndex = dms->window.dictLimit; byte * dictBase = dms->window.@base; byte * dictStart = dictBase + dictStartIndex; byte * dictEnd = dms->window.nextSrc; uint dictIndexDelta = prefixStartIndex - (uint)(dictEnd - dictBase); uint dictAndPrefixLength = (uint)(ip - prefixStart + dictEnd - dictStart); uint dictHLog = dictCParams->hashLog; uint maxDistance = 1U << (int)cParams->windowLog; uint endIndex = (uint)((nuint)(ip - @base) + srcSize); assert(endIndex - prefixStartIndex <= maxDistance); assert(prefixStartIndex >= (uint)(dictEnd - dictBase)); ip += ((dictAndPrefixLength == 0) ? 1 : 0); assert(offset_1 <= dictAndPrefixLength); assert(offset_2 <= dictAndPrefixLength); while (ip < ilimit) { nuint mLength; nuint h = ZSTD_hashPtr((void *)ip, hlog, mls); uint curr = (uint)(ip - @base); uint matchIndex = hashTable[h]; byte *match = @base + matchIndex; uint repIndex = curr + 1 - offset_1; byte *repMatch = (repIndex < prefixStartIndex) ? dictBase + (repIndex - dictIndexDelta) : @base + repIndex; hashTable[h] = curr; if (((uint)((prefixStartIndex - 1) - repIndex) >= 3) && (MEM_read32((void *)repMatch) == MEM_read32((void *)(ip + 1)))) { byte *repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; ip++; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, 0, mLength - 3); } else if ((matchIndex <= prefixStartIndex)) { nuint dictHash = ZSTD_hashPtr((void *)ip, dictHLog, mls); uint dictMatchIndex = dictHashTable[dictHash]; byte *dictMatch = dictBase + dictMatchIndex; if (dictMatchIndex <= dictStartIndex || MEM_read32((void *)dictMatch) != MEM_read32((void *)ip)) { assert(stepSize >= 1); ip += (ulong)((ip - anchor) >> 8) + stepSize; continue; } else { uint offset = (uint)(curr - dictMatchIndex - dictIndexDelta); mLength = ZSTD_count_2segments(ip + 4, dictMatch + 4, iend, dictEnd, prefixStart) + 4; while ((((ip > anchor) && (dictMatch > dictStart))) && (ip[-1] == dictMatch[-1])) { ip--; dictMatch--; mLength++; } offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); } } else if (MEM_read32((void *)match) != MEM_read32((void *)ip)) { assert(stepSize >= 1); ip += (ulong)((ip - anchor) >> 8) + stepSize; continue; } else { uint offset = (uint)(ip - match); mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; while ((((ip > anchor) && (match > prefixStart))) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); } ip += mLength; anchor = ip; if (ip <= ilimit) { assert(@base + curr + 2 > istart); hashTable[ZSTD_hashPtr((void *)(@base + curr + 2), hlog, mls)] = curr + 2; hashTable[ZSTD_hashPtr((void *)(ip - 2), hlog, mls)] = (uint)(ip - 2 - @base); while (ip <= ilimit) { uint current2 = (uint)(ip - @base); uint repIndex2 = current2 - offset_2; byte *repMatch2 = repIndex2 < prefixStartIndex ? dictBase - dictIndexDelta + repIndex2 : @base + repIndex2; if (((uint)((prefixStartIndex - 1) - (uint)(repIndex2)) >= 3) && (MEM_read32((void *)repMatch2) == MEM_read32((void *)ip))) { byte *repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; nuint repLength2 = ZSTD_count_2segments(ip + 4, repMatch2 + 4, iend, repEnd2, prefixStart) + 4; uint tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2 - 3); hashTable[ZSTD_hashPtr((void *)ip, hlog, mls)] = current2; ip += repLength2; anchor = ip; continue; } break; } } } rep[0] = offset_1 != 0 ? offset_1 : offsetSaved; rep[1] = offset_2 != 0 ? offset_2 : offsetSaved; return((nuint)(iend - anchor)); }
private static nuint ZSTD_compressBlock_doubleFast_generic(ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize, uint mls, ZSTD_dictMode_e dictMode) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashLong = ms->hashTable; uint hBitsL = cParams->hashLog; uint * hashSmall = ms->chainTable; uint hBitsS = cParams->chainLog; byte * @base = ms->window.@base; byte * istart = (byte *)(src); byte * ip = istart; byte * anchor = istart; uint endIndex = (uint)((nuint)(istart - @base) + srcSize); uint prefixLowestIndex = ZSTD_getLowestPrefixIndex(ms, endIndex, cParams->windowLog); byte * prefixLowest = @base + prefixLowestIndex; byte * iend = istart + srcSize; byte * ilimit = iend - 8; uint offset_1 = rep[0], offset_2 = rep[1]; uint offsetSaved = 0; ZSTD_matchState_t * dms = ms->dictMatchState; ZSTD_compressionParameters *dictCParams = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? &dms->cParams : null; uint * dictHashLong = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dms->hashTable : null; uint * dictHashSmall = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dms->chainTable : null; uint dictStartIndex = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dms->window.dictLimit : 0; byte * dictBase = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dms->window.@base : null; byte * dictStart = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dictBase + dictStartIndex : null; byte * dictEnd = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dms->window.nextSrc : null; uint dictIndexDelta = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? prefixLowestIndex - (uint)(dictEnd - dictBase) : 0; uint dictHBitsL = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dictCParams->hashLog : hBitsL; uint dictHBitsS = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState ? dictCParams->chainLog : hBitsS; uint dictAndPrefixLength = (uint)((ip - prefixLowest) + (dictEnd - dictStart)); assert(dictMode == ZSTD_dictMode_e.ZSTD_noDict || dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState); if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { assert(ms->window.dictLimit + (1U << (int)cParams->windowLog) >= endIndex); } ip += ((dictAndPrefixLength == 0) ? 1 : 0); if (dictMode == ZSTD_dictMode_e.ZSTD_noDict) { uint curr = (uint)(ip - @base); uint windowLow = ZSTD_getLowestPrefixIndex(ms, curr, cParams->windowLog); uint maxRep = curr - windowLow; if (offset_2 > maxRep) { offsetSaved = offset_2; offset_2 = 0; } if (offset_1 > maxRep) { offsetSaved = offset_1; offset_1 = 0; } } if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { assert(offset_1 <= dictAndPrefixLength); assert(offset_2 <= dictAndPrefixLength); } while (ip < ilimit) { nuint mLength; uint offset; nuint h2 = ZSTD_hashPtr((void *)ip, hBitsL, 8); nuint h = ZSTD_hashPtr((void *)ip, hBitsS, mls); nuint dictHL = ZSTD_hashPtr((void *)ip, dictHBitsL, 8); nuint dictHS = ZSTD_hashPtr((void *)ip, dictHBitsS, mls); uint curr = (uint)(ip - @base); uint matchIndexL = hashLong[h2]; uint matchIndexS = hashSmall[h]; byte *matchLong = @base + matchIndexL; byte *match = @base + matchIndexS; uint repIndex = curr + 1 - offset_1; byte *repMatch = (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState && repIndex < prefixLowestIndex) ? dictBase + (repIndex - dictIndexDelta) : @base + repIndex; hashLong[h2] = hashSmall[h] = curr; if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState && ((uint)((prefixLowestIndex - 1) - repIndex) >= 3) && (MEM_read32((void *)repMatch) == MEM_read32((void *)(ip + 1)))) { byte *repMatchEnd = repIndex < prefixLowestIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixLowest) + 4; ip++; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, 0, mLength - 3); goto _match_stored; } if (dictMode == ZSTD_dictMode_e.ZSTD_noDict && (((offset_1 > 0) && (MEM_read32((void *)(ip + 1 - offset_1)) == MEM_read32((void *)(ip + 1)))))) { mLength = ZSTD_count(ip + 1 + 4, ip + 1 + 4 - offset_1, iend) + 4; ip++; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, 0, mLength - 3); goto _match_stored; } if (matchIndexL > prefixLowestIndex) { if (MEM_read64((void *)matchLong) == MEM_read64((void *)ip)) { mLength = ZSTD_count(ip + 8, matchLong + 8, iend) + 8; offset = (uint)(ip - matchLong); while ((((ip > anchor) && (matchLong > prefixLowest))) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } goto _match_found; } } else if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { uint dictMatchIndexL = dictHashLong[dictHL]; byte *dictMatchL = dictBase + dictMatchIndexL; assert(dictMatchL < dictEnd); if (dictMatchL > dictStart && MEM_read64((void *)dictMatchL) == MEM_read64((void *)ip)) { mLength = ZSTD_count_2segments(ip + 8, dictMatchL + 8, iend, dictEnd, prefixLowest) + 8; offset = (uint)(curr - dictMatchIndexL - dictIndexDelta); while ((((ip > anchor) && (dictMatchL > dictStart))) && (ip[-1] == dictMatchL[-1])) { ip--; dictMatchL--; mLength++; } goto _match_found; } } if (matchIndexS > prefixLowestIndex) { if (MEM_read32((void *)match) == MEM_read32((void *)ip)) { goto _search_next_long; } } else if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { uint dictMatchIndexS = dictHashSmall[dictHS]; match = dictBase + dictMatchIndexS; matchIndexS = dictMatchIndexS + dictIndexDelta; if (match > dictStart && MEM_read32((void *)match) == MEM_read32((void *)ip)) { goto _search_next_long; } } ip += ((ip - anchor) >> 8) + 1; continue; _search_next_long: { nuint hl3 = ZSTD_hashPtr((void *)(ip + 1), hBitsL, 8); nuint dictHLNext = ZSTD_hashPtr((void *)(ip + 1), dictHBitsL, 8); uint matchIndexL3 = hashLong[hl3]; byte *matchL3 = @base + matchIndexL3; hashLong[hl3] = curr + 1; if (matchIndexL3 > prefixLowestIndex) { if (MEM_read64((void *)matchL3) == MEM_read64((void *)(ip + 1))) { mLength = ZSTD_count(ip + 9, matchL3 + 8, iend) + 8; ip++; offset = (uint)(ip - matchL3); while ((((ip > anchor) && (matchL3 > prefixLowest))) && (ip[-1] == matchL3[-1])) { ip--; matchL3--; mLength++; } goto _match_found; } } else if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { uint dictMatchIndexL3 = dictHashLong[dictHLNext]; byte *dictMatchL3 = dictBase + dictMatchIndexL3; assert(dictMatchL3 < dictEnd); if (dictMatchL3 > dictStart && MEM_read64((void *)dictMatchL3) == MEM_read64((void *)(ip + 1))) { mLength = ZSTD_count_2segments(ip + 1 + 8, dictMatchL3 + 8, iend, dictEnd, prefixLowest) + 8; ip++; offset = (uint)(curr + 1 - dictMatchIndexL3 - dictIndexDelta); while ((((ip > anchor) && (dictMatchL3 > dictStart))) && (ip[-1] == dictMatchL3[-1])) { ip--; dictMatchL3--; mLength++; } goto _match_found; } } } if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState && matchIndexS < prefixLowestIndex) { mLength = ZSTD_count_2segments(ip + 4, match + 4, iend, dictEnd, prefixLowest) + 4; offset = (uint)(curr - matchIndexS); while ((((ip > anchor) && (match > dictStart))) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } } else { mLength = ZSTD_count(ip + 4, match + 4, iend) + 4; offset = (uint)(ip - match); while ((((ip > anchor) && (match > prefixLowest))) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } } _match_found: offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); _match_stored: ip += mLength; anchor = ip; if (ip <= ilimit) { { uint indexToInsert = curr + 2; hashLong[ZSTD_hashPtr((void *)(@base + indexToInsert), hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr((void *)(ip - 2), hBitsL, 8)] = (uint)(ip - 2 - @base); hashSmall[ZSTD_hashPtr((void *)(@base + indexToInsert), hBitsS, mls)] = indexToInsert; hashSmall[ZSTD_hashPtr((void *)(ip - 1), hBitsS, mls)] = (uint)(ip - 1 - @base); } if (dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState) { while (ip <= ilimit) { uint current2 = (uint)(ip - @base); uint repIndex2 = current2 - offset_2; byte *repMatch2 = dictMode == ZSTD_dictMode_e.ZSTD_dictMatchState && repIndex2 < prefixLowestIndex ? dictBase + repIndex2 - dictIndexDelta : @base + repIndex2; if (((uint)((prefixLowestIndex - 1) - (uint)(repIndex2)) >= 3) && (MEM_read32((void *)repMatch2) == MEM_read32((void *)ip))) { byte *repEnd2 = repIndex2 < prefixLowestIndex ? dictEnd : iend; nuint repLength2 = ZSTD_count_2segments(ip + 4, repMatch2 + 4, iend, repEnd2, prefixLowest) + 4; uint tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2 - 3); hashSmall[ZSTD_hashPtr((void *)ip, hBitsS, mls)] = current2; hashLong[ZSTD_hashPtr((void *)ip, hBitsL, 8)] = current2; ip += repLength2; anchor = ip; continue; } break; } } if (dictMode == ZSTD_dictMode_e.ZSTD_noDict) { while ((ip <= ilimit) && (((offset_2 > 0) && (MEM_read32((void *)ip) == MEM_read32((void *)(ip - offset_2)))))) { nuint rLength = ZSTD_count(ip + 4, ip + 4 - offset_2, iend) + 4; uint tmpOff = offset_2; offset_2 = offset_1; offset_1 = tmpOff; hashSmall[ZSTD_hashPtr((void *)ip, hBitsS, mls)] = (uint)(ip - @base); hashLong[ZSTD_hashPtr((void *)ip, hBitsL, 8)] = (uint)(ip - @base); ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, rLength - 3); ip += rLength; anchor = ip; continue; } } } } rep[0] = offset_1 != 0 ? offset_1 : offsetSaved; rep[1] = offset_2 != 0 ? offset_2 : offsetSaved; return((nuint)(iend - anchor)); }
private static nuint ZSTD_compressBlock_doubleFast_extDict_generic(ZSTD_matchState_t *ms, seqStore_t *seqStore, uint *rep, void *src, nuint srcSize, uint mls) { ZSTD_compressionParameters *cParams = &ms->cParams; uint * hashLong = ms->hashTable; uint hBitsL = cParams->hashLog; uint * hashSmall = ms->chainTable; uint hBitsS = cParams->chainLog; byte * istart = (byte *)(src); byte * ip = istart; byte * anchor = istart; byte * iend = istart + srcSize; byte * ilimit = iend - 8; byte * @base = ms->window.@base; uint endIndex = (uint)((nuint)(istart - @base) + srcSize); uint lowLimit = ZSTD_getLowestMatchIndex(ms, endIndex, cParams->windowLog); uint dictStartIndex = lowLimit; uint dictLimit = ms->window.dictLimit; uint prefixStartIndex = (dictLimit > lowLimit) ? dictLimit : lowLimit; byte * prefixStart = @base + prefixStartIndex; byte * dictBase = ms->window.dictBase; byte * dictStart = dictBase + dictStartIndex; byte * dictEnd = dictBase + prefixStartIndex; uint offset_1 = rep[0], offset_2 = rep[1]; if (prefixStartIndex == dictStartIndex) { return(ZSTD_compressBlock_doubleFast_generic(ms, seqStore, rep, src, srcSize, mls, ZSTD_dictMode_e.ZSTD_noDict)); } while (ip < ilimit) { nuint hSmall = ZSTD_hashPtr((void *)ip, hBitsS, mls); uint matchIndex = hashSmall[hSmall]; byte *matchBase = matchIndex < prefixStartIndex ? dictBase : @base; byte *match = matchBase + matchIndex; nuint hLong = ZSTD_hashPtr((void *)ip, hBitsL, 8); uint matchLongIndex = hashLong[hLong]; byte *matchLongBase = matchLongIndex < prefixStartIndex ? dictBase : @base; byte *matchLong = matchLongBase + matchLongIndex; uint curr = (uint)(ip - @base); uint repIndex = curr + 1 - offset_1; byte *repBase = repIndex < prefixStartIndex ? dictBase : @base; byte *repMatch = repBase + repIndex; nuint mLength; hashSmall[hSmall] = hashLong[hLong] = curr; if (((((uint)((prefixStartIndex - 1) - repIndex) >= 3) && (repIndex > dictStartIndex))) && (MEM_read32((void *)repMatch) == MEM_read32((void *)(ip + 1)))) { byte *repMatchEnd = repIndex < prefixStartIndex ? dictEnd : iend; mLength = ZSTD_count_2segments(ip + 1 + 4, repMatch + 4, iend, repMatchEnd, prefixStart) + 4; ip++; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, 0, mLength - 3); } else { if ((matchLongIndex > dictStartIndex) && (MEM_read64((void *)matchLong) == MEM_read64((void *)ip))) { byte *matchEnd = matchLongIndex < prefixStartIndex ? dictEnd : iend; byte *lowMatchPtr = matchLongIndex < prefixStartIndex ? dictStart : prefixStart; uint offset; mLength = ZSTD_count_2segments(ip + 8, matchLong + 8, iend, matchEnd, prefixStart) + 8; offset = curr - matchLongIndex; while ((((ip > anchor) && (matchLong > lowMatchPtr))) && (ip[-1] == matchLong[-1])) { ip--; matchLong--; mLength++; } offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); } else if ((matchIndex > dictStartIndex) && (MEM_read32((void *)match) == MEM_read32((void *)ip))) { nuint h3 = ZSTD_hashPtr((void *)(ip + 1), hBitsL, 8); uint matchIndex3 = hashLong[h3]; byte *match3Base = matchIndex3 < prefixStartIndex ? dictBase : @base; byte *match3 = match3Base + matchIndex3; uint offset; hashLong[h3] = curr + 1; if ((matchIndex3 > dictStartIndex) && (MEM_read64((void *)match3) == MEM_read64((void *)(ip + 1)))) { byte *matchEnd = matchIndex3 < prefixStartIndex ? dictEnd : iend; byte *lowMatchPtr = matchIndex3 < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip + 9, match3 + 8, iend, matchEnd, prefixStart) + 8; ip++; offset = curr + 1 - matchIndex3; while ((((ip > anchor) && (match3 > lowMatchPtr))) && (ip[-1] == match3[-1])) { ip--; match3--; mLength++; } } else { byte *matchEnd = matchIndex < prefixStartIndex ? dictEnd : iend; byte *lowMatchPtr = matchIndex < prefixStartIndex ? dictStart : prefixStart; mLength = ZSTD_count_2segments(ip + 4, match + 4, iend, matchEnd, prefixStart) + 4; offset = curr - matchIndex; while ((((ip > anchor) && (match > lowMatchPtr))) && (ip[-1] == match[-1])) { ip--; match--; mLength++; } } offset_2 = offset_1; offset_1 = offset; ZSTD_storeSeq(seqStore, (nuint)(ip - anchor), anchor, iend, offset + (uint)((3 - 1)), mLength - 3); } else { ip += ((ip - anchor) >> 8) + 1; continue; } } ip += mLength; anchor = ip; if (ip <= ilimit) { { uint indexToInsert = curr + 2; hashLong[ZSTD_hashPtr((void *)(@base + indexToInsert), hBitsL, 8)] = indexToInsert; hashLong[ZSTD_hashPtr((void *)(ip - 2), hBitsL, 8)] = (uint)(ip - 2 - @base); hashSmall[ZSTD_hashPtr((void *)(@base + indexToInsert), hBitsS, mls)] = indexToInsert; hashSmall[ZSTD_hashPtr((void *)(ip - 1), hBitsS, mls)] = (uint)(ip - 1 - @base); } while (ip <= ilimit) { uint current2 = (uint)(ip - @base); uint repIndex2 = current2 - offset_2; byte *repMatch2 = repIndex2 < prefixStartIndex ? dictBase + repIndex2 : @base + repIndex2; if (((((uint)((prefixStartIndex - 1) - repIndex2) >= 3) && (repIndex2 > dictStartIndex))) && (MEM_read32((void *)repMatch2) == MEM_read32((void *)ip))) { byte *repEnd2 = repIndex2 < prefixStartIndex ? dictEnd : iend; nuint repLength2 = ZSTD_count_2segments(ip + 4, repMatch2 + 4, iend, repEnd2, prefixStart) + 4; uint tmpOffset = offset_2; offset_2 = offset_1; offset_1 = tmpOffset; ZSTD_storeSeq(seqStore, 0, anchor, iend, 0, repLength2 - 3); hashSmall[ZSTD_hashPtr((void *)ip, hBitsS, mls)] = current2; hashLong[ZSTD_hashPtr((void *)ip, hBitsL, 8)] = current2; ip += repLength2; anchor = ip; continue; } break; } } } rep[0] = offset_1; rep[1] = offset_2; return((nuint)(iend - anchor)); }