Chromium Code Reviews| 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 |