/* ZSTD_ldm_skipRawSeqStoreBytes(): * Moves forward in rawSeqStore by nbBytes, updating fields 'pos' and 'posInSequence'. * Not to be used in conjunction with ZSTD_ldm_skipSequences(). * Must be called for data with is not passed to ZSTD_ldm_blockCompress(). */ public static void ZSTD_ldm_skipRawSeqStoreBytes(rawSeqStore_t *rawSeqStore, nuint nbBytes) { uint currPos = (uint)(rawSeqStore->posInSequence + nbBytes); while (currPos != 0 && rawSeqStore->pos < rawSeqStore->size) { rawSeq currSeq = rawSeqStore->seq[rawSeqStore->pos]; if (currPos >= currSeq.litLength + currSeq.matchLength) { currPos -= currSeq.litLength + currSeq.matchLength; rawSeqStore->pos++; } else { rawSeqStore->posInSequence = currPos; break; } } if (currPos == 0 || rawSeqStore->pos == rawSeqStore->size) { rawSeqStore->posInSequence = 0; } }
/** * If the sequence length is longer than remaining then the sequence is split * between this block and the next. * * Returns the current sequence to handle, or if the rest of the block should * be literals, it returns a sequence with offset == 0. */ private static rawSeq maybeSplitSequence(rawSeqStore_t *rawSeqStore, uint remaining, uint minMatch) { rawSeq sequence = rawSeqStore->seq[rawSeqStore->pos]; assert(sequence.offset > 0); if (remaining >= sequence.litLength + sequence.matchLength) { rawSeqStore->pos++; return(sequence); } if (remaining <= sequence.litLength) { sequence.offset = 0; } else if (remaining < sequence.litLength + sequence.matchLength) { sequence.matchLength = remaining - sequence.litLength; if (sequence.matchLength < minMatch) { sequence.offset = 0; } } ZSTD_ldm_skipSequences(rawSeqStore, remaining, minMatch); return(sequence); }
/** * 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))); }