+ *matches_ret = matches;
+ return num_matches;
+}
+
+static void
+lzms_skip_bytes(struct lzms_compressor *ctx, input_idx_t n)
+{
+ while (n--)
+ lz_sarray_skip_position(&ctx->lz_sarray);
+}
+
+static u32
+lzms_get_prev_literal_cost(struct lzms_compressor *ctx,
+ struct lzms_cost_state *cost_state)
+{
+ u8 literal = ctx->window[lz_sarray_get_pos(&ctx->lz_sarray) - 1];
+ u32 cost = 0;
+
+ cost_state->lru.upcoming_offset = 0;
+ lzms_update_lz_lru_queues(&cost_state->lru);
+
+ cost += lzms_rc_bit_cost(&ctx->main_range_encoder,
+ &cost_state->main_state, 0);
+ cost += lzms_huffman_symbol_cost(&ctx->literal_encoder, literal);
+
+ return cost;
+}
+
+static u32
+lzms_get_match_cost(struct lzms_compressor *ctx,
+ struct lzms_cost_state *cost_state,
+ input_idx_t length, input_idx_t offset)
+{
+ u32 cost = 0;
+ int recent_offset_idx;
+
+ cost += lzms_rc_bit_cost(&ctx->main_range_encoder,
+ &cost_state->main_state, 1);
+ cost += lzms_rc_bit_cost(&ctx->match_range_encoder,
+ &cost_state->match_state, 0);
+
+ for (recent_offset_idx = 0;
+ recent_offset_idx < LZMS_NUM_RECENT_OFFSETS;
+ recent_offset_idx++)
+ if (offset == cost_state->lru.recent_offsets[recent_offset_idx])
+ break;
+
+ if (recent_offset_idx == LZMS_NUM_RECENT_OFFSETS) {
+ /* Explicit offset. */
+ cost += lzms_rc_bit_cost(&ctx->lz_match_range_encoder,
+ &cost_state->lz_match_state, 0);
+
+ cost += lzms_value_cost(&ctx->lz_offset_encoder, offset);
+ } else {
+ int i;
+
+ /* Repeat offset. */
+ cost += lzms_rc_bit_cost(&ctx->lz_match_range_encoder,
+ &cost_state->lz_match_state, 1);
+
+ for (i = 0; i < recent_offset_idx; i++)
+ cost++; /* TODO */
+
+ if (i < LZMS_NUM_RECENT_OFFSETS - 1)
+ cost++; /* TODO */
+
+ /* Initial update of the LZ match offset LRU queue. */
+ for (; i < LZMS_NUM_RECENT_OFFSETS; i++)
+ cost_state->lru.recent_offsets[i] = cost_state->lru.recent_offsets[i + 1];
+ }
+
+ cost += lzms_value_cost(&ctx->length_encoder, length);
+
+ cost_state->lru.upcoming_offset = offset;
+ lzms_update_lz_lru_queues(&cost_state->lru);
+
+ return cost;
+}
+
+static struct raw_match
+lzms_get_near_optimal_match(struct lzms_compressor *ctx)
+{
+ struct lzms_cost_state initial_state = {
+ .lru = ctx->lru.lz,
+ .main_state = ctx->main_range_encoder.state,
+ .match_state = ctx->match_range_encoder.state,
+ .lz_match_state = ctx->lz_match_range_encoder.state,
+ };
+ return lz_get_near_optimal_match(&ctx->mc,
+ lzms_get_matches,
+ lzms_skip_bytes,
+ lzms_get_prev_literal_cost,
+ lzms_get_match_cost,
+ ctx,
+ &initial_state);