| /* Copyright 2015 Google Inc. All Rights Reserved. |
| |
| Distributed under MIT license. |
| See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
| */ |
| |
| /* Brotli state for partial streaming decoding. */ |
| |
| #ifndef BROTLI_DEC_STATE_H_ |
| #define BROTLI_DEC_STATE_H_ |
| |
| #include <stdio.h> |
| #include "./bit_reader.h" |
| #include "./huffman.h" |
| #include "./types.h" |
| |
| #if defined(__cplusplus) || defined(c_plusplus) |
| extern "C" { |
| #endif |
| |
| typedef enum { |
| BROTLI_STATE_UNINITED, |
| BROTLI_STATE_METABLOCK_BEGIN, |
| BROTLI_STATE_METABLOCK_HEADER, |
| BROTLI_STATE_METABLOCK_HEADER_2, |
| BROTLI_STATE_CONTEXT_MODES, |
| BROTLI_STATE_COMMAND_BEGIN, |
| BROTLI_STATE_COMMAND_INNER, |
| BROTLI_STATE_COMMAND_POST_DECODE_LITERALS, |
| BROTLI_STATE_COMMAND_POST_WRAP_COPY, |
| BROTLI_STATE_UNCOMPRESSED, |
| BROTLI_STATE_METADATA, |
| BROTLI_STATE_COMMAND_INNER_WRITE, |
| BROTLI_STATE_METABLOCK_DONE, |
| BROTLI_STATE_COMMAND_POST_WRITE_1, |
| BROTLI_STATE_COMMAND_POST_WRITE_2, |
| BROTLI_STATE_HUFFMAN_CODE_0, |
| BROTLI_STATE_HUFFMAN_CODE_1, |
| BROTLI_STATE_HUFFMAN_CODE_2, |
| BROTLI_STATE_HUFFMAN_CODE_3, |
| BROTLI_STATE_CONTEXT_MAP_1, |
| BROTLI_STATE_CONTEXT_MAP_2, |
| BROTLI_STATE_TREE_GROUP, |
| BROTLI_STATE_DONE |
| } BrotliRunningState; |
| |
| typedef enum { |
| BROTLI_STATE_METABLOCK_HEADER_NONE, |
| BROTLI_STATE_METABLOCK_HEADER_EMPTY, |
| BROTLI_STATE_METABLOCK_HEADER_NIBBLES, |
| BROTLI_STATE_METABLOCK_HEADER_SIZE, |
| BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED, |
| BROTLI_STATE_METABLOCK_HEADER_RESERVED, |
| BROTLI_STATE_METABLOCK_HEADER_BYTES, |
| BROTLI_STATE_METABLOCK_HEADER_METADATA |
| } BrotliRunningMetablockHeaderState; |
| |
| typedef enum { |
| BROTLI_STATE_UNCOMPRESSED_NONE, |
| BROTLI_STATE_UNCOMPRESSED_WRITE |
| } BrotliRunningUncompressedState; |
| |
| typedef enum { |
| BROTLI_STATE_TREE_GROUP_NONE, |
| BROTLI_STATE_TREE_GROUP_LOOP |
| } BrotliRunningTreeGroupState; |
| |
| typedef enum { |
| BROTLI_STATE_CONTEXT_MAP_NONE, |
| BROTLI_STATE_CONTEXT_MAP_READ_PREFIX, |
| BROTLI_STATE_CONTEXT_MAP_HUFFMAN, |
| BROTLI_STATE_CONTEXT_MAP_DECODE, |
| BROTLI_STATE_CONTEXT_MAP_TRANSFORM |
| } BrotliRunningContextMapState; |
| |
| typedef enum { |
| BROTLI_STATE_HUFFMAN_NONE, |
| BROTLI_STATE_HUFFMAN_SIMPLE_SIZE, |
| BROTLI_STATE_HUFFMAN_SIMPLE_READ, |
| BROTLI_STATE_HUFFMAN_SIMPLE_BUILD, |
| BROTLI_STATE_HUFFMAN_COMPLEX, |
| BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS |
| } BrotliRunningHuffmanState; |
| |
| typedef enum { |
| BROTLI_STATE_DECODE_UINT8_NONE, |
| BROTLI_STATE_DECODE_UINT8_SHORT, |
| BROTLI_STATE_DECODE_UINT8_LONG |
| } BrotliRunningDecodeUint8State; |
| |
| typedef enum { |
| BROTLI_STATE_READ_BLOCK_LENGTH_NONE, |
| BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX |
| } BrotliRunningReadBlockLengthState; |
| |
| struct BrotliStateStruct { |
| BrotliRunningState state; |
| BrotliBitReader br; |
| |
| brotli_alloc_func alloc_func; |
| brotli_free_func free_func; |
| void* memory_manager_opaque; |
| |
| /* Temporary storage for remaining input. */ |
| union { |
| uint64_t u64; |
| uint8_t u8[8]; |
| } buffer; |
| uint32_t buffer_length; |
| |
| /* This counter is reused for several disjoint loops. */ |
| int loop_counter; |
| int pos; |
| int max_backward_distance; |
| int max_backward_distance_minus_custom_dict_size; |
| int max_distance; |
| int ringbuffer_size; |
| int ringbuffer_mask; |
| int dist_rb_idx; |
| int dist_rb[4]; |
| uint8_t* ringbuffer; |
| uint8_t* ringbuffer_end; |
| HuffmanCode* htree_command; |
| const uint8_t* context_lookup1; |
| const uint8_t* context_lookup2; |
| uint8_t* context_map_slice; |
| uint8_t* dist_context_map_slice; |
| |
| uint32_t sub_loop_counter; |
| |
| /* This ring buffer holds a few past copy distances that will be used by */ |
| /* some special distance codes. */ |
| HuffmanTreeGroup literal_hgroup; |
| HuffmanTreeGroup insert_copy_hgroup; |
| HuffmanTreeGroup distance_hgroup; |
| HuffmanCode* block_type_trees; |
| HuffmanCode* block_len_trees; |
| /* This is true if the literal context map histogram type always matches the |
| block type. It is then not needed to keep the context (faster decoding). */ |
| int trivial_literal_context; |
| int distance_context; |
| int meta_block_remaining_len; |
| uint32_t block_length_index; |
| uint32_t block_length[3]; |
| uint32_t num_block_types[3]; |
| uint32_t block_type_rb[6]; |
| uint32_t distance_postfix_bits; |
| uint32_t num_direct_distance_codes; |
| int distance_postfix_mask; |
| uint32_t num_dist_htrees; |
| uint8_t* dist_context_map; |
| HuffmanCode *literal_htree; |
| uint8_t literal_htree_index; |
| uint8_t dist_htree_index; |
| uint32_t repeat_code_len; |
| uint32_t prev_code_len; |
| |
| |
| int copy_length; |
| int distance_code; |
| |
| /* For partial write operations */ |
| size_t rb_roundtrips; /* How many times we went around the ringbuffer */ |
| size_t partial_pos_out; /* How much output to the user in total (<= rb) */ |
| |
| /* For ReadHuffmanCode */ |
| uint32_t symbol; |
| uint32_t repeat; |
| uint32_t space; |
| |
| HuffmanCode table[32]; |
| /* List of of symbol chains. */ |
| uint16_t* symbol_lists; |
| /* Storage from symbol_lists. */ |
| uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 + |
| BROTLI_HUFFMAN_MAX_CODE_LENGTHS_SIZE]; |
| /* Tails of symbol chains. */ |
| int next_symbol[32]; |
| uint8_t code_length_code_lengths[18]; |
| /* Population counts for the code lengths */ |
| uint16_t code_length_histo[16]; |
| |
| /* For HuffmanTreeGroupDecode */ |
| int htree_index; |
| HuffmanCode* next; |
| |
| /* For DecodeContextMap */ |
| uint32_t context_index; |
| uint32_t max_run_length_prefix; |
| uint32_t code; |
| HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_TABLE_SIZE]; |
| |
| /* For InverseMoveToFrontTransform */ |
| uint32_t mtf_upper_bound; |
| uint8_t mtf[256]; |
| |
| /* For custom dictionaries */ |
| const uint8_t* custom_dict; |
| int custom_dict_size; |
| |
| /* less used attributes are in the end of this struct */ |
| /* States inside function calls */ |
| BrotliRunningMetablockHeaderState substate_metablock_header; |
| BrotliRunningTreeGroupState substate_tree_group; |
| BrotliRunningContextMapState substate_context_map; |
| BrotliRunningUncompressedState substate_uncompressed; |
| BrotliRunningHuffmanState substate_huffman; |
| BrotliRunningDecodeUint8State substate_decode_uint8; |
| BrotliRunningReadBlockLengthState substate_read_block_length; |
| |
| uint8_t is_last_metablock; |
| uint8_t is_uncompressed; |
| uint8_t is_metadata; |
| uint8_t size_nibbles; |
| uint32_t window_bits; |
| |
| uint32_t num_literal_htrees; |
| uint8_t* context_map; |
| uint8_t* context_modes; |
| |
| uint8_t* legacy_input_buffer; |
| uint8_t* legacy_output_buffer; |
| size_t legacy_input_len; |
| size_t legacy_output_len; |
| size_t legacy_input_pos; |
| size_t legacy_output_pos; |
| }; |
| |
| typedef struct BrotliStateStruct BrotliState; |
| |
| void BrotliStateInit(BrotliState* s); |
| void BrotliStateInitWithCustomAllocators(BrotliState* s, |
| brotli_alloc_func alloc_func, |
| brotli_free_func free_func, |
| void* opaque); |
| void BrotliStateCleanup(BrotliState* s); |
| void BrotliStateMetablockBegin(BrotliState* s); |
| void BrotliStateCleanupAfterMetablock(BrotliState* s); |
| void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group, |
| uint32_t alphabet_size, uint32_t ntrees); |
| void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group); |
| |
| /* Returns 1, if s is in a state where we have not read any input bytes yet, |
| and 0 otherwise */ |
| int BrotliStateIsStreamStart(const BrotliState* s); |
| |
| /* Returns 1, if s is in a state where we reached the end of the input and |
| produced all of the output, and 0 otherwise. */ |
| int BrotliStateIsStreamEnd(const BrotliState* s); |
| |
| |
| #if defined(__cplusplus) || defined(c_plusplus) |
| } /* extern "C" */ |
| #endif |
| |
| #endif /* BROTLI_DEC_STATE_H_ */ |