xref: /freebsd/contrib/xz/src/liblzma/lz/lz_encoder.c (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD
2*3b35e7eeSXin LI 
381ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
481ad8388SMartin Matuska //
581ad8388SMartin Matuska /// \file       lz_encoder.c
681ad8388SMartin Matuska /// \brief      LZ in window
781ad8388SMartin Matuska ///
881ad8388SMartin Matuska //  Authors:    Igor Pavlov
981ad8388SMartin Matuska //              Lasse Collin
1081ad8388SMartin Matuska //
1181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1281ad8388SMartin Matuska 
1381ad8388SMartin Matuska #include "lz_encoder.h"
1481ad8388SMartin Matuska #include "lz_encoder_hash.h"
1581ad8388SMartin Matuska 
1681ad8388SMartin Matuska // See lz_encoder_hash.h. This is a bit hackish but avoids making
1781ad8388SMartin Matuska // endianness a conditional in makefiles.
1881ad8388SMartin Matuska #if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
1981ad8388SMartin Matuska #	include "lz_encoder_hash_table.h"
2081ad8388SMartin Matuska #endif
2181ad8388SMartin Matuska 
2253200025SRui Paulo #include "memcmplen.h"
2353200025SRui Paulo 
2481ad8388SMartin Matuska 
251456f0f9SXin LI typedef struct {
2681ad8388SMartin Matuska 	/// LZ-based encoder e.g. LZMA
2781ad8388SMartin Matuska 	lzma_lz_encoder lz;
2881ad8388SMartin Matuska 
2981ad8388SMartin Matuska 	/// History buffer and match finder
3081ad8388SMartin Matuska 	lzma_mf mf;
3181ad8388SMartin Matuska 
3281ad8388SMartin Matuska 	/// Next coder in the chain
3381ad8388SMartin Matuska 	lzma_next_coder next;
341456f0f9SXin LI } lzma_coder;
3581ad8388SMartin Matuska 
3681ad8388SMartin Matuska 
3781ad8388SMartin Matuska /// \brief      Moves the data in the input window to free space for new data
3881ad8388SMartin Matuska ///
3981ad8388SMartin Matuska /// mf->buffer is a sliding input window, which keeps mf->keep_size_before
4081ad8388SMartin Matuska /// bytes of input history available all the time. Now and then we need to
4181ad8388SMartin Matuska /// "slide" the buffer to make space for the new data to the end of the
4281ad8388SMartin Matuska /// buffer. At the same time, data older than keep_size_before is dropped.
4381ad8388SMartin Matuska ///
4481ad8388SMartin Matuska static void
4581ad8388SMartin Matuska move_window(lzma_mf *mf)
4681ad8388SMartin Matuska {
4781ad8388SMartin Matuska 	// Align the move to a multiple of 16 bytes. Some LZ-based encoders
4881ad8388SMartin Matuska 	// like LZMA use the lowest bits of mf->read_pos to know the
4981ad8388SMartin Matuska 	// alignment of the uncompressed data. We also get better speed
5081ad8388SMartin Matuska 	// for memmove() with aligned buffers.
5181ad8388SMartin Matuska 	assert(mf->read_pos > mf->keep_size_before);
5281ad8388SMartin Matuska 	const uint32_t move_offset
5381ad8388SMartin Matuska 		= (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
5481ad8388SMartin Matuska 
5581ad8388SMartin Matuska 	assert(mf->write_pos > move_offset);
5681ad8388SMartin Matuska 	const size_t move_size = mf->write_pos - move_offset;
5781ad8388SMartin Matuska 
5881ad8388SMartin Matuska 	assert(move_offset + move_size <= mf->size);
5981ad8388SMartin Matuska 
6081ad8388SMartin Matuska 	memmove(mf->buffer, mf->buffer + move_offset, move_size);
6181ad8388SMartin Matuska 
6281ad8388SMartin Matuska 	mf->offset += move_offset;
6381ad8388SMartin Matuska 	mf->read_pos -= move_offset;
6481ad8388SMartin Matuska 	mf->read_limit -= move_offset;
6581ad8388SMartin Matuska 	mf->write_pos -= move_offset;
6681ad8388SMartin Matuska 
6781ad8388SMartin Matuska 	return;
6881ad8388SMartin Matuska }
6981ad8388SMartin Matuska 
7081ad8388SMartin Matuska 
7181ad8388SMartin Matuska /// \brief      Tries to fill the input window (mf->buffer)
7281ad8388SMartin Matuska ///
7381ad8388SMartin Matuska /// If we are the last encoder in the chain, our input data is in in[].
7481ad8388SMartin Matuska /// Otherwise we call the next filter in the chain to process in[] and
7581ad8388SMartin Matuska /// write its output to mf->buffer.
7681ad8388SMartin Matuska ///
7781ad8388SMartin Matuska /// This function must not be called once it has returned LZMA_STREAM_END.
7881ad8388SMartin Matuska ///
7981ad8388SMartin Matuska static lzma_ret
8053200025SRui Paulo fill_window(lzma_coder *coder, const lzma_allocator *allocator,
8153200025SRui Paulo 		const uint8_t *in, size_t *in_pos, size_t in_size,
8253200025SRui Paulo 		lzma_action action)
8381ad8388SMartin Matuska {
8481ad8388SMartin Matuska 	assert(coder->mf.read_pos <= coder->mf.write_pos);
8581ad8388SMartin Matuska 
8681ad8388SMartin Matuska 	// Move the sliding window if needed.
8781ad8388SMartin Matuska 	if (coder->mf.read_pos >= coder->mf.size - coder->mf.keep_size_after)
8881ad8388SMartin Matuska 		move_window(&coder->mf);
8981ad8388SMartin Matuska 
9081ad8388SMartin Matuska 	// Maybe this is ugly, but lzma_mf uses uint32_t for most things
9181ad8388SMartin Matuska 	// (which I find cleanest), but we need size_t here when filling
9281ad8388SMartin Matuska 	// the history window.
9381ad8388SMartin Matuska 	size_t write_pos = coder->mf.write_pos;
9481ad8388SMartin Matuska 	lzma_ret ret;
9581ad8388SMartin Matuska 	if (coder->next.code == NULL) {
9681ad8388SMartin Matuska 		// Not using a filter, simply memcpy() as much as possible.
9781ad8388SMartin Matuska 		lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
9881ad8388SMartin Matuska 				&write_pos, coder->mf.size);
9981ad8388SMartin Matuska 
10081ad8388SMartin Matuska 		ret = action != LZMA_RUN && *in_pos == in_size
10181ad8388SMartin Matuska 				? LZMA_STREAM_END : LZMA_OK;
10281ad8388SMartin Matuska 
10381ad8388SMartin Matuska 	} else {
10481ad8388SMartin Matuska 		ret = coder->next.code(coder->next.coder, allocator,
10581ad8388SMartin Matuska 				in, in_pos, in_size,
10681ad8388SMartin Matuska 				coder->mf.buffer, &write_pos,
10781ad8388SMartin Matuska 				coder->mf.size, action);
10881ad8388SMartin Matuska 	}
10981ad8388SMartin Matuska 
11081ad8388SMartin Matuska 	coder->mf.write_pos = write_pos;
11181ad8388SMartin Matuska 
112342bcb12SXin LI 	// Silence Valgrind. lzma_memcmplen() can read extra bytes
113342bcb12SXin LI 	// and Valgrind will give warnings if those bytes are uninitialized
114342bcb12SXin LI 	// because Valgrind cannot see that the values of the uninitialized
115342bcb12SXin LI 	// bytes are eventually ignored.
116342bcb12SXin LI 	memzero(coder->mf.buffer + write_pos, LZMA_MEMCMPLEN_EXTRA);
117342bcb12SXin LI 
11881ad8388SMartin Matuska 	// If end of stream has been reached or flushing completed, we allow
11981ad8388SMartin Matuska 	// the encoder to process all the input (that is, read_pos is allowed
12081ad8388SMartin Matuska 	// to reach write_pos). Otherwise we keep keep_size_after bytes
12181ad8388SMartin Matuska 	// available as prebuffer.
12281ad8388SMartin Matuska 	if (ret == LZMA_STREAM_END) {
12381ad8388SMartin Matuska 		assert(*in_pos == in_size);
12481ad8388SMartin Matuska 		ret = LZMA_OK;
12581ad8388SMartin Matuska 		coder->mf.action = action;
12681ad8388SMartin Matuska 		coder->mf.read_limit = coder->mf.write_pos;
12781ad8388SMartin Matuska 
12881ad8388SMartin Matuska 	} else if (coder->mf.write_pos > coder->mf.keep_size_after) {
12981ad8388SMartin Matuska 		// This needs to be done conditionally, because if we got
13081ad8388SMartin Matuska 		// only little new input, there may be too little input
13181ad8388SMartin Matuska 		// to do any encoding yet.
13281ad8388SMartin Matuska 		coder->mf.read_limit = coder->mf.write_pos
13381ad8388SMartin Matuska 				- coder->mf.keep_size_after;
13481ad8388SMartin Matuska 	}
13581ad8388SMartin Matuska 
13681ad8388SMartin Matuska 	// Restart the match finder after finished LZMA_SYNC_FLUSH.
13781ad8388SMartin Matuska 	if (coder->mf.pending > 0
13881ad8388SMartin Matuska 			&& coder->mf.read_pos < coder->mf.read_limit) {
13981ad8388SMartin Matuska 		// Match finder may update coder->pending and expects it to
14081ad8388SMartin Matuska 		// start from zero, so use a temporary variable.
141fe50a38eSXin LI 		const uint32_t pending = coder->mf.pending;
14281ad8388SMartin Matuska 		coder->mf.pending = 0;
14381ad8388SMartin Matuska 
14481ad8388SMartin Matuska 		// Rewind read_pos so that the match finder can hash
14581ad8388SMartin Matuska 		// the pending bytes.
14681ad8388SMartin Matuska 		assert(coder->mf.read_pos >= pending);
14781ad8388SMartin Matuska 		coder->mf.read_pos -= pending;
14881ad8388SMartin Matuska 
14981ad8388SMartin Matuska 		// Call the skip function directly instead of using
15081ad8388SMartin Matuska 		// mf_skip(), since we don't want to touch mf->read_ahead.
15181ad8388SMartin Matuska 		coder->mf.skip(&coder->mf, pending);
15281ad8388SMartin Matuska 	}
15381ad8388SMartin Matuska 
15481ad8388SMartin Matuska 	return ret;
15581ad8388SMartin Matuska }
15681ad8388SMartin Matuska 
15781ad8388SMartin Matuska 
15881ad8388SMartin Matuska static lzma_ret
1591456f0f9SXin LI lz_encode(void *coder_ptr, const lzma_allocator *allocator,
16081ad8388SMartin Matuska 		const uint8_t *restrict in, size_t *restrict in_pos,
16181ad8388SMartin Matuska 		size_t in_size,
16281ad8388SMartin Matuska 		uint8_t *restrict out, size_t *restrict out_pos,
16381ad8388SMartin Matuska 		size_t out_size, lzma_action action)
16481ad8388SMartin Matuska {
1651456f0f9SXin LI 	lzma_coder *coder = coder_ptr;
1661456f0f9SXin LI 
16781ad8388SMartin Matuska 	while (*out_pos < out_size
16881ad8388SMartin Matuska 			&& (*in_pos < in_size || action != LZMA_RUN)) {
16981ad8388SMartin Matuska 		// Read more data to coder->mf.buffer if needed.
17081ad8388SMartin Matuska 		if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
17181ad8388SMartin Matuska 				>= coder->mf.read_limit)
17281ad8388SMartin Matuska 			return_if_error(fill_window(coder, allocator,
17381ad8388SMartin Matuska 					in, in_pos, in_size, action));
17481ad8388SMartin Matuska 
17581ad8388SMartin Matuska 		// Encode
17681ad8388SMartin Matuska 		const lzma_ret ret = coder->lz.code(coder->lz.coder,
17781ad8388SMartin Matuska 				&coder->mf, out, out_pos, out_size);
17881ad8388SMartin Matuska 		if (ret != LZMA_OK) {
17981ad8388SMartin Matuska 			// Setting this to LZMA_RUN for cases when we are
18081ad8388SMartin Matuska 			// flushing. It doesn't matter when finishing or if
18181ad8388SMartin Matuska 			// an error occurred.
18281ad8388SMartin Matuska 			coder->mf.action = LZMA_RUN;
18381ad8388SMartin Matuska 			return ret;
18481ad8388SMartin Matuska 		}
18581ad8388SMartin Matuska 	}
18681ad8388SMartin Matuska 
18781ad8388SMartin Matuska 	return LZMA_OK;
18881ad8388SMartin Matuska }
18981ad8388SMartin Matuska 
19081ad8388SMartin Matuska 
19181ad8388SMartin Matuska static bool
19253200025SRui Paulo lz_encoder_prepare(lzma_mf *mf, const lzma_allocator *allocator,
19381ad8388SMartin Matuska 		const lzma_lz_options *lz_options)
19481ad8388SMartin Matuska {
19581ad8388SMartin Matuska 	// For now, the dictionary size is limited to 1.5 GiB. This may grow
19681ad8388SMartin Matuska 	// in the future if needed, but it needs a little more work than just
19781ad8388SMartin Matuska 	// changing this check.
1985ffb19acSXin LI 	if (!IS_ENC_DICT_SIZE_VALID(lz_options->dict_size)
19981ad8388SMartin Matuska 			|| lz_options->nice_len > lz_options->match_len_max)
20081ad8388SMartin Matuska 		return true;
20181ad8388SMartin Matuska 
20281ad8388SMartin Matuska 	mf->keep_size_before = lz_options->before_size + lz_options->dict_size;
20381ad8388SMartin Matuska 
20481ad8388SMartin Matuska 	mf->keep_size_after = lz_options->after_size
20581ad8388SMartin Matuska 			+ lz_options->match_len_max;
20681ad8388SMartin Matuska 
20781ad8388SMartin Matuska 	// To avoid constant memmove()s, allocate some extra space. Since
20881ad8388SMartin Matuska 	// memmove()s become more expensive when the size of the buffer
20981ad8388SMartin Matuska 	// increases, we reserve more space when a large dictionary is
21081ad8388SMartin Matuska 	// used to make the memmove() calls rarer.
21181ad8388SMartin Matuska 	//
21281ad8388SMartin Matuska 	// This works with dictionaries up to about 3 GiB. If bigger
21381ad8388SMartin Matuska 	// dictionary is wanted, some extra work is needed:
21481ad8388SMartin Matuska 	//   - Several variables in lzma_mf have to be changed from uint32_t
21581ad8388SMartin Matuska 	//     to size_t.
21681ad8388SMartin Matuska 	//   - Memory usage calculation needs something too, e.g. use uint64_t
21781ad8388SMartin Matuska 	//     for mf->size.
21881ad8388SMartin Matuska 	uint32_t reserve = lz_options->dict_size / 2;
21981ad8388SMartin Matuska 	if (reserve > (UINT32_C(1) << 30))
22081ad8388SMartin Matuska 		reserve /= 2;
22181ad8388SMartin Matuska 
22281ad8388SMartin Matuska 	reserve += (lz_options->before_size + lz_options->match_len_max
22381ad8388SMartin Matuska 			+ lz_options->after_size) / 2 + (UINT32_C(1) << 19);
22481ad8388SMartin Matuska 
22581ad8388SMartin Matuska 	const uint32_t old_size = mf->size;
22681ad8388SMartin Matuska 	mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
22781ad8388SMartin Matuska 
22881ad8388SMartin Matuska 	// Deallocate the old history buffer if it exists but has different
22981ad8388SMartin Matuska 	// size than what is needed now.
23081ad8388SMartin Matuska 	if (mf->buffer != NULL && old_size != mf->size) {
23181ad8388SMartin Matuska 		lzma_free(mf->buffer, allocator);
23281ad8388SMartin Matuska 		mf->buffer = NULL;
23381ad8388SMartin Matuska 	}
23481ad8388SMartin Matuska 
23581ad8388SMartin Matuska 	// Match finder options
23681ad8388SMartin Matuska 	mf->match_len_max = lz_options->match_len_max;
23781ad8388SMartin Matuska 	mf->nice_len = lz_options->nice_len;
23881ad8388SMartin Matuska 
23981ad8388SMartin Matuska 	// cyclic_size has to stay smaller than 2 Gi. Note that this doesn't
24081ad8388SMartin Matuska 	// mean limiting dictionary size to less than 2 GiB. With a match
24181ad8388SMartin Matuska 	// finder that uses multibyte resolution (hashes start at e.g. every
24281ad8388SMartin Matuska 	// fourth byte), cyclic_size would stay below 2 Gi even when
24381ad8388SMartin Matuska 	// dictionary size is greater than 2 GiB.
24481ad8388SMartin Matuska 	//
24581ad8388SMartin Matuska 	// It would be possible to allow cyclic_size >= 2 Gi, but then we
24681ad8388SMartin Matuska 	// would need to be careful to use 64-bit types in various places
24781ad8388SMartin Matuska 	// (size_t could do since we would need bigger than 32-bit address
24881ad8388SMartin Matuska 	// space anyway). It would also require either zeroing a multigigabyte
24981ad8388SMartin Matuska 	// buffer at initialization (waste of time and RAM) or allow
25081ad8388SMartin Matuska 	// normalization in lz_encoder_mf.c to access uninitialized
25181ad8388SMartin Matuska 	// memory to keep the code simpler. The current way is simple and
25281ad8388SMartin Matuska 	// still allows pretty big dictionaries, so I don't expect these
25381ad8388SMartin Matuska 	// limits to change.
25481ad8388SMartin Matuska 	mf->cyclic_size = lz_options->dict_size + 1;
25581ad8388SMartin Matuska 
25681ad8388SMartin Matuska 	// Validate the match finder ID and setup the function pointers.
25781ad8388SMartin Matuska 	switch (lz_options->match_finder) {
25881ad8388SMartin Matuska #ifdef HAVE_MF_HC3
25981ad8388SMartin Matuska 	case LZMA_MF_HC3:
26081ad8388SMartin Matuska 		mf->find = &lzma_mf_hc3_find;
26181ad8388SMartin Matuska 		mf->skip = &lzma_mf_hc3_skip;
26281ad8388SMartin Matuska 		break;
26381ad8388SMartin Matuska #endif
26481ad8388SMartin Matuska #ifdef HAVE_MF_HC4
26581ad8388SMartin Matuska 	case LZMA_MF_HC4:
26681ad8388SMartin Matuska 		mf->find = &lzma_mf_hc4_find;
26781ad8388SMartin Matuska 		mf->skip = &lzma_mf_hc4_skip;
26881ad8388SMartin Matuska 		break;
26981ad8388SMartin Matuska #endif
27081ad8388SMartin Matuska #ifdef HAVE_MF_BT2
27181ad8388SMartin Matuska 	case LZMA_MF_BT2:
27281ad8388SMartin Matuska 		mf->find = &lzma_mf_bt2_find;
27381ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt2_skip;
27481ad8388SMartin Matuska 		break;
27581ad8388SMartin Matuska #endif
27681ad8388SMartin Matuska #ifdef HAVE_MF_BT3
27781ad8388SMartin Matuska 	case LZMA_MF_BT3:
27881ad8388SMartin Matuska 		mf->find = &lzma_mf_bt3_find;
27981ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt3_skip;
28081ad8388SMartin Matuska 		break;
28181ad8388SMartin Matuska #endif
28281ad8388SMartin Matuska #ifdef HAVE_MF_BT4
28381ad8388SMartin Matuska 	case LZMA_MF_BT4:
28481ad8388SMartin Matuska 		mf->find = &lzma_mf_bt4_find;
28581ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt4_skip;
28681ad8388SMartin Matuska 		break;
28781ad8388SMartin Matuska #endif
28881ad8388SMartin Matuska 
28981ad8388SMartin Matuska 	default:
29081ad8388SMartin Matuska 		return true;
29181ad8388SMartin Matuska 	}
29281ad8388SMartin Matuska 
29373ed8e77SXin LI 	// Calculate the sizes of mf->hash and mf->son.
29473ed8e77SXin LI 	//
29573ed8e77SXin LI 	// NOTE: Since 5.3.5beta the LZMA encoder ensures that nice_len
29673ed8e77SXin LI 	// is big enough for the selected match finder. This makes it
29773ed8e77SXin LI 	// easier for applications as nice_len = 2 will always be accepted
29873ed8e77SXin LI 	// even though the effective value can be slightly bigger.
29973ed8e77SXin LI 	const uint32_t hash_bytes
30073ed8e77SXin LI 			= mf_get_hash_bytes(lz_options->match_finder);
30173ed8e77SXin LI 	assert(hash_bytes <= mf->nice_len);
30281ad8388SMartin Matuska 
30381ad8388SMartin Matuska 	const bool is_bt = (lz_options->match_finder & 0x10) != 0;
30481ad8388SMartin Matuska 	uint32_t hs;
30581ad8388SMartin Matuska 
30681ad8388SMartin Matuska 	if (hash_bytes == 2) {
30781ad8388SMartin Matuska 		hs = 0xFFFF;
30881ad8388SMartin Matuska 	} else {
30981ad8388SMartin Matuska 		// Round dictionary size up to the next 2^n - 1 so it can
31081ad8388SMartin Matuska 		// be used as a hash mask.
31181ad8388SMartin Matuska 		hs = lz_options->dict_size - 1;
31281ad8388SMartin Matuska 		hs |= hs >> 1;
31381ad8388SMartin Matuska 		hs |= hs >> 2;
31481ad8388SMartin Matuska 		hs |= hs >> 4;
31581ad8388SMartin Matuska 		hs |= hs >> 8;
31681ad8388SMartin Matuska 		hs >>= 1;
31781ad8388SMartin Matuska 		hs |= 0xFFFF;
31881ad8388SMartin Matuska 
31981ad8388SMartin Matuska 		if (hs > (UINT32_C(1) << 24)) {
32081ad8388SMartin Matuska 			if (hash_bytes == 3)
32181ad8388SMartin Matuska 				hs = (UINT32_C(1) << 24) - 1;
32281ad8388SMartin Matuska 			else
32381ad8388SMartin Matuska 				hs >>= 1;
32481ad8388SMartin Matuska 		}
32581ad8388SMartin Matuska 	}
32681ad8388SMartin Matuska 
32781ad8388SMartin Matuska 	mf->hash_mask = hs;
32881ad8388SMartin Matuska 
32981ad8388SMartin Matuska 	++hs;
33081ad8388SMartin Matuska 	if (hash_bytes > 2)
33181ad8388SMartin Matuska 		hs += HASH_2_SIZE;
33281ad8388SMartin Matuska 	if (hash_bytes > 3)
33381ad8388SMartin Matuska 		hs += HASH_3_SIZE;
33481ad8388SMartin Matuska /*
33581ad8388SMartin Matuska 	No match finder uses this at the moment.
33681ad8388SMartin Matuska 	if (mf->hash_bytes > 4)
33781ad8388SMartin Matuska 		hs += HASH_4_SIZE;
33881ad8388SMartin Matuska */
33981ad8388SMartin Matuska 
34053200025SRui Paulo 	const uint32_t old_hash_count = mf->hash_count;
34153200025SRui Paulo 	const uint32_t old_sons_count = mf->sons_count;
34253200025SRui Paulo 	mf->hash_count = hs;
34381ad8388SMartin Matuska 	mf->sons_count = mf->cyclic_size;
34481ad8388SMartin Matuska 	if (is_bt)
34581ad8388SMartin Matuska 		mf->sons_count *= 2;
34681ad8388SMartin Matuska 
34781ad8388SMartin Matuska 	// Deallocate the old hash array if it exists and has different size
34881ad8388SMartin Matuska 	// than what is needed now.
34953200025SRui Paulo 	if (old_hash_count != mf->hash_count
35053200025SRui Paulo 			|| old_sons_count != mf->sons_count) {
35181ad8388SMartin Matuska 		lzma_free(mf->hash, allocator);
35281ad8388SMartin Matuska 		mf->hash = NULL;
35353200025SRui Paulo 
35453200025SRui Paulo 		lzma_free(mf->son, allocator);
35553200025SRui Paulo 		mf->son = NULL;
35681ad8388SMartin Matuska 	}
35781ad8388SMartin Matuska 
35881ad8388SMartin Matuska 	// Maximum number of match finder cycles
35981ad8388SMartin Matuska 	mf->depth = lz_options->depth;
36081ad8388SMartin Matuska 	if (mf->depth == 0) {
361e0f0e66dSMartin Matuska 		if (is_bt)
362e0f0e66dSMartin Matuska 			mf->depth = 16 + mf->nice_len / 2;
363e0f0e66dSMartin Matuska 		else
364e0f0e66dSMartin Matuska 			mf->depth = 4 + mf->nice_len / 4;
36581ad8388SMartin Matuska 	}
36681ad8388SMartin Matuska 
36781ad8388SMartin Matuska 	return false;
36881ad8388SMartin Matuska }
36981ad8388SMartin Matuska 
37081ad8388SMartin Matuska 
37181ad8388SMartin Matuska static bool
37253200025SRui Paulo lz_encoder_init(lzma_mf *mf, const lzma_allocator *allocator,
37381ad8388SMartin Matuska 		const lzma_lz_options *lz_options)
37481ad8388SMartin Matuska {
37581ad8388SMartin Matuska 	// Allocate the history buffer.
37681ad8388SMartin Matuska 	if (mf->buffer == NULL) {
37753200025SRui Paulo 		// lzma_memcmplen() is used for the dictionary buffer
37853200025SRui Paulo 		// so we need to allocate a few extra bytes to prevent
37953200025SRui Paulo 		// it from reading past the end of the buffer.
38053200025SRui Paulo 		mf->buffer = lzma_alloc(mf->size + LZMA_MEMCMPLEN_EXTRA,
38153200025SRui Paulo 				allocator);
38281ad8388SMartin Matuska 		if (mf->buffer == NULL)
38381ad8388SMartin Matuska 			return true;
38453200025SRui Paulo 
38553200025SRui Paulo 		// Keep Valgrind happy with lzma_memcmplen() and initialize
38653200025SRui Paulo 		// the extra bytes whose value may get read but which will
38753200025SRui Paulo 		// effectively get ignored.
38853200025SRui Paulo 		memzero(mf->buffer + mf->size, LZMA_MEMCMPLEN_EXTRA);
38981ad8388SMartin Matuska 	}
39081ad8388SMartin Matuska 
39181ad8388SMartin Matuska 	// Use cyclic_size as initial mf->offset. This allows
39281ad8388SMartin Matuska 	// avoiding a few branches in the match finders. The downside is
39381ad8388SMartin Matuska 	// that match finder needs to be normalized more often, which may
39481ad8388SMartin Matuska 	// hurt performance with huge dictionaries.
39581ad8388SMartin Matuska 	mf->offset = mf->cyclic_size;
39681ad8388SMartin Matuska 	mf->read_pos = 0;
39781ad8388SMartin Matuska 	mf->read_ahead = 0;
39881ad8388SMartin Matuska 	mf->read_limit = 0;
39981ad8388SMartin Matuska 	mf->write_pos = 0;
40081ad8388SMartin Matuska 	mf->pending = 0;
40181ad8388SMartin Matuska 
40281ad8388SMartin Matuska #if UINT32_MAX >= SIZE_MAX / 4
40381ad8388SMartin Matuska 	// Check for integer overflow. (Huge dictionaries are not
40481ad8388SMartin Matuska 	// possible on 32-bit CPU.)
40553200025SRui Paulo 	if (mf->hash_count > SIZE_MAX / sizeof(uint32_t)
40653200025SRui Paulo 			|| mf->sons_count > SIZE_MAX / sizeof(uint32_t))
40781ad8388SMartin Matuska 		return true;
40881ad8388SMartin Matuska #endif
40981ad8388SMartin Matuska 
41053200025SRui Paulo 	// Allocate and initialize the hash table. Since EMPTY_HASH_VALUE
41153200025SRui Paulo 	// is zero, we can use lzma_alloc_zero() or memzero() for mf->hash.
41253200025SRui Paulo 	//
41353200025SRui Paulo 	// We don't need to initialize mf->son, but not doing that may
41453200025SRui Paulo 	// make Valgrind complain in normalization (see normalize() in
41553200025SRui Paulo 	// lz_encoder_mf.c). Skipping the initialization is *very* good
41653200025SRui Paulo 	// when big dictionary is used but only small amount of data gets
41753200025SRui Paulo 	// actually compressed: most of the mf->son won't get actually
41853200025SRui Paulo 	// allocated by the kernel, so we avoid wasting RAM and improve
41953200025SRui Paulo 	// initialization speed a lot.
42081ad8388SMartin Matuska 	if (mf->hash == NULL) {
42153200025SRui Paulo 		mf->hash = lzma_alloc_zero(mf->hash_count * sizeof(uint32_t),
42281ad8388SMartin Matuska 				allocator);
42353200025SRui Paulo 		mf->son = lzma_alloc(mf->sons_count * sizeof(uint32_t),
42453200025SRui Paulo 				allocator);
42553200025SRui Paulo 
42653200025SRui Paulo 		if (mf->hash == NULL || mf->son == NULL) {
42753200025SRui Paulo 			lzma_free(mf->hash, allocator);
42853200025SRui Paulo 			mf->hash = NULL;
42953200025SRui Paulo 
43053200025SRui Paulo 			lzma_free(mf->son, allocator);
43153200025SRui Paulo 			mf->son = NULL;
43253200025SRui Paulo 
43381ad8388SMartin Matuska 			return true;
43481ad8388SMartin Matuska 		}
43553200025SRui Paulo 	} else {
43681ad8388SMartin Matuska /*
43753200025SRui Paulo 		for (uint32_t i = 0; i < mf->hash_count; ++i)
43881ad8388SMartin Matuska 			mf->hash[i] = EMPTY_HASH_VALUE;
43981ad8388SMartin Matuska */
44053200025SRui Paulo 		memzero(mf->hash, mf->hash_count * sizeof(uint32_t));
44153200025SRui Paulo 	}
44281ad8388SMartin Matuska 
44353200025SRui Paulo 	mf->cyclic_pos = 0;
44481ad8388SMartin Matuska 
44581ad8388SMartin Matuska 	// Handle preset dictionary.
44681ad8388SMartin Matuska 	if (lz_options->preset_dict != NULL
44781ad8388SMartin Matuska 			&& lz_options->preset_dict_size > 0) {
44881ad8388SMartin Matuska 		// If the preset dictionary is bigger than the actual
44981ad8388SMartin Matuska 		// dictionary, use only the tail.
450e0f0e66dSMartin Matuska 		mf->write_pos = my_min(lz_options->preset_dict_size, mf->size);
45181ad8388SMartin Matuska 		memcpy(mf->buffer, lz_options->preset_dict
45281ad8388SMartin Matuska 				+ lz_options->preset_dict_size - mf->write_pos,
45381ad8388SMartin Matuska 				mf->write_pos);
45481ad8388SMartin Matuska 		mf->action = LZMA_SYNC_FLUSH;
45581ad8388SMartin Matuska 		mf->skip(mf, mf->write_pos);
45681ad8388SMartin Matuska 	}
45781ad8388SMartin Matuska 
45881ad8388SMartin Matuska 	mf->action = LZMA_RUN;
45981ad8388SMartin Matuska 
46081ad8388SMartin Matuska 	return false;
46181ad8388SMartin Matuska }
46281ad8388SMartin Matuska 
46381ad8388SMartin Matuska 
46481ad8388SMartin Matuska extern uint64_t
46581ad8388SMartin Matuska lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
46681ad8388SMartin Matuska {
46781ad8388SMartin Matuska 	// Old buffers must not exist when calling lz_encoder_prepare().
46881ad8388SMartin Matuska 	lzma_mf mf = {
46981ad8388SMartin Matuska 		.buffer = NULL,
47081ad8388SMartin Matuska 		.hash = NULL,
47153200025SRui Paulo 		.son = NULL,
47253200025SRui Paulo 		.hash_count = 0,
473e0f0e66dSMartin Matuska 		.sons_count = 0,
47481ad8388SMartin Matuska 	};
47581ad8388SMartin Matuska 
47681ad8388SMartin Matuska 	// Setup the size information into mf.
47781ad8388SMartin Matuska 	if (lz_encoder_prepare(&mf, NULL, lz_options))
47881ad8388SMartin Matuska 		return UINT64_MAX;
47981ad8388SMartin Matuska 
48081ad8388SMartin Matuska 	// Calculate the memory usage.
48153200025SRui Paulo 	return ((uint64_t)(mf.hash_count) + mf.sons_count) * sizeof(uint32_t)
48253200025SRui Paulo 			+ mf.size + sizeof(lzma_coder);
48381ad8388SMartin Matuska }
48481ad8388SMartin Matuska 
48581ad8388SMartin Matuska 
48681ad8388SMartin Matuska static void
4871456f0f9SXin LI lz_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
48881ad8388SMartin Matuska {
4891456f0f9SXin LI 	lzma_coder *coder = coder_ptr;
4901456f0f9SXin LI 
49181ad8388SMartin Matuska 	lzma_next_end(&coder->next, allocator);
49281ad8388SMartin Matuska 
49353200025SRui Paulo 	lzma_free(coder->mf.son, allocator);
49481ad8388SMartin Matuska 	lzma_free(coder->mf.hash, allocator);
49581ad8388SMartin Matuska 	lzma_free(coder->mf.buffer, allocator);
49681ad8388SMartin Matuska 
49781ad8388SMartin Matuska 	if (coder->lz.end != NULL)
49881ad8388SMartin Matuska 		coder->lz.end(coder->lz.coder, allocator);
49981ad8388SMartin Matuska 	else
50081ad8388SMartin Matuska 		lzma_free(coder->lz.coder, allocator);
50181ad8388SMartin Matuska 
50281ad8388SMartin Matuska 	lzma_free(coder, allocator);
50381ad8388SMartin Matuska 	return;
50481ad8388SMartin Matuska }
50581ad8388SMartin Matuska 
50681ad8388SMartin Matuska 
50781ad8388SMartin Matuska static lzma_ret
5081456f0f9SXin LI lz_encoder_update(void *coder_ptr, const lzma_allocator *allocator,
509e24134bcSMartin Matuska 		const lzma_filter *filters_null lzma_attribute((__unused__)),
51081ad8388SMartin Matuska 		const lzma_filter *reversed_filters)
51181ad8388SMartin Matuska {
5121456f0f9SXin LI 	lzma_coder *coder = coder_ptr;
5131456f0f9SXin LI 
51481ad8388SMartin Matuska 	if (coder->lz.options_update == NULL)
51581ad8388SMartin Matuska 		return LZMA_PROG_ERROR;
51681ad8388SMartin Matuska 
51781ad8388SMartin Matuska 	return_if_error(coder->lz.options_update(
51881ad8388SMartin Matuska 			coder->lz.coder, reversed_filters));
51981ad8388SMartin Matuska 
52081ad8388SMartin Matuska 	return lzma_next_filter_update(
52181ad8388SMartin Matuska 			&coder->next, allocator, reversed_filters + 1);
52281ad8388SMartin Matuska }
52381ad8388SMartin Matuska 
52481ad8388SMartin Matuska 
52573ed8e77SXin LI static lzma_ret
52673ed8e77SXin LI lz_encoder_set_out_limit(void *coder_ptr, uint64_t *uncomp_size,
52773ed8e77SXin LI 		uint64_t out_limit)
52873ed8e77SXin LI {
52973ed8e77SXin LI 	lzma_coder *coder = coder_ptr;
53073ed8e77SXin LI 
53173ed8e77SXin LI 	// This is supported only if there are no other filters chained.
53273ed8e77SXin LI 	if (coder->next.code == NULL && coder->lz.set_out_limit != NULL)
53373ed8e77SXin LI 		return coder->lz.set_out_limit(
53473ed8e77SXin LI 				coder->lz.coder, uncomp_size, out_limit);
53573ed8e77SXin LI 
53673ed8e77SXin LI 	return LZMA_OPTIONS_ERROR;
53773ed8e77SXin LI }
53873ed8e77SXin LI 
53973ed8e77SXin LI 
54081ad8388SMartin Matuska extern lzma_ret
54153200025SRui Paulo lzma_lz_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
54281ad8388SMartin Matuska 		const lzma_filter_info *filters,
54381ad8388SMartin Matuska 		lzma_ret (*lz_init)(lzma_lz_encoder *lz,
54473ed8e77SXin LI 			const lzma_allocator *allocator,
54573ed8e77SXin LI 			lzma_vli id, const void *options,
54681ad8388SMartin Matuska 			lzma_lz_options *lz_options))
54781ad8388SMartin Matuska {
54873ed8e77SXin LI #if defined(HAVE_SMALL) && !defined(HAVE_FUNC_ATTRIBUTE_CONSTRUCTOR)
549*3b35e7eeSXin LI 	// The CRC32 table must be initialized.
55081ad8388SMartin Matuska 	lzma_crc32_init();
55181ad8388SMartin Matuska #endif
55281ad8388SMartin Matuska 
55381ad8388SMartin Matuska 	// Allocate and initialize the base data structure.
5541456f0f9SXin LI 	lzma_coder *coder = next->coder;
5551456f0f9SXin LI 	if (coder == NULL) {
5561456f0f9SXin LI 		coder = lzma_alloc(sizeof(lzma_coder), allocator);
5571456f0f9SXin LI 		if (coder == NULL)
55881ad8388SMartin Matuska 			return LZMA_MEM_ERROR;
55981ad8388SMartin Matuska 
5601456f0f9SXin LI 		next->coder = coder;
56181ad8388SMartin Matuska 		next->code = &lz_encode;
56281ad8388SMartin Matuska 		next->end = &lz_encoder_end;
56381ad8388SMartin Matuska 		next->update = &lz_encoder_update;
56473ed8e77SXin LI 		next->set_out_limit = &lz_encoder_set_out_limit;
56581ad8388SMartin Matuska 
5661456f0f9SXin LI 		coder->lz.coder = NULL;
5671456f0f9SXin LI 		coder->lz.code = NULL;
5681456f0f9SXin LI 		coder->lz.end = NULL;
569*3b35e7eeSXin LI 		coder->lz.options_update = NULL;
570*3b35e7eeSXin LI 		coder->lz.set_out_limit = NULL;
57181ad8388SMartin Matuska 
5721456f0f9SXin LI 		// mf.size is initialized to silence Valgrind
5731456f0f9SXin LI 		// when used on optimized binaries (GCC may reorder
5741456f0f9SXin LI 		// code in a way that Valgrind gets unhappy).
5751456f0f9SXin LI 		coder->mf.buffer = NULL;
5761456f0f9SXin LI 		coder->mf.size = 0;
5771456f0f9SXin LI 		coder->mf.hash = NULL;
5781456f0f9SXin LI 		coder->mf.son = NULL;
5791456f0f9SXin LI 		coder->mf.hash_count = 0;
5801456f0f9SXin LI 		coder->mf.sons_count = 0;
58181ad8388SMartin Matuska 
5821456f0f9SXin LI 		coder->next = LZMA_NEXT_CODER_INIT;
58381ad8388SMartin Matuska 	}
58481ad8388SMartin Matuska 
58581ad8388SMartin Matuska 	// Initialize the LZ-based encoder.
58681ad8388SMartin Matuska 	lzma_lz_options lz_options;
5871456f0f9SXin LI 	return_if_error(lz_init(&coder->lz, allocator,
58873ed8e77SXin LI 			filters[0].id, filters[0].options, &lz_options));
58981ad8388SMartin Matuska 
5901456f0f9SXin LI 	// Setup the size information into coder->mf and deallocate
59181ad8388SMartin Matuska 	// old buffers if they have wrong size.
5921456f0f9SXin LI 	if (lz_encoder_prepare(&coder->mf, allocator, &lz_options))
59381ad8388SMartin Matuska 		return LZMA_OPTIONS_ERROR;
59481ad8388SMartin Matuska 
59581ad8388SMartin Matuska 	// Allocate new buffers if needed, and do the rest of
59681ad8388SMartin Matuska 	// the initialization.
5971456f0f9SXin LI 	if (lz_encoder_init(&coder->mf, allocator, &lz_options))
59881ad8388SMartin Matuska 		return LZMA_MEM_ERROR;
59981ad8388SMartin Matuska 
60081ad8388SMartin Matuska 	// Initialize the next filter in the chain, if any.
6011456f0f9SXin LI 	return lzma_next_filter_init(&coder->next, allocator, filters + 1);
60281ad8388SMartin Matuska }
60381ad8388SMartin Matuska 
60481ad8388SMartin Matuska 
60581ad8388SMartin Matuska extern LZMA_API(lzma_bool)
60681ad8388SMartin Matuska lzma_mf_is_supported(lzma_match_finder mf)
60781ad8388SMartin Matuska {
6089e6bbe47SXin LI 	switch (mf) {
60981ad8388SMartin Matuska #ifdef HAVE_MF_HC3
6109e6bbe47SXin LI 	case LZMA_MF_HC3:
6119e6bbe47SXin LI 		return true;
61281ad8388SMartin Matuska #endif
61381ad8388SMartin Matuska #ifdef HAVE_MF_HC4
6149e6bbe47SXin LI 	case LZMA_MF_HC4:
6159e6bbe47SXin LI 		return true;
61681ad8388SMartin Matuska #endif
61781ad8388SMartin Matuska #ifdef HAVE_MF_BT2
6189e6bbe47SXin LI 	case LZMA_MF_BT2:
6199e6bbe47SXin LI 		return true;
62081ad8388SMartin Matuska #endif
62181ad8388SMartin Matuska #ifdef HAVE_MF_BT3
6229e6bbe47SXin LI 	case LZMA_MF_BT3:
6239e6bbe47SXin LI 		return true;
62481ad8388SMartin Matuska #endif
62581ad8388SMartin Matuska #ifdef HAVE_MF_BT4
6269e6bbe47SXin LI 	case LZMA_MF_BT4:
6279e6bbe47SXin LI 		return true;
62881ad8388SMartin Matuska #endif
6299e6bbe47SXin LI 	default:
6309e6bbe47SXin LI 		return false;
6319e6bbe47SXin LI 	}
63281ad8388SMartin Matuska }
633