OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 part of dart.io; | 5 part of dart.io; |
6 | 6 |
7 | 7 |
8 abstract class ZLibConstant { | |
9 /// Minimal value for [windowBits] | |
Lasse Reichstein Nielsen
2014/02/05 10:33:32
There is no [windowBits] declaration in scope, so
vicb
2014/02/06 13:54:06
fixed
| |
10 static const int MIN_WINDOW_BITS = 8; | |
11 /// Maximal value for [windowBits] | |
12 static const int MAX_WINDOW_BITS = 15; | |
13 /// Default value for [windowBits] | |
14 static const int DEFAULT_WINDOW_BITS = 15; | |
15 | |
16 /// Minimal value for [level] | |
17 static const int MIN_LEVEL = -1; | |
18 /// Maximal value for [level] | |
19 static const int MAX_LEVEL = 9; | |
20 /// Default value for [level] | |
21 static const int DEFAULT_LEVEL = 6; | |
22 | |
23 /// Minimal value for [memLevel] | |
24 static const int MIN_MEM_LEVEL = 1; | |
25 /// Maximal value for [memLevel] | |
26 static const int MAX_MEM_LEVEL = 9; | |
27 /// Default value for [memLevel] | |
28 static const int DEFAULT_MEM_LEVEL = 8; | |
29 | |
30 /// Compression strategies | |
Lasse Reichstein Nielsen
2014/02/05 10:33:32
This dartdoc only attaches to STRATEGY_FILTERED.
E
vicb
2014/02/06 13:54:06
fixed
| |
31 static const int STRATEGY_FILTERED = 1; | |
32 static const int STRATEGY_HUFFMAN_ONLY = 2; | |
33 static const int STRATEGY_RLE = 3; | |
34 static const int STRATEGY_FIXED = 4; | |
35 static const int STRATEGY_DEFAULT = 0; | |
36 } | |
37 | |
8 /** | 38 /** |
9 * An instance of the default implementation of the [ZLibCodec]. | 39 * An instance of the default implementation of the [ZLibCodec]. |
10 */ | 40 */ |
11 const ZLibCodec ZLIB = const ZLibCodec(); | 41 const ZLibCodec ZLIB = const ZLibCodec._default(); |
12 | |
13 | 42 |
14 /** | 43 /** |
15 * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib | 44 * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib |
16 * compressed bytes to raw bytes. | 45 * compressed bytes to raw bytes. |
17 */ | 46 */ |
18 class ZLibCodec extends Codec<List<int>, List<int>> { | 47 class ZLibCodec extends Codec<List<int>, List<int>> { |
19 /** | 48 /** |
20 * The compression level of the [ZLibCodec]. | 49 * When true, `GZip` frames will be added to the compressed data. |
50 */ | |
51 final bool gzip; | |
52 | |
53 /** | |
54 * The compression-[level] can be set in the range of `-1..9`, with `6` being | |
55 * the default compression level. Levels above `6` will have higher | |
56 * compression rates at the cost of more CPU and memory usage. Levels below | |
57 * `6` will use less CPU and memory at the cost of lower compression rates. | |
21 */ | 58 */ |
22 final int level; | 59 final int level; |
23 | 60 |
24 /** | 61 /** |
25 * Get a [Converter] for encoding to `ZLib` compressed data. | 62 * Specifies how much memory should be allocated for the internal compression |
63 * state. `1` uses minimum memory but is slow and reduces compression ratio; | |
64 * `9` uses maximum memory for optimal speed. The default value is `8`. | |
65 * | |
66 * The memory requirements for deflate are (in bytes): | |
67 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) | |
Lasse Reichstein Nielsen
2014/02/05 10:33:32
Empty line before and four-space indent to make th
vicb
2014/02/06 13:54:06
fixed
| |
68 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | |
69 */ | |
70 final int memLevel; | |
71 | |
72 /** | |
73 * Tunes the compression algorithm. Use the value STRATEGY_DEFAULT for normal | |
74 * data, STRATEGY_FILTERED for data produced by a filter (or predictor), | |
75 * STRATEGY_HUFFMAN_ONLY to force Huffman encoding only (no string match), or | |
76 * STRATEGY_RLE to limit match distances to one (run-length encoding). | |
77 */ | |
78 final int strategy; | |
79 | |
80 /** | |
81 * Base two logarithm of the window size (the size of the history buffer). It | |
82 * should be in the range 8..15. Larger values result in better compression at | |
83 * the expense of memory usage. The default value is 15 | |
84 */ | |
85 final int windowBits; | |
86 | |
87 /** | |
88 * When true, deflate generates raw data with no zlib header or trailer, and | |
89 * will not compute an adler32 check value | |
90 */ | |
91 final bool raw; | |
92 | |
93 /** | |
94 * Initial compression dictionary. | |
95 * | |
96 * It should consist of strings (byte sequences) that are likely to be | |
97 * encountered later in the data to be compressed, with the most commonly used | |
98 * strings preferably put towards the end of the dictionary. Using a dictionary | |
99 * is most useful when the data to be compressed is short and can be predicted | |
100 * with good accuracy; the data can then be compressed better than with the | |
101 * default empty dictionary. | |
102 */ | |
103 final List<int> dictionary; | |
104 | |
105 ZLibCodec({this.level: ZLibConstant.DEFAULT_LEVEL, | |
106 this.windowBits: ZLibConstant.DEFAULT_WINDOW_BITS, | |
107 this.memLevel: ZLibConstant.DEFAULT_MEM_LEVEL, | |
108 this.strategy: ZLibConstant.STRATEGY_DEFAULT, | |
109 this.dictionary: null, | |
110 this.raw: false}) { | |
111 _validateZLibeLevel(level); | |
112 _validateZLibMemLevel(memLevel); | |
113 _validateZLibStrategy(strategy); | |
114 _validateZLibWindowBits(windowBits); | |
115 } | |
116 | |
117 const ZLibCodec._default() | |
118 : level = ZLibConstant.DEFAULT_LEVEL, | |
119 windowBits = ZLibConstant.DEFAULT_WINDOW_BITS, | |
120 memLevel = ZLibConstant.DEFAULT_MEM_LEVEL, | |
121 strategy = ZLibConstant.STRATEGY_DEFAULT, | |
122 raw = false; | |
123 | |
124 /** | |
125 * Get a [ZLibEncoder] for encoding to `ZLib` compressed data. | |
26 */ | 126 */ |
27 Converter<List<int>, List<int>> get encoder => | 127 Converter<List<int>, List<int>> get encoder => |
28 new ZLibEncoder(gzip: false, level: level); | 128 new ZLibEncoder(gzip: false, level: level, windowBits: windowBits, |
29 | 129 memLevel: memLevel, strategy: strategy, |
30 /** | 130 dictionary: dictionary, raw: raw); |
31 * Get a [Converter] for decoding `ZLib` compressed data. | 131 |
32 */ | 132 /** |
33 Converter<List<int>, List<int>> get decoder => const ZLibDecoder(); | 133 * Get a [ZLibDecoder] for decoding `ZLib` compressed data. |
34 | 134 */ |
35 /** | 135 Converter<List<int>, List<int>> get decoder => |
36 * The compression-[level] can be set in the range of `1..10`, with `6` being | 136 new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); |
37 * the default compression level. Levels above 6 will have higher compression | |
38 * rates at the cost of more CPU and memory usage. Levels below 6 will use | |
39 * less CPU and memory, but at the cost of lower compression rates. | |
40 */ | |
41 const ZLibCodec({this.level: 6}); | |
42 } | 137 } |
43 | 138 |
44 | 139 |
45 /** | 140 /** |
46 * An instance of the default implementation of the [GZipCodec]. | 141 * An instance of the default implementation of the [GZipCodec]. |
47 */ | 142 */ |
48 const GZipCodec GZIP = const GZipCodec(); | 143 const GZipCodec GZIP = const GZipCodec._default(); |
49 | 144 |
50 | 145 |
51 /** | 146 /** |
52 * The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip | 147 * The GZipCodec encodes raw bytes to GZip compressed bytes and decodes GZip |
53 * compressed bytes to raw bytes. | 148 * compressed bytes to raw bytes. |
54 * | 149 * |
55 * The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec] | 150 * The difference between [ZLibCodec] and GZipCodec is that the GZipCodec wraps |
56 * wraps the `ZLib` compressed bytes in `GZip` frames. | 151 * the `ZLib` compressed bytes in `GZip` frames. |
57 */ | 152 */ |
58 class GZipCodec extends Codec<List<int>, List<int>> { | 153 class GZipCodec extends Codec<List<int>, List<int>> { |
59 /** | 154 /** |
60 * The compression level of the [ZLibCodec]. | 155 * When true, `GZip` frames will be added to the compressed data. |
156 */ | |
157 final bool gzip; | |
158 | |
159 /** | |
160 * The compression-[level] can be set in the range of `-1..9`, with `6` being | |
161 * the default compression level. Levels above `6` will have higher | |
162 * compression rates at the cost of more CPU and memory usage. Levels below | |
163 * `6` will use less CPU and memory at the cost of lower compression rates. | |
61 */ | 164 */ |
62 final int level; | 165 final int level; |
63 | 166 |
64 /** | 167 /** |
65 * Get a [Converter] for encoding to `GZip` compressed data. | 168 * Specifies how much memory should be allocated for the internal compression |
169 * state. `1` uses minimum memory but is slow and reduces compression ratio; | |
170 * `9` uses maximum memory for optimal speed. The default value is `8`. | |
171 * | |
172 * The memory requirements for deflate are (in bytes): | |
173 * | |
174 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) | |
175 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | |
176 */ | |
177 final int memLevel; | |
178 | |
179 /** | |
180 * Tunes the compression algorithm. Use the value | |
181 * [ZlibConstant.STRATEGY_DEFAULT] for normal data, | |
182 * [ZlibConstant.STRATEGY_FILTERED] for data produced by a filter | |
183 * (or predictor), | |
184 * [ZlibConstant.STRATEGY_HUFFMAN_ONLY] to force Huffman encoding only (no | |
185 * string match), or [ZlibConstant.STRATEGY_RLE] to limit match distances to | |
186 * one (run-length encoding). | |
187 */ | |
188 final int strategy; | |
189 | |
190 /** | |
191 * Base two logarithm of the window size (the size of the history buffer). It | |
192 * should be in the range 8..15. Larger values result in better compression at | |
193 * the expense of memory usage. The default value is 15 | |
194 */ | |
195 final int windowBits; | |
196 | |
197 /** | |
198 * Initial compression dictionary. | |
199 * | |
200 * It should consist of strings (byte sequences) that are likely to be | |
201 * encountered later in the data to be compressed, with the most commonly used | |
202 * strings preferably put towards the end of the dictionary. Using a dictionary | |
203 * is most useful when the data to be compressed is short and can be predicted | |
204 * with good accuracy; the data can then be compressed better than with the | |
205 * default empty dictionary. | |
206 */ | |
207 final List<int> dictionary; | |
208 | |
209 /** | |
210 * When true, deflate generates raw data with no zlib header or trailer, and | |
211 * will not compute an adler32 check value | |
212 */ | |
213 final bool raw; | |
214 | |
215 GZipCodec({this.level: ZLibConstant.DEFAULT_LEVEL, | |
216 this.windowBits: ZLibConstant.DEFAULT_WINDOW_BITS, | |
217 this.memLevel: ZLibConstant.DEFAULT_MEM_LEVEL, | |
218 this.strategy: ZLibConstant.STRATEGY_DEFAULT, | |
219 this.dictionary: null, | |
220 this.raw: false}) { | |
221 _validateZLibeLevel(level); | |
222 _validateZLibMemLevel(memLevel); | |
223 _validateZLibStrategy(strategy); | |
224 _validateZLibWindowBits(windowBits); | |
225 } | |
226 | |
227 const GZipCodec._default() | |
228 : level = ZLibConstant.DEFAULT_LEVEL, | |
229 windowBits = ZLibConstant.DEFAULT_WINDOW_BITS, | |
230 memLevel = ZLibConstant.DEFAULT_MEM_LEVEL, | |
231 strategy = ZLibConstant.STRATEGY_DEFAULT, | |
232 raw = false; | |
233 | |
234 /** | |
235 * Get a [ZLibEncoder] for encoding to `GZip` compressed data. | |
66 */ | 236 */ |
67 Converter<List<int>, List<int>> get encoder => | 237 Converter<List<int>, List<int>> get encoder => |
68 new ZLibEncoder(gzip: true, level: level); | 238 new ZLibEncoder(gzip: true, level: level, windowBits: windowBits, |
69 | 239 memLevel: memLevel, strategy: strategy, |
70 /** | 240 dictionary: dictionary, raw: raw); |
71 * Get a [Converter] for decoding `GZip` compressed data. | 241 |
72 */ | 242 /** |
73 Converter<List<int>, List<int>> get decoder => const ZLibDecoder(); | 243 * Get a [ZLibDecoder] for decoding `GZip` compressed data. |
74 | 244 */ |
75 /** | 245 Converter<List<int>, List<int>> get decoder => |
76 * The compression-[level] can be set in the range of `1..10`, with `6` being | 246 new ZLibDecoder(windowBits: windowBits, dictionary: dictionary, raw: raw); |
77 * the default compression level. Levels above 6 will have higher compression | |
78 * rates at the cost of more CPU and memory usage. Levels below 6 will use | |
79 * less CPU and memory, but at the cost of lower compression rates. | |
80 */ | |
81 const GZipCodec({this.level: 6}); | |
82 } | 247 } |
83 | 248 |
84 | |
85 /** | 249 /** |
86 * The [ZLibEncoder] is the encoder used by [ZLibCodec] and [GZipCodec] to | 250 * The ZLibEncoder encoder is used by [ZLibCodec] and [GZipCodec] to compress |
87 * compress data. | 251 * data. |
88 */ | 252 */ |
89 class ZLibEncoder extends Converter<List<int>, List<int>> { | 253 class ZLibEncoder extends Converter<List<int>, List<int>> { |
90 /** | 254 /** |
91 * If [gzip] is true, `GZip` frames will be added to the compressed data. | 255 * When true, `GZip` frames will be added to the compressed data. |
92 */ | 256 */ |
93 final bool gzip; | 257 final bool gzip; |
94 | 258 |
95 /** | 259 /** |
96 * The compression level used by the encoder. | 260 * The compression-[level] can be set in the range of `-1..9`, with `6` being |
261 * the default compression level. Levels above `6` will have higher | |
262 * compression rates at the cost of more CPU and memory usage. Levels below | |
263 * `6` will use less CPU and memory at the cost of lower compression rates. | |
97 */ | 264 */ |
98 final int level; | 265 final int level; |
99 | 266 |
100 /** | 267 /** |
101 * Create a new [ZLibEncoder] converter. If the [gzip] flag is set, the | 268 * Specifies how much memory should be allocated for the internal compression |
102 * encoder will wrap the encoded ZLib data in GZip frames. | 269 * state. `1` uses minimum memory but is slow and reduces compression ratio; |
103 */ | 270 * `9` uses maximum memory for optimal speed. The default value is `8`. |
104 const ZLibEncoder({this.gzip: false, this.level: 6}); | 271 * |
105 | 272 * The memory requirements for deflate are (in bytes): |
106 | 273 * |
107 /** | 274 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) |
108 * Convert a list of bytes using the options given to the [ZLibEncoder] | 275 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) |
276 */ | |
277 final int memLevel; | |
278 | |
279 /** | |
280 * Tunes the compression algorithm. Use the value | |
281 * [ZlibConstant.STRATEGY_DEFAULT] for normal data, | |
282 * [ZlibConstant.STRATEGY_FILTERED] for data produced by a filter | |
283 * (or predictor), | |
284 * [ZlibConstant.STRATEGY_HUFFMAN_ONLY] to force Huffman encoding only (no | |
285 * string match), or [ZlibConstant.STRATEGY_RLE] to limit match distances to | |
286 * one (run-length encoding). | |
287 */ | |
288 final int strategy; | |
289 | |
290 /** | |
291 * Base two logarithm of the window size (the size of the history buffer). It | |
292 * should be in the range 8..15. Larger values result in better compression at | |
293 * the expense of memory usage. The default value is 15 | |
294 */ | |
295 final int windowBits; | |
296 | |
297 /** | |
298 * Initial compression dictionary. | |
299 * | |
300 * It should consist of strings (byte sequences) that are likely to be | |
301 * encountered later in the data to be compressed, with the most commonly used | |
302 * strings preferably put towards the end of the dictionary. Using a dictionary | |
303 * is most useful when the data to be compressed is short and can be predicted | |
304 * with good accuracy; the data can then be compressed better than with the | |
305 * default empty dictionary. | |
306 */ | |
307 final List<int> dictionary; | |
308 | |
309 | |
310 /** | |
311 * When true, deflate generates raw data with no zlib header or trailer, and | |
312 * will not compute an adler32 check value | |
313 */ | |
314 final bool raw; | |
315 | |
316 ZLibEncoder({this.gzip: false, | |
317 this.level: ZLibConstant.DEFAULT_LEVEL, | |
318 this.windowBits: ZLibConstant.DEFAULT_WINDOW_BITS, | |
319 this.memLevel: ZLibConstant.DEFAULT_MEM_LEVEL, | |
320 this.strategy: ZLibConstant.STRATEGY_DEFAULT, | |
321 this.dictionary: null, | |
322 this.raw: false}) { | |
323 _validateZLibeLevel(level); | |
324 _validateZLibMemLevel(memLevel); | |
325 _validateZLibStrategy(strategy); | |
326 _validateZLibWindowBits(windowBits); | |
327 } | |
328 | |
329 /** | |
330 * Convert a list of bytes using the options given to the ZLibEncoder | |
109 * constructor. | 331 * constructor. |
110 */ | 332 */ |
111 List<int> convert(List<int> bytes) { | 333 List<int> convert(List<int> bytes) { |
112 _BufferSink sink = new _BufferSink(); | 334 _BufferSink sink = new _BufferSink(); |
113 startChunkedConversion(sink) | 335 startChunkedConversion(sink)..add(bytes)..close(); |
114 ..add(bytes) | |
115 ..close(); | |
116 return sink.builder.takeBytes(); | 336 return sink.builder.takeBytes(); |
117 } | 337 } |
118 | 338 |
119 /** | 339 /** |
120 * Start a chunked conversion using the options given to the [ZLibEncoder] | 340 * Start a chunked conversion using the options given to the [ZLibEncoder] |
121 * constructor. While it accepts any [ChunkedConversionSink] taking | 341 * constructor. While it accepts any [ChunkedConversionSink] taking |
122 * [List<int>]'s, the optimal sink to be passed as [sink] is a | 342 * [List<int>]'s, the optimal sink to be passed as [sink] is a |
123 * [ByteConversionSink]. | 343 * [ByteConversionSink]. |
124 */ | 344 */ |
125 ByteConversionSink startChunkedConversion( | 345 ByteConversionSink startChunkedConversion( |
126 ChunkedConversionSink<List<int>> sink) { | 346 ChunkedConversionSink<List<int>> sink) { |
127 if (sink is! ByteConversionSink) { | 347 if (sink is! ByteConversionSink) { |
128 sink = new ByteConversionSink.from(sink); | 348 sink = new ByteConversionSink.from(sink); |
129 } | 349 } |
130 return new _ZLibEncoderSink(sink, gzip, level); | 350 |
351 return new _ZLibEncoderSink(sink, gzip, level, windowBits, memLevel, | |
352 strategy, dictionary, raw); | |
131 } | 353 } |
132 } | 354 } |
133 | 355 |
134 | 356 |
135 /** | 357 /** |
136 * The [ZLibDecoder] is the decoder used by [ZLibCodec] and [GZipCodec] to | 358 * The ZLibDecoder is used by [ZLibCodec] and [GZipCodec] to decompress data. |
137 * decompress data. | |
138 */ | 359 */ |
139 class ZLibDecoder extends Converter<List<int>, List<int>> { | 360 class ZLibDecoder extends Converter<List<int>, List<int>> { |
361 /** | |
362 * Base two logarithm of the window size (the size of the history buffer). It | |
363 * should be in the range 8..15. Larger values result in better compression at | |
364 * the expense of memory usage. The default value is 15 | |
365 */ | |
366 final int windowBits; | |
140 | 367 |
141 /** | 368 /** |
142 * Create a new [ZLibEncoder] converter. | 369 * Initial compression dictionary. |
143 */ | 370 * |
144 const ZLibDecoder(); | 371 * It should consist of strings (byte sequences) that are likely to be |
372 * encountered later in the data to be compressed, with the most commonly used | |
373 * strings preferably put towards the end of the dictionary. Using a dictionary | |
374 * is most useful when the data to be compressed is short and can be predicted | |
375 * with good accuracy; the data can then be compressed better than with the | |
376 * default empty dictionary. | |
377 */ | |
378 final List<int> dictionary; | |
379 | |
380 /** | |
381 * When true, deflate generates raw data with no zlib header or trailer, and | |
382 * will not compute an adler32 check value | |
383 */ | |
384 final bool raw; | |
385 | |
386 ZLibDecoder({this.windowBits: ZLibConstant.DEFAULT_WINDOW_BITS, | |
387 this.dictionary: null, this.raw: false}) { | |
388 _validateZLibWindowBits(windowBits); | |
389 } | |
145 | 390 |
146 /** | 391 /** |
147 * Convert a list of bytes using the options given to the [ZLibDecoder] | 392 * Convert a list of bytes using the options given to the [ZLibDecoder] |
148 * constructor. | 393 * constructor. |
149 */ | 394 */ |
150 List<int> convert(List<int> bytes) { | 395 List<int> convert(List<int> bytes) { |
151 _BufferSink sink = new _BufferSink(); | 396 _BufferSink sink = new _BufferSink(); |
152 startChunkedConversion(sink) | 397 startChunkedConversion(sink)..add(bytes)..close(); |
153 ..add(bytes) | |
154 ..close(); | |
155 return sink.builder.takeBytes(); | 398 return sink.builder.takeBytes(); |
156 } | 399 } |
157 | 400 |
158 /** | 401 /** |
159 * Start a chunked conversion. While it accepts any [ChunkedConversionSink] | 402 * Start a chunked conversion. While it accepts any [ChunkedConversionSink] |
160 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a | 403 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a |
161 * [ByteConversionSink]. | 404 * [ByteConversionSink]. |
162 */ | 405 */ |
163 ByteConversionSink startChunkedConversion( | 406 ByteConversionSink startChunkedConversion( |
164 ChunkedConversionSink<List<int>> sink) { | 407 ChunkedConversionSink<List<int>> sink) { |
165 if (sink is! ByteConversionSink) { | 408 if (sink is! ByteConversionSink) { |
166 sink = new ByteConversionSink.from(sink); | 409 sink = new ByteConversionSink.from(sink); |
167 } | 410 } |
168 return new _ZLibDecoderSink(sink); | 411 return new _ZLibDecoderSink(sink, windowBits, dictionary, raw); |
169 } | 412 } |
170 } | 413 } |
171 | 414 |
172 | 415 |
173 class _BufferSink extends ByteConversionSink { | 416 class _BufferSink extends ByteConversionSink { |
174 final BytesBuilder builder = new BytesBuilder(); | 417 final BytesBuilder builder = new BytesBuilder(); |
175 | 418 |
176 void add(List<int> chunk) { | 419 void add(List<int> chunk) { |
177 builder.add(chunk); | 420 builder.add(chunk); |
178 } | 421 } |
179 | 422 |
180 void addSlice(List<int> chunk, int start, int end, bool isLast) { | 423 void addSlice(List<int> chunk, int start, int end, bool isLast) { |
181 if (chunk is Uint8List) { | 424 if (chunk is Uint8List) { |
182 Uint8List list = chunk; | 425 Uint8List list = chunk; |
183 builder.add(new Uint8List.view(list.buffer, start, end - start)); | 426 builder.add(new Uint8List.view(list.buffer, start, end - start)); |
184 } else { | 427 } else { |
185 builder.add(chunk.sublist(start, end)); | 428 builder.add(chunk.sublist(start, end)); |
186 } | 429 } |
187 } | 430 } |
188 | 431 |
189 void close() {} | 432 void close() {} |
190 } | 433 } |
191 | 434 |
192 | 435 |
193 class _ZLibEncoderSink extends _FilterSink { | 436 class _ZLibEncoderSink extends _FilterSink { |
194 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level) | 437 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level, |
195 : super(sink, _Filter.newZLibDeflateFilter(gzip, level)); | 438 int windowBits, int memLevel, int strategy, |
439 List<int> dictionary, bool raw) | |
440 : super(sink, _Filter.newZLibDeflateFilter(gzip, level, windowBits, | |
441 memLevel, strategy, | |
442 dictionary, raw)); | |
443 } | |
444 | |
445 class _ZLibDecoderSink extends _FilterSink { | |
446 _ZLibDecoderSink(ByteConversionSink sink, int windowBits, | |
447 List<int> dictionary, bool raw) | |
448 : super(sink, _Filter.newZLibInflateFilter(windowBits, dictionary, raw)); | |
196 } | 449 } |
197 | 450 |
198 | 451 |
199 class _ZLibDecoderSink extends _FilterSink { | |
200 _ZLibDecoderSink(ByteConversionSink sink) | |
201 : super(sink, _Filter.newZLibInflateFilter()); | |
202 } | |
203 | |
204 | |
205 class _FilterSink extends ByteConversionSink { | 452 class _FilterSink extends ByteConversionSink { |
206 final _Filter _filter; | 453 final _Filter _filter; |
207 final ByteConversionSink _sink; | 454 final ByteConversionSink _sink; |
208 bool _closed = false; | 455 bool _closed = false; |
209 bool _empty = true; | 456 bool _empty = true; |
210 | 457 |
211 _FilterSink(ByteConversionSink this._sink, _Filter this._filter); | 458 _FilterSink(this._sink, this._filter); |
212 | 459 |
213 void add(List<int> data) { | 460 void add(List<int> data) { |
214 addSlice(data, 0, data.length, false); | 461 addSlice(data, 0, data.length, false); |
215 } | 462 } |
216 | 463 |
217 void addSlice(List<int> data, int start, int end, bool isLast) { | 464 void addSlice(List<int> data, int start, int end, bool isLast) { |
218 if (_closed) return; | 465 if (_closed) return; |
219 if (start < 0 || start > data.length) { | 466 if (start < 0 || start > data.length) { |
220 throw new ArgumentError("Invalid start position"); | 467 throw new ArgumentError("Invalid start position"); |
221 } | 468 } |
(...skipping 29 matching lines...) Expand all Loading... | |
251 _closed = true; | 498 _closed = true; |
252 throw e; | 499 throw e; |
253 } | 500 } |
254 if (!_closed) _filter.end(); | 501 if (!_closed) _filter.end(); |
255 _closed = true; | 502 _closed = true; |
256 _sink.close(); | 503 _sink.close(); |
257 } | 504 } |
258 } | 505 } |
259 | 506 |
260 | 507 |
261 | |
262 /** | 508 /** |
263 * Private helper-class to handle native filters. | 509 * Private helper-class to handle native filters. |
264 */ | 510 */ |
265 abstract class _Filter { | 511 abstract class _Filter { |
266 /** | 512 /** |
267 * Call to process a chunk of data. A call to [process] should only be made | 513 * Call to process a chunk of data. A call to [process] should only be made |
268 * when [processed] returns [:null:]. | 514 * when [processed] returns [:null:]. |
269 */ | 515 */ |
270 void process(List<int> data, int start, int end); | 516 void process(List<int> data, int start, int end); |
271 | 517 |
272 /** | 518 /** |
273 * Get a chunk of processed data. When there are no more data available, | 519 * Get a chunk of processed data. When there are no more data available, |
274 * [processed] will return [:null:]. Set [flush] to [:false:] for non-final | 520 * [processed] will return [:null:]. Set [flush] to [:false:] for non-final |
275 * calls to improve performance of some filters. | 521 * calls to improve performance of some filters. |
276 * | 522 * |
277 * The last call to [processed] should have [end] set to [:true:]. This will m ake | 523 * The last call to [processed] should have [end] set to [:true:]. This will |
278 * sure a 'end' packet is written on the stream. | 524 * make sure an 'end' packet is written on the stream. |
279 */ | 525 */ |
280 List<int> processed({bool flush: true, bool end: false}); | 526 List<int> processed({bool flush: true, bool end: false}); |
281 | 527 |
282 /** | 528 /** |
283 * Mark the filter as closed. Always call this method for any filter created | 529 * Mark the filter as closed. Always call this method for any filter created |
284 * to avoid leaking resources. [end] can be called at any time, but any | 530 * to avoid leaking resources. [end] can be called at any time, but any |
285 * successive calls to [process] or [processed] will fail. | 531 * successive calls to [process] or [processed] will fail. |
286 */ | 532 */ |
287 void end(); | 533 void end(); |
288 | 534 |
289 external static _Filter newZLibDeflateFilter(bool gzip, int level); | 535 external static _Filter newZLibDeflateFilter(bool gzip, int level, |
290 external static _Filter newZLibInflateFilter(); | 536 int windowBits, int memLevel, |
537 int strategy, | |
538 List<int> dictionary, bool raw); | |
539 | |
540 external static _Filter newZLibInflateFilter(int windowBits, | |
541 List<int> dictionary, bool raw); | |
291 } | 542 } |
543 | |
544 void _validateZLibWindowBits(int windowBits) { | |
545 if (ZLibConstant.MIN_WINDOW_BITS > windowBits || | |
546 ZLibConstant.MAX_WINDOW_BITS < windowBits) { | |
547 throw new RangeError.range(windowsBits, ZLibConstant.MIN_WINDOW_BITS, | |
548 ZLibConstant.MAX_WINDOW_BITS); | |
549 } | |
550 } | |
551 | |
552 void _validateZLibeLevel(int level) { | |
553 if (ZLibConstant.MIN_LEVEL > level || | |
554 ZLibConstant.MAX_LEVEL < level) { | |
555 throw new RangeError.range(level, ZLibConstant.MIN_LEVEL, | |
556 ZLibConstant.MAX_LEVEL); | |
557 } | |
558 } | |
559 | |
560 void _validateZLibMemLevel(int memLevel) { | |
561 if (ZLibConstant.MIN_MEM_LEVEL > memLevel || | |
562 ZLibConstant.MAX_MEM_LEVEL < memLevel) { | |
563 throw new RangeError(memLvel, ZLibConstant.MIN_MEM_LEVEL, | |
564 ZLibConstant.MAX_MEM_LEVEL); | |
565 } | |
566 } | |
567 | |
568 void _validateZLibStrategy(int strategy) { | |
569 const strategies = const <int>[ZLibConstant.STRATEGY_FILTERED, | |
570 ZLibConstant.STRATEGY_HUFFMAN_ONLY, ZLibConstant.STRATEGY_RLE, | |
571 ZLibConstant.STRATEGY_FIXED, ZLibConstant.STRATEGY_DEFAULT]; | |
572 if (strategies.indexOf(strategy) == -1) { | |
573 throw new ArgumentError("Unsupported 'strategy'"); | |
574 } | |
575 } | |
OLD | NEW |