/* 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 "../common/constants.h" | |
#include "../common/types.h" | |
#include "./bit_reader.h" | |
#include "./huffman.h" | |
#include "./port.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 BrotliDecoderStateStruct { | |
BrotliRunningState state; | |
/* This counter is reused for several disjoint loops. */ | |
int loop_counter; | |
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; | |
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]; | |
int error_code; | |
uint32_t sub_loop_counter; | |
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; | |
/* 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 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_NUM_COMMAND_SYMBOLS]; | |
/* Tails of symbol chains. */ | |
int next_symbol[32]; | |
uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES]; | |
/* 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_SIZE_272]; | |
/* For InverseMoveToFrontTransform */ | |
uint32_t mtf_upper_bound; | |
uint8_t mtf[256 + 4]; | |
/* 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; | |
uint32_t trivial_literal_contexts[8]; /* 256 bits */ | |
}; | |
typedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal; | |
#define BrotliDecoderState BrotliDecoderStateInternal | |
BROTLI_INTERNAL void BrotliDecoderStateInit(BrotliDecoderState* s); | |
BROTLI_INTERNAL void BrotliDecoderStateInitWithCustomAllocators( | |
BrotliDecoderState* s, brotli_alloc_func alloc_func, | |
brotli_free_func free_func, void* opaque); | |
BROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState* s); | |
BROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s); | |
BROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock( | |
BrotliDecoderState* s); | |
BROTLI_INTERNAL void BrotliDecoderHuffmanTreeGroupInit( | |
BrotliDecoderState* s, HuffmanTreeGroup* group, uint32_t alphabet_size, | |
uint32_t ntrees); | |
BROTLI_INTERNAL void BrotliDecoderHuffmanTreeGroupRelease( | |
BrotliDecoderState* s, HuffmanTreeGroup* group); | |
#if defined(__cplusplus) || defined(c_plusplus) | |
} /* extern "C" */ | |
#endif | |
#endif /* BROTLI_DEC_STATE_H_ */ |