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