/////////////////////////////////////////////////////////////////////////////// // /// \file lzma_encoder_private.h /// \brief Private definitions for LZMA encoder // // Copyright (C) 1999-2006 Igor Pavlov // Copyright (C) 2007 Lasse Collin // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // /////////////////////////////////////////////////////////////////////////////// #ifndef LZMA_LZMA_ENCODER_PRIVATE_H #define LZMA_LZMA_ENCODER_PRIVATE_H #include "lzma_encoder.h" #include "lzma_common.h" #include "lz_encoder.h" // We need space for about two encoding loops, because there is no check // for available buffer space before end of payload marker gets written. // 2*26 bytes should be enough for this... but Lasse isn't very sure about // the exact value. 64 bytes certainly is enough. :-) #define RC_BUFFER_SIZE 64 #include "range_encoder.h" #define move_pos(num) \ do { \ assert((int32_t)(num) >= 0); \ if ((num) != 0) { \ coder->additional_offset += num; \ coder->lz.skip(&coder->lz, num); \ } \ } while (0) #define get_pos_slot(pos) \ ((pos) < (1 << 11) \ ? lzma_fastpos[pos] \ : ((pos) < (1 << 21) \ ? lzma_fastpos[(pos) >> 10] + 20 \ : lzma_fastpos[(pos) >> 20] + 40)) #define get_pos_slot_2(pos) \ ((pos) < (1 << 17) \ ? lzma_fastpos[(pos) >> 6] + 12 \ : ((pos) < (1 << 27) \ ? lzma_fastpos[(pos) >> 16] + 32 \ : lzma_fastpos[(pos) >> 26] + 52)) /// This isn't modified once its contents have been /// initialized by lzma_fastpos_init(). extern uint8_t lzma_fastpos[1 << 11]; typedef struct { probability choice; probability choice2; probability low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; probability mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; probability high[LEN_HIGH_SYMBOLS]; uint32_t prices[POS_STATES_MAX][LEN_SYMBOLS]; uint32_t table_size; uint32_t counters[POS_STATES_MAX]; } lzma_length_encoder; typedef struct { uint32_t state; bool prev_1_is_char; bool prev_2; uint32_t pos_prev_2; uint32_t back_prev_2; uint32_t price; uint32_t pos_prev; // pos_next; uint32_t back_prev; uint32_t backs[4]; } lzma_optimal; struct lzma_coder_s { // Next coder in the chain lzma_next_coder next; // In window and match finder lzma_lz_encoder lz; // Range encoder lzma_range_encoder rc; // State uint32_t state; uint8_t previous_byte; uint32_t rep_distances[REP_DISTANCES]; // Misc uint32_t match_distances[MATCH_MAX_LEN * 2 + 2 + 1]; uint32_t num_distance_pairs; uint32_t additional_offset; uint32_t now_pos; // Lowest 32 bits are enough here. bool best_compression; ///< True when LZMA_MODE_BEST is used bool is_initialized; // Literal encoder lzma_literal_coder *literal_coder; // Bit encoders probability is_match[STATES][POS_STATES_MAX]; probability is_rep[STATES]; probability is_rep0[STATES]; probability is_rep1[STATES]; probability is_rep2[STATES]; probability is_rep0_long[STATES][POS_STATES_MAX]; probability pos_encoders[FULL_DISTANCES - END_POS_MODEL_INDEX]; // Bit Tree Encoders probability pos_slot_encoder[LEN_TO_POS_STATES][1 << POS_SLOT_BITS]; probability pos_align_encoder[1 << ALIGN_BITS]; // Length encoders lzma_length_encoder len_encoder; lzma_length_encoder rep_match_len_encoder; // Optimal lzma_optimal optimum[OPTS]; uint32_t optimum_end_index; uint32_t optimum_current_index; uint32_t longest_match_length; bool longest_match_was_found; // Prices uint32_t pos_slot_prices[LEN_TO_POS_STATES][DIST_TABLE_SIZE_MAX]; uint32_t distances_prices[LEN_TO_POS_STATES][FULL_DISTANCES]; uint32_t align_prices[ALIGN_TABLE_SIZE]; uint32_t align_price_count; uint32_t dist_table_size; uint32_t match_price_count; // LZMA specific settings uint32_t dictionary_size; ///< Size in bytes uint32_t fast_bytes; uint32_t pos_state_bits; uint32_t pos_mask; ///< (1 << pos_state_bits) - 1 }; extern void lzma_length_encoder_update_table(lzma_length_encoder *lencoder, const uint32_t pos_state); extern bool lzma_lzma_encode(lzma_coder *coder, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size); extern void lzma_get_optimum(lzma_coder *restrict coder, uint32_t *restrict back_res, uint32_t *restrict len_res); extern void lzma_get_optimum_fast(lzma_coder *restrict coder, uint32_t *restrict back_res, uint32_t *restrict len_res); // NOTE: Don't add 'restrict'. static inline void lzma_read_match_distances(lzma_coder *coder, uint32_t *len_res, uint32_t *num_distance_pairs) { *len_res = 0; coder->lz.get_matches(&coder->lz, coder->match_distances); *num_distance_pairs = coder->match_distances[0]; if (*num_distance_pairs > 0) { *len_res = coder->match_distances[*num_distance_pairs - 1]; assert(*len_res <= MATCH_MAX_LEN); if (*len_res == coder->fast_bytes) { uint32_t offset = *len_res - 1; const uint32_t distance = coder->match_distances[ *num_distance_pairs] + 1; uint32_t limit = MATCH_MAX_LEN - *len_res; assert(offset + limit < coder->lz.keep_size_after); assert(coder->lz.read_pos <= coder->lz.write_pos); // If we are close to end of the stream, we may need // to limit the length of the match. if (coder->lz.write_pos - coder->lz.read_pos < offset + limit) limit = coder->lz.write_pos - (coder->lz.read_pos + offset); offset += coder->lz.read_pos; uint32_t i = 0; while (i < limit && coder->lz.buffer[offset + i] == coder->lz.buffer[ offset + i - distance]) ++i; *len_res += i; } } ++coder->additional_offset; return; } #endif