xref: /freebsd/contrib/xz/src/liblzma/lz/lz_encoder.c (revision e0f0e66dfeda9df4f104f48bd42d5a28d8ae631e)
181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
281ad8388SMartin Matuska //
381ad8388SMartin Matuska /// \file       lz_encoder.c
481ad8388SMartin Matuska /// \brief      LZ in window
581ad8388SMartin Matuska ///
681ad8388SMartin Matuska //  Authors:    Igor Pavlov
781ad8388SMartin Matuska //              Lasse Collin
881ad8388SMartin Matuska //
981ad8388SMartin Matuska //  This file has been put into the public domain.
1081ad8388SMartin Matuska //  You can do whatever you want with this file.
1181ad8388SMartin Matuska //
1281ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1381ad8388SMartin Matuska 
1481ad8388SMartin Matuska #include "lz_encoder.h"
1581ad8388SMartin Matuska #include "lz_encoder_hash.h"
1681ad8388SMartin Matuska 
1781ad8388SMartin Matuska // See lz_encoder_hash.h. This is a bit hackish but avoids making
1881ad8388SMartin Matuska // endianness a conditional in makefiles.
1981ad8388SMartin Matuska #if defined(WORDS_BIGENDIAN) && !defined(HAVE_SMALL)
2081ad8388SMartin Matuska #	include "lz_encoder_hash_table.h"
2181ad8388SMartin Matuska #endif
2281ad8388SMartin Matuska 
2381ad8388SMartin Matuska 
2481ad8388SMartin Matuska struct lzma_coder_s {
2581ad8388SMartin Matuska 	/// LZ-based encoder e.g. LZMA
2681ad8388SMartin Matuska 	lzma_lz_encoder lz;
2781ad8388SMartin Matuska 
2881ad8388SMartin Matuska 	/// History buffer and match finder
2981ad8388SMartin Matuska 	lzma_mf mf;
3081ad8388SMartin Matuska 
3181ad8388SMartin Matuska 	/// Next coder in the chain
3281ad8388SMartin Matuska 	lzma_next_coder next;
3381ad8388SMartin Matuska };
3481ad8388SMartin Matuska 
3581ad8388SMartin Matuska 
3681ad8388SMartin Matuska /// \brief      Moves the data in the input window to free space for new data
3781ad8388SMartin Matuska ///
3881ad8388SMartin Matuska /// mf->buffer is a sliding input window, which keeps mf->keep_size_before
3981ad8388SMartin Matuska /// bytes of input history available all the time. Now and then we need to
4081ad8388SMartin Matuska /// "slide" the buffer to make space for the new data to the end of the
4181ad8388SMartin Matuska /// buffer. At the same time, data older than keep_size_before is dropped.
4281ad8388SMartin Matuska ///
4381ad8388SMartin Matuska static void
4481ad8388SMartin Matuska move_window(lzma_mf *mf)
4581ad8388SMartin Matuska {
4681ad8388SMartin Matuska 	// Align the move to a multiple of 16 bytes. Some LZ-based encoders
4781ad8388SMartin Matuska 	// like LZMA use the lowest bits of mf->read_pos to know the
4881ad8388SMartin Matuska 	// alignment of the uncompressed data. We also get better speed
4981ad8388SMartin Matuska 	// for memmove() with aligned buffers.
5081ad8388SMartin Matuska 	assert(mf->read_pos > mf->keep_size_before);
5181ad8388SMartin Matuska 	const uint32_t move_offset
5281ad8388SMartin Matuska 		= (mf->read_pos - mf->keep_size_before) & ~UINT32_C(15);
5381ad8388SMartin Matuska 
5481ad8388SMartin Matuska 	assert(mf->write_pos > move_offset);
5581ad8388SMartin Matuska 	const size_t move_size = mf->write_pos - move_offset;
5681ad8388SMartin Matuska 
5781ad8388SMartin Matuska 	assert(move_offset + move_size <= mf->size);
5881ad8388SMartin Matuska 
5981ad8388SMartin Matuska 	memmove(mf->buffer, mf->buffer + move_offset, move_size);
6081ad8388SMartin Matuska 
6181ad8388SMartin Matuska 	mf->offset += move_offset;
6281ad8388SMartin Matuska 	mf->read_pos -= move_offset;
6381ad8388SMartin Matuska 	mf->read_limit -= move_offset;
6481ad8388SMartin Matuska 	mf->write_pos -= move_offset;
6581ad8388SMartin Matuska 
6681ad8388SMartin Matuska 	return;
6781ad8388SMartin Matuska }
6881ad8388SMartin Matuska 
6981ad8388SMartin Matuska 
7081ad8388SMartin Matuska /// \brief      Tries to fill the input window (mf->buffer)
7181ad8388SMartin Matuska ///
7281ad8388SMartin Matuska /// If we are the last encoder in the chain, our input data is in in[].
7381ad8388SMartin Matuska /// Otherwise we call the next filter in the chain to process in[] and
7481ad8388SMartin Matuska /// write its output to mf->buffer.
7581ad8388SMartin Matuska ///
7681ad8388SMartin Matuska /// This function must not be called once it has returned LZMA_STREAM_END.
7781ad8388SMartin Matuska ///
7881ad8388SMartin Matuska static lzma_ret
7981ad8388SMartin Matuska fill_window(lzma_coder *coder, lzma_allocator *allocator, const uint8_t *in,
8081ad8388SMartin Matuska 		size_t *in_pos, size_t in_size, lzma_action action)
8181ad8388SMartin Matuska {
8281ad8388SMartin Matuska 	assert(coder->mf.read_pos <= coder->mf.write_pos);
8381ad8388SMartin Matuska 
8481ad8388SMartin Matuska 	// Move the sliding window if needed.
8581ad8388SMartin Matuska 	if (coder->mf.read_pos >= coder->mf.size - coder->mf.keep_size_after)
8681ad8388SMartin Matuska 		move_window(&coder->mf);
8781ad8388SMartin Matuska 
8881ad8388SMartin Matuska 	// Maybe this is ugly, but lzma_mf uses uint32_t for most things
8981ad8388SMartin Matuska 	// (which I find cleanest), but we need size_t here when filling
9081ad8388SMartin Matuska 	// the history window.
9181ad8388SMartin Matuska 	size_t write_pos = coder->mf.write_pos;
9281ad8388SMartin Matuska 	lzma_ret ret;
9381ad8388SMartin Matuska 	if (coder->next.code == NULL) {
9481ad8388SMartin Matuska 		// Not using a filter, simply memcpy() as much as possible.
9581ad8388SMartin Matuska 		lzma_bufcpy(in, in_pos, in_size, coder->mf.buffer,
9681ad8388SMartin Matuska 				&write_pos, coder->mf.size);
9781ad8388SMartin Matuska 
9881ad8388SMartin Matuska 		ret = action != LZMA_RUN && *in_pos == in_size
9981ad8388SMartin Matuska 				? LZMA_STREAM_END : LZMA_OK;
10081ad8388SMartin Matuska 
10181ad8388SMartin Matuska 	} else {
10281ad8388SMartin Matuska 		ret = coder->next.code(coder->next.coder, allocator,
10381ad8388SMartin Matuska 				in, in_pos, in_size,
10481ad8388SMartin Matuska 				coder->mf.buffer, &write_pos,
10581ad8388SMartin Matuska 				coder->mf.size, action);
10681ad8388SMartin Matuska 	}
10781ad8388SMartin Matuska 
10881ad8388SMartin Matuska 	coder->mf.write_pos = write_pos;
10981ad8388SMartin Matuska 
11081ad8388SMartin Matuska 	// If end of stream has been reached or flushing completed, we allow
11181ad8388SMartin Matuska 	// the encoder to process all the input (that is, read_pos is allowed
11281ad8388SMartin Matuska 	// to reach write_pos). Otherwise we keep keep_size_after bytes
11381ad8388SMartin Matuska 	// available as prebuffer.
11481ad8388SMartin Matuska 	if (ret == LZMA_STREAM_END) {
11581ad8388SMartin Matuska 		assert(*in_pos == in_size);
11681ad8388SMartin Matuska 		ret = LZMA_OK;
11781ad8388SMartin Matuska 		coder->mf.action = action;
11881ad8388SMartin Matuska 		coder->mf.read_limit = coder->mf.write_pos;
11981ad8388SMartin Matuska 
12081ad8388SMartin Matuska 	} else if (coder->mf.write_pos > coder->mf.keep_size_after) {
12181ad8388SMartin Matuska 		// This needs to be done conditionally, because if we got
12281ad8388SMartin Matuska 		// only little new input, there may be too little input
12381ad8388SMartin Matuska 		// to do any encoding yet.
12481ad8388SMartin Matuska 		coder->mf.read_limit = coder->mf.write_pos
12581ad8388SMartin Matuska 				- coder->mf.keep_size_after;
12681ad8388SMartin Matuska 	}
12781ad8388SMartin Matuska 
12881ad8388SMartin Matuska 	// Restart the match finder after finished LZMA_SYNC_FLUSH.
12981ad8388SMartin Matuska 	if (coder->mf.pending > 0
13081ad8388SMartin Matuska 			&& coder->mf.read_pos < coder->mf.read_limit) {
13181ad8388SMartin Matuska 		// Match finder may update coder->pending and expects it to
13281ad8388SMartin Matuska 		// start from zero, so use a temporary variable.
13381ad8388SMartin Matuska 		const size_t pending = coder->mf.pending;
13481ad8388SMartin Matuska 		coder->mf.pending = 0;
13581ad8388SMartin Matuska 
13681ad8388SMartin Matuska 		// Rewind read_pos so that the match finder can hash
13781ad8388SMartin Matuska 		// the pending bytes.
13881ad8388SMartin Matuska 		assert(coder->mf.read_pos >= pending);
13981ad8388SMartin Matuska 		coder->mf.read_pos -= pending;
14081ad8388SMartin Matuska 
14181ad8388SMartin Matuska 		// Call the skip function directly instead of using
14281ad8388SMartin Matuska 		// mf_skip(), since we don't want to touch mf->read_ahead.
14381ad8388SMartin Matuska 		coder->mf.skip(&coder->mf, pending);
14481ad8388SMartin Matuska 	}
14581ad8388SMartin Matuska 
14681ad8388SMartin Matuska 	return ret;
14781ad8388SMartin Matuska }
14881ad8388SMartin Matuska 
14981ad8388SMartin Matuska 
15081ad8388SMartin Matuska static lzma_ret
15181ad8388SMartin Matuska lz_encode(lzma_coder *coder, lzma_allocator *allocator,
15281ad8388SMartin Matuska 		const uint8_t *restrict in, size_t *restrict in_pos,
15381ad8388SMartin Matuska 		size_t in_size,
15481ad8388SMartin Matuska 		uint8_t *restrict out, size_t *restrict out_pos,
15581ad8388SMartin Matuska 		size_t out_size, lzma_action action)
15681ad8388SMartin Matuska {
15781ad8388SMartin Matuska 	while (*out_pos < out_size
15881ad8388SMartin Matuska 			&& (*in_pos < in_size || action != LZMA_RUN)) {
15981ad8388SMartin Matuska 		// Read more data to coder->mf.buffer if needed.
16081ad8388SMartin Matuska 		if (coder->mf.action == LZMA_RUN && coder->mf.read_pos
16181ad8388SMartin Matuska 				>= coder->mf.read_limit)
16281ad8388SMartin Matuska 			return_if_error(fill_window(coder, allocator,
16381ad8388SMartin Matuska 					in, in_pos, in_size, action));
16481ad8388SMartin Matuska 
16581ad8388SMartin Matuska 		// Encode
16681ad8388SMartin Matuska 		const lzma_ret ret = coder->lz.code(coder->lz.coder,
16781ad8388SMartin Matuska 				&coder->mf, out, out_pos, out_size);
16881ad8388SMartin Matuska 		if (ret != LZMA_OK) {
16981ad8388SMartin Matuska 			// Setting this to LZMA_RUN for cases when we are
17081ad8388SMartin Matuska 			// flushing. It doesn't matter when finishing or if
17181ad8388SMartin Matuska 			// an error occurred.
17281ad8388SMartin Matuska 			coder->mf.action = LZMA_RUN;
17381ad8388SMartin Matuska 			return ret;
17481ad8388SMartin Matuska 		}
17581ad8388SMartin Matuska 	}
17681ad8388SMartin Matuska 
17781ad8388SMartin Matuska 	return LZMA_OK;
17881ad8388SMartin Matuska }
17981ad8388SMartin Matuska 
18081ad8388SMartin Matuska 
18181ad8388SMartin Matuska static bool
18281ad8388SMartin Matuska lz_encoder_prepare(lzma_mf *mf, lzma_allocator *allocator,
18381ad8388SMartin Matuska 		const lzma_lz_options *lz_options)
18481ad8388SMartin Matuska {
18581ad8388SMartin Matuska 	// For now, the dictionary size is limited to 1.5 GiB. This may grow
18681ad8388SMartin Matuska 	// in the future if needed, but it needs a little more work than just
18781ad8388SMartin Matuska 	// changing this check.
18881ad8388SMartin Matuska 	if (lz_options->dict_size < LZMA_DICT_SIZE_MIN
18981ad8388SMartin Matuska 			|| lz_options->dict_size
19081ad8388SMartin Matuska 				> (UINT32_C(1) << 30) + (UINT32_C(1) << 29)
19181ad8388SMartin Matuska 			|| lz_options->nice_len > lz_options->match_len_max)
19281ad8388SMartin Matuska 		return true;
19381ad8388SMartin Matuska 
19481ad8388SMartin Matuska 	mf->keep_size_before = lz_options->before_size + lz_options->dict_size;
19581ad8388SMartin Matuska 
19681ad8388SMartin Matuska 	mf->keep_size_after = lz_options->after_size
19781ad8388SMartin Matuska 			+ lz_options->match_len_max;
19881ad8388SMartin Matuska 
19981ad8388SMartin Matuska 	// To avoid constant memmove()s, allocate some extra space. Since
20081ad8388SMartin Matuska 	// memmove()s become more expensive when the size of the buffer
20181ad8388SMartin Matuska 	// increases, we reserve more space when a large dictionary is
20281ad8388SMartin Matuska 	// used to make the memmove() calls rarer.
20381ad8388SMartin Matuska 	//
20481ad8388SMartin Matuska 	// This works with dictionaries up to about 3 GiB. If bigger
20581ad8388SMartin Matuska 	// dictionary is wanted, some extra work is needed:
20681ad8388SMartin Matuska 	//   - Several variables in lzma_mf have to be changed from uint32_t
20781ad8388SMartin Matuska 	//     to size_t.
20881ad8388SMartin Matuska 	//   - Memory usage calculation needs something too, e.g. use uint64_t
20981ad8388SMartin Matuska 	//     for mf->size.
21081ad8388SMartin Matuska 	uint32_t reserve = lz_options->dict_size / 2;
21181ad8388SMartin Matuska 	if (reserve > (UINT32_C(1) << 30))
21281ad8388SMartin Matuska 		reserve /= 2;
21381ad8388SMartin Matuska 
21481ad8388SMartin Matuska 	reserve += (lz_options->before_size + lz_options->match_len_max
21581ad8388SMartin Matuska 			+ lz_options->after_size) / 2 + (UINT32_C(1) << 19);
21681ad8388SMartin Matuska 
21781ad8388SMartin Matuska 	const uint32_t old_size = mf->size;
21881ad8388SMartin Matuska 	mf->size = mf->keep_size_before + reserve + mf->keep_size_after;
21981ad8388SMartin Matuska 
22081ad8388SMartin Matuska 	// Deallocate the old history buffer if it exists but has different
22181ad8388SMartin Matuska 	// size than what is needed now.
22281ad8388SMartin Matuska 	if (mf->buffer != NULL && old_size != mf->size) {
22381ad8388SMartin Matuska 		lzma_free(mf->buffer, allocator);
22481ad8388SMartin Matuska 		mf->buffer = NULL;
22581ad8388SMartin Matuska 	}
22681ad8388SMartin Matuska 
22781ad8388SMartin Matuska 	// Match finder options
22881ad8388SMartin Matuska 	mf->match_len_max = lz_options->match_len_max;
22981ad8388SMartin Matuska 	mf->nice_len = lz_options->nice_len;
23081ad8388SMartin Matuska 
23181ad8388SMartin Matuska 	// cyclic_size has to stay smaller than 2 Gi. Note that this doesn't
23281ad8388SMartin Matuska 	// mean limiting dictionary size to less than 2 GiB. With a match
23381ad8388SMartin Matuska 	// finder that uses multibyte resolution (hashes start at e.g. every
23481ad8388SMartin Matuska 	// fourth byte), cyclic_size would stay below 2 Gi even when
23581ad8388SMartin Matuska 	// dictionary size is greater than 2 GiB.
23681ad8388SMartin Matuska 	//
23781ad8388SMartin Matuska 	// It would be possible to allow cyclic_size >= 2 Gi, but then we
23881ad8388SMartin Matuska 	// would need to be careful to use 64-bit types in various places
23981ad8388SMartin Matuska 	// (size_t could do since we would need bigger than 32-bit address
24081ad8388SMartin Matuska 	// space anyway). It would also require either zeroing a multigigabyte
24181ad8388SMartin Matuska 	// buffer at initialization (waste of time and RAM) or allow
24281ad8388SMartin Matuska 	// normalization in lz_encoder_mf.c to access uninitialized
24381ad8388SMartin Matuska 	// memory to keep the code simpler. The current way is simple and
24481ad8388SMartin Matuska 	// still allows pretty big dictionaries, so I don't expect these
24581ad8388SMartin Matuska 	// limits to change.
24681ad8388SMartin Matuska 	mf->cyclic_size = lz_options->dict_size + 1;
24781ad8388SMartin Matuska 
24881ad8388SMartin Matuska 	// Validate the match finder ID and setup the function pointers.
24981ad8388SMartin Matuska 	switch (lz_options->match_finder) {
25081ad8388SMartin Matuska #ifdef HAVE_MF_HC3
25181ad8388SMartin Matuska 	case LZMA_MF_HC3:
25281ad8388SMartin Matuska 		mf->find = &lzma_mf_hc3_find;
25381ad8388SMartin Matuska 		mf->skip = &lzma_mf_hc3_skip;
25481ad8388SMartin Matuska 		break;
25581ad8388SMartin Matuska #endif
25681ad8388SMartin Matuska #ifdef HAVE_MF_HC4
25781ad8388SMartin Matuska 	case LZMA_MF_HC4:
25881ad8388SMartin Matuska 		mf->find = &lzma_mf_hc4_find;
25981ad8388SMartin Matuska 		mf->skip = &lzma_mf_hc4_skip;
26081ad8388SMartin Matuska 		break;
26181ad8388SMartin Matuska #endif
26281ad8388SMartin Matuska #ifdef HAVE_MF_BT2
26381ad8388SMartin Matuska 	case LZMA_MF_BT2:
26481ad8388SMartin Matuska 		mf->find = &lzma_mf_bt2_find;
26581ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt2_skip;
26681ad8388SMartin Matuska 		break;
26781ad8388SMartin Matuska #endif
26881ad8388SMartin Matuska #ifdef HAVE_MF_BT3
26981ad8388SMartin Matuska 	case LZMA_MF_BT3:
27081ad8388SMartin Matuska 		mf->find = &lzma_mf_bt3_find;
27181ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt3_skip;
27281ad8388SMartin Matuska 		break;
27381ad8388SMartin Matuska #endif
27481ad8388SMartin Matuska #ifdef HAVE_MF_BT4
27581ad8388SMartin Matuska 	case LZMA_MF_BT4:
27681ad8388SMartin Matuska 		mf->find = &lzma_mf_bt4_find;
27781ad8388SMartin Matuska 		mf->skip = &lzma_mf_bt4_skip;
27881ad8388SMartin Matuska 		break;
27981ad8388SMartin Matuska #endif
28081ad8388SMartin Matuska 
28181ad8388SMartin Matuska 	default:
28281ad8388SMartin Matuska 		return true;
28381ad8388SMartin Matuska 	}
28481ad8388SMartin Matuska 
28581ad8388SMartin Matuska 	// Calculate the sizes of mf->hash and mf->son and check that
28681ad8388SMartin Matuska 	// nice_len is big enough for the selected match finder.
28781ad8388SMartin Matuska 	const uint32_t hash_bytes = lz_options->match_finder & 0x0F;
28881ad8388SMartin Matuska 	if (hash_bytes > mf->nice_len)
28981ad8388SMartin Matuska 		return true;
29081ad8388SMartin Matuska 
29181ad8388SMartin Matuska 	const bool is_bt = (lz_options->match_finder & 0x10) != 0;
29281ad8388SMartin Matuska 	uint32_t hs;
29381ad8388SMartin Matuska 
29481ad8388SMartin Matuska 	if (hash_bytes == 2) {
29581ad8388SMartin Matuska 		hs = 0xFFFF;
29681ad8388SMartin Matuska 	} else {
29781ad8388SMartin Matuska 		// Round dictionary size up to the next 2^n - 1 so it can
29881ad8388SMartin Matuska 		// be used as a hash mask.
29981ad8388SMartin Matuska 		hs = lz_options->dict_size - 1;
30081ad8388SMartin Matuska 		hs |= hs >> 1;
30181ad8388SMartin Matuska 		hs |= hs >> 2;
30281ad8388SMartin Matuska 		hs |= hs >> 4;
30381ad8388SMartin Matuska 		hs |= hs >> 8;
30481ad8388SMartin Matuska 		hs >>= 1;
30581ad8388SMartin Matuska 		hs |= 0xFFFF;
30681ad8388SMartin Matuska 
30781ad8388SMartin Matuska 		if (hs > (UINT32_C(1) << 24)) {
30881ad8388SMartin Matuska 			if (hash_bytes == 3)
30981ad8388SMartin Matuska 				hs = (UINT32_C(1) << 24) - 1;
31081ad8388SMartin Matuska 			else
31181ad8388SMartin Matuska 				hs >>= 1;
31281ad8388SMartin Matuska 		}
31381ad8388SMartin Matuska 	}
31481ad8388SMartin Matuska 
31581ad8388SMartin Matuska 	mf->hash_mask = hs;
31681ad8388SMartin Matuska 
31781ad8388SMartin Matuska 	++hs;
31881ad8388SMartin Matuska 	if (hash_bytes > 2)
31981ad8388SMartin Matuska 		hs += HASH_2_SIZE;
32081ad8388SMartin Matuska 	if (hash_bytes > 3)
32181ad8388SMartin Matuska 		hs += HASH_3_SIZE;
32281ad8388SMartin Matuska /*
32381ad8388SMartin Matuska 	No match finder uses this at the moment.
32481ad8388SMartin Matuska 	if (mf->hash_bytes > 4)
32581ad8388SMartin Matuska 		hs += HASH_4_SIZE;
32681ad8388SMartin Matuska */
32781ad8388SMartin Matuska 
32881ad8388SMartin Matuska 	// If the above code calculating hs is modified, make sure that
32981ad8388SMartin Matuska 	// this assertion stays valid (UINT32_MAX / 5 is not strictly the
33081ad8388SMartin Matuska 	// exact limit). If it doesn't, you need to calculate that
33181ad8388SMartin Matuska 	// hash_size_sum + sons_count cannot overflow.
33281ad8388SMartin Matuska 	assert(hs < UINT32_MAX / 5);
33381ad8388SMartin Matuska 
33481ad8388SMartin Matuska 	const uint32_t old_count = mf->hash_size_sum + mf->sons_count;
33581ad8388SMartin Matuska 	mf->hash_size_sum = hs;
33681ad8388SMartin Matuska 	mf->sons_count = mf->cyclic_size;
33781ad8388SMartin Matuska 	if (is_bt)
33881ad8388SMartin Matuska 		mf->sons_count *= 2;
33981ad8388SMartin Matuska 
34081ad8388SMartin Matuska 	const uint32_t new_count = mf->hash_size_sum + mf->sons_count;
34181ad8388SMartin Matuska 
34281ad8388SMartin Matuska 	// Deallocate the old hash array if it exists and has different size
34381ad8388SMartin Matuska 	// than what is needed now.
344*e0f0e66dSMartin Matuska 	if (old_count != new_count) {
34581ad8388SMartin Matuska 		lzma_free(mf->hash, allocator);
34681ad8388SMartin Matuska 		mf->hash = NULL;
34781ad8388SMartin Matuska 	}
34881ad8388SMartin Matuska 
34981ad8388SMartin Matuska 	// Maximum number of match finder cycles
35081ad8388SMartin Matuska 	mf->depth = lz_options->depth;
35181ad8388SMartin Matuska 	if (mf->depth == 0) {
352*e0f0e66dSMartin Matuska 		if (is_bt)
353*e0f0e66dSMartin Matuska 			mf->depth = 16 + mf->nice_len / 2;
354*e0f0e66dSMartin Matuska 		else
355*e0f0e66dSMartin Matuska 			mf->depth = 4 + mf->nice_len / 4;
35681ad8388SMartin Matuska 	}
35781ad8388SMartin Matuska 
35881ad8388SMartin Matuska 	return false;
35981ad8388SMartin Matuska }
36081ad8388SMartin Matuska 
36181ad8388SMartin Matuska 
36281ad8388SMartin Matuska static bool
36381ad8388SMartin Matuska lz_encoder_init(lzma_mf *mf, lzma_allocator *allocator,
36481ad8388SMartin Matuska 		const lzma_lz_options *lz_options)
36581ad8388SMartin Matuska {
36681ad8388SMartin Matuska 	// Allocate the history buffer.
36781ad8388SMartin Matuska 	if (mf->buffer == NULL) {
36881ad8388SMartin Matuska 		mf->buffer = lzma_alloc(mf->size, allocator);
36981ad8388SMartin Matuska 		if (mf->buffer == NULL)
37081ad8388SMartin Matuska 			return true;
37181ad8388SMartin Matuska 	}
37281ad8388SMartin Matuska 
37381ad8388SMartin Matuska 	// Use cyclic_size as initial mf->offset. This allows
37481ad8388SMartin Matuska 	// avoiding a few branches in the match finders. The downside is
37581ad8388SMartin Matuska 	// that match finder needs to be normalized more often, which may
37681ad8388SMartin Matuska 	// hurt performance with huge dictionaries.
37781ad8388SMartin Matuska 	mf->offset = mf->cyclic_size;
37881ad8388SMartin Matuska 	mf->read_pos = 0;
37981ad8388SMartin Matuska 	mf->read_ahead = 0;
38081ad8388SMartin Matuska 	mf->read_limit = 0;
38181ad8388SMartin Matuska 	mf->write_pos = 0;
38281ad8388SMartin Matuska 	mf->pending = 0;
38381ad8388SMartin Matuska 
38481ad8388SMartin Matuska 	// Allocate match finder's hash array.
38581ad8388SMartin Matuska 	const size_t alloc_count = mf->hash_size_sum + mf->sons_count;
38681ad8388SMartin Matuska 
38781ad8388SMartin Matuska #if UINT32_MAX >= SIZE_MAX / 4
38881ad8388SMartin Matuska 	// Check for integer overflow. (Huge dictionaries are not
38981ad8388SMartin Matuska 	// possible on 32-bit CPU.)
39081ad8388SMartin Matuska 	if (alloc_count > SIZE_MAX / sizeof(uint32_t))
39181ad8388SMartin Matuska 		return true;
39281ad8388SMartin Matuska #endif
39381ad8388SMartin Matuska 
39481ad8388SMartin Matuska 	if (mf->hash == NULL) {
39581ad8388SMartin Matuska 		mf->hash = lzma_alloc(alloc_count * sizeof(uint32_t),
39681ad8388SMartin Matuska 				allocator);
39781ad8388SMartin Matuska 		if (mf->hash == NULL)
39881ad8388SMartin Matuska 			return true;
39981ad8388SMartin Matuska 	}
40081ad8388SMartin Matuska 
40181ad8388SMartin Matuska 	mf->son = mf->hash + mf->hash_size_sum;
40281ad8388SMartin Matuska 	mf->cyclic_pos = 0;
40381ad8388SMartin Matuska 
40481ad8388SMartin Matuska 	// Initialize the hash table. Since EMPTY_HASH_VALUE is zero, we
40581ad8388SMartin Matuska 	// can use memset().
40681ad8388SMartin Matuska /*
40781ad8388SMartin Matuska 	for (uint32_t i = 0; i < hash_size_sum; ++i)
40881ad8388SMartin Matuska 		mf->hash[i] = EMPTY_HASH_VALUE;
40981ad8388SMartin Matuska */
41081ad8388SMartin Matuska 	memzero(mf->hash, (size_t)(mf->hash_size_sum) * sizeof(uint32_t));
41181ad8388SMartin Matuska 
41281ad8388SMartin Matuska 	// We don't need to initialize mf->son, but not doing that will
41381ad8388SMartin Matuska 	// make Valgrind complain in normalization (see normalize() in
41481ad8388SMartin Matuska 	// lz_encoder_mf.c).
41581ad8388SMartin Matuska 	//
41681ad8388SMartin Matuska 	// Skipping this initialization is *very* good when big dictionary is
41781ad8388SMartin Matuska 	// used but only small amount of data gets actually compressed: most
41881ad8388SMartin Matuska 	// of the mf->hash won't get actually allocated by the kernel, so
41981ad8388SMartin Matuska 	// we avoid wasting RAM and improve initialization speed a lot.
42081ad8388SMartin Matuska 	//memzero(mf->son, (size_t)(mf->sons_count) * sizeof(uint32_t));
42181ad8388SMartin Matuska 
42281ad8388SMartin Matuska 	// Handle preset dictionary.
42381ad8388SMartin Matuska 	if (lz_options->preset_dict != NULL
42481ad8388SMartin Matuska 			&& lz_options->preset_dict_size > 0) {
42581ad8388SMartin Matuska 		// If the preset dictionary is bigger than the actual
42681ad8388SMartin Matuska 		// dictionary, use only the tail.
427*e0f0e66dSMartin Matuska 		mf->write_pos = my_min(lz_options->preset_dict_size, mf->size);
42881ad8388SMartin Matuska 		memcpy(mf->buffer, lz_options->preset_dict
42981ad8388SMartin Matuska 				+ lz_options->preset_dict_size - mf->write_pos,
43081ad8388SMartin Matuska 				mf->write_pos);
43181ad8388SMartin Matuska 		mf->action = LZMA_SYNC_FLUSH;
43281ad8388SMartin Matuska 		mf->skip(mf, mf->write_pos);
43381ad8388SMartin Matuska 	}
43481ad8388SMartin Matuska 
43581ad8388SMartin Matuska 	mf->action = LZMA_RUN;
43681ad8388SMartin Matuska 
43781ad8388SMartin Matuska 	return false;
43881ad8388SMartin Matuska }
43981ad8388SMartin Matuska 
44081ad8388SMartin Matuska 
44181ad8388SMartin Matuska extern uint64_t
44281ad8388SMartin Matuska lzma_lz_encoder_memusage(const lzma_lz_options *lz_options)
44381ad8388SMartin Matuska {
44481ad8388SMartin Matuska 	// Old buffers must not exist when calling lz_encoder_prepare().
44581ad8388SMartin Matuska 	lzma_mf mf = {
44681ad8388SMartin Matuska 		.buffer = NULL,
44781ad8388SMartin Matuska 		.hash = NULL,
448*e0f0e66dSMartin Matuska 		.hash_size_sum = 0,
449*e0f0e66dSMartin Matuska 		.sons_count = 0,
45081ad8388SMartin Matuska 	};
45181ad8388SMartin Matuska 
45281ad8388SMartin Matuska 	// Setup the size information into mf.
45381ad8388SMartin Matuska 	if (lz_encoder_prepare(&mf, NULL, lz_options))
45481ad8388SMartin Matuska 		return UINT64_MAX;
45581ad8388SMartin Matuska 
45681ad8388SMartin Matuska 	// Calculate the memory usage.
45781ad8388SMartin Matuska 	return (uint64_t)(mf.hash_size_sum + mf.sons_count)
45881ad8388SMartin Matuska 				* sizeof(uint32_t)
45981ad8388SMartin Matuska 			+ (uint64_t)(mf.size) + sizeof(lzma_coder);
46081ad8388SMartin Matuska }
46181ad8388SMartin Matuska 
46281ad8388SMartin Matuska 
46381ad8388SMartin Matuska static void
46481ad8388SMartin Matuska lz_encoder_end(lzma_coder *coder, lzma_allocator *allocator)
46581ad8388SMartin Matuska {
46681ad8388SMartin Matuska 	lzma_next_end(&coder->next, allocator);
46781ad8388SMartin Matuska 
46881ad8388SMartin Matuska 	lzma_free(coder->mf.hash, allocator);
46981ad8388SMartin Matuska 	lzma_free(coder->mf.buffer, allocator);
47081ad8388SMartin Matuska 
47181ad8388SMartin Matuska 	if (coder->lz.end != NULL)
47281ad8388SMartin Matuska 		coder->lz.end(coder->lz.coder, allocator);
47381ad8388SMartin Matuska 	else
47481ad8388SMartin Matuska 		lzma_free(coder->lz.coder, allocator);
47581ad8388SMartin Matuska 
47681ad8388SMartin Matuska 	lzma_free(coder, allocator);
47781ad8388SMartin Matuska 	return;
47881ad8388SMartin Matuska }
47981ad8388SMartin Matuska 
48081ad8388SMartin Matuska 
48181ad8388SMartin Matuska static lzma_ret
48281ad8388SMartin Matuska lz_encoder_update(lzma_coder *coder, lzma_allocator *allocator,
48381ad8388SMartin Matuska 		const lzma_filter *filters_null lzma_attribute((unused)),
48481ad8388SMartin Matuska 		const lzma_filter *reversed_filters)
48581ad8388SMartin Matuska {
48681ad8388SMartin Matuska 	if (coder->lz.options_update == NULL)
48781ad8388SMartin Matuska 		return LZMA_PROG_ERROR;
48881ad8388SMartin Matuska 
48981ad8388SMartin Matuska 	return_if_error(coder->lz.options_update(
49081ad8388SMartin Matuska 			coder->lz.coder, reversed_filters));
49181ad8388SMartin Matuska 
49281ad8388SMartin Matuska 	return lzma_next_filter_update(
49381ad8388SMartin Matuska 			&coder->next, allocator, reversed_filters + 1);
49481ad8388SMartin Matuska }
49581ad8388SMartin Matuska 
49681ad8388SMartin Matuska 
49781ad8388SMartin Matuska extern lzma_ret
49881ad8388SMartin Matuska lzma_lz_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
49981ad8388SMartin Matuska 		const lzma_filter_info *filters,
50081ad8388SMartin Matuska 		lzma_ret (*lz_init)(lzma_lz_encoder *lz,
50181ad8388SMartin Matuska 			lzma_allocator *allocator, const void *options,
50281ad8388SMartin Matuska 			lzma_lz_options *lz_options))
50381ad8388SMartin Matuska {
50481ad8388SMartin Matuska #ifdef HAVE_SMALL
50581ad8388SMartin Matuska 	// We need that the CRC32 table has been initialized.
50681ad8388SMartin Matuska 	lzma_crc32_init();
50781ad8388SMartin Matuska #endif
50881ad8388SMartin Matuska 
50981ad8388SMartin Matuska 	// Allocate and initialize the base data structure.
51081ad8388SMartin Matuska 	if (next->coder == NULL) {
51181ad8388SMartin Matuska 		next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
51281ad8388SMartin Matuska 		if (next->coder == NULL)
51381ad8388SMartin Matuska 			return LZMA_MEM_ERROR;
51481ad8388SMartin Matuska 
51581ad8388SMartin Matuska 		next->code = &lz_encode;
51681ad8388SMartin Matuska 		next->end = &lz_encoder_end;
51781ad8388SMartin Matuska 		next->update = &lz_encoder_update;
51881ad8388SMartin Matuska 
51981ad8388SMartin Matuska 		next->coder->lz.coder = NULL;
52081ad8388SMartin Matuska 		next->coder->lz.code = NULL;
52181ad8388SMartin Matuska 		next->coder->lz.end = NULL;
52281ad8388SMartin Matuska 
52381ad8388SMartin Matuska 		next->coder->mf.buffer = NULL;
52481ad8388SMartin Matuska 		next->coder->mf.hash = NULL;
525*e0f0e66dSMartin Matuska 		next->coder->mf.hash_size_sum = 0;
526*e0f0e66dSMartin Matuska 		next->coder->mf.sons_count = 0;
52781ad8388SMartin Matuska 
52881ad8388SMartin Matuska 		next->coder->next = LZMA_NEXT_CODER_INIT;
52981ad8388SMartin Matuska 	}
53081ad8388SMartin Matuska 
53181ad8388SMartin Matuska 	// Initialize the LZ-based encoder.
53281ad8388SMartin Matuska 	lzma_lz_options lz_options;
53381ad8388SMartin Matuska 	return_if_error(lz_init(&next->coder->lz, allocator,
53481ad8388SMartin Matuska 			filters[0].options, &lz_options));
53581ad8388SMartin Matuska 
53681ad8388SMartin Matuska 	// Setup the size information into next->coder->mf and deallocate
53781ad8388SMartin Matuska 	// old buffers if they have wrong size.
53881ad8388SMartin Matuska 	if (lz_encoder_prepare(&next->coder->mf, allocator, &lz_options))
53981ad8388SMartin Matuska 		return LZMA_OPTIONS_ERROR;
54081ad8388SMartin Matuska 
54181ad8388SMartin Matuska 	// Allocate new buffers if needed, and do the rest of
54281ad8388SMartin Matuska 	// the initialization.
54381ad8388SMartin Matuska 	if (lz_encoder_init(&next->coder->mf, allocator, &lz_options))
54481ad8388SMartin Matuska 		return LZMA_MEM_ERROR;
54581ad8388SMartin Matuska 
54681ad8388SMartin Matuska 	// Initialize the next filter in the chain, if any.
54781ad8388SMartin Matuska 	return lzma_next_filter_init(&next->coder->next, allocator,
54881ad8388SMartin Matuska 			filters + 1);
54981ad8388SMartin Matuska }
55081ad8388SMartin Matuska 
55181ad8388SMartin Matuska 
55281ad8388SMartin Matuska extern LZMA_API(lzma_bool)
55381ad8388SMartin Matuska lzma_mf_is_supported(lzma_match_finder mf)
55481ad8388SMartin Matuska {
55581ad8388SMartin Matuska 	bool ret = false;
55681ad8388SMartin Matuska 
55781ad8388SMartin Matuska #ifdef HAVE_MF_HC3
55881ad8388SMartin Matuska 	if (mf == LZMA_MF_HC3)
55981ad8388SMartin Matuska 		ret = true;
56081ad8388SMartin Matuska #endif
56181ad8388SMartin Matuska 
56281ad8388SMartin Matuska #ifdef HAVE_MF_HC4
56381ad8388SMartin Matuska 	if (mf == LZMA_MF_HC4)
56481ad8388SMartin Matuska 		ret = true;
56581ad8388SMartin Matuska #endif
56681ad8388SMartin Matuska 
56781ad8388SMartin Matuska #ifdef HAVE_MF_BT2
56881ad8388SMartin Matuska 	if (mf == LZMA_MF_BT2)
56981ad8388SMartin Matuska 		ret = true;
57081ad8388SMartin Matuska #endif
57181ad8388SMartin Matuska 
57281ad8388SMartin Matuska #ifdef HAVE_MF_BT3
57381ad8388SMartin Matuska 	if (mf == LZMA_MF_BT3)
57481ad8388SMartin Matuska 		ret = true;
57581ad8388SMartin Matuska #endif
57681ad8388SMartin Matuska 
57781ad8388SMartin Matuska #ifdef HAVE_MF_BT4
57881ad8388SMartin Matuska 	if (mf == LZMA_MF_BT4)
57981ad8388SMartin Matuska 		ret = true;
58081ad8388SMartin Matuska #endif
58181ad8388SMartin Matuska 
58281ad8388SMartin Matuska 	return ret;
58381ad8388SMartin Matuska }
584