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