xref: /minix3/external/public-domain/xz/dist/src/liblzma/lz/lz_encoder_mf.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
15a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
25a645f22SBen Gras //
35a645f22SBen Gras /// \file       lz_encoder_mf.c
45a645f22SBen Gras /// \brief      Match finders
55a645f22SBen Gras ///
65a645f22SBen Gras //  Authors:    Igor Pavlov
75a645f22SBen Gras //              Lasse Collin
85a645f22SBen Gras //
95a645f22SBen Gras //  This file has been put into the public domain.
105a645f22SBen Gras //  You can do whatever you want with this file.
115a645f22SBen Gras //
125a645f22SBen Gras ///////////////////////////////////////////////////////////////////////////////
135a645f22SBen Gras 
145a645f22SBen Gras #include "lz_encoder.h"
155a645f22SBen Gras #include "lz_encoder_hash.h"
16*0a6a1f1dSLionel Sambuc #include "memcmplen.h"
175a645f22SBen Gras 
185a645f22SBen Gras 
195a645f22SBen Gras /// \brief      Find matches starting from the current byte
205a645f22SBen Gras ///
215a645f22SBen Gras /// \return     The length of the longest match found
225a645f22SBen Gras extern uint32_t
lzma_mf_find(lzma_mf * mf,uint32_t * count_ptr,lzma_match * matches)235a645f22SBen Gras lzma_mf_find(lzma_mf *mf, uint32_t *count_ptr, lzma_match *matches)
245a645f22SBen Gras {
255a645f22SBen Gras 	// Call the match finder. It returns the number of length-distance
265a645f22SBen Gras 	// pairs found.
275a645f22SBen Gras 	// FIXME: Minimum count is zero, what _exactly_ is the maximum?
285a645f22SBen Gras 	const uint32_t count = mf->find(mf, matches);
295a645f22SBen Gras 
305a645f22SBen Gras 	// Length of the longest match; assume that no matches were found
315a645f22SBen Gras 	// and thus the maximum length is zero.
325a645f22SBen Gras 	uint32_t len_best = 0;
335a645f22SBen Gras 
345a645f22SBen Gras 	if (count > 0) {
355a645f22SBen Gras #ifndef NDEBUG
365a645f22SBen Gras 		// Validate the matches.
375a645f22SBen Gras 		for (uint32_t i = 0; i < count; ++i) {
385a645f22SBen Gras 			assert(matches[i].len <= mf->nice_len);
395a645f22SBen Gras 			assert(matches[i].dist < mf->read_pos);
405a645f22SBen Gras 			assert(memcmp(mf_ptr(mf) - 1,
415a645f22SBen Gras 				mf_ptr(mf) - matches[i].dist - 2,
425a645f22SBen Gras 				matches[i].len) == 0);
435a645f22SBen Gras 		}
445a645f22SBen Gras #endif
455a645f22SBen Gras 
465a645f22SBen Gras 		// The last used element in the array contains
475a645f22SBen Gras 		// the longest match.
485a645f22SBen Gras 		len_best = matches[count - 1].len;
495a645f22SBen Gras 
505a645f22SBen Gras 		// If a match of maximum search length was found, try to
515a645f22SBen Gras 		// extend the match to maximum possible length.
525a645f22SBen Gras 		if (len_best == mf->nice_len) {
535a645f22SBen Gras 			// The limit for the match length is either the
545a645f22SBen Gras 			// maximum match length supported by the LZ-based
555a645f22SBen Gras 			// encoder or the number of bytes left in the
565a645f22SBen Gras 			// dictionary, whichever is smaller.
575a645f22SBen Gras 			uint32_t limit = mf_avail(mf) + 1;
585a645f22SBen Gras 			if (limit > mf->match_len_max)
595a645f22SBen Gras 				limit = mf->match_len_max;
605a645f22SBen Gras 
615a645f22SBen Gras 			// Pointer to the byte we just ran through
625a645f22SBen Gras 			// the match finder.
635a645f22SBen Gras 			const uint8_t *p1 = mf_ptr(mf) - 1;
645a645f22SBen Gras 
655a645f22SBen Gras 			// Pointer to the beginning of the match. We need -1
665a645f22SBen Gras 			// here because the match distances are zero based.
675a645f22SBen Gras 			const uint8_t *p2 = p1 - matches[count - 1].dist - 1;
685a645f22SBen Gras 
69*0a6a1f1dSLionel Sambuc 			len_best = lzma_memcmplen(p1, p2, len_best, limit);
705a645f22SBen Gras 		}
715a645f22SBen Gras 	}
725a645f22SBen Gras 
735a645f22SBen Gras 	*count_ptr = count;
745a645f22SBen Gras 
755a645f22SBen Gras 	// Finally update the read position to indicate that match finder was
765a645f22SBen Gras 	// run for this dictionary offset.
775a645f22SBen Gras 	++mf->read_ahead;
785a645f22SBen Gras 
795a645f22SBen Gras 	return len_best;
805a645f22SBen Gras }
815a645f22SBen Gras 
825a645f22SBen Gras 
835a645f22SBen Gras /// Hash value to indicate unused element in the hash. Since we start the
845a645f22SBen Gras /// positions from dict_size + 1, zero is always too far to qualify
855a645f22SBen Gras /// as usable match position.
865a645f22SBen Gras #define EMPTY_HASH_VALUE 0
875a645f22SBen Gras 
885a645f22SBen Gras 
895a645f22SBen Gras /// Normalization must be done when lzma_mf.offset + lzma_mf.read_pos
905a645f22SBen Gras /// reaches MUST_NORMALIZE_POS.
915a645f22SBen Gras #define MUST_NORMALIZE_POS UINT32_MAX
925a645f22SBen Gras 
935a645f22SBen Gras 
945a645f22SBen Gras /// \brief      Normalizes hash values
955a645f22SBen Gras ///
965a645f22SBen Gras /// The hash arrays store positions of match candidates. The positions are
975a645f22SBen Gras /// relative to an arbitrary offset that is not the same as the absolute
985a645f22SBen Gras /// offset in the input stream. The relative position of the current byte
995a645f22SBen Gras /// is lzma_mf.offset + lzma_mf.read_pos. The distances of the matches are
1005a645f22SBen Gras /// the differences of the current read position and the position found from
1015a645f22SBen Gras /// the hash.
1025a645f22SBen Gras ///
1035a645f22SBen Gras /// To prevent integer overflows of the offsets stored in the hash arrays,
1045a645f22SBen Gras /// we need to "normalize" the stored values now and then. During the
1055a645f22SBen Gras /// normalization, we drop values that indicate distance greater than the
1065a645f22SBen Gras /// dictionary size, thus making space for new values.
1075a645f22SBen Gras static void
normalize(lzma_mf * mf)1085a645f22SBen Gras normalize(lzma_mf *mf)
1095a645f22SBen Gras {
1105a645f22SBen Gras 	assert(mf->read_pos + mf->offset == MUST_NORMALIZE_POS);
1115a645f22SBen Gras 
1125a645f22SBen Gras 	// In future we may not want to touch the lowest bits, because there
1135a645f22SBen Gras 	// may be match finders that use larger resolution than one byte.
1145a645f22SBen Gras 	const uint32_t subvalue
1155a645f22SBen Gras 			= (MUST_NORMALIZE_POS - mf->cyclic_size);
1165a645f22SBen Gras 				// & (~(UINT32_C(1) << 10) - 1);
1175a645f22SBen Gras 
118*0a6a1f1dSLionel Sambuc 	for (uint32_t i = 0; i < mf->hash_count; ++i) {
1195a645f22SBen Gras 		// If the distance is greater than the dictionary size,
1205a645f22SBen Gras 		// we can simply mark the hash element as empty.
121*0a6a1f1dSLionel Sambuc 		if (mf->hash[i] <= subvalue)
122*0a6a1f1dSLionel Sambuc 			mf->hash[i] = EMPTY_HASH_VALUE;
1235a645f22SBen Gras 		else
124*0a6a1f1dSLionel Sambuc 			mf->hash[i] -= subvalue;
125*0a6a1f1dSLionel Sambuc 	}
126*0a6a1f1dSLionel Sambuc 
127*0a6a1f1dSLionel Sambuc 	for (uint32_t i = 0; i < mf->sons_count; ++i) {
128*0a6a1f1dSLionel Sambuc 		// Do the same for mf->son.
129*0a6a1f1dSLionel Sambuc 		//
130*0a6a1f1dSLionel Sambuc 		// NOTE: There may be uninitialized elements in mf->son.
131*0a6a1f1dSLionel Sambuc 		// Valgrind may complain that the "if" below depends on
132*0a6a1f1dSLionel Sambuc 		// an uninitialized value. In this case it is safe to ignore
133*0a6a1f1dSLionel Sambuc 		// the warning. See also the comments in lz_encoder_init()
134*0a6a1f1dSLionel Sambuc 		// in lz_encoder.c.
135*0a6a1f1dSLionel Sambuc 		if (mf->son[i] <= subvalue)
136*0a6a1f1dSLionel Sambuc 			mf->son[i] = EMPTY_HASH_VALUE;
137*0a6a1f1dSLionel Sambuc 		else
138*0a6a1f1dSLionel Sambuc 			mf->son[i] -= subvalue;
1395a645f22SBen Gras 	}
1405a645f22SBen Gras 
1415a645f22SBen Gras 	// Update offset to match the new locations.
1425a645f22SBen Gras 	mf->offset -= subvalue;
1435a645f22SBen Gras 
1445a645f22SBen Gras 	return;
1455a645f22SBen Gras }
1465a645f22SBen Gras 
1475a645f22SBen Gras 
1485a645f22SBen Gras /// Mark the current byte as processed from point of view of the match finder.
1495a645f22SBen Gras static void
move_pos(lzma_mf * mf)1505a645f22SBen Gras move_pos(lzma_mf *mf)
1515a645f22SBen Gras {
1525a645f22SBen Gras 	if (++mf->cyclic_pos == mf->cyclic_size)
1535a645f22SBen Gras 		mf->cyclic_pos = 0;
1545a645f22SBen Gras 
1555a645f22SBen Gras 	++mf->read_pos;
1565a645f22SBen Gras 	assert(mf->read_pos <= mf->write_pos);
1575a645f22SBen Gras 
1585a645f22SBen Gras 	if (unlikely(mf->read_pos + mf->offset == UINT32_MAX))
1595a645f22SBen Gras 		normalize(mf);
1605a645f22SBen Gras }
1615a645f22SBen Gras 
1625a645f22SBen Gras 
1635a645f22SBen Gras /// When flushing, we cannot run the match finder unless there is nice_len
1645a645f22SBen Gras /// bytes available in the dictionary. Instead, we skip running the match
1655a645f22SBen Gras /// finder (indicating that no match was found), and count how many bytes we
1665a645f22SBen Gras /// have ignored this way.
1675a645f22SBen Gras ///
1685a645f22SBen Gras /// When new data is given after the flushing was completed, the match finder
1695a645f22SBen Gras /// is restarted by rewinding mf->read_pos backwards by mf->pending. Then
1705a645f22SBen Gras /// the missed bytes are added to the hash using the match finder's skip
1715a645f22SBen Gras /// function (with small amount of input, it may start using mf->pending
1725a645f22SBen Gras /// again if flushing).
1735a645f22SBen Gras ///
1745a645f22SBen Gras /// Due to this rewinding, we don't touch cyclic_pos or test for
1755a645f22SBen Gras /// normalization. It will be done when the match finder's skip function
1765a645f22SBen Gras /// catches up after a flush.
1775a645f22SBen Gras static void
move_pending(lzma_mf * mf)1785a645f22SBen Gras move_pending(lzma_mf *mf)
1795a645f22SBen Gras {
1805a645f22SBen Gras 	++mf->read_pos;
1815a645f22SBen Gras 	assert(mf->read_pos <= mf->write_pos);
1825a645f22SBen Gras 	++mf->pending;
1835a645f22SBen Gras }
1845a645f22SBen Gras 
1855a645f22SBen Gras 
1865a645f22SBen Gras /// Calculate len_limit and determine if there is enough input to run
1875a645f22SBen Gras /// the actual match finder code. Sets up "cur" and "pos". This macro
1885a645f22SBen Gras /// is used by all find functions and binary tree skip functions. Hash
1895a645f22SBen Gras /// chain skip function doesn't need len_limit so a simpler code is used
1905a645f22SBen Gras /// in them.
1915a645f22SBen Gras #define header(is_bt, len_min, ret_op) \
1925a645f22SBen Gras 	uint32_t len_limit = mf_avail(mf); \
1935a645f22SBen Gras 	if (mf->nice_len <= len_limit) { \
1945a645f22SBen Gras 		len_limit = mf->nice_len; \
1955a645f22SBen Gras 	} else if (len_limit < (len_min) \
1965a645f22SBen Gras 			|| (is_bt && mf->action == LZMA_SYNC_FLUSH)) { \
1975a645f22SBen Gras 		assert(mf->action != LZMA_RUN); \
1985a645f22SBen Gras 		move_pending(mf); \
1995a645f22SBen Gras 		ret_op; \
2005a645f22SBen Gras 	} \
2015a645f22SBen Gras 	const uint8_t *cur = mf_ptr(mf); \
2025a645f22SBen Gras 	const uint32_t pos = mf->read_pos + mf->offset
2035a645f22SBen Gras 
2045a645f22SBen Gras 
2055a645f22SBen Gras /// Header for find functions. "return 0" indicates that zero matches
2065a645f22SBen Gras /// were found.
2075a645f22SBen Gras #define header_find(is_bt, len_min) \
2085a645f22SBen Gras 	header(is_bt, len_min, return 0); \
2095a645f22SBen Gras 	uint32_t matches_count = 0
2105a645f22SBen Gras 
2115a645f22SBen Gras 
2125a645f22SBen Gras /// Header for a loop in a skip function. "continue" tells to skip the rest
2135a645f22SBen Gras /// of the code in the loop.
2145a645f22SBen Gras #define header_skip(is_bt, len_min) \
2155a645f22SBen Gras 	header(is_bt, len_min, continue)
2165a645f22SBen Gras 
2175a645f22SBen Gras 
2185a645f22SBen Gras /// Calls hc_find_func() or bt_find_func() and calculates the total number
2195a645f22SBen Gras /// of matches found. Updates the dictionary position and returns the number
2205a645f22SBen Gras /// of matches found.
2215a645f22SBen Gras #define call_find(func, len_best) \
2225a645f22SBen Gras do { \
2235a645f22SBen Gras 	matches_count = func(len_limit, pos, cur, cur_match, mf->depth, \
2245a645f22SBen Gras 				mf->son, mf->cyclic_pos, mf->cyclic_size, \
2255a645f22SBen Gras 				matches + matches_count, len_best) \
2265a645f22SBen Gras 			- matches; \
2275a645f22SBen Gras 	move_pos(mf); \
2285a645f22SBen Gras 	return matches_count; \
2295a645f22SBen Gras } while (0)
2305a645f22SBen Gras 
2315a645f22SBen Gras 
2325a645f22SBen Gras ////////////////
2335a645f22SBen Gras // Hash Chain //
2345a645f22SBen Gras ////////////////
2355a645f22SBen Gras 
2365a645f22SBen Gras #if defined(HAVE_MF_HC3) || defined(HAVE_MF_HC4)
2375a645f22SBen Gras ///
2385a645f22SBen Gras ///
2395a645f22SBen Gras /// \param      len_limit       Don't look for matches longer than len_limit.
2405a645f22SBen Gras /// \param      pos             lzma_mf.read_pos + lzma_mf.offset
2415a645f22SBen Gras /// \param      cur             Pointer to current byte (mf_ptr(mf))
2425a645f22SBen Gras /// \param      cur_match       Start position of the current match candidate
2435a645f22SBen Gras /// \param      depth           Maximum length of the hash chain
2445a645f22SBen Gras /// \param      son             lzma_mf.son (contains the hash chain)
2455a645f22SBen Gras /// \param      cyclic_pos
2465a645f22SBen Gras /// \param      cyclic_size
2475a645f22SBen Gras /// \param      matches         Array to hold the matches.
2485a645f22SBen Gras /// \param      len_best        The length of the longest match found so far.
2495a645f22SBen Gras static lzma_match *
hc_find_func(const uint32_t len_limit,const uint32_t pos,const uint8_t * const cur,uint32_t cur_match,uint32_t depth,uint32_t * const son,const uint32_t cyclic_pos,const uint32_t cyclic_size,lzma_match * matches,uint32_t len_best)2505a645f22SBen Gras hc_find_func(
2515a645f22SBen Gras 		const uint32_t len_limit,
2525a645f22SBen Gras 		const uint32_t pos,
2535a645f22SBen Gras 		const uint8_t *const cur,
2545a645f22SBen Gras 		uint32_t cur_match,
2555a645f22SBen Gras 		uint32_t depth,
2565a645f22SBen Gras 		uint32_t *const son,
2575a645f22SBen Gras 		const uint32_t cyclic_pos,
2585a645f22SBen Gras 		const uint32_t cyclic_size,
2595a645f22SBen Gras 		lzma_match *matches,
2605a645f22SBen Gras 		uint32_t len_best)
2615a645f22SBen Gras {
2625a645f22SBen Gras 	son[cyclic_pos] = cur_match;
2635a645f22SBen Gras 
2645a645f22SBen Gras 	while (true) {
2655a645f22SBen Gras 		const uint32_t delta = pos - cur_match;
2665a645f22SBen Gras 		if (depth-- == 0 || delta >= cyclic_size)
2675a645f22SBen Gras 			return matches;
2685a645f22SBen Gras 
2695a645f22SBen Gras 		const uint8_t *const pb = cur - delta;
2705a645f22SBen Gras 		cur_match = son[cyclic_pos - delta
2715a645f22SBen Gras 				+ (delta > cyclic_pos ? cyclic_size : 0)];
2725a645f22SBen Gras 
2735a645f22SBen Gras 		if (pb[len_best] == cur[len_best] && pb[0] == cur[0]) {
274*0a6a1f1dSLionel Sambuc 			uint32_t len = lzma_memcmplen(pb, cur, 1, len_limit);
2755a645f22SBen Gras 
2765a645f22SBen Gras 			if (len_best < len) {
2775a645f22SBen Gras 				len_best = len;
2785a645f22SBen Gras 				matches->len = len;
2795a645f22SBen Gras 				matches->dist = delta - 1;
2805a645f22SBen Gras 				++matches;
2815a645f22SBen Gras 
2825a645f22SBen Gras 				if (len == len_limit)
2835a645f22SBen Gras 					return matches;
2845a645f22SBen Gras 			}
2855a645f22SBen Gras 		}
2865a645f22SBen Gras 	}
2875a645f22SBen Gras }
2885a645f22SBen Gras 
2895a645f22SBen Gras 
2905a645f22SBen Gras #define hc_find(len_best) \
2915a645f22SBen Gras 	call_find(hc_find_func, len_best)
2925a645f22SBen Gras 
2935a645f22SBen Gras 
2945a645f22SBen Gras #define hc_skip() \
2955a645f22SBen Gras do { \
2965a645f22SBen Gras 	mf->son[mf->cyclic_pos] = cur_match; \
2975a645f22SBen Gras 	move_pos(mf); \
2985a645f22SBen Gras } while (0)
2995a645f22SBen Gras 
3005a645f22SBen Gras #endif
3015a645f22SBen Gras 
3025a645f22SBen Gras 
3035a645f22SBen Gras #ifdef HAVE_MF_HC3
3045a645f22SBen Gras extern uint32_t
lzma_mf_hc3_find(lzma_mf * mf,lzma_match * matches)3055a645f22SBen Gras lzma_mf_hc3_find(lzma_mf *mf, lzma_match *matches)
3065a645f22SBen Gras {
3075a645f22SBen Gras 	header_find(false, 3);
3085a645f22SBen Gras 
3095a645f22SBen Gras 	hash_3_calc();
3105a645f22SBen Gras 
3115a645f22SBen Gras 	const uint32_t delta2 = pos - mf->hash[hash_2_value];
3125a645f22SBen Gras 	const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
3135a645f22SBen Gras 
3145a645f22SBen Gras 	mf->hash[hash_2_value] = pos;
3155a645f22SBen Gras 	mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
3165a645f22SBen Gras 
3175a645f22SBen Gras 	uint32_t len_best = 2;
3185a645f22SBen Gras 
3195a645f22SBen Gras 	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
320*0a6a1f1dSLionel Sambuc 		len_best = lzma_memcmplen(cur - delta2, cur,
321*0a6a1f1dSLionel Sambuc 				len_best, len_limit);
3225a645f22SBen Gras 
3235a645f22SBen Gras 		matches[0].len = len_best;
3245a645f22SBen Gras 		matches[0].dist = delta2 - 1;
3255a645f22SBen Gras 		matches_count = 1;
3265a645f22SBen Gras 
3275a645f22SBen Gras 		if (len_best == len_limit) {
3285a645f22SBen Gras 			hc_skip();
3295a645f22SBen Gras 			return 1; // matches_count
3305a645f22SBen Gras 		}
3315a645f22SBen Gras 	}
3325a645f22SBen Gras 
3335a645f22SBen Gras 	hc_find(len_best);
3345a645f22SBen Gras }
3355a645f22SBen Gras 
3365a645f22SBen Gras 
3375a645f22SBen Gras extern void
lzma_mf_hc3_skip(lzma_mf * mf,uint32_t amount)3385a645f22SBen Gras lzma_mf_hc3_skip(lzma_mf *mf, uint32_t amount)
3395a645f22SBen Gras {
3405a645f22SBen Gras 	do {
3415a645f22SBen Gras 		if (mf_avail(mf) < 3) {
3425a645f22SBen Gras 			move_pending(mf);
3435a645f22SBen Gras 			continue;
3445a645f22SBen Gras 		}
3455a645f22SBen Gras 
3465a645f22SBen Gras 		const uint8_t *cur = mf_ptr(mf);
3475a645f22SBen Gras 		const uint32_t pos = mf->read_pos + mf->offset;
3485a645f22SBen Gras 
3495a645f22SBen Gras 		hash_3_calc();
3505a645f22SBen Gras 
3515a645f22SBen Gras 		const uint32_t cur_match
3525a645f22SBen Gras 				= mf->hash[FIX_3_HASH_SIZE + hash_value];
3535a645f22SBen Gras 
3545a645f22SBen Gras 		mf->hash[hash_2_value] = pos;
3555a645f22SBen Gras 		mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
3565a645f22SBen Gras 
3575a645f22SBen Gras 		hc_skip();
3585a645f22SBen Gras 
3595a645f22SBen Gras 	} while (--amount != 0);
3605a645f22SBen Gras }
3615a645f22SBen Gras #endif
3625a645f22SBen Gras 
3635a645f22SBen Gras 
3645a645f22SBen Gras #ifdef HAVE_MF_HC4
3655a645f22SBen Gras extern uint32_t
lzma_mf_hc4_find(lzma_mf * mf,lzma_match * matches)3665a645f22SBen Gras lzma_mf_hc4_find(lzma_mf *mf, lzma_match *matches)
3675a645f22SBen Gras {
3685a645f22SBen Gras 	header_find(false, 4);
3695a645f22SBen Gras 
3705a645f22SBen Gras 	hash_4_calc();
3715a645f22SBen Gras 
3725a645f22SBen Gras 	uint32_t delta2 = pos - mf->hash[hash_2_value];
3735a645f22SBen Gras 	const uint32_t delta3
3745a645f22SBen Gras 			= pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
3755a645f22SBen Gras 	const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
3765a645f22SBen Gras 
3775a645f22SBen Gras 	mf->hash[hash_2_value ] = pos;
3785a645f22SBen Gras 	mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
3795a645f22SBen Gras 	mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
3805a645f22SBen Gras 
3815a645f22SBen Gras 	uint32_t len_best = 1;
3825a645f22SBen Gras 
3835a645f22SBen Gras 	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
3845a645f22SBen Gras 		len_best = 2;
3855a645f22SBen Gras 		matches[0].len = 2;
3865a645f22SBen Gras 		matches[0].dist = delta2 - 1;
3875a645f22SBen Gras 		matches_count = 1;
3885a645f22SBen Gras 	}
3895a645f22SBen Gras 
3905a645f22SBen Gras 	if (delta2 != delta3 && delta3 < mf->cyclic_size
3915a645f22SBen Gras 			&& *(cur - delta3) == *cur) {
3925a645f22SBen Gras 		len_best = 3;
3935a645f22SBen Gras 		matches[matches_count++].dist = delta3 - 1;
3945a645f22SBen Gras 		delta2 = delta3;
3955a645f22SBen Gras 	}
3965a645f22SBen Gras 
3975a645f22SBen Gras 	if (matches_count != 0) {
398*0a6a1f1dSLionel Sambuc 		len_best = lzma_memcmplen(cur - delta2, cur,
399*0a6a1f1dSLionel Sambuc 				len_best, len_limit);
4005a645f22SBen Gras 
4015a645f22SBen Gras 		matches[matches_count - 1].len = len_best;
4025a645f22SBen Gras 
4035a645f22SBen Gras 		if (len_best == len_limit) {
4045a645f22SBen Gras 			hc_skip();
4055a645f22SBen Gras 			return matches_count;
4065a645f22SBen Gras 		}
4075a645f22SBen Gras 	}
4085a645f22SBen Gras 
4095a645f22SBen Gras 	if (len_best < 3)
4105a645f22SBen Gras 		len_best = 3;
4115a645f22SBen Gras 
4125a645f22SBen Gras 	hc_find(len_best);
4135a645f22SBen Gras }
4145a645f22SBen Gras 
4155a645f22SBen Gras 
4165a645f22SBen Gras extern void
lzma_mf_hc4_skip(lzma_mf * mf,uint32_t amount)4175a645f22SBen Gras lzma_mf_hc4_skip(lzma_mf *mf, uint32_t amount)
4185a645f22SBen Gras {
4195a645f22SBen Gras 	do {
4205a645f22SBen Gras 		if (mf_avail(mf) < 4) {
4215a645f22SBen Gras 			move_pending(mf);
4225a645f22SBen Gras 			continue;
4235a645f22SBen Gras 		}
4245a645f22SBen Gras 
4255a645f22SBen Gras 		const uint8_t *cur = mf_ptr(mf);
4265a645f22SBen Gras 		const uint32_t pos = mf->read_pos + mf->offset;
4275a645f22SBen Gras 
4285a645f22SBen Gras 		hash_4_calc();
4295a645f22SBen Gras 
4305a645f22SBen Gras 		const uint32_t cur_match
4315a645f22SBen Gras 				= mf->hash[FIX_4_HASH_SIZE + hash_value];
4325a645f22SBen Gras 
4335a645f22SBen Gras 		mf->hash[hash_2_value] = pos;
4345a645f22SBen Gras 		mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
4355a645f22SBen Gras 		mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
4365a645f22SBen Gras 
4375a645f22SBen Gras 		hc_skip();
4385a645f22SBen Gras 
4395a645f22SBen Gras 	} while (--amount != 0);
4405a645f22SBen Gras }
4415a645f22SBen Gras #endif
4425a645f22SBen Gras 
4435a645f22SBen Gras 
4445a645f22SBen Gras /////////////////
4455a645f22SBen Gras // Binary Tree //
4465a645f22SBen Gras /////////////////
4475a645f22SBen Gras 
4485a645f22SBen Gras #if defined(HAVE_MF_BT2) || defined(HAVE_MF_BT3) || defined(HAVE_MF_BT4)
4495a645f22SBen Gras static lzma_match *
bt_find_func(const uint32_t len_limit,const uint32_t pos,const uint8_t * const cur,uint32_t cur_match,uint32_t depth,uint32_t * const son,const uint32_t cyclic_pos,const uint32_t cyclic_size,lzma_match * matches,uint32_t len_best)4505a645f22SBen Gras bt_find_func(
4515a645f22SBen Gras 		const uint32_t len_limit,
4525a645f22SBen Gras 		const uint32_t pos,
4535a645f22SBen Gras 		const uint8_t *const cur,
4545a645f22SBen Gras 		uint32_t cur_match,
4555a645f22SBen Gras 		uint32_t depth,
4565a645f22SBen Gras 		uint32_t *const son,
4575a645f22SBen Gras 		const uint32_t cyclic_pos,
4585a645f22SBen Gras 		const uint32_t cyclic_size,
4595a645f22SBen Gras 		lzma_match *matches,
4605a645f22SBen Gras 		uint32_t len_best)
4615a645f22SBen Gras {
4625a645f22SBen Gras 	uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
4635a645f22SBen Gras 	uint32_t *ptr1 = son + (cyclic_pos << 1);
4645a645f22SBen Gras 
4655a645f22SBen Gras 	uint32_t len0 = 0;
4665a645f22SBen Gras 	uint32_t len1 = 0;
4675a645f22SBen Gras 
4685a645f22SBen Gras 	while (true) {
4695a645f22SBen Gras 		const uint32_t delta = pos - cur_match;
4705a645f22SBen Gras 		if (depth-- == 0 || delta >= cyclic_size) {
4715a645f22SBen Gras 			*ptr0 = EMPTY_HASH_VALUE;
4725a645f22SBen Gras 			*ptr1 = EMPTY_HASH_VALUE;
4735a645f22SBen Gras 			return matches;
4745a645f22SBen Gras 		}
4755a645f22SBen Gras 
4765a645f22SBen Gras 		uint32_t *const pair = son + ((cyclic_pos - delta
4775a645f22SBen Gras 				+ (delta > cyclic_pos ? cyclic_size : 0))
4785a645f22SBen Gras 				<< 1);
4795a645f22SBen Gras 
4805a645f22SBen Gras 		const uint8_t *const pb = cur - delta;
4815a645f22SBen Gras 		uint32_t len = my_min(len0, len1);
4825a645f22SBen Gras 
4835a645f22SBen Gras 		if (pb[len] == cur[len]) {
484*0a6a1f1dSLionel Sambuc 			len = lzma_memcmplen(pb, cur, len + 1, len_limit);
4855a645f22SBen Gras 
4865a645f22SBen Gras 			if (len_best < len) {
4875a645f22SBen Gras 				len_best = len;
4885a645f22SBen Gras 				matches->len = len;
4895a645f22SBen Gras 				matches->dist = delta - 1;
4905a645f22SBen Gras 				++matches;
4915a645f22SBen Gras 
4925a645f22SBen Gras 				if (len == len_limit) {
4935a645f22SBen Gras 					*ptr1 = pair[0];
4945a645f22SBen Gras 					*ptr0 = pair[1];
4955a645f22SBen Gras 					return matches;
4965a645f22SBen Gras 				}
4975a645f22SBen Gras 			}
4985a645f22SBen Gras 		}
4995a645f22SBen Gras 
5005a645f22SBen Gras 		if (pb[len] < cur[len]) {
5015a645f22SBen Gras 			*ptr1 = cur_match;
5025a645f22SBen Gras 			ptr1 = pair + 1;
5035a645f22SBen Gras 			cur_match = *ptr1;
5045a645f22SBen Gras 			len1 = len;
5055a645f22SBen Gras 		} else {
5065a645f22SBen Gras 			*ptr0 = cur_match;
5075a645f22SBen Gras 			ptr0 = pair;
5085a645f22SBen Gras 			cur_match = *ptr0;
5095a645f22SBen Gras 			len0 = len;
5105a645f22SBen Gras 		}
5115a645f22SBen Gras 	}
5125a645f22SBen Gras }
5135a645f22SBen Gras 
5145a645f22SBen Gras 
5155a645f22SBen Gras static void
bt_skip_func(const uint32_t len_limit,const uint32_t pos,const uint8_t * const cur,uint32_t cur_match,uint32_t depth,uint32_t * const son,const uint32_t cyclic_pos,const uint32_t cyclic_size)5165a645f22SBen Gras bt_skip_func(
5175a645f22SBen Gras 		const uint32_t len_limit,
5185a645f22SBen Gras 		const uint32_t pos,
5195a645f22SBen Gras 		const uint8_t *const cur,
5205a645f22SBen Gras 		uint32_t cur_match,
5215a645f22SBen Gras 		uint32_t depth,
5225a645f22SBen Gras 		uint32_t *const son,
5235a645f22SBen Gras 		const uint32_t cyclic_pos,
5245a645f22SBen Gras 		const uint32_t cyclic_size)
5255a645f22SBen Gras {
5265a645f22SBen Gras 	uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
5275a645f22SBen Gras 	uint32_t *ptr1 = son + (cyclic_pos << 1);
5285a645f22SBen Gras 
5295a645f22SBen Gras 	uint32_t len0 = 0;
5305a645f22SBen Gras 	uint32_t len1 = 0;
5315a645f22SBen Gras 
5325a645f22SBen Gras 	while (true) {
5335a645f22SBen Gras 		const uint32_t delta = pos - cur_match;
5345a645f22SBen Gras 		if (depth-- == 0 || delta >= cyclic_size) {
5355a645f22SBen Gras 			*ptr0 = EMPTY_HASH_VALUE;
5365a645f22SBen Gras 			*ptr1 = EMPTY_HASH_VALUE;
5375a645f22SBen Gras 			return;
5385a645f22SBen Gras 		}
5395a645f22SBen Gras 
5405a645f22SBen Gras 		uint32_t *pair = son + ((cyclic_pos - delta
5415a645f22SBen Gras 				+ (delta > cyclic_pos ? cyclic_size : 0))
5425a645f22SBen Gras 				<< 1);
5435a645f22SBen Gras 		const uint8_t *pb = cur - delta;
5445a645f22SBen Gras 		uint32_t len = my_min(len0, len1);
5455a645f22SBen Gras 
5465a645f22SBen Gras 		if (pb[len] == cur[len]) {
547*0a6a1f1dSLionel Sambuc 			len = lzma_memcmplen(pb, cur, len + 1, len_limit);
5485a645f22SBen Gras 
5495a645f22SBen Gras 			if (len == len_limit) {
5505a645f22SBen Gras 				*ptr1 = pair[0];
5515a645f22SBen Gras 				*ptr0 = pair[1];
5525a645f22SBen Gras 				return;
5535a645f22SBen Gras 			}
5545a645f22SBen Gras 		}
5555a645f22SBen Gras 
5565a645f22SBen Gras 		if (pb[len] < cur[len]) {
5575a645f22SBen Gras 			*ptr1 = cur_match;
5585a645f22SBen Gras 			ptr1 = pair + 1;
5595a645f22SBen Gras 			cur_match = *ptr1;
5605a645f22SBen Gras 			len1 = len;
5615a645f22SBen Gras 		} else {
5625a645f22SBen Gras 			*ptr0 = cur_match;
5635a645f22SBen Gras 			ptr0 = pair;
5645a645f22SBen Gras 			cur_match = *ptr0;
5655a645f22SBen Gras 			len0 = len;
5665a645f22SBen Gras 		}
5675a645f22SBen Gras 	}
5685a645f22SBen Gras }
5695a645f22SBen Gras 
5705a645f22SBen Gras 
5715a645f22SBen Gras #define bt_find(len_best) \
5725a645f22SBen Gras 	call_find(bt_find_func, len_best)
5735a645f22SBen Gras 
5745a645f22SBen Gras #define bt_skip() \
5755a645f22SBen Gras do { \
5765a645f22SBen Gras 	bt_skip_func(len_limit, pos, cur, cur_match, mf->depth, \
5775a645f22SBen Gras 			mf->son, mf->cyclic_pos, \
5785a645f22SBen Gras 			mf->cyclic_size); \
5795a645f22SBen Gras 	move_pos(mf); \
5805a645f22SBen Gras } while (0)
5815a645f22SBen Gras 
5825a645f22SBen Gras #endif
5835a645f22SBen Gras 
5845a645f22SBen Gras 
5855a645f22SBen Gras #ifdef HAVE_MF_BT2
5865a645f22SBen Gras extern uint32_t
lzma_mf_bt2_find(lzma_mf * mf,lzma_match * matches)5875a645f22SBen Gras lzma_mf_bt2_find(lzma_mf *mf, lzma_match *matches)
5885a645f22SBen Gras {
5895a645f22SBen Gras 	header_find(true, 2);
5905a645f22SBen Gras 
5915a645f22SBen Gras 	hash_2_calc();
5925a645f22SBen Gras 
5935a645f22SBen Gras 	const uint32_t cur_match = mf->hash[hash_value];
5945a645f22SBen Gras 	mf->hash[hash_value] = pos;
5955a645f22SBen Gras 
5965a645f22SBen Gras 	bt_find(1);
5975a645f22SBen Gras }
5985a645f22SBen Gras 
5995a645f22SBen Gras 
6005a645f22SBen Gras extern void
lzma_mf_bt2_skip(lzma_mf * mf,uint32_t amount)6015a645f22SBen Gras lzma_mf_bt2_skip(lzma_mf *mf, uint32_t amount)
6025a645f22SBen Gras {
6035a645f22SBen Gras 	do {
6045a645f22SBen Gras 		header_skip(true, 2);
6055a645f22SBen Gras 
6065a645f22SBen Gras 		hash_2_calc();
6075a645f22SBen Gras 
6085a645f22SBen Gras 		const uint32_t cur_match = mf->hash[hash_value];
6095a645f22SBen Gras 		mf->hash[hash_value] = pos;
6105a645f22SBen Gras 
6115a645f22SBen Gras 		bt_skip();
6125a645f22SBen Gras 
6135a645f22SBen Gras 	} while (--amount != 0);
6145a645f22SBen Gras }
6155a645f22SBen Gras #endif
6165a645f22SBen Gras 
6175a645f22SBen Gras 
6185a645f22SBen Gras #ifdef HAVE_MF_BT3
6195a645f22SBen Gras extern uint32_t
lzma_mf_bt3_find(lzma_mf * mf,lzma_match * matches)6205a645f22SBen Gras lzma_mf_bt3_find(lzma_mf *mf, lzma_match *matches)
6215a645f22SBen Gras {
6225a645f22SBen Gras 	header_find(true, 3);
6235a645f22SBen Gras 
6245a645f22SBen Gras 	hash_3_calc();
6255a645f22SBen Gras 
6265a645f22SBen Gras 	const uint32_t delta2 = pos - mf->hash[hash_2_value];
6275a645f22SBen Gras 	const uint32_t cur_match = mf->hash[FIX_3_HASH_SIZE + hash_value];
6285a645f22SBen Gras 
6295a645f22SBen Gras 	mf->hash[hash_2_value] = pos;
6305a645f22SBen Gras 	mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
6315a645f22SBen Gras 
6325a645f22SBen Gras 	uint32_t len_best = 2;
6335a645f22SBen Gras 
6345a645f22SBen Gras 	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
635*0a6a1f1dSLionel Sambuc 		len_best = lzma_memcmplen(
636*0a6a1f1dSLionel Sambuc 				cur, cur - delta2, len_best, len_limit);
6375a645f22SBen Gras 
6385a645f22SBen Gras 		matches[0].len = len_best;
6395a645f22SBen Gras 		matches[0].dist = delta2 - 1;
6405a645f22SBen Gras 		matches_count = 1;
6415a645f22SBen Gras 
6425a645f22SBen Gras 		if (len_best == len_limit) {
6435a645f22SBen Gras 			bt_skip();
6445a645f22SBen Gras 			return 1; // matches_count
6455a645f22SBen Gras 		}
6465a645f22SBen Gras 	}
6475a645f22SBen Gras 
6485a645f22SBen Gras 	bt_find(len_best);
6495a645f22SBen Gras }
6505a645f22SBen Gras 
6515a645f22SBen Gras 
6525a645f22SBen Gras extern void
lzma_mf_bt3_skip(lzma_mf * mf,uint32_t amount)6535a645f22SBen Gras lzma_mf_bt3_skip(lzma_mf *mf, uint32_t amount)
6545a645f22SBen Gras {
6555a645f22SBen Gras 	do {
6565a645f22SBen Gras 		header_skip(true, 3);
6575a645f22SBen Gras 
6585a645f22SBen Gras 		hash_3_calc();
6595a645f22SBen Gras 
6605a645f22SBen Gras 		const uint32_t cur_match
6615a645f22SBen Gras 				= mf->hash[FIX_3_HASH_SIZE + hash_value];
6625a645f22SBen Gras 
6635a645f22SBen Gras 		mf->hash[hash_2_value] = pos;
6645a645f22SBen Gras 		mf->hash[FIX_3_HASH_SIZE + hash_value] = pos;
6655a645f22SBen Gras 
6665a645f22SBen Gras 		bt_skip();
6675a645f22SBen Gras 
6685a645f22SBen Gras 	} while (--amount != 0);
6695a645f22SBen Gras }
6705a645f22SBen Gras #endif
6715a645f22SBen Gras 
6725a645f22SBen Gras 
6735a645f22SBen Gras #ifdef HAVE_MF_BT4
6745a645f22SBen Gras extern uint32_t
lzma_mf_bt4_find(lzma_mf * mf,lzma_match * matches)6755a645f22SBen Gras lzma_mf_bt4_find(lzma_mf *mf, lzma_match *matches)
6765a645f22SBen Gras {
6775a645f22SBen Gras 	header_find(true, 4);
6785a645f22SBen Gras 
6795a645f22SBen Gras 	hash_4_calc();
6805a645f22SBen Gras 
6815a645f22SBen Gras 	uint32_t delta2 = pos - mf->hash[hash_2_value];
6825a645f22SBen Gras 	const uint32_t delta3
6835a645f22SBen Gras 			= pos - mf->hash[FIX_3_HASH_SIZE + hash_3_value];
6845a645f22SBen Gras 	const uint32_t cur_match = mf->hash[FIX_4_HASH_SIZE + hash_value];
6855a645f22SBen Gras 
6865a645f22SBen Gras 	mf->hash[hash_2_value] = pos;
6875a645f22SBen Gras 	mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
6885a645f22SBen Gras 	mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
6895a645f22SBen Gras 
6905a645f22SBen Gras 	uint32_t len_best = 1;
6915a645f22SBen Gras 
6925a645f22SBen Gras 	if (delta2 < mf->cyclic_size && *(cur - delta2) == *cur) {
6935a645f22SBen Gras 		len_best = 2;
6945a645f22SBen Gras 		matches[0].len = 2;
6955a645f22SBen Gras 		matches[0].dist = delta2 - 1;
6965a645f22SBen Gras 		matches_count = 1;
6975a645f22SBen Gras 	}
6985a645f22SBen Gras 
6995a645f22SBen Gras 	if (delta2 != delta3 && delta3 < mf->cyclic_size
7005a645f22SBen Gras 			&& *(cur - delta3) == *cur) {
7015a645f22SBen Gras 		len_best = 3;
7025a645f22SBen Gras 		matches[matches_count++].dist = delta3 - 1;
7035a645f22SBen Gras 		delta2 = delta3;
7045a645f22SBen Gras 	}
7055a645f22SBen Gras 
7065a645f22SBen Gras 	if (matches_count != 0) {
707*0a6a1f1dSLionel Sambuc 		len_best = lzma_memcmplen(
708*0a6a1f1dSLionel Sambuc 				cur, cur - delta2, len_best, len_limit);
7095a645f22SBen Gras 
7105a645f22SBen Gras 		matches[matches_count - 1].len = len_best;
7115a645f22SBen Gras 
7125a645f22SBen Gras 		if (len_best == len_limit) {
7135a645f22SBen Gras 			bt_skip();
7145a645f22SBen Gras 			return matches_count;
7155a645f22SBen Gras 		}
7165a645f22SBen Gras 	}
7175a645f22SBen Gras 
7185a645f22SBen Gras 	if (len_best < 3)
7195a645f22SBen Gras 		len_best = 3;
7205a645f22SBen Gras 
7215a645f22SBen Gras 	bt_find(len_best);
7225a645f22SBen Gras }
7235a645f22SBen Gras 
7245a645f22SBen Gras 
7255a645f22SBen Gras extern void
lzma_mf_bt4_skip(lzma_mf * mf,uint32_t amount)7265a645f22SBen Gras lzma_mf_bt4_skip(lzma_mf *mf, uint32_t amount)
7275a645f22SBen Gras {
7285a645f22SBen Gras 	do {
7295a645f22SBen Gras 		header_skip(true, 4);
7305a645f22SBen Gras 
7315a645f22SBen Gras 		hash_4_calc();
7325a645f22SBen Gras 
7335a645f22SBen Gras 		const uint32_t cur_match
7345a645f22SBen Gras 				= mf->hash[FIX_4_HASH_SIZE + hash_value];
7355a645f22SBen Gras 
7365a645f22SBen Gras 		mf->hash[hash_2_value] = pos;
7375a645f22SBen Gras 		mf->hash[FIX_3_HASH_SIZE + hash_3_value] = pos;
7385a645f22SBen Gras 		mf->hash[FIX_4_HASH_SIZE + hash_value] = pos;
7395a645f22SBen Gras 
7405a645f22SBen Gras 		bt_skip();
7415a645f22SBen Gras 
7425a645f22SBen Gras 	} while (--amount != 0);
7435a645f22SBen Gras }
7445a645f22SBen Gras #endif
745