| 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 |