OLD | NEW |
| (Empty) |
1 /* Copyright 2013 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 // API for Brotli compression | |
8 | |
9 #ifndef BROTLI_ENC_ENCODE_H_ | |
10 #define BROTLI_ENC_ENCODE_H_ | |
11 | |
12 #include <string> | |
13 #include <vector> | |
14 #include "./command.h" | |
15 #include "./hash.h" | |
16 #include "./ringbuffer.h" | |
17 #include "./static_dict.h" | |
18 #include "./streams.h" | |
19 #include "./types.h" | |
20 | |
21 namespace brotli { | |
22 | |
23 static const int kMaxWindowBits = 24; | |
24 static const int kMinWindowBits = 10; | |
25 static const int kMinInputBlockBits = 16; | |
26 static const int kMaxInputBlockBits = 24; | |
27 | |
28 struct BrotliParams { | |
29 BrotliParams(void) | |
30 : mode(MODE_GENERIC), | |
31 quality(11), | |
32 lgwin(22), | |
33 lgblock(0), | |
34 enable_dictionary(true), | |
35 enable_transforms(false), | |
36 greedy_block_split(false), | |
37 enable_context_modeling(true) {} | |
38 | |
39 enum Mode { | |
40 // Default compression mode. The compressor does not know anything in | |
41 // advance about the properties of the input. | |
42 MODE_GENERIC = 0, | |
43 // Compression mode for UTF-8 format text input. | |
44 MODE_TEXT = 1, | |
45 // Compression mode used in WOFF 2.0. | |
46 MODE_FONT = 2 | |
47 }; | |
48 Mode mode; | |
49 | |
50 // Controls the compression-speed vs compression-density tradeoffs. The higher | |
51 // the quality, the slower the compression. Range is 0 to 11. | |
52 int quality; | |
53 // Base 2 logarithm of the sliding window size. Range is 10 to 24. | |
54 int lgwin; | |
55 // Base 2 logarithm of the maximum input block size. Range is 16 to 24. | |
56 // If set to 0, the value will be set based on the quality. | |
57 int lgblock; | |
58 | |
59 // These settings are deprecated and will be ignored. | |
60 // All speed vs. size compromises are controlled by the quality param. | |
61 bool enable_dictionary; | |
62 bool enable_transforms; | |
63 bool greedy_block_split; | |
64 bool enable_context_modeling; | |
65 }; | |
66 | |
67 // An instance can not be reused for multiple brotli streams. | |
68 class BrotliCompressor { | |
69 public: | |
70 explicit BrotliCompressor(BrotliParams params); | |
71 ~BrotliCompressor(void); | |
72 | |
73 // The maximum input size that can be processed at once. | |
74 size_t input_block_size(void) const { return size_t(1) << params_.lgblock; } | |
75 | |
76 // Encodes the data in input_buffer as a meta-block and writes it to | |
77 // encoded_buffer (*encoded_size should be set to the size of | |
78 // encoded_buffer) and sets *encoded_size to the number of bytes that | |
79 // was written. The input_size must be <= input_block_size(). | |
80 // Returns 0 if there was an error and 1 otherwise. | |
81 bool WriteMetaBlock(const size_t input_size, | |
82 const uint8_t* input_buffer, | |
83 const bool is_last, | |
84 size_t* encoded_size, | |
85 uint8_t* encoded_buffer); | |
86 | |
87 // Writes a metadata meta-block containing the given input to encoded_buffer. | |
88 // *encoded_size should be set to the size of the encoded_buffer. | |
89 // Sets *encoded_size to the number of bytes that was written. | |
90 // Note that the given input data will not be part of the sliding window and | |
91 // thus no backward references can be made to this data from subsequent | |
92 // metablocks. | |
93 bool WriteMetadata(const size_t input_size, | |
94 const uint8_t* input_buffer, | |
95 const bool is_last, | |
96 size_t* encoded_size, | |
97 uint8_t* encoded_buffer); | |
98 | |
99 // Writes a zero-length meta-block with end-of-input bit set to the | |
100 // internal output buffer and copies the output buffer to encoded_buffer | |
101 // (*encoded_size should be set to the size of encoded_buffer) and sets | |
102 // *encoded_size to the number of bytes written. Returns false if there was | |
103 // an error and true otherwise. | |
104 bool FinishStream(size_t* encoded_size, uint8_t* encoded_buffer); | |
105 | |
106 // Copies the given input data to the internal ring buffer of the compressor. | |
107 // No processing of the data occurs at this time and this function can be | |
108 // called multiple times before calling WriteBrotliData() to process the | |
109 // accumulated input. At most input_block_size() bytes of input data can be | |
110 // copied to the ring buffer, otherwise the next WriteBrotliData() will fail. | |
111 void CopyInputToRingBuffer(const size_t input_size, | |
112 const uint8_t* input_buffer); | |
113 | |
114 // Processes the accumulated input data and sets *out_size to the length of | |
115 // the new output meta-block, or to zero if no new output meta-block was | |
116 // created (in this case the processed input data is buffered internally). | |
117 // If *out_size is positive, *output points to the start of the output data. | |
118 // If is_last or force_flush is true, an output meta-block is always created. | |
119 // Returns false if the size of the input data is larger than | |
120 // input_block_size(). | |
121 bool WriteBrotliData(const bool is_last, const bool force_flush, | |
122 size_t* out_size, uint8_t** output); | |
123 | |
124 // Fills the new state with a dictionary for LZ77, warming up the ringbuffer, | |
125 // e.g. for custom static dictionaries for data formats. | |
126 // Not to be confused with the built-in transformable dictionary of Brotli. | |
127 // To decode, use BrotliSetCustomDictionary of the decoder with the same | |
128 // dictionary. | |
129 void BrotliSetCustomDictionary(size_t size, const uint8_t* dict); | |
130 | |
131 // No-op, but we keep it here for API backward-compatibility. | |
132 void WriteStreamHeader(void) {} | |
133 | |
134 private: | |
135 uint8_t* GetBrotliStorage(size_t size); | |
136 | |
137 // Allocates and clears a hash table using memory in "*this", | |
138 // stores the number of buckets in "*table_size" and returns a pointer to | |
139 // the base of the hash table. | |
140 int* GetHashTable(int quality, | |
141 size_t input_size, size_t* table_size); | |
142 | |
143 BrotliParams params_; | |
144 Hashers* hashers_; | |
145 int hash_type_; | |
146 uint64_t input_pos_; | |
147 RingBuffer* ringbuffer_; | |
148 size_t cmd_alloc_size_; | |
149 Command* commands_; | |
150 size_t num_commands_; | |
151 size_t num_literals_; | |
152 size_t last_insert_len_; | |
153 uint64_t last_flush_pos_; | |
154 uint64_t last_processed_pos_; | |
155 int dist_cache_[4]; | |
156 int saved_dist_cache_[4]; | |
157 uint8_t last_byte_; | |
158 uint8_t last_byte_bits_; | |
159 uint8_t prev_byte_; | |
160 uint8_t prev_byte2_; | |
161 size_t storage_size_; | |
162 uint8_t* storage_; | |
163 // Hash table for quality 0 mode. | |
164 int small_table_[1 << 10]; // 2KB | |
165 int* large_table_; // Allocated only when needed | |
166 // Command and distance prefix codes (each 64 symbols, stored back-to-back) | |
167 // used for the next block in quality 0. The command prefix code is over a | |
168 // smaller alphabet with the following 64 symbols: | |
169 // 0 - 15: insert length code 0, copy length code 0 - 15, same distance | |
170 // 16 - 39: insert length code 0, copy length code 0 - 23 | |
171 // 40 - 63: insert length code 0 - 23, copy length code 0 | |
172 // Note that symbols 16 and 40 represent the same code in the full alphabet, | |
173 // but we do not use either of them in quality 0. | |
174 uint8_t cmd_depths_[128]; | |
175 uint16_t cmd_bits_[128]; | |
176 // The compressed form of the command and distance prefix codes for the next | |
177 // block in quality 0. | |
178 uint8_t cmd_code_[512]; | |
179 size_t cmd_code_numbits_; | |
180 // Command and literal buffers for quality 1. | |
181 uint32_t* command_buf_; | |
182 uint8_t* literal_buf_; | |
183 | |
184 int is_last_block_emitted_; | |
185 }; | |
186 | |
187 // Compresses the data in input_buffer into encoded_buffer, and sets | |
188 // *encoded_size to the compressed length. | |
189 // Returns 0 if there was an error and 1 otherwise. | |
190 int BrotliCompressBuffer(BrotliParams params, | |
191 size_t input_size, | |
192 const uint8_t* input_buffer, | |
193 size_t* encoded_size, | |
194 uint8_t* encoded_buffer); | |
195 | |
196 // Same as above, but uses the specified input and output classes instead | |
197 // of reading from and writing to pre-allocated memory buffers. | |
198 int BrotliCompress(BrotliParams params, BrotliIn* in, BrotliOut* out); | |
199 | |
200 // Before compressing the data, sets a custom LZ77 dictionary with | |
201 // BrotliCompressor::BrotliSetCustomDictionary. | |
202 int BrotliCompressWithCustomDictionary(size_t dictsize, const uint8_t* dict, | |
203 BrotliParams params, | |
204 BrotliIn* in, BrotliOut* out); | |
205 | |
206 | |
207 } // namespace brotli | |
208 | |
209 #endif // BROTLI_ENC_ENCODE_H_ | |
OLD | NEW |