2015-03-20 15:13:15 +00:00
|
|
|
/* Copyright 2015 Google Inc. All Rights Reserved.
|
|
|
|
|
2015-12-11 10:11:51 +00:00
|
|
|
Distributed under MIT license.
|
2015-11-27 10:27:11 +00:00
|
|
|
See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
|
2015-03-20 15:13:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* Brotli state for partial streaming decoding. */
|
|
|
|
|
|
|
|
#ifndef BROTLI_DEC_STATE_H_
|
|
|
|
#define BROTLI_DEC_STATE_H_
|
|
|
|
|
|
|
|
#include "./bit_reader.h"
|
|
|
|
#include "./huffman.h"
|
|
|
|
#include "./types.h"
|
|
|
|
|
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef enum {
|
2015-08-10 11:35:23 +00:00
|
|
|
BROTLI_STATE_UNINITED,
|
|
|
|
BROTLI_STATE_METABLOCK_BEGIN,
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_METABLOCK_HEADER,
|
2015-11-06 10:46:04 +00:00
|
|
|
BROTLI_STATE_METABLOCK_HEADER_2,
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_CONTEXT_MODES,
|
2015-08-28 13:20:24 +00:00
|
|
|
BROTLI_STATE_COMMAND_BEGIN,
|
|
|
|
BROTLI_STATE_COMMAND_INNER,
|
2015-11-06 10:46:04 +00:00
|
|
|
BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,
|
|
|
|
BROTLI_STATE_COMMAND_POST_WRAP_COPY,
|
2015-08-10 11:35:23 +00:00
|
|
|
BROTLI_STATE_UNCOMPRESSED,
|
|
|
|
BROTLI_STATE_METADATA,
|
2015-08-28 13:20:24 +00:00
|
|
|
BROTLI_STATE_COMMAND_INNER_WRITE,
|
2015-08-10 11:35:23 +00:00
|
|
|
BROTLI_STATE_METABLOCK_DONE,
|
2015-08-28 13:20:24 +00:00
|
|
|
BROTLI_STATE_COMMAND_POST_WRITE_1,
|
|
|
|
BROTLI_STATE_COMMAND_POST_WRITE_2,
|
2015-08-10 11:35:23 +00:00
|
|
|
BROTLI_STATE_HUFFMAN_CODE_0,
|
|
|
|
BROTLI_STATE_HUFFMAN_CODE_1,
|
|
|
|
BROTLI_STATE_HUFFMAN_CODE_2,
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_HUFFMAN_CODE_3,
|
2015-08-10 11:35:23 +00:00
|
|
|
BROTLI_STATE_CONTEXT_MAP_1,
|
|
|
|
BROTLI_STATE_CONTEXT_MAP_2,
|
|
|
|
BROTLI_STATE_TREE_GROUP,
|
|
|
|
BROTLI_STATE_DONE
|
2015-03-20 15:13:15 +00:00
|
|
|
} BrotliRunningState;
|
|
|
|
|
2015-08-10 11:35:23 +00:00
|
|
|
typedef enum {
|
2015-09-23 10:24:06 +00:00
|
|
|
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;
|
2015-08-10 11:35:23 +00:00
|
|
|
|
|
|
|
typedef enum {
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_UNCOMPRESSED_NONE,
|
2015-09-28 10:40:39 +00:00
|
|
|
BROTLI_STATE_UNCOMPRESSED_WRITE
|
2015-09-23 10:24:06 +00:00
|
|
|
} BrotliRunningUncompressedState;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
BROTLI_STATE_TREE_GROUP_NONE,
|
|
|
|
BROTLI_STATE_TREE_GROUP_LOOP
|
|
|
|
} BrotliRunningTreeGroupState;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
BROTLI_STATE_CONTEXT_MAP_NONE,
|
2015-09-24 16:35:25 +00:00
|
|
|
BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_CONTEXT_MAP_HUFFMAN,
|
2015-11-06 10:46:04 +00:00
|
|
|
BROTLI_STATE_CONTEXT_MAP_DECODE,
|
|
|
|
BROTLI_STATE_CONTEXT_MAP_TRANSFORM
|
2015-09-23 10:24:06 +00:00
|
|
|
} BrotliRunningContextMapState;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
BROTLI_STATE_HUFFMAN_NONE,
|
2015-11-06 10:46:04 +00:00
|
|
|
BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,
|
|
|
|
BROTLI_STATE_HUFFMAN_SIMPLE_READ,
|
|
|
|
BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,
|
|
|
|
BROTLI_STATE_HUFFMAN_COMPLEX,
|
2015-09-23 10:24:06 +00:00
|
|
|
BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS
|
|
|
|
} BrotliRunningHuffmanState;
|
2015-08-10 11:35:23 +00:00
|
|
|
|
2015-09-24 16:35:25 +00:00
|
|
|
typedef enum {
|
|
|
|
BROTLI_STATE_DECODE_UINT8_NONE,
|
|
|
|
BROTLI_STATE_DECODE_UINT8_SHORT,
|
|
|
|
BROTLI_STATE_DECODE_UINT8_LONG
|
|
|
|
} BrotliRunningDecodeUint8State;
|
|
|
|
|
2015-11-06 10:46:04 +00:00
|
|
|
typedef enum {
|
|
|
|
BROTLI_STATE_READ_BLOCK_LENGTH_NONE,
|
|
|
|
BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX
|
|
|
|
} BrotliRunningReadBlockLengthState;
|
|
|
|
|
|
|
|
struct BrotliStateStruct {
|
2015-03-20 15:13:15 +00:00
|
|
|
BrotliRunningState state;
|
2016-01-22 09:19:41 +00:00
|
|
|
|
|
|
|
/* This counter is reused for several disjoint loops. */
|
|
|
|
int loop_counter;
|
|
|
|
|
2015-08-28 13:20:24 +00:00
|
|
|
BrotliBitReader br;
|
2015-11-06 10:46:04 +00:00
|
|
|
|
2015-11-23 09:21:09 +00:00
|
|
|
brotli_alloc_func alloc_func;
|
|
|
|
brotli_free_func free_func;
|
|
|
|
void* memory_manager_opaque;
|
|
|
|
|
2015-11-06 10:46:04 +00:00
|
|
|
/* Temporary storage for remaining input. */
|
|
|
|
union {
|
|
|
|
uint64_t u64;
|
|
|
|
uint8_t u8[8];
|
|
|
|
} buffer;
|
|
|
|
uint32_t buffer_length;
|
|
|
|
|
2015-03-20 15:13:15 +00:00
|
|
|
int pos;
|
|
|
|
int max_backward_distance;
|
2015-08-28 13:20:24 +00:00
|
|
|
int max_backward_distance_minus_custom_dict_size;
|
2015-03-20 15:13:15 +00:00
|
|
|
int max_distance;
|
|
|
|
int ringbuffer_size;
|
|
|
|
int ringbuffer_mask;
|
2015-08-28 13:20:24 +00:00
|
|
|
int dist_rb_idx;
|
|
|
|
int dist_rb[4];
|
2015-03-20 15:13:15 +00:00
|
|
|
uint8_t* ringbuffer;
|
|
|
|
uint8_t* ringbuffer_end;
|
2015-08-28 13:20:24 +00:00
|
|
|
HuffmanCode* htree_command;
|
|
|
|
const uint8_t* context_lookup1;
|
|
|
|
const uint8_t* context_lookup2;
|
|
|
|
uint8_t* context_map_slice;
|
|
|
|
uint8_t* dist_context_map_slice;
|
|
|
|
|
2015-11-06 10:46:04 +00:00
|
|
|
uint32_t sub_loop_counter;
|
|
|
|
|
2015-03-20 15:13:15 +00:00
|
|
|
/* This ring buffer holds a few past copy distances that will be used by */
|
|
|
|
/* some special distance codes. */
|
2015-08-10 11:35:23 +00:00
|
|
|
HuffmanTreeGroup literal_hgroup;
|
|
|
|
HuffmanTreeGroup insert_copy_hgroup;
|
|
|
|
HuffmanTreeGroup distance_hgroup;
|
2015-03-20 15:13:15 +00:00
|
|
|
HuffmanCode* block_type_trees;
|
|
|
|
HuffmanCode* block_len_trees;
|
2015-04-01 14:15:39 +00:00
|
|
|
/* 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;
|
2015-08-28 13:20:24 +00:00
|
|
|
int distance_context;
|
2015-03-20 15:13:15 +00:00
|
|
|
int meta_block_remaining_len;
|
2015-11-06 10:46:04 +00:00
|
|
|
uint32_t block_length_index;
|
|
|
|
uint32_t block_length[3];
|
2015-10-05 08:23:32 +00:00
|
|
|
uint32_t num_block_types[3];
|
|
|
|
uint32_t block_type_rb[6];
|
|
|
|
uint32_t distance_postfix_bits;
|
|
|
|
uint32_t num_direct_distance_codes;
|
2015-03-20 15:13:15 +00:00
|
|
|
int distance_postfix_mask;
|
2015-10-05 08:23:32 +00:00
|
|
|
uint32_t num_dist_htrees;
|
2015-03-20 15:13:15 +00:00
|
|
|
uint8_t* dist_context_map;
|
2015-08-28 13:20:24 +00:00
|
|
|
HuffmanCode *literal_htree;
|
2015-09-23 10:24:06 +00:00
|
|
|
uint8_t literal_htree_index;
|
2015-03-20 15:13:15 +00:00
|
|
|
uint8_t dist_htree_index;
|
2015-11-06 10:46:04 +00:00
|
|
|
uint32_t repeat_code_len;
|
|
|
|
uint32_t prev_code_len;
|
2015-03-20 15:13:15 +00:00
|
|
|
|
2015-09-23 10:24:06 +00:00
|
|
|
|
2015-03-20 15:13:15 +00:00
|
|
|
int copy_length;
|
|
|
|
int distance_code;
|
|
|
|
|
2015-04-22 15:33:21 +00:00
|
|
|
/* For partial write operations */
|
2015-11-06 10:46:04 +00:00
|
|
|
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) */
|
2015-04-22 15:33:21 +00:00
|
|
|
|
2015-08-28 13:20:24 +00:00
|
|
|
/* For ReadHuffmanCode */
|
|
|
|
uint32_t symbol;
|
|
|
|
uint32_t repeat;
|
|
|
|
uint32_t space;
|
2015-03-20 15:13:15 +00:00
|
|
|
|
|
|
|
HuffmanCode table[32];
|
2015-08-28 13:20:24 +00:00
|
|
|
/* 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];
|
2015-03-20 15:13:15 +00:00
|
|
|
uint8_t code_length_code_lengths[18];
|
2015-08-10 11:35:23 +00:00
|
|
|
/* Population counts for the code lengths */
|
|
|
|
uint16_t code_length_histo[16];
|
2015-03-20 15:13:15 +00:00
|
|
|
|
|
|
|
/* For HuffmanTreeGroupDecode */
|
|
|
|
int htree_index;
|
|
|
|
HuffmanCode* next;
|
|
|
|
|
|
|
|
/* For DecodeContextMap */
|
2015-10-05 08:23:32 +00:00
|
|
|
uint32_t context_index;
|
|
|
|
uint32_t max_run_length_prefix;
|
2015-11-06 10:46:04 +00:00
|
|
|
uint32_t code;
|
2016-01-22 09:19:41 +00:00
|
|
|
HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];
|
2015-06-12 13:43:54 +00:00
|
|
|
|
2015-08-10 11:35:23 +00:00
|
|
|
/* For InverseMoveToFrontTransform */
|
2015-10-05 08:23:32 +00:00
|
|
|
uint32_t mtf_upper_bound;
|
2015-08-10 11:35:23 +00:00
|
|
|
uint8_t mtf[256];
|
|
|
|
|
2015-06-12 13:43:54 +00:00
|
|
|
/* For custom dictionaries */
|
|
|
|
const uint8_t* custom_dict;
|
|
|
|
int custom_dict_size;
|
2015-08-28 13:20:24 +00:00
|
|
|
|
|
|
|
/* less used attributes are in the end of this struct */
|
2015-09-23 10:24:06 +00:00
|
|
|
/* States inside function calls */
|
|
|
|
BrotliRunningMetablockHeaderState substate_metablock_header;
|
|
|
|
BrotliRunningTreeGroupState substate_tree_group;
|
|
|
|
BrotliRunningContextMapState substate_context_map;
|
|
|
|
BrotliRunningUncompressedState substate_uncompressed;
|
|
|
|
BrotliRunningHuffmanState substate_huffman;
|
2015-09-24 16:35:25 +00:00
|
|
|
BrotliRunningDecodeUint8State substate_decode_uint8;
|
2015-11-06 10:46:04 +00:00
|
|
|
BrotliRunningReadBlockLengthState substate_read_block_length;
|
2015-09-23 10:24:06 +00:00
|
|
|
|
|
|
|
uint8_t is_last_metablock;
|
|
|
|
uint8_t is_uncompressed;
|
|
|
|
uint8_t is_metadata;
|
|
|
|
uint8_t size_nibbles;
|
2015-08-28 13:20:24 +00:00
|
|
|
uint32_t window_bits;
|
|
|
|
|
2015-10-05 08:23:32 +00:00
|
|
|
uint32_t num_literal_htrees;
|
2015-08-28 13:20:24 +00:00
|
|
|
uint8_t* context_map;
|
|
|
|
uint8_t* context_modes;
|
2015-11-06 10:46:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct BrotliStateStruct BrotliState;
|
2015-03-20 15:13:15 +00:00
|
|
|
|
|
|
|
void BrotliStateInit(BrotliState* s);
|
2015-11-23 09:21:09 +00:00
|
|
|
void BrotliStateInitWithCustomAllocators(BrotliState* s,
|
|
|
|
brotli_alloc_func alloc_func,
|
|
|
|
brotli_free_func free_func,
|
|
|
|
void* opaque);
|
2015-03-20 15:13:15 +00:00
|
|
|
void BrotliStateCleanup(BrotliState* s);
|
2015-08-10 11:35:23 +00:00
|
|
|
void BrotliStateMetablockBegin(BrotliState* s);
|
|
|
|
void BrotliStateCleanupAfterMetablock(BrotliState* s);
|
2015-11-23 09:21:09 +00:00
|
|
|
void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group,
|
|
|
|
uint32_t alphabet_size, uint32_t ntrees);
|
|
|
|
void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group);
|
2015-11-06 10:46:04 +00:00
|
|
|
|
|
|
|
/* 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);
|
|
|
|
|
|
|
|
|
2015-03-20 15:13:15 +00:00
|
|
|
#if defined(__cplusplus) || defined(c_plusplus)
|
|
|
|
} /* extern "C" */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* BROTLI_DEC_STATE_H_ */
|