Line data Source code
1 : /* Copyright 2015 Google Inc. All Rights Reserved.
2 :
3 : Distributed under MIT license.
4 : See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
5 : */
6 :
7 : #include "./state.h"
8 :
9 : #include <stdlib.h> /* free, malloc */
10 :
11 : #include "./huffman.h"
12 : #include "./types.h"
13 :
14 : #if defined(__cplusplus) || defined(c_plusplus)
15 : extern "C" {
16 : #endif
17 :
18 : /* Declared in decode.h */
19 : int BrotliStateIsStreamStart(const BrotliState* s);
20 : int BrotliStateIsStreamEnd(const BrotliState* s);
21 :
22 0 : static void* DefaultAllocFunc(void* opaque, size_t size) {
23 : BROTLI_UNUSED(opaque);
24 0 : return malloc(size);
25 : }
26 :
27 0 : static void DefaultFreeFunc(void* opaque, void* address) {
28 : BROTLI_UNUSED(opaque);
29 0 : free(address);
30 0 : }
31 :
32 0 : void BrotliStateInit(BrotliState* s) {
33 0 : BrotliStateInitWithCustomAllocators(s, 0, 0, 0);
34 0 : }
35 :
36 0 : void BrotliStateInitWithCustomAllocators(BrotliState* s,
37 : brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {
38 0 : if (!alloc_func) {
39 0 : s->alloc_func = DefaultAllocFunc;
40 0 : s->free_func = DefaultFreeFunc;
41 0 : s->memory_manager_opaque = 0;
42 : } else {
43 0 : s->alloc_func = alloc_func;
44 0 : s->free_func = free_func;
45 0 : s->memory_manager_opaque = opaque;
46 : }
47 :
48 0 : BrotliInitBitReader(&s->br);
49 0 : s->state = BROTLI_STATE_UNINITED;
50 0 : s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;
51 0 : s->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;
52 0 : s->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;
53 0 : s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;
54 0 : s->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;
55 0 : s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;
56 0 : s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;
57 :
58 0 : s->buffer_length = 0;
59 0 : s->loop_counter = 0;
60 0 : s->pos = 0;
61 0 : s->rb_roundtrips = 0;
62 0 : s->partial_pos_out = 0;
63 :
64 0 : s->block_type_trees = NULL;
65 0 : s->block_len_trees = NULL;
66 0 : s->ringbuffer = NULL;
67 :
68 0 : s->context_map = NULL;
69 0 : s->context_modes = NULL;
70 0 : s->dist_context_map = NULL;
71 0 : s->context_map_slice = NULL;
72 0 : s->dist_context_map_slice = NULL;
73 :
74 0 : s->sub_loop_counter = 0;
75 :
76 0 : s->literal_hgroup.codes = NULL;
77 0 : s->literal_hgroup.htrees = NULL;
78 0 : s->insert_copy_hgroup.codes = NULL;
79 0 : s->insert_copy_hgroup.htrees = NULL;
80 0 : s->distance_hgroup.codes = NULL;
81 0 : s->distance_hgroup.htrees = NULL;
82 :
83 0 : s->custom_dict = NULL;
84 0 : s->custom_dict_size = 0;
85 :
86 0 : s->is_last_metablock = 0;
87 0 : s->window_bits = 0;
88 0 : s->max_distance = 0;
89 0 : s->dist_rb[0] = 16;
90 0 : s->dist_rb[1] = 15;
91 0 : s->dist_rb[2] = 11;
92 0 : s->dist_rb[3] = 4;
93 0 : s->dist_rb_idx = 0;
94 0 : s->block_type_trees = NULL;
95 0 : s->block_len_trees = NULL;
96 :
97 : /* Make small negative indexes addressable. */
98 0 : s->symbol_lists = &s->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];
99 :
100 0 : s->mtf_upper_bound = 255;
101 0 : }
102 :
103 0 : void BrotliStateMetablockBegin(BrotliState* s) {
104 0 : s->meta_block_remaining_len = 0;
105 0 : s->block_length[0] = 1U << 28;
106 0 : s->block_length[1] = 1U << 28;
107 0 : s->block_length[2] = 1U << 28;
108 0 : s->num_block_types[0] = 1;
109 0 : s->num_block_types[1] = 1;
110 0 : s->num_block_types[2] = 1;
111 0 : s->block_type_rb[0] = 1;
112 0 : s->block_type_rb[1] = 0;
113 0 : s->block_type_rb[2] = 1;
114 0 : s->block_type_rb[3] = 0;
115 0 : s->block_type_rb[4] = 1;
116 0 : s->block_type_rb[5] = 0;
117 0 : s->context_map = NULL;
118 0 : s->context_modes = NULL;
119 0 : s->dist_context_map = NULL;
120 0 : s->context_map_slice = NULL;
121 0 : s->literal_htree = NULL;
122 0 : s->dist_context_map_slice = NULL;
123 0 : s->dist_htree_index = 0;
124 0 : s->context_lookup1 = NULL;
125 0 : s->context_lookup2 = NULL;
126 0 : s->literal_hgroup.codes = NULL;
127 0 : s->literal_hgroup.htrees = NULL;
128 0 : s->insert_copy_hgroup.codes = NULL;
129 0 : s->insert_copy_hgroup.htrees = NULL;
130 0 : s->distance_hgroup.codes = NULL;
131 0 : s->distance_hgroup.htrees = NULL;
132 0 : }
133 :
134 0 : void BrotliStateCleanupAfterMetablock(BrotliState* s) {
135 0 : BROTLI_FREE(s, s->context_modes);
136 0 : BROTLI_FREE(s, s->context_map);
137 0 : BROTLI_FREE(s, s->dist_context_map);
138 :
139 0 : BrotliHuffmanTreeGroupRelease(s, &s->literal_hgroup);
140 0 : BrotliHuffmanTreeGroupRelease(s, &s->insert_copy_hgroup);
141 0 : BrotliHuffmanTreeGroupRelease(s, &s->distance_hgroup);
142 0 : }
143 :
144 0 : void BrotliStateCleanup(BrotliState* s) {
145 0 : BrotliStateCleanupAfterMetablock(s);
146 :
147 0 : BROTLI_FREE(s, s->ringbuffer);
148 0 : BROTLI_FREE(s, s->block_type_trees);
149 0 : }
150 :
151 0 : int BrotliStateIsStreamStart(const BrotliState* s) {
152 0 : return (s->state == BROTLI_STATE_UNINITED &&
153 0 : BrotliGetAvailableBits(&s->br) == 0);
154 : }
155 :
156 0 : int BrotliStateIsStreamEnd(const BrotliState* s) {
157 0 : return s->state == BROTLI_STATE_DONE;
158 : }
159 :
160 0 : void BrotliHuffmanTreeGroupInit(BrotliState* s, HuffmanTreeGroup* group,
161 : uint32_t alphabet_size, uint32_t ntrees) {
162 : /* Pack two allocations into one */
163 0 : const size_t max_table_size = kMaxHuffmanTableSize[(alphabet_size + 31) >> 5];
164 0 : const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;
165 0 : const size_t htree_size = sizeof(HuffmanCode*) * ntrees;
166 0 : char* p = (char*)BROTLI_ALLOC(s, code_size + htree_size);
167 0 : group->alphabet_size = (uint16_t)alphabet_size;
168 0 : group->num_htrees = (uint16_t)ntrees;
169 0 : group->codes = (HuffmanCode*)p;
170 0 : group->htrees = (HuffmanCode**)(p + code_size);
171 0 : }
172 :
173 0 : void BrotliHuffmanTreeGroupRelease(BrotliState* s, HuffmanTreeGroup* group) {
174 0 : BROTLI_FREE(s, group->codes);
175 0 : group->htrees = NULL;
176 0 : }
177 :
178 : #if defined(__cplusplus) || defined(c_plusplus)
179 : } /* extern "C" */
180 : #endif
|