1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 2*3b35e7eeSXin LI 381ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 481ad8388SMartin Matuska // 581ad8388SMartin Matuska /// \file lzma_encoder.c 681ad8388SMartin Matuska /// \brief LZMA encoder 781ad8388SMartin Matuska /// 881ad8388SMartin Matuska // Authors: Igor Pavlov 981ad8388SMartin Matuska // Lasse Collin 1081ad8388SMartin Matuska // 1181ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 1281ad8388SMartin Matuska 1381ad8388SMartin Matuska #include "lzma2_encoder.h" 1481ad8388SMartin Matuska #include "lzma_encoder_private.h" 1581ad8388SMartin Matuska #include "fastpos.h" 1681ad8388SMartin Matuska 1781ad8388SMartin Matuska 1881ad8388SMartin Matuska ///////////// 1981ad8388SMartin Matuska // Literal // 2081ad8388SMartin Matuska ///////////// 2181ad8388SMartin Matuska 2281ad8388SMartin Matuska static inline void 2381ad8388SMartin Matuska literal_matched(lzma_range_encoder *rc, probability *subcoder, 2481ad8388SMartin Matuska uint32_t match_byte, uint32_t symbol) 2581ad8388SMartin Matuska { 2681ad8388SMartin Matuska uint32_t offset = 0x100; 2781ad8388SMartin Matuska symbol += UINT32_C(1) << 8; 2881ad8388SMartin Matuska 2981ad8388SMartin Matuska do { 3081ad8388SMartin Matuska match_byte <<= 1; 3181ad8388SMartin Matuska const uint32_t match_bit = match_byte & offset; 3281ad8388SMartin Matuska const uint32_t subcoder_index 3381ad8388SMartin Matuska = offset + match_bit + (symbol >> 8); 3481ad8388SMartin Matuska const uint32_t bit = (symbol >> 7) & 1; 3581ad8388SMartin Matuska rc_bit(rc, &subcoder[subcoder_index], bit); 3681ad8388SMartin Matuska 3781ad8388SMartin Matuska symbol <<= 1; 3881ad8388SMartin Matuska offset &= ~(match_byte ^ symbol); 3981ad8388SMartin Matuska 4081ad8388SMartin Matuska } while (symbol < (UINT32_C(1) << 16)); 4181ad8388SMartin Matuska } 4281ad8388SMartin Matuska 4381ad8388SMartin Matuska 4481ad8388SMartin Matuska static inline void 451456f0f9SXin LI literal(lzma_lzma1_encoder *coder, lzma_mf *mf, uint32_t position) 4681ad8388SMartin Matuska { 4781ad8388SMartin Matuska // Locate the literal byte to be encoded and the subcoder. 4881ad8388SMartin Matuska const uint8_t cur_byte = mf->buffer[ 4981ad8388SMartin Matuska mf->read_pos - mf->read_ahead]; 5081ad8388SMartin Matuska probability *subcoder = literal_subcoder(coder->literal, 51*3b35e7eeSXin LI coder->literal_context_bits, coder->literal_mask, 5281ad8388SMartin Matuska position, mf->buffer[mf->read_pos - mf->read_ahead - 1]); 5381ad8388SMartin Matuska 5481ad8388SMartin Matuska if (is_literal_state(coder->state)) { 5581ad8388SMartin Matuska // Previous LZMA-symbol was a literal. Encode a normal 5681ad8388SMartin Matuska // literal without a match byte. 57*3b35e7eeSXin LI update_literal_normal(coder->state); 5881ad8388SMartin Matuska rc_bittree(&coder->rc, subcoder, 8, cur_byte); 5981ad8388SMartin Matuska } else { 6081ad8388SMartin Matuska // Previous LZMA-symbol was a match. Use the last byte of 6181ad8388SMartin Matuska // the match as a "match byte". That is, compare the bits 6281ad8388SMartin Matuska // of the current literal and the match byte. 63*3b35e7eeSXin LI update_literal_matched(coder->state); 6481ad8388SMartin Matuska const uint8_t match_byte = mf->buffer[ 6581ad8388SMartin Matuska mf->read_pos - coder->reps[0] - 1 6681ad8388SMartin Matuska - mf->read_ahead]; 6781ad8388SMartin Matuska literal_matched(&coder->rc, subcoder, match_byte, cur_byte); 6881ad8388SMartin Matuska } 6981ad8388SMartin Matuska } 7081ad8388SMartin Matuska 7181ad8388SMartin Matuska 7281ad8388SMartin Matuska ////////////////// 7381ad8388SMartin Matuska // Match length // 7481ad8388SMartin Matuska ////////////////// 7581ad8388SMartin Matuska 7681ad8388SMartin Matuska static void 7781ad8388SMartin Matuska length_update_prices(lzma_length_encoder *lc, const uint32_t pos_state) 7881ad8388SMartin Matuska { 7981ad8388SMartin Matuska const uint32_t table_size = lc->table_size; 8081ad8388SMartin Matuska lc->counters[pos_state] = table_size; 8181ad8388SMartin Matuska 8281ad8388SMartin Matuska const uint32_t a0 = rc_bit_0_price(lc->choice); 8381ad8388SMartin Matuska const uint32_t a1 = rc_bit_1_price(lc->choice); 8481ad8388SMartin Matuska const uint32_t b0 = a1 + rc_bit_0_price(lc->choice2); 8581ad8388SMartin Matuska const uint32_t b1 = a1 + rc_bit_1_price(lc->choice2); 8681ad8388SMartin Matuska uint32_t *const prices = lc->prices[pos_state]; 8781ad8388SMartin Matuska 8881ad8388SMartin Matuska uint32_t i; 8981ad8388SMartin Matuska for (i = 0; i < table_size && i < LEN_LOW_SYMBOLS; ++i) 9081ad8388SMartin Matuska prices[i] = a0 + rc_bittree_price(lc->low[pos_state], 9181ad8388SMartin Matuska LEN_LOW_BITS, i); 9281ad8388SMartin Matuska 9381ad8388SMartin Matuska for (; i < table_size && i < LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS; ++i) 9481ad8388SMartin Matuska prices[i] = b0 + rc_bittree_price(lc->mid[pos_state], 9581ad8388SMartin Matuska LEN_MID_BITS, i - LEN_LOW_SYMBOLS); 9681ad8388SMartin Matuska 9781ad8388SMartin Matuska for (; i < table_size; ++i) 9881ad8388SMartin Matuska prices[i] = b1 + rc_bittree_price(lc->high, LEN_HIGH_BITS, 9981ad8388SMartin Matuska i - LEN_LOW_SYMBOLS - LEN_MID_SYMBOLS); 10081ad8388SMartin Matuska 10181ad8388SMartin Matuska return; 10281ad8388SMartin Matuska } 10381ad8388SMartin Matuska 10481ad8388SMartin Matuska 10581ad8388SMartin Matuska static inline void 10681ad8388SMartin Matuska length(lzma_range_encoder *rc, lzma_length_encoder *lc, 10781ad8388SMartin Matuska const uint32_t pos_state, uint32_t len, const bool fast_mode) 10881ad8388SMartin Matuska { 10981ad8388SMartin Matuska assert(len <= MATCH_LEN_MAX); 11081ad8388SMartin Matuska len -= MATCH_LEN_MIN; 11181ad8388SMartin Matuska 11281ad8388SMartin Matuska if (len < LEN_LOW_SYMBOLS) { 11381ad8388SMartin Matuska rc_bit(rc, &lc->choice, 0); 11481ad8388SMartin Matuska rc_bittree(rc, lc->low[pos_state], LEN_LOW_BITS, len); 11581ad8388SMartin Matuska } else { 11681ad8388SMartin Matuska rc_bit(rc, &lc->choice, 1); 11781ad8388SMartin Matuska len -= LEN_LOW_SYMBOLS; 11881ad8388SMartin Matuska 11981ad8388SMartin Matuska if (len < LEN_MID_SYMBOLS) { 12081ad8388SMartin Matuska rc_bit(rc, &lc->choice2, 0); 12181ad8388SMartin Matuska rc_bittree(rc, lc->mid[pos_state], LEN_MID_BITS, len); 12281ad8388SMartin Matuska } else { 12381ad8388SMartin Matuska rc_bit(rc, &lc->choice2, 1); 12481ad8388SMartin Matuska len -= LEN_MID_SYMBOLS; 12581ad8388SMartin Matuska rc_bittree(rc, lc->high, LEN_HIGH_BITS, len); 12681ad8388SMartin Matuska } 12781ad8388SMartin Matuska } 12881ad8388SMartin Matuska 12981ad8388SMartin Matuska // Only getoptimum uses the prices so don't update the table when 13081ad8388SMartin Matuska // in fast mode. 13181ad8388SMartin Matuska if (!fast_mode) 13281ad8388SMartin Matuska if (--lc->counters[pos_state] == 0) 13381ad8388SMartin Matuska length_update_prices(lc, pos_state); 13481ad8388SMartin Matuska } 13581ad8388SMartin Matuska 13681ad8388SMartin Matuska 13781ad8388SMartin Matuska /////////// 13881ad8388SMartin Matuska // Match // 13981ad8388SMartin Matuska /////////// 14081ad8388SMartin Matuska 14181ad8388SMartin Matuska static inline void 1421456f0f9SXin LI match(lzma_lzma1_encoder *coder, const uint32_t pos_state, 14381ad8388SMartin Matuska const uint32_t distance, const uint32_t len) 14481ad8388SMartin Matuska { 14581ad8388SMartin Matuska update_match(coder->state); 14681ad8388SMartin Matuska 14781ad8388SMartin Matuska length(&coder->rc, &coder->match_len_encoder, pos_state, len, 14881ad8388SMartin Matuska coder->fast_mode); 14981ad8388SMartin Matuska 15053200025SRui Paulo const uint32_t dist_slot = get_dist_slot(distance); 15153200025SRui Paulo const uint32_t dist_state = get_dist_state(len); 15253200025SRui Paulo rc_bittree(&coder->rc, coder->dist_slot[dist_state], 15353200025SRui Paulo DIST_SLOT_BITS, dist_slot); 15481ad8388SMartin Matuska 15553200025SRui Paulo if (dist_slot >= DIST_MODEL_START) { 15653200025SRui Paulo const uint32_t footer_bits = (dist_slot >> 1) - 1; 15753200025SRui Paulo const uint32_t base = (2 | (dist_slot & 1)) << footer_bits; 15853200025SRui Paulo const uint32_t dist_reduced = distance - base; 15981ad8388SMartin Matuska 16053200025SRui Paulo if (dist_slot < DIST_MODEL_END) { 16153200025SRui Paulo // Careful here: base - dist_slot - 1 can be -1, but 16281ad8388SMartin Matuska // rc_bittree_reverse starts at probs[1], not probs[0]. 16381ad8388SMartin Matuska rc_bittree_reverse(&coder->rc, 16453200025SRui Paulo coder->dist_special + base - dist_slot - 1, 16553200025SRui Paulo footer_bits, dist_reduced); 16681ad8388SMartin Matuska } else { 16753200025SRui Paulo rc_direct(&coder->rc, dist_reduced >> ALIGN_BITS, 16881ad8388SMartin Matuska footer_bits - ALIGN_BITS); 16981ad8388SMartin Matuska rc_bittree_reverse( 17053200025SRui Paulo &coder->rc, coder->dist_align, 17153200025SRui Paulo ALIGN_BITS, dist_reduced & ALIGN_MASK); 17281ad8388SMartin Matuska ++coder->align_price_count; 17381ad8388SMartin Matuska } 17481ad8388SMartin Matuska } 17581ad8388SMartin Matuska 17681ad8388SMartin Matuska coder->reps[3] = coder->reps[2]; 17781ad8388SMartin Matuska coder->reps[2] = coder->reps[1]; 17881ad8388SMartin Matuska coder->reps[1] = coder->reps[0]; 17981ad8388SMartin Matuska coder->reps[0] = distance; 18081ad8388SMartin Matuska ++coder->match_price_count; 18181ad8388SMartin Matuska } 18281ad8388SMartin Matuska 18381ad8388SMartin Matuska 18481ad8388SMartin Matuska //////////////////// 18581ad8388SMartin Matuska // Repeated match // 18681ad8388SMartin Matuska //////////////////// 18781ad8388SMartin Matuska 18881ad8388SMartin Matuska static inline void 1891456f0f9SXin LI rep_match(lzma_lzma1_encoder *coder, const uint32_t pos_state, 19081ad8388SMartin Matuska const uint32_t rep, const uint32_t len) 19181ad8388SMartin Matuska { 19281ad8388SMartin Matuska if (rep == 0) { 19381ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep0[coder->state], 0); 19481ad8388SMartin Matuska rc_bit(&coder->rc, 19581ad8388SMartin Matuska &coder->is_rep0_long[coder->state][pos_state], 19681ad8388SMartin Matuska len != 1); 19781ad8388SMartin Matuska } else { 19881ad8388SMartin Matuska const uint32_t distance = coder->reps[rep]; 19981ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep0[coder->state], 1); 20081ad8388SMartin Matuska 20181ad8388SMartin Matuska if (rep == 1) { 20281ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep1[coder->state], 0); 20381ad8388SMartin Matuska } else { 20481ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep1[coder->state], 1); 20581ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep2[coder->state], 20681ad8388SMartin Matuska rep - 2); 20781ad8388SMartin Matuska 20881ad8388SMartin Matuska if (rep == 3) 20981ad8388SMartin Matuska coder->reps[3] = coder->reps[2]; 21081ad8388SMartin Matuska 21181ad8388SMartin Matuska coder->reps[2] = coder->reps[1]; 21281ad8388SMartin Matuska } 21381ad8388SMartin Matuska 21481ad8388SMartin Matuska coder->reps[1] = coder->reps[0]; 21581ad8388SMartin Matuska coder->reps[0] = distance; 21681ad8388SMartin Matuska } 21781ad8388SMartin Matuska 21881ad8388SMartin Matuska if (len == 1) { 21981ad8388SMartin Matuska update_short_rep(coder->state); 22081ad8388SMartin Matuska } else { 22181ad8388SMartin Matuska length(&coder->rc, &coder->rep_len_encoder, pos_state, len, 22281ad8388SMartin Matuska coder->fast_mode); 22381ad8388SMartin Matuska update_long_rep(coder->state); 22481ad8388SMartin Matuska } 22581ad8388SMartin Matuska } 22681ad8388SMartin Matuska 22781ad8388SMartin Matuska 22881ad8388SMartin Matuska ////////// 22981ad8388SMartin Matuska // Main // 23081ad8388SMartin Matuska ////////// 23181ad8388SMartin Matuska 23281ad8388SMartin Matuska static void 2331456f0f9SXin LI encode_symbol(lzma_lzma1_encoder *coder, lzma_mf *mf, 23481ad8388SMartin Matuska uint32_t back, uint32_t len, uint32_t position) 23581ad8388SMartin Matuska { 23681ad8388SMartin Matuska const uint32_t pos_state = position & coder->pos_mask; 23781ad8388SMartin Matuska 23881ad8388SMartin Matuska if (back == UINT32_MAX) { 23981ad8388SMartin Matuska // Literal i.e. eight-bit byte 24081ad8388SMartin Matuska assert(len == 1); 24181ad8388SMartin Matuska rc_bit(&coder->rc, 24281ad8388SMartin Matuska &coder->is_match[coder->state][pos_state], 0); 24381ad8388SMartin Matuska literal(coder, mf, position); 24481ad8388SMartin Matuska } else { 24581ad8388SMartin Matuska // Some type of match 24681ad8388SMartin Matuska rc_bit(&coder->rc, 24781ad8388SMartin Matuska &coder->is_match[coder->state][pos_state], 1); 24881ad8388SMartin Matuska 24953200025SRui Paulo if (back < REPS) { 25081ad8388SMartin Matuska // It's a repeated match i.e. the same distance 25181ad8388SMartin Matuska // has been used earlier. 25281ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep[coder->state], 1); 25381ad8388SMartin Matuska rep_match(coder, pos_state, back, len); 25481ad8388SMartin Matuska } else { 25581ad8388SMartin Matuska // Normal match 25681ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep[coder->state], 0); 25753200025SRui Paulo match(coder, pos_state, back - REPS, len); 25881ad8388SMartin Matuska } 25981ad8388SMartin Matuska } 26081ad8388SMartin Matuska 26181ad8388SMartin Matuska assert(mf->read_ahead >= len); 26281ad8388SMartin Matuska mf->read_ahead -= len; 26381ad8388SMartin Matuska } 26481ad8388SMartin Matuska 26581ad8388SMartin Matuska 26681ad8388SMartin Matuska static bool 2671456f0f9SXin LI encode_init(lzma_lzma1_encoder *coder, lzma_mf *mf) 26881ad8388SMartin Matuska { 26981ad8388SMartin Matuska assert(mf_position(mf) == 0); 27073ed8e77SXin LI assert(coder->uncomp_size == 0); 27181ad8388SMartin Matuska 27281ad8388SMartin Matuska if (mf->read_pos == mf->read_limit) { 27381ad8388SMartin Matuska if (mf->action == LZMA_RUN) 27481ad8388SMartin Matuska return false; // We cannot do anything. 27581ad8388SMartin Matuska 27681ad8388SMartin Matuska // We are finishing (we cannot get here when flushing). 27781ad8388SMartin Matuska assert(mf->write_pos == mf->read_pos); 27881ad8388SMartin Matuska assert(mf->action == LZMA_FINISH); 27981ad8388SMartin Matuska } else { 28081ad8388SMartin Matuska // Do the actual initialization. The first LZMA symbol must 28181ad8388SMartin Matuska // always be a literal. 28281ad8388SMartin Matuska mf_skip(mf, 1); 28381ad8388SMartin Matuska mf->read_ahead = 0; 28481ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_match[0][0], 0); 285*3b35e7eeSXin LI rc_bittree(&coder->rc, coder->literal + 0, 8, mf->buffer[0]); 28673ed8e77SXin LI ++coder->uncomp_size; 28781ad8388SMartin Matuska } 28881ad8388SMartin Matuska 28981ad8388SMartin Matuska // Initialization is done (except if empty file). 29081ad8388SMartin Matuska coder->is_initialized = true; 29181ad8388SMartin Matuska 29281ad8388SMartin Matuska return true; 29381ad8388SMartin Matuska } 29481ad8388SMartin Matuska 29581ad8388SMartin Matuska 29681ad8388SMartin Matuska static void 2971456f0f9SXin LI encode_eopm(lzma_lzma1_encoder *coder, uint32_t position) 29881ad8388SMartin Matuska { 29981ad8388SMartin Matuska const uint32_t pos_state = position & coder->pos_mask; 30081ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_match[coder->state][pos_state], 1); 30181ad8388SMartin Matuska rc_bit(&coder->rc, &coder->is_rep[coder->state], 0); 30281ad8388SMartin Matuska match(coder, pos_state, UINT32_MAX, MATCH_LEN_MIN); 30381ad8388SMartin Matuska } 30481ad8388SMartin Matuska 30581ad8388SMartin Matuska 30681ad8388SMartin Matuska /// Number of bytes that a single encoding loop in lzma_lzma_encode() can 30781ad8388SMartin Matuska /// consume from the dictionary. This limit comes from lzma_lzma_optimum() 30881ad8388SMartin Matuska /// and may need to be updated if that function is significantly modified. 30981ad8388SMartin Matuska #define LOOP_INPUT_MAX (OPTS + 1) 31081ad8388SMartin Matuska 31181ad8388SMartin Matuska 31281ad8388SMartin Matuska extern lzma_ret 3131456f0f9SXin LI lzma_lzma_encode(lzma_lzma1_encoder *restrict coder, lzma_mf *restrict mf, 31481ad8388SMartin Matuska uint8_t *restrict out, size_t *restrict out_pos, 31581ad8388SMartin Matuska size_t out_size, uint32_t limit) 31681ad8388SMartin Matuska { 31781ad8388SMartin Matuska // Initialize the stream if no data has been encoded yet. 31881ad8388SMartin Matuska if (!coder->is_initialized && !encode_init(coder, mf)) 31981ad8388SMartin Matuska return LZMA_OK; 32081ad8388SMartin Matuska 32173ed8e77SXin LI // Encode pending output bytes from the range encoder. 32273ed8e77SXin LI // At the start of the stream, encode_init() encodes one literal. 32373ed8e77SXin LI // Later there can be pending output only with LZMA1 because LZMA2 32473ed8e77SXin LI // ensures that there is always enough output space. Thus when using 32573ed8e77SXin LI // LZMA2, rc_encode() calls in this function will always return false. 32681ad8388SMartin Matuska if (rc_encode(&coder->rc, out, out_pos, out_size)) { 32773ed8e77SXin LI // We don't get here with LZMA2. 32881ad8388SMartin Matuska assert(limit == UINT32_MAX); 32981ad8388SMartin Matuska return LZMA_OK; 33081ad8388SMartin Matuska } 33181ad8388SMartin Matuska 33273ed8e77SXin LI // If the range encoder was flushed in an earlier call to this 33373ed8e77SXin LI // function but there wasn't enough output buffer space, those 33473ed8e77SXin LI // bytes would have now been encoded by the above rc_encode() call 33573ed8e77SXin LI // and the stream has now been finished. This can only happen with 33673ed8e77SXin LI // LZMA1 as LZMA2 always provides enough output buffer space. 33773ed8e77SXin LI if (coder->is_flushed) { 33873ed8e77SXin LI assert(limit == UINT32_MAX); 33973ed8e77SXin LI return LZMA_STREAM_END; 34073ed8e77SXin LI } 34173ed8e77SXin LI 34273ed8e77SXin LI while (true) { 34381ad8388SMartin Matuska // With LZMA2 we need to take care that compressed size of 34481ad8388SMartin Matuska // a chunk doesn't get too big. 345542aef48SMartin Matuska // FIXME? Check if this could be improved. 34681ad8388SMartin Matuska if (limit != UINT32_MAX 34781ad8388SMartin Matuska && (mf->read_pos - mf->read_ahead >= limit 34881ad8388SMartin Matuska || *out_pos + rc_pending(&coder->rc) 34981ad8388SMartin Matuska >= LZMA2_CHUNK_MAX 35081ad8388SMartin Matuska - LOOP_INPUT_MAX)) 35181ad8388SMartin Matuska break; 35281ad8388SMartin Matuska 35381ad8388SMartin Matuska // Check that there is some input to process. 35481ad8388SMartin Matuska if (mf->read_pos >= mf->read_limit) { 35581ad8388SMartin Matuska if (mf->action == LZMA_RUN) 35681ad8388SMartin Matuska return LZMA_OK; 35781ad8388SMartin Matuska 35881ad8388SMartin Matuska if (mf->read_ahead == 0) 35981ad8388SMartin Matuska break; 36081ad8388SMartin Matuska } 36181ad8388SMartin Matuska 36281ad8388SMartin Matuska // Get optimal match (repeat position and length). 36381ad8388SMartin Matuska // Value ranges for pos: 36453200025SRui Paulo // - [0, REPS): repeated match 36553200025SRui Paulo // - [REPS, UINT32_MAX): 36653200025SRui Paulo // match at (pos - REPS) 36781ad8388SMartin Matuska // - UINT32_MAX: not a match but a literal 36881ad8388SMartin Matuska // Value ranges for len: 36981ad8388SMartin Matuska // - [MATCH_LEN_MIN, MATCH_LEN_MAX] 37081ad8388SMartin Matuska uint32_t len; 37181ad8388SMartin Matuska uint32_t back; 37281ad8388SMartin Matuska 37381ad8388SMartin Matuska if (coder->fast_mode) 37481ad8388SMartin Matuska lzma_lzma_optimum_fast(coder, mf, &back, &len); 37581ad8388SMartin Matuska else 37673ed8e77SXin LI lzma_lzma_optimum_normal(coder, mf, &back, &len, 37773ed8e77SXin LI (uint32_t)(coder->uncomp_size)); 37881ad8388SMartin Matuska 37973ed8e77SXin LI encode_symbol(coder, mf, back, len, 38073ed8e77SXin LI (uint32_t)(coder->uncomp_size)); 38181ad8388SMartin Matuska 38273ed8e77SXin LI // If output size limiting is active (out_limit != 0), check 38373ed8e77SXin LI // if encoding this LZMA symbol would make the output size 38473ed8e77SXin LI // exceed the specified limit. 38573ed8e77SXin LI if (coder->out_limit != 0 && rc_encode_dummy( 38673ed8e77SXin LI &coder->rc, coder->out_limit)) { 38773ed8e77SXin LI // The most recent LZMA symbol would make the output 38873ed8e77SXin LI // too big. Throw it away. 38973ed8e77SXin LI rc_forget(&coder->rc); 39073ed8e77SXin LI 39173ed8e77SXin LI // FIXME: Tell the LZ layer to not read more input as 39273ed8e77SXin LI // it would be waste of time. This doesn't matter if 39373ed8e77SXin LI // output-size-limited encoding is done with a single 39473ed8e77SXin LI // call though. 39573ed8e77SXin LI 39673ed8e77SXin LI break; 39781ad8388SMartin Matuska } 39881ad8388SMartin Matuska 39973ed8e77SXin LI // This symbol will be encoded so update the uncompressed size. 40073ed8e77SXin LI coder->uncomp_size += len; 40181ad8388SMartin Matuska 40273ed8e77SXin LI // Encode the LZMA symbol. 40373ed8e77SXin LI if (rc_encode(&coder->rc, out, out_pos, out_size)) { 40473ed8e77SXin LI // Once again, this can only happen with LZMA1. 40573ed8e77SXin LI assert(limit == UINT32_MAX); 40673ed8e77SXin LI return LZMA_OK; 40773ed8e77SXin LI } 40873ed8e77SXin LI } 40973ed8e77SXin LI 41073ed8e77SXin LI // Make the uncompressed size available to the application. 41173ed8e77SXin LI if (coder->uncomp_size_ptr != NULL) 41273ed8e77SXin LI *coder->uncomp_size_ptr = coder->uncomp_size; 41373ed8e77SXin LI 41473ed8e77SXin LI // LZMA2 doesn't use EOPM at LZMA level. 41573ed8e77SXin LI // 41673ed8e77SXin LI // Plain LZMA streams without EOPM aren't supported except when 41773ed8e77SXin LI // output size limiting is enabled. 41873ed8e77SXin LI if (coder->use_eopm) 41973ed8e77SXin LI encode_eopm(coder, (uint32_t)(coder->uncomp_size)); 42081ad8388SMartin Matuska 42181ad8388SMartin Matuska // Flush the remaining bytes from the range encoder. 42281ad8388SMartin Matuska rc_flush(&coder->rc); 42381ad8388SMartin Matuska 42481ad8388SMartin Matuska // Copy the remaining bytes to the output buffer. If there 42581ad8388SMartin Matuska // isn't enough output space, we will copy out the remaining 42673ed8e77SXin LI // bytes on the next call to this function. 42781ad8388SMartin Matuska if (rc_encode(&coder->rc, out, out_pos, out_size)) { 42873ed8e77SXin LI // This cannot happen with LZMA2. 42981ad8388SMartin Matuska assert(limit == UINT32_MAX); 43073ed8e77SXin LI 43173ed8e77SXin LI coder->is_flushed = true; 43281ad8388SMartin Matuska return LZMA_OK; 43381ad8388SMartin Matuska } 43481ad8388SMartin Matuska 43581ad8388SMartin Matuska return LZMA_STREAM_END; 43681ad8388SMartin Matuska } 43781ad8388SMartin Matuska 43881ad8388SMartin Matuska 43981ad8388SMartin Matuska static lzma_ret 4401456f0f9SXin LI lzma_encode(void *coder, lzma_mf *restrict mf, 44181ad8388SMartin Matuska uint8_t *restrict out, size_t *restrict out_pos, 44281ad8388SMartin Matuska size_t out_size) 44381ad8388SMartin Matuska { 44481ad8388SMartin Matuska // Plain LZMA has no support for sync-flushing. 44581ad8388SMartin Matuska if (unlikely(mf->action == LZMA_SYNC_FLUSH)) 44681ad8388SMartin Matuska return LZMA_OPTIONS_ERROR; 44781ad8388SMartin Matuska 44881ad8388SMartin Matuska return lzma_lzma_encode(coder, mf, out, out_pos, out_size, UINT32_MAX); 44981ad8388SMartin Matuska } 45081ad8388SMartin Matuska 45181ad8388SMartin Matuska 45273ed8e77SXin LI static lzma_ret 45373ed8e77SXin LI lzma_lzma_set_out_limit( 45473ed8e77SXin LI void *coder_ptr, uint64_t *uncomp_size, uint64_t out_limit) 45573ed8e77SXin LI { 45673ed8e77SXin LI // Minimum output size is 5 bytes but that cannot hold any output 45773ed8e77SXin LI // so we use 6 bytes. 45873ed8e77SXin LI if (out_limit < 6) 45973ed8e77SXin LI return LZMA_BUF_ERROR; 46073ed8e77SXin LI 46173ed8e77SXin LI lzma_lzma1_encoder *coder = coder_ptr; 46273ed8e77SXin LI coder->out_limit = out_limit; 46373ed8e77SXin LI coder->uncomp_size_ptr = uncomp_size; 46473ed8e77SXin LI coder->use_eopm = false; 46573ed8e77SXin LI return LZMA_OK; 46673ed8e77SXin LI } 46773ed8e77SXin LI 46873ed8e77SXin LI 46981ad8388SMartin Matuska //////////////////// 47081ad8388SMartin Matuska // Initialization // 47181ad8388SMartin Matuska //////////////////// 47281ad8388SMartin Matuska 47381ad8388SMartin Matuska static bool 47481ad8388SMartin Matuska is_options_valid(const lzma_options_lzma *options) 47581ad8388SMartin Matuska { 47681ad8388SMartin Matuska // Validate some of the options. LZ encoder validates nice_len too 47781ad8388SMartin Matuska // but we need a valid value here earlier. 47881ad8388SMartin Matuska return is_lclppb_valid(options) 47981ad8388SMartin Matuska && options->nice_len >= MATCH_LEN_MIN 48081ad8388SMartin Matuska && options->nice_len <= MATCH_LEN_MAX 48181ad8388SMartin Matuska && (options->mode == LZMA_MODE_FAST 48281ad8388SMartin Matuska || options->mode == LZMA_MODE_NORMAL); 48381ad8388SMartin Matuska } 48481ad8388SMartin Matuska 48581ad8388SMartin Matuska 48681ad8388SMartin Matuska static void 48781ad8388SMartin Matuska set_lz_options(lzma_lz_options *lz_options, const lzma_options_lzma *options) 48881ad8388SMartin Matuska { 48981ad8388SMartin Matuska // LZ encoder initialization does the validation for these so we 49081ad8388SMartin Matuska // don't need to validate here. 49181ad8388SMartin Matuska lz_options->before_size = OPTS; 49281ad8388SMartin Matuska lz_options->dict_size = options->dict_size; 49381ad8388SMartin Matuska lz_options->after_size = LOOP_INPUT_MAX; 49481ad8388SMartin Matuska lz_options->match_len_max = MATCH_LEN_MAX; 49573ed8e77SXin LI lz_options->nice_len = my_max(mf_get_hash_bytes(options->mf), 49673ed8e77SXin LI options->nice_len); 49781ad8388SMartin Matuska lz_options->match_finder = options->mf; 49881ad8388SMartin Matuska lz_options->depth = options->depth; 49981ad8388SMartin Matuska lz_options->preset_dict = options->preset_dict; 50081ad8388SMartin Matuska lz_options->preset_dict_size = options->preset_dict_size; 50181ad8388SMartin Matuska return; 50281ad8388SMartin Matuska } 50381ad8388SMartin Matuska 50481ad8388SMartin Matuska 50581ad8388SMartin Matuska static void 50681ad8388SMartin Matuska length_encoder_reset(lzma_length_encoder *lencoder, 50781ad8388SMartin Matuska const uint32_t num_pos_states, const bool fast_mode) 50881ad8388SMartin Matuska { 50981ad8388SMartin Matuska bit_reset(lencoder->choice); 51081ad8388SMartin Matuska bit_reset(lencoder->choice2); 51181ad8388SMartin Matuska 51281ad8388SMartin Matuska for (size_t pos_state = 0; pos_state < num_pos_states; ++pos_state) { 51381ad8388SMartin Matuska bittree_reset(lencoder->low[pos_state], LEN_LOW_BITS); 51481ad8388SMartin Matuska bittree_reset(lencoder->mid[pos_state], LEN_MID_BITS); 51581ad8388SMartin Matuska } 51681ad8388SMartin Matuska 51781ad8388SMartin Matuska bittree_reset(lencoder->high, LEN_HIGH_BITS); 51881ad8388SMartin Matuska 51981ad8388SMartin Matuska if (!fast_mode) 520fe50a38eSXin LI for (uint32_t pos_state = 0; pos_state < num_pos_states; 52181ad8388SMartin Matuska ++pos_state) 52281ad8388SMartin Matuska length_update_prices(lencoder, pos_state); 52381ad8388SMartin Matuska 52481ad8388SMartin Matuska return; 52581ad8388SMartin Matuska } 52681ad8388SMartin Matuska 52781ad8388SMartin Matuska 52881ad8388SMartin Matuska extern lzma_ret 5291456f0f9SXin LI lzma_lzma_encoder_reset(lzma_lzma1_encoder *coder, 5301456f0f9SXin LI const lzma_options_lzma *options) 53181ad8388SMartin Matuska { 53281ad8388SMartin Matuska if (!is_options_valid(options)) 53381ad8388SMartin Matuska return LZMA_OPTIONS_ERROR; 53481ad8388SMartin Matuska 53581ad8388SMartin Matuska coder->pos_mask = (1U << options->pb) - 1; 53681ad8388SMartin Matuska coder->literal_context_bits = options->lc; 537*3b35e7eeSXin LI coder->literal_mask = literal_mask_calc(options->lc, options->lp); 53881ad8388SMartin Matuska 53981ad8388SMartin Matuska // Range coder 54081ad8388SMartin Matuska rc_reset(&coder->rc); 54181ad8388SMartin Matuska 54281ad8388SMartin Matuska // State 54381ad8388SMartin Matuska coder->state = STATE_LIT_LIT; 54453200025SRui Paulo for (size_t i = 0; i < REPS; ++i) 54581ad8388SMartin Matuska coder->reps[i] = 0; 54681ad8388SMartin Matuska 54781ad8388SMartin Matuska literal_init(coder->literal, options->lc, options->lp); 54881ad8388SMartin Matuska 54981ad8388SMartin Matuska // Bit encoders 55081ad8388SMartin Matuska for (size_t i = 0; i < STATES; ++i) { 55181ad8388SMartin Matuska for (size_t j = 0; j <= coder->pos_mask; ++j) { 55281ad8388SMartin Matuska bit_reset(coder->is_match[i][j]); 55381ad8388SMartin Matuska bit_reset(coder->is_rep0_long[i][j]); 55481ad8388SMartin Matuska } 55581ad8388SMartin Matuska 55681ad8388SMartin Matuska bit_reset(coder->is_rep[i]); 55781ad8388SMartin Matuska bit_reset(coder->is_rep0[i]); 55881ad8388SMartin Matuska bit_reset(coder->is_rep1[i]); 55981ad8388SMartin Matuska bit_reset(coder->is_rep2[i]); 56081ad8388SMartin Matuska } 56181ad8388SMartin Matuska 56253200025SRui Paulo for (size_t i = 0; i < FULL_DISTANCES - DIST_MODEL_END; ++i) 56353200025SRui Paulo bit_reset(coder->dist_special[i]); 56481ad8388SMartin Matuska 56581ad8388SMartin Matuska // Bit tree encoders 56653200025SRui Paulo for (size_t i = 0; i < DIST_STATES; ++i) 56753200025SRui Paulo bittree_reset(coder->dist_slot[i], DIST_SLOT_BITS); 56881ad8388SMartin Matuska 56953200025SRui Paulo bittree_reset(coder->dist_align, ALIGN_BITS); 57081ad8388SMartin Matuska 57181ad8388SMartin Matuska // Length encoders 57281ad8388SMartin Matuska length_encoder_reset(&coder->match_len_encoder, 57381ad8388SMartin Matuska 1U << options->pb, coder->fast_mode); 57481ad8388SMartin Matuska 57581ad8388SMartin Matuska length_encoder_reset(&coder->rep_len_encoder, 57681ad8388SMartin Matuska 1U << options->pb, coder->fast_mode); 57781ad8388SMartin Matuska 57881ad8388SMartin Matuska // Price counts are incremented every time appropriate probabilities 57981ad8388SMartin Matuska // are changed. price counts are set to zero when the price tables 58081ad8388SMartin Matuska // are updated, which is done when the appropriate price counts have 58181ad8388SMartin Matuska // big enough value, and lzma_mf.read_ahead == 0 which happens at 58281ad8388SMartin Matuska // least every OPTS (a few thousand) possible price count increments. 58381ad8388SMartin Matuska // 58481ad8388SMartin Matuska // By resetting price counts to UINT32_MAX / 2, we make sure that the 58581ad8388SMartin Matuska // price tables will be initialized before they will be used (since 58681ad8388SMartin Matuska // the value is definitely big enough), and that it is OK to increment 58781ad8388SMartin Matuska // price counts without risk of integer overflow (since UINT32_MAX / 2 58881ad8388SMartin Matuska // is small enough). The current code doesn't increment price counts 58981ad8388SMartin Matuska // before initializing price tables, but it maybe done in future if 59081ad8388SMartin Matuska // we add support for saving the state between LZMA2 chunks. 59181ad8388SMartin Matuska coder->match_price_count = UINT32_MAX / 2; 59281ad8388SMartin Matuska coder->align_price_count = UINT32_MAX / 2; 59381ad8388SMartin Matuska 59481ad8388SMartin Matuska coder->opts_end_index = 0; 59581ad8388SMartin Matuska coder->opts_current_index = 0; 59681ad8388SMartin Matuska 59781ad8388SMartin Matuska return LZMA_OK; 59881ad8388SMartin Matuska } 59981ad8388SMartin Matuska 60081ad8388SMartin Matuska 60181ad8388SMartin Matuska extern lzma_ret 60273ed8e77SXin LI lzma_lzma_encoder_create(void **coder_ptr, const lzma_allocator *allocator, 60373ed8e77SXin LI lzma_vli id, const lzma_options_lzma *options, 60473ed8e77SXin LI lzma_lz_options *lz_options) 60581ad8388SMartin Matuska { 60673ed8e77SXin LI assert(id == LZMA_FILTER_LZMA1 || id == LZMA_FILTER_LZMA1EXT 60773ed8e77SXin LI || id == LZMA_FILTER_LZMA2); 60873ed8e77SXin LI 6091456f0f9SXin LI // Allocate lzma_lzma1_encoder if it wasn't already allocated. 61081ad8388SMartin Matuska if (*coder_ptr == NULL) { 6111456f0f9SXin LI *coder_ptr = lzma_alloc(sizeof(lzma_lzma1_encoder), allocator); 61281ad8388SMartin Matuska if (*coder_ptr == NULL) 61381ad8388SMartin Matuska return LZMA_MEM_ERROR; 61481ad8388SMartin Matuska } 61581ad8388SMartin Matuska 6161456f0f9SXin LI lzma_lzma1_encoder *coder = *coder_ptr; 61781ad8388SMartin Matuska 6180ca90ed4SXin LI // Set compression mode. Note that we haven't validated the options 6190ca90ed4SXin LI // yet. Invalid options will get rejected by lzma_lzma_encoder_reset() 6200ca90ed4SXin LI // call at the end of this function. 62181ad8388SMartin Matuska switch (options->mode) { 62281ad8388SMartin Matuska case LZMA_MODE_FAST: 62381ad8388SMartin Matuska coder->fast_mode = true; 62481ad8388SMartin Matuska break; 62581ad8388SMartin Matuska 62681ad8388SMartin Matuska case LZMA_MODE_NORMAL: { 62781ad8388SMartin Matuska coder->fast_mode = false; 62881ad8388SMartin Matuska 62981ad8388SMartin Matuska // Set dist_table_size. 63081ad8388SMartin Matuska // Round the dictionary size up to next 2^n. 6310ca90ed4SXin LI // 6320ca90ed4SXin LI // Currently the maximum encoder dictionary size 6330ca90ed4SXin LI // is 1.5 GiB due to lz_encoder.c and here we need 6340ca90ed4SXin LI // to be below 2 GiB to make the rounded up value 6351f3ced26SXin LI // fit in an uint32_t and avoid an infinite while-loop 6360ca90ed4SXin LI // (and undefined behavior due to a too large shift). 6370ca90ed4SXin LI // So do the same check as in LZ encoder, 6380ca90ed4SXin LI // limiting to 1.5 GiB. 6390ca90ed4SXin LI if (options->dict_size > (UINT32_C(1) << 30) 6400ca90ed4SXin LI + (UINT32_C(1) << 29)) 6410ca90ed4SXin LI return LZMA_OPTIONS_ERROR; 6420ca90ed4SXin LI 64381ad8388SMartin Matuska uint32_t log_size = 0; 64481ad8388SMartin Matuska while ((UINT32_C(1) << log_size) < options->dict_size) 64581ad8388SMartin Matuska ++log_size; 64681ad8388SMartin Matuska 64781ad8388SMartin Matuska coder->dist_table_size = log_size * 2; 64881ad8388SMartin Matuska 64981ad8388SMartin Matuska // Length encoders' price table size 65073ed8e77SXin LI const uint32_t nice_len = my_max( 65173ed8e77SXin LI mf_get_hash_bytes(options->mf), 65273ed8e77SXin LI options->nice_len); 65373ed8e77SXin LI 65481ad8388SMartin Matuska coder->match_len_encoder.table_size 65573ed8e77SXin LI = nice_len + 1 - MATCH_LEN_MIN; 65681ad8388SMartin Matuska coder->rep_len_encoder.table_size 65773ed8e77SXin LI = nice_len + 1 - MATCH_LEN_MIN; 65881ad8388SMartin Matuska break; 65981ad8388SMartin Matuska } 66081ad8388SMartin Matuska 66181ad8388SMartin Matuska default: 66281ad8388SMartin Matuska return LZMA_OPTIONS_ERROR; 66381ad8388SMartin Matuska } 66481ad8388SMartin Matuska 66581ad8388SMartin Matuska // We don't need to write the first byte as literal if there is 66681ad8388SMartin Matuska // a non-empty preset dictionary. encode_init() wouldn't even work 66781ad8388SMartin Matuska // if there is a non-empty preset dictionary, because encode_init() 66881ad8388SMartin Matuska // assumes that position is zero and previous byte is also zero. 66981ad8388SMartin Matuska coder->is_initialized = options->preset_dict != NULL 67081ad8388SMartin Matuska && options->preset_dict_size > 0; 67181ad8388SMartin Matuska coder->is_flushed = false; 67273ed8e77SXin LI coder->uncomp_size = 0; 67373ed8e77SXin LI coder->uncomp_size_ptr = NULL; 67473ed8e77SXin LI 6751f3ced26SXin LI // Output size limiting is disabled by default. 67673ed8e77SXin LI coder->out_limit = 0; 67773ed8e77SXin LI 67873ed8e77SXin LI // Determine if end marker is wanted: 67973ed8e77SXin LI // - It is never used with LZMA2. 68073ed8e77SXin LI // - It is always used with LZMA_FILTER_LZMA1 (unless 68173ed8e77SXin LI // lzma_lzma_set_out_limit() is called later). 68273ed8e77SXin LI // - LZMA_FILTER_LZMA1EXT has a flag for it in the options. 68373ed8e77SXin LI coder->use_eopm = (id == LZMA_FILTER_LZMA1); 68473ed8e77SXin LI if (id == LZMA_FILTER_LZMA1EXT) { 68573ed8e77SXin LI // Check if unsupported flags are present. 68673ed8e77SXin LI if (options->ext_flags & ~LZMA_LZMA1EXT_ALLOW_EOPM) 68773ed8e77SXin LI return LZMA_OPTIONS_ERROR; 68873ed8e77SXin LI 68973ed8e77SXin LI coder->use_eopm = (options->ext_flags 69073ed8e77SXin LI & LZMA_LZMA1EXT_ALLOW_EOPM) != 0; 69173ed8e77SXin LI 69273ed8e77SXin LI // TODO? As long as there are no filters that change the size 69373ed8e77SXin LI // of the data, it is enough to look at lzma_stream.total_in 69473ed8e77SXin LI // after encoding has been finished to know the uncompressed 69573ed8e77SXin LI // size of the LZMA1 stream. But in the future there could be 69673ed8e77SXin LI // filters that change the size of the data and then total_in 69773ed8e77SXin LI // doesn't work as the LZMA1 stream size might be different 69873ed8e77SXin LI // due to another filter in the chain. The problem is simple 69973ed8e77SXin LI // to solve: Add another flag to ext_flags and then set 70073ed8e77SXin LI // coder->uncomp_size_ptr to the address stored in 70173ed8e77SXin LI // lzma_options_lzma.reserved_ptr2 (or _ptr1). 70273ed8e77SXin LI } 70381ad8388SMartin Matuska 70481ad8388SMartin Matuska set_lz_options(lz_options, options); 70581ad8388SMartin Matuska 70681ad8388SMartin Matuska return lzma_lzma_encoder_reset(coder, options); 70781ad8388SMartin Matuska } 70881ad8388SMartin Matuska 70981ad8388SMartin Matuska 71081ad8388SMartin Matuska static lzma_ret 71153200025SRui Paulo lzma_encoder_init(lzma_lz_encoder *lz, const lzma_allocator *allocator, 71273ed8e77SXin LI lzma_vli id, const void *options, lzma_lz_options *lz_options) 71381ad8388SMartin Matuska { 714*3b35e7eeSXin LI if (options == NULL) 715*3b35e7eeSXin LI return LZMA_PROG_ERROR; 716*3b35e7eeSXin LI 71781ad8388SMartin Matuska lz->code = &lzma_encode; 71873ed8e77SXin LI lz->set_out_limit = &lzma_lzma_set_out_limit; 71981ad8388SMartin Matuska return lzma_lzma_encoder_create( 72073ed8e77SXin LI &lz->coder, allocator, id, options, lz_options); 72181ad8388SMartin Matuska } 72281ad8388SMartin Matuska 72381ad8388SMartin Matuska 72481ad8388SMartin Matuska extern lzma_ret 72553200025SRui Paulo lzma_lzma_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, 72681ad8388SMartin Matuska const lzma_filter_info *filters) 72781ad8388SMartin Matuska { 72881ad8388SMartin Matuska return lzma_lz_encoder_init( 72981ad8388SMartin Matuska next, allocator, filters, &lzma_encoder_init); 73081ad8388SMartin Matuska } 73181ad8388SMartin Matuska 73281ad8388SMartin Matuska 73381ad8388SMartin Matuska extern uint64_t 73481ad8388SMartin Matuska lzma_lzma_encoder_memusage(const void *options) 73581ad8388SMartin Matuska { 73681ad8388SMartin Matuska if (!is_options_valid(options)) 73781ad8388SMartin Matuska return UINT64_MAX; 73881ad8388SMartin Matuska 73981ad8388SMartin Matuska lzma_lz_options lz_options; 74081ad8388SMartin Matuska set_lz_options(&lz_options, options); 74181ad8388SMartin Matuska 74281ad8388SMartin Matuska const uint64_t lz_memusage = lzma_lz_encoder_memusage(&lz_options); 74381ad8388SMartin Matuska if (lz_memusage == UINT64_MAX) 74481ad8388SMartin Matuska return UINT64_MAX; 74581ad8388SMartin Matuska 7461456f0f9SXin LI return (uint64_t)(sizeof(lzma_lzma1_encoder)) + lz_memusage; 74781ad8388SMartin Matuska } 74881ad8388SMartin Matuska 74981ad8388SMartin Matuska 75081ad8388SMartin Matuska extern bool 75181ad8388SMartin Matuska lzma_lzma_lclppb_encode(const lzma_options_lzma *options, uint8_t *byte) 75281ad8388SMartin Matuska { 75381ad8388SMartin Matuska if (!is_lclppb_valid(options)) 75481ad8388SMartin Matuska return true; 75581ad8388SMartin Matuska 75681ad8388SMartin Matuska *byte = (options->pb * 5 + options->lp) * 9 + options->lc; 75781ad8388SMartin Matuska assert(*byte <= (4 * 5 + 4) * 9 + 8); 75881ad8388SMartin Matuska 75981ad8388SMartin Matuska return false; 76081ad8388SMartin Matuska } 76181ad8388SMartin Matuska 76281ad8388SMartin Matuska 76381ad8388SMartin Matuska #ifdef HAVE_ENCODER_LZMA1 76481ad8388SMartin Matuska extern lzma_ret 76581ad8388SMartin Matuska lzma_lzma_props_encode(const void *options, uint8_t *out) 76681ad8388SMartin Matuska { 7679e6bbe47SXin LI if (options == NULL) 7689e6bbe47SXin LI return LZMA_PROG_ERROR; 7699e6bbe47SXin LI 77081ad8388SMartin Matuska const lzma_options_lzma *const opt = options; 77181ad8388SMartin Matuska 77281ad8388SMartin Matuska if (lzma_lzma_lclppb_encode(opt, out)) 77381ad8388SMartin Matuska return LZMA_PROG_ERROR; 77481ad8388SMartin Matuska 775a8675d92SXin LI write32le(out + 1, opt->dict_size); 77681ad8388SMartin Matuska 77781ad8388SMartin Matuska return LZMA_OK; 77881ad8388SMartin Matuska } 77981ad8388SMartin Matuska #endif 78081ad8388SMartin Matuska 78181ad8388SMartin Matuska 78281ad8388SMartin Matuska extern LZMA_API(lzma_bool) 78381ad8388SMartin Matuska lzma_mode_is_supported(lzma_mode mode) 78481ad8388SMartin Matuska { 78581ad8388SMartin Matuska return mode == LZMA_MODE_FAST || mode == LZMA_MODE_NORMAL; 78681ad8388SMartin Matuska } 787