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