/** * ZSTD_ldm_skipSequences(): * * Skip past `srcSize` bytes worth of sequences in `rawSeqStore`. * Avoids emitting matches less than `minMatch` bytes. * Must be called for data that is not passed to ZSTD_ldm_blockCompress(). */ public static void ZSTD_ldm_skipSequences(rawSeqStore_t *rawSeqStore, nuint srcSize, uint minMatch) { while (srcSize > 0 && rawSeqStore->pos < rawSeqStore->size) { rawSeq *seq = rawSeqStore->seq + rawSeqStore->pos; if (srcSize <= seq->litLength) { seq->litLength -= (uint)(srcSize); return; } srcSize -= seq->litLength; seq->litLength = 0; if (srcSize < seq->matchLength) { seq->matchLength -= (uint)(srcSize); if (seq->matchLength < minMatch) { if (rawSeqStore->pos + 1 < rawSeqStore->size) { seq[1].litLength += seq[0].matchLength; } rawSeqStore->pos++; } return; } srcSize -= seq->matchLength; seq->matchLength = 0; rawSeqStore->pos++; } }
private static nuint ZSTD_ldm_generateSequences_internal(ldmState_t *ldmState, rawSeqStore_t *rawSeqStore, ldmParams_t * @params, void *src, nuint srcSize) { int extDict = (int)(ZSTD_window_hasExtDict(ldmState->window)); uint minMatchLength = @params->minMatchLength; uint entsPerBucket = 1U << (int)@params->bucketSizeLog; uint hBits = @params->hashLog - @params->bucketSizeLog; uint dictLimit = ldmState->window.dictLimit; uint lowestIndex = extDict != 0 ? ldmState->window.lowLimit : dictLimit; byte * @base = ldmState->window.@base; byte * dictBase = extDict != 0 ? ldmState->window.dictBase : null; byte * dictStart = extDict != 0 ? dictBase + lowestIndex : null; byte * dictEnd = extDict != 0 ? dictBase + dictLimit : null; byte * lowPrefixPtr = @base + dictLimit; byte * istart = (byte *)(src); byte * iend = istart + srcSize; byte * ilimit = iend - 8; byte * anchor = istart; byte * ip = istart; ldmRollingHashState_t hashState; nuint *splits = (nuint *)ldmState->splitIndices; ldmMatchCandidate_t *candidates = (ldmMatchCandidate_t *)ldmState->matchCandidates; uint numSplits; if (srcSize < minMatchLength) { return((nuint)(iend - anchor)); } ZSTD_ldm_gear_init(&hashState, @params); { nuint n = 0; while (n < minMatchLength) { numSplits = 0; n += ZSTD_ldm_gear_feed(&hashState, ip + n, minMatchLength - n, splits, &numSplits); } ip += minMatchLength; } while (ip < ilimit) { nuint hashed; uint n; numSplits = 0; hashed = ZSTD_ldm_gear_feed(&hashState, ip, (nuint)(ilimit - ip), splits, &numSplits); for (n = 0; n < numSplits; n++) { byte *split = ip + splits[n] - minMatchLength; ulong xxhash = XXH64((void *)split, minMatchLength, 0); uint hash = (uint)(xxhash & (((uint)(1) << (int)hBits) - 1)); candidates[n].split = split; candidates[n].hash = hash; candidates[n].checksum = (uint)(xxhash >> 32); candidates[n].bucket = ZSTD_ldm_getBucket(ldmState, hash, *@params); Prefetch0((void *)(candidates[n].bucket)); } for (n = 0; n < numSplits; n++) { nuint forwardMatchLength = 0, backwardMatchLength = 0, bestMatchLength = 0, mLength; byte * split = candidates[n].split; uint checksum = candidates[n].checksum; uint hash = candidates[n].hash; ldmEntry_t *bucket = candidates[n].bucket; ldmEntry_t *cur; ldmEntry_t *bestEntry = (ldmEntry_t *)null; ldmEntry_t newEntry; newEntry.offset = (uint)(split - @base); newEntry.checksum = checksum; if (split < anchor) { ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *@params); continue; } for (cur = bucket; cur < bucket + entsPerBucket; cur++) { nuint curForwardMatchLength, curBackwardMatchLength, curTotalMatchLength; if (cur->checksum != checksum || cur->offset <= lowestIndex) { continue; } if (extDict != 0) { byte *curMatchBase = cur->offset < dictLimit ? dictBase : @base; byte *pMatch = curMatchBase + cur->offset; byte *matchEnd = cur->offset < dictLimit ? dictEnd : iend; byte *lowMatchPtr = cur->offset < dictLimit ? dictStart : lowPrefixPtr; curForwardMatchLength = ZSTD_count_2segments(split, pMatch, iend, matchEnd, lowPrefixPtr); if (curForwardMatchLength < minMatchLength) { continue; } curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch_2segments(split, anchor, pMatch, lowMatchPtr, dictStart, dictEnd); } else { byte *pMatch = @base + cur->offset; curForwardMatchLength = ZSTD_count(split, pMatch, iend); if (curForwardMatchLength < minMatchLength) { continue; } curBackwardMatchLength = ZSTD_ldm_countBackwardsMatch(split, anchor, pMatch, lowPrefixPtr); } curTotalMatchLength = curForwardMatchLength + curBackwardMatchLength; if (curTotalMatchLength > bestMatchLength) { bestMatchLength = curTotalMatchLength; forwardMatchLength = curForwardMatchLength; backwardMatchLength = curBackwardMatchLength; bestEntry = cur; } } if (bestEntry == null) { ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *@params); continue; } mLength = forwardMatchLength + backwardMatchLength; { uint offset = (uint)(split - @base) - bestEntry->offset; rawSeq *seq = rawSeqStore->seq + rawSeqStore->size; if (rawSeqStore->size == rawSeqStore->capacity) { return(unchecked ((nuint)(-(int)ZSTD_ErrorCode.ZSTD_error_dstSize_tooSmall))); } seq->litLength = (uint)(split - backwardMatchLength - anchor); seq->matchLength = (uint)(mLength); seq->offset = offset; rawSeqStore->size++; } ZSTD_ldm_insertEntry(ldmState, hash, newEntry, *@params); anchor = split + forwardMatchLength; } ip += hashed; } return((nuint)(iend - anchor)); }