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