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 /// Minimal value for [windowBits] | |
9 const int ZLIB_MIN_WINDOW_BITS = 8; | |
Anders Johnsen
2014/01/27 12:27:45
If these are moved to ZLibCodec as final members,
vicb
2014/01/27 15:14:19
But in the doc they'll be listed in ZLibCodec, not
| |
10 /// Maximal value for [windowBits] | |
11 const int ZLIB_MAX_WINDOW_BITS = 15; | |
12 /// Default value for [windowBits] | |
13 const int ZLIB_DFT_WINDOW_BITS = 15; | |
14 | |
15 /// Minimal value for [level] | |
16 const int ZLIB_MIN_LEVEL = -1; | |
17 /// Maximal value for [level] | |
18 const int ZLIB_MAX_LEVEL = 9; | |
19 /// Default value for [level] | |
20 const int ZLIB_DFT_LEVEL = 6; | |
21 | |
22 /// Minimal value for [memLevel] | |
23 const int ZLIB_MIN_MEM_LEVEL = 1; | |
24 /// Maximal value for [memLevel] | |
25 const int ZLIB_MAX_MEM_LEVEL = 9; | |
26 /// Default value for [memLevel] | |
27 const int ZLIB_DFT_MEM_LEVEL = 8; | |
28 | |
29 /// Compression strategies | |
30 const int ZLIB_STRATEGY_FILTERED = 1; | |
31 const int ZLIB_STRATEGY_HUFFMAN_ONLY = 2; | |
32 const int ZLIB_STRATEGY_RLE = 3; | |
33 const int ZLIB_STRATEGY_FIXED = 4; | |
34 const int ZLIB_STRATEGY_DEFAULT = 0; | |
35 | |
36 | |
8 /** | 37 /** |
9 * An instance of the default implementation of the [ZLibCodec]. | 38 * An instance of the default implementation of the [ZLibCodec]. |
10 */ | 39 */ |
11 const ZLibCodec ZLIB = const ZLibCodec(); | 40 final ZLibCodec ZLIB = new ZLibCodec(); |
Anders Johnsen
2014/01/27 12:27:45
make const.
vicb
2014/01/27 15:14:19
Can not because of the required checks
| |
12 | |
13 | 41 |
14 /** | 42 /** |
15 * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib | 43 * The [ZLibCodec] encodes raw bytes to ZLib compressed bytes and decodes ZLib |
16 * compressed bytes to raw bytes. | 44 * compressed bytes to raw bytes. |
17 */ | 45 */ |
18 class ZLibCodec extends Codec<List<int>, List<int>> { | 46 class ZLibCodec extends Codec<List<int>, List<int>> { |
19 /** | 47 /** |
20 * The compression level of the [ZLibCodec]. | 48 * When true, `GZip` frames will be added to the compressed data. |
49 */ | |
50 final bool gzip; | |
51 | |
52 /** | |
53 * The compression-[level] can be set in the range of `-1..9`, with `6` being | |
54 * the default compression level. Levels above `6` will have higher compressio n | |
55 * rates at the cost of more CPU and memory usage. Levels below `6` will use | |
56 * less CPU and memory at the cost of lower compression rates. | |
21 */ | 57 */ |
22 final int level; | 58 final int level; |
23 | 59 |
24 /** | 60 /** |
61 * Specifies how much memory should be allocated for the internal compression | |
62 * state. `1` uses minimum memory but is slow and reduces compression ratio; | |
63 * `9` uses maximum memory for optimal speed. The default value is `8`. | |
64 * | |
65 * The memory requirements for deflate are (in bytes): | |
66 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) | |
67 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | |
68 */ | |
69 final int memLevel; | |
70 | |
71 /** | |
72 * Tunes the compression algorithm. Use the value STRATEGY_DEFAULT for normal | |
73 * data, STRATEGY_FILTERED for data produced by a filter (or predictor), | |
74 * STRATEGY_HUFFMAN_ONLY to force Huffman encoding only (no string match), or | |
75 * STRATEGY_RLE to limit match distances to one (run-length encoding). | |
76 */ | |
77 final int strategy; | |
78 | |
79 /** | |
80 * Base two logarithm of the window size (the size of the history buffer). It | |
81 * should be in the range 8..15. Larger values result in better compression at | |
82 * the expense of memory usage. The default value is 15 | |
83 */ | |
84 final int windowBits; | |
85 | |
86 /** | |
87 * When true, deflate generates raw data with no zlib header or trailer, and | |
88 * will not compute an adler32 check value | |
89 */ | |
90 final bool raw; | |
91 | |
92 /** | |
93 * Initial compression dictionary. | |
94 * | |
95 * It should consist of strings (byte sequences) that are likely to be | |
96 * encountered later in the data to be compressed, with the most commonly used | |
97 * strings preferably put towards the end of the dictionary. Using a dictionary | |
98 * is most useful when the data to be compressed is short and can be predicted | |
99 * with good accuracy; the data can then be compressed better than with the | |
100 * default empty dictionary. | |
101 */ | |
102 final List<int> dictionary; | |
103 | |
104 ZLibCodec({this.level: ZLIB_DFT_LEVEL, | |
105 this.windowBits: ZLIB_DFT_WINDOW_BITS, | |
106 this.memLevel: ZLIB_DFT_MEM_LEVEL, | |
107 this.strategy: ZLIB_STRATEGY_DEFAULT, | |
108 this.dictionary: null, | |
109 this.raw: false}) { | |
110 validateZLibeLevel(level); | |
Anders Johnsen
2014/01/27 12:27:45
Move checks to encoder and decoder getters, or bet
vicb
2014/01/27 15:14:19
As the decoder & encoder are lazily instantiated t
| |
111 validateZLibMemLevel(memLevel); | |
112 validateZLibStrategy(strategy); | |
113 validateZLibWindowBits(windowBits); | |
114 } | |
115 | |
116 /** | |
25 * Get a [Converter] for encoding to `ZLib` compressed data. | 117 * Get a [Converter] for encoding to `ZLib` compressed data. |
26 */ | 118 */ |
27 Converter<List<int>, List<int>> get encoder => | 119 Converter<List<int>, List<int>> get encoder => |
28 new ZLibEncoder(gzip: false, level: level); | 120 new ZLibEncoder(gzip: false, level: level, windowBits: windowBits, |
121 memLevel: memLevel, strategy: strategy, | |
122 dictionary: dictionary, raw: raw); | |
29 | 123 |
30 /** | 124 /** |
31 * Get a [Converter] for decoding `ZLib` compressed data. | 125 * Get a [Converter] for decoding `ZLib` compressed data. |
32 */ | 126 */ |
33 Converter<List<int>, List<int>> get decoder => const ZLibDecoder(); | 127 Converter<List<int>, List<int>> get decoder => new ZLibDecoder( |
34 | 128 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 } | 129 } |
43 | 130 |
44 | 131 |
45 /** | 132 /** |
46 * An instance of the default implementation of the [GZipCodec]. | 133 * An instance of the default implementation of the [GZipCodec]. |
47 */ | 134 */ |
48 const GZipCodec GZIP = const GZipCodec(); | 135 final GZipCodec GZIP = new GZipCodec(); |
49 | 136 |
50 | 137 |
51 /** | 138 /** |
52 * The [GZipCodec] encodes raw bytes to GZip compressed bytes and decodes GZip | 139 * The GZipCodec encodes raw bytes to GZip compressed bytes and decodes GZip |
53 * compressed bytes to raw bytes. | 140 * compressed bytes to raw bytes. |
54 * | 141 * |
55 * The difference between [ZLibCodec] and [GZipCodec] is that the [GZipCodec] | 142 * The difference between [ZLibCodec] and GZipCodec is that the GZipCodec wraps |
56 * wraps the `ZLib` compressed bytes in `GZip` frames. | 143 * the `ZLib` compressed bytes in `GZip` frames. |
57 */ | 144 */ |
58 class GZipCodec extends Codec<List<int>, List<int>> { | 145 class GZipCodec extends Codec<List<int>, List<int>> { |
59 /** | 146 /** |
60 * The compression level of the [ZLibCodec]. | 147 * When true, `GZip` frames will be added to the compressed data. |
148 */ | |
149 final bool gzip; | |
150 | |
151 /** | |
152 * The compression-[level] can be set in the range of `-1..9`, with `6` being | |
153 * the default compression level. Levels above `6` will have higher compressio n | |
154 * rates at the cost of more CPU and memory usage. Levels below `6` will use | |
155 * less CPU and memory at the cost of lower compression rates. | |
61 */ | 156 */ |
62 final int level; | 157 final int level; |
63 | 158 |
64 /** | 159 /** |
160 * Specifies how much memory should be allocated for the internal compression | |
161 * state. `1` uses minimum memory but is slow and reduces compression ratio; | |
162 * `9` uses maximum memory for optimal speed. The default value is `8`. | |
163 * | |
164 * The memory requirements for deflate are (in bytes): | |
165 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) | |
166 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) | |
167 */ | |
168 final int memLevel; | |
169 | |
170 /** | |
171 * Tunes the compression algorithm. Use the value STRATEGY_DEFAULT for normal | |
172 * data, STRATEGY_FILTERED for data produced by a filter (or predictor), | |
173 * STRATEGY_HUFFMAN_ONLY to force Huffman encoding only (no string match), or | |
174 * STRATEGY_RLE to limit match distances to one (run-length encoding). | |
175 */ | |
176 final int strategy; | |
177 | |
178 /** | |
179 * Base two logarithm of the window size (the size of the history buffer). It | |
180 * should be in the range 8..15. Larger values result in better compression at | |
181 * the expense of memory usage. The default value is 15 | |
182 */ | |
183 final int windowBits; | |
184 | |
185 /** | |
186 * Initial compression dictionary. | |
187 * | |
188 * It should consist of strings (byte sequences) that are likely to be | |
189 * encountered later in the data to be compressed, with the most commonly used | |
190 * strings preferably put towards the end of the dictionary. Using a dictionary | |
191 * is most useful when the data to be compressed is short and can be predicted | |
192 * with good accuracy; the data can then be compressed better than with the | |
193 * default empty dictionary. | |
Anders Johnsen
2014/01/27 12:27:45
Maybe write some more about lifeness - do we take
vicb
2014/01/27 15:14:19
I tool models on the current converters. However t
| |
194 */ | |
195 final List<int> dictionary; | |
196 | |
197 /** | |
198 * When true, deflate generates raw data with no zlib header or trailer, and | |
199 * will not compute an adler32 check value | |
200 */ | |
201 final bool raw; | |
202 | |
203 GZipCodec({this.level: ZLIB_DFT_LEVEL, | |
204 this.windowBits: ZLIB_DFT_WINDOW_BITS, | |
205 this.memLevel: ZLIB_DFT_MEM_LEVEL, | |
206 this.strategy: ZLIB_STRATEGY_DEFAULT, | |
207 this.dictionary: null, | |
208 raw: false}) { | |
209 validateZLibeLevel(level); | |
210 validateZLibMemLevel(memLevel); | |
211 validateZLibStrategy(strategy); | |
212 validateZLibWindowBits(windowBits); | |
213 } | |
214 | |
215 /** | |
65 * Get a [Converter] for encoding to `GZip` compressed data. | 216 * Get a [Converter] for encoding to `GZip` compressed data. |
66 */ | 217 */ |
67 Converter<List<int>, List<int>> get encoder => | 218 Converter<List<int>, List<int>> get encoder => |
68 new ZLibEncoder(gzip: true, level: level); | 219 new ZLibEncoder(gzip: true, level: level, windowBits: windowBits, |
220 memLevel: memLevel, strategy: strategy, | |
221 dictionary: dictionary, raw: raw); | |
69 | 222 |
70 /** | 223 /** |
71 * Get a [Converter] for decoding `GZip` compressed data. | 224 * Get a [Converter] for decoding `GZip` compressed data. |
72 */ | 225 */ |
73 Converter<List<int>, List<int>> get decoder => const ZLibDecoder(); | 226 Converter<List<int>, List<int>> get decoder => new ZLibDecoder( |
74 | 227 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 } | 228 } |
83 | 229 |
84 | |
85 /** | 230 /** |
86 * The [ZLibEncoder] is the encoder used by [ZLibCodec] and [GZipCodec] to | 231 * The ZLibEncoder encoder is used by [ZLibCodec] and [GZipCodec] to compress |
87 * compress data. | 232 * data. |
88 */ | 233 */ |
89 class ZLibEncoder extends Converter<List<int>, List<int>> { | 234 class ZLibEncoder extends Converter<List<int>, List<int>> { |
90 /** | 235 /** |
91 * If [gzip] is true, `GZip` frames will be added to the compressed data. | 236 * When true, `GZip` frames will be added to the compressed data. |
92 */ | 237 */ |
93 final bool gzip; | 238 final bool gzip; |
94 | 239 |
95 /** | 240 /** |
96 * The compression level used by the encoder. | 241 * The compression-[level] can be set in the range of `-1..9`, with `6` being |
242 * the default compression level. Levels above `6` will have higher compressio n | |
243 * rates at the cost of more CPU and memory usage. Levels below `6` will use | |
244 * less CPU and memory at the cost of lower compression rates. | |
97 */ | 245 */ |
98 final int level; | 246 final int level; |
99 | 247 |
100 /** | 248 /** |
101 * Create a new [ZLibEncoder] converter. If the [gzip] flag is set, the | 249 * Specifies how much memory should be allocated for the internal compression |
102 * encoder will wrap the encoded ZLib data in GZip frames. | 250 * state. `1` uses minimum memory but is slow and reduces compression ratio; |
103 */ | 251 * `9` uses maximum memory for optimal speed. The default value is `8`. |
104 const ZLibEncoder({this.gzip: false, this.level: 6}); | 252 * |
105 | 253 * The memory requirements for deflate are (in bytes): |
106 | 254 * (1 << (windowBits + 2)) + (1 << (memLevel + 9)) |
107 /** | 255 * that is: 128K for windowBits = 15 + 128K for memLevel = 8 (default values) |
108 * Convert a list of bytes using the options given to the [ZLibEncoder] | 256 */ |
257 final int memLevel; | |
258 | |
259 /** | |
260 * Tunes the compression algorithm. Use the value STRATEGY_DEFAULT for normal | |
261 * data, STRATEGY_FILTERED for data produced by a filter (or predictor), | |
262 * STRATEGY_HUFFMAN_ONLY to force Huffman encoding only (no string match), or | |
263 * STRATEGY_RLE to limit match distances to one (run-length encoding). | |
264 */ | |
265 final int strategy; | |
266 | |
267 /** | |
268 * Base two logarithm of the window size (the size of the history buffer). It | |
269 * should be in the range 8..15. Larger values result in better compression at | |
270 * the expense of memory usage. The default value is 15 | |
271 */ | |
272 final int windowBits; | |
273 | |
274 /** | |
275 * Initial compression dictionary. | |
276 * | |
277 * It should consist of strings (byte sequences) that are likely to be | |
278 * encountered later in the data to be compressed, with the most commonly used | |
279 * strings preferably put towards the end of the dictionary. Using a dictionary | |
280 * is most useful when the data to be compressed is short and can be predicted | |
281 * with good accuracy; the data can then be compressed better than with the | |
282 * default empty dictionary. | |
283 */ | |
284 final List<int> dictionary; | |
285 | |
286 | |
287 /** | |
288 <<<<<<< HEAD | |
Anders Johnsen
2014/01/27 12:27:45
Merge stuff.
vicb
2014/01/27 15:14:19
fixed
| |
289 * When true, deflate generates raw data with no zlib header or trailer, and | |
290 * will not compute an adler32 check value | |
291 */ | |
292 final bool raw; | |
293 | |
294 ZLibEncoder({this.gzip: false, | |
295 this.level: ZLIB_DFT_LEVEL, | |
296 this.windowBits: ZLIB_DFT_WINDOW_BITS, | |
297 this.memLevel: ZLIB_DFT_MEM_LEVEL, | |
298 this.strategy: ZLIB_STRATEGY_DEFAULT, | |
299 this.dictionary: null, | |
300 this.raw: false}) { | |
301 validateZLibeLevel(level); | |
302 validateZLibMemLevel(memLevel); | |
303 validateZLibStrategy(strategy); | |
304 validateZLibWindowBits(windowBits); | |
305 } | |
306 | |
307 /** | |
308 * Convert a list of bytes using the options given to the ZLibEncoder | |
109 * constructor. | 309 * constructor. |
110 */ | 310 */ |
111 List<int> convert(List<int> bytes) { | 311 List<int> convert(List<int> bytes) { |
112 _BufferSink sink = new _BufferSink(); | 312 _BufferSink sink = new _BufferSink(); |
113 startChunkedConversion(sink) | 313 startChunkedConversion(sink) |
114 ..add(bytes) | 314 ..add(bytes) |
115 ..close(); | 315 ..close(); |
116 return sink.builder.takeBytes(); | 316 return sink.builder.takeBytes(); |
117 } | 317 } |
118 | 318 |
119 /** | 319 /** |
120 * Start a chunked conversion using the options given to the [ZLibEncoder] | 320 * Start a chunked conversion using the options given to the ZLibEncoder |
121 * constructor. While it accepts any [ChunkedConversionSink] taking | 321 * constructor. While it accepts any [ChunkedConversionSink] taking |
122 * [List<int>]'s, the optimal sink to be passed as [sink] is a | 322 * [List<int>]'s, the optimal sink to be passed as [sink] is a |
123 * [ByteConversionSink]. | 323 * [ByteConversionSink]. |
124 */ | 324 */ |
125 ByteConversionSink startChunkedConversion( | 325 ByteConversionSink startChunkedConversion( |
126 ChunkedConversionSink<List<int>> sink) { | 326 ChunkedConversionSink<List<int>> sink) { |
127 if (sink is! ByteConversionSink) { | 327 if (sink is! ByteConversionSink) { |
128 sink = new ByteConversionSink.from(sink); | 328 sink = new ByteConversionSink.from(sink); |
129 } | 329 } |
130 return new _ZLibEncoderSink(sink, gzip, level); | 330 |
331 print("Dart _ZLibEncoderSink"); | |
Anders Johnsen
2014/01/27 12:27:45
Debug stuff.
| |
332 return new _ZLibEncoderSink(sink, gzip, level, windowBits, memLevel, | |
333 strategy, dictionary, raw); | |
131 } | 334 } |
132 } | 335 } |
133 | 336 |
134 | 337 |
135 /** | 338 /** |
136 * The [ZLibDecoder] is the decoder used by [ZLibCodec] and [GZipCodec] to | 339 * The ZLibDecoder is used by [ZLibCodec] and [GZipCodec] to decompress data. |
137 * decompress data. | |
138 */ | 340 */ |
139 class ZLibDecoder extends Converter<List<int>, List<int>> { | 341 class ZLibDecoder extends Converter<List<int>, List<int>> { |
342 /** | |
343 * Base two logarithm of the window size (the size of the history buffer). It | |
344 * should be in the range 8..15. Larger values result in better compression at | |
345 * the expense of memory usage. The default value is 15 | |
346 */ | |
347 final int windowBits; | |
140 | 348 |
141 /** | 349 /** |
142 * Create a new [ZLibEncoder] converter. | 350 * Initial compression dictionary. |
143 */ | 351 * |
144 const ZLibDecoder(); | 352 * It should consist of strings (byte sequences) that are likely to be |
353 * encountered later in the data to be compressed, with the most commonly used | |
354 * strings preferably put towards the end of the dictionary. Using a dictionary | |
355 * is most useful when the data to be compressed is short and can be predicted | |
356 * with good accuracy; the data can then be compressed better than with the | |
357 * default empty dictionary. | |
358 */ | |
359 final List<int> dictionary; | |
360 | |
361 /** | |
362 * When true, deflate generates raw data with no zlib header or trailer, and | |
363 * will not compute an adler32 check value | |
364 */ | |
365 final bool raw; | |
366 | |
367 ZLibDecoder({this.windowBits: ZLIB_DFT_WINDOW_BITS, this.dictionary: null, | |
368 this.raw: false}) { | |
369 validateZLibWindowBits(windowBits); | |
370 } | |
145 | 371 |
146 /** | 372 /** |
147 * Convert a list of bytes using the options given to the [ZLibDecoder] | 373 * Convert a list of bytes using the options given to the [ZLibDecoder] |
148 * constructor. | 374 * constructor. |
149 */ | 375 */ |
150 List<int> convert(List<int> bytes) { | 376 List<int> convert(List<int> bytes) { |
151 _BufferSink sink = new _BufferSink(); | 377 _BufferSink sink = new _BufferSink(); |
152 startChunkedConversion(sink) | 378 startChunkedConversion(sink) |
153 ..add(bytes) | 379 ..add(bytes) |
154 ..close(); | 380 ..close(); |
155 return sink.builder.takeBytes(); | 381 return sink.builder.takeBytes(); |
156 } | 382 } |
157 | 383 |
158 /** | 384 /** |
159 * Start a chunked conversion. While it accepts any [ChunkedConversionSink] | 385 * Start a chunked conversion. While it accepts any [ChunkedConversionSink] |
160 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a | 386 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a |
161 * [ByteConversionSink]. | 387 * [ByteConversionSink]. |
162 */ | 388 */ |
163 ByteConversionSink startChunkedConversion( | 389 ByteConversionSink startChunkedConversion( |
164 ChunkedConversionSink<List<int>> sink) { | 390 ChunkedConversionSink<List<int>> sink) { |
165 if (sink is! ByteConversionSink) { | 391 if (sink is! ByteConversionSink) { |
166 sink = new ByteConversionSink.from(sink); | 392 sink = new ByteConversionSink.from(sink); |
167 } | 393 } |
168 return new _ZLibDecoderSink(sink); | 394 print("Dart _ZLibDecoderSink"); |
395 return new _ZLibDecoderSink(sink, windowBits, dictionary, raw); | |
169 } | 396 } |
170 } | 397 } |
171 | 398 |
172 | 399 |
173 class _BufferSink extends ByteConversionSink { | 400 class _BufferSink extends ByteConversionSink { |
174 final BytesBuilder builder = new BytesBuilder(); | 401 final BytesBuilder builder = new BytesBuilder(); |
175 | 402 |
176 void add(List<int> chunk) { | 403 void add(List<int> chunk) { |
177 builder.add(chunk); | 404 builder.add(chunk); |
178 } | 405 } |
179 | 406 |
180 void addSlice(List<int> chunk, int start, int end, bool isLast) { | 407 void addSlice(List<int> chunk, int start, int end, bool isLast) { |
181 if (chunk is Uint8List) { | 408 if (chunk is Uint8List) { |
182 Uint8List list = chunk; | 409 Uint8List list = chunk; |
183 builder.add(new Uint8List.view(list.buffer, start, end - start)); | 410 builder.add(new Uint8List.view(list.buffer, start, end - start)); |
184 } else { | 411 } else { |
185 builder.add(chunk.sublist(start, end)); | 412 builder.add(chunk.sublist(start, end)); |
186 } | 413 } |
187 } | 414 } |
188 | 415 |
189 void close() {} | 416 void close() {} |
190 } | 417 } |
191 | 418 |
192 | 419 |
193 class _ZLibEncoderSink extends _FilterSink { | 420 class _ZLibEncoderSink extends _FilterSink { |
194 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level) | 421 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level, |
195 : super(sink, _Filter.newZLibDeflateFilter(gzip, level)); | 422 int windowBits, int memLevel, int strategy, |
423 List<int> dictionary, bool raw) | |
424 : super(sink, _Filter.newZLibDeflateFilter(gzip, level, windowBits, | |
425 memLevel, strategy, | |
426 dictionary, raw)); | |
427 } | |
428 | |
429 class _ZLibDecoderSink extends _FilterSink { | |
430 _ZLibDecoderSink(ByteConversionSink sink, int windowBits, | |
431 List<int> dictionary, bool raw) | |
432 : super(sink, _Filter.newZLibInflateFilter(windowBits, dictionary, raw)); | |
196 } | 433 } |
197 | 434 |
198 | 435 |
199 class _ZLibDecoderSink extends _FilterSink { | |
200 _ZLibDecoderSink(ByteConversionSink sink) | |
201 : super(sink, _Filter.newZLibInflateFilter()); | |
202 } | |
203 | |
204 | |
205 class _FilterSink extends ByteConversionSink { | 436 class _FilterSink extends ByteConversionSink { |
206 final _Filter _filter; | 437 final _Filter _filter; |
207 final ByteConversionSink _sink; | 438 final ByteConversionSink _sink; |
208 bool _closed = false; | 439 bool _closed = false; |
209 bool _empty = true; | 440 bool _empty = true; |
210 | 441 |
211 _FilterSink(ByteConversionSink this._sink, _Filter this._filter); | 442 _FilterSink(this._sink, this._filter); |
212 | 443 |
213 void add(List<int> data) { | 444 void add(List<int> data) { |
214 addSlice(data, 0, data.length, false); | 445 addSlice(data, 0, data.length, false); |
215 } | 446 } |
216 | 447 |
217 void addSlice(List<int> data, int start, int end, bool isLast) { | 448 void addSlice(List<int> data, int start, int end, bool isLast) { |
218 if (_closed) return; | 449 if (_closed) return; |
219 if (start < 0 || start > data.length) { | 450 if (start < 0 || start > data.length) { |
220 throw new ArgumentError("Invalid start position"); | 451 throw new ArgumentError("Invalid start position"); |
221 } | 452 } |
(...skipping 29 matching lines...) Expand all Loading... | |
251 _closed = true; | 482 _closed = true; |
252 throw e; | 483 throw e; |
253 } | 484 } |
254 if (!_closed) _filter.end(); | 485 if (!_closed) _filter.end(); |
255 _closed = true; | 486 _closed = true; |
256 _sink.close(); | 487 _sink.close(); |
257 } | 488 } |
258 } | 489 } |
259 | 490 |
260 | 491 |
261 | |
262 /** | 492 /** |
263 * Private helper-class to handle native filters. | 493 * Private helper-class to handle native filters. |
264 */ | 494 */ |
265 abstract class _Filter { | 495 abstract class _Filter { |
266 /** | 496 /** |
267 * Call to process a chunk of data. A call to [process] should only be made | 497 * Call to process a chunk of data. A call to [process] should only be made |
268 * when [processed] returns [:null:]. | 498 * when [processed] returns [:null:]. |
269 */ | 499 */ |
270 void process(List<int> data, int start, int end); | 500 void process(List<int> data, int start, int end); |
271 | 501 |
272 /** | 502 /** |
273 * Get a chunk of processed data. When there are no more data available, | 503 * 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 | 504 * [processed] will return [:null:]. Set [flush] to [:false:] for non-final |
275 * calls to improve performance of some filters. | 505 * calls to improve performance of some filters. |
276 * | 506 * |
277 * The last call to [processed] should have [end] set to [:true:]. This will m ake | 507 * The last call to [processed] should have [end] set to [:true:]. This will m ake |
278 * sure a 'end' packet is written on the stream. | 508 * sure a 'end' packet is written on the stream. |
279 */ | 509 */ |
280 List<int> processed({bool flush: true, bool end: false}); | 510 List<int> processed({bool flush: true, bool end: false}); |
281 | 511 |
282 /** | 512 /** |
283 * Mark the filter as closed. Always call this method for any filter created | 513 * 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 | 514 * to avoid leaking resources. [end] can be called at any time, but any |
285 * successive calls to [process] or [processed] will fail. | 515 * successive calls to [process] or [processed] will fail. |
286 */ | 516 */ |
287 void end(); | 517 void end(); |
288 | 518 |
289 external static _Filter newZLibDeflateFilter(bool gzip, int level); | 519 external static _Filter newZLibDeflateFilter(bool gzip, int level, |
290 external static _Filter newZLibInflateFilter(); | 520 int windowBits, int memLevel, |
521 int strategy, | |
522 List<int> dictionary, bool raw); | |
523 | |
524 external static _Filter newZLibInflateFilter(int windowBits, | |
525 List<int> dictionary, bool raw); | |
291 } | 526 } |
527 | |
528 void validateZLibWindowBits(int windowBits) { | |
Anders Johnsen
2014/01/27 12:27:45
Make these functions private.
vicb
2014/01/27 15:14:19
fixed
| |
529 if (windowBits is! int || | |
530 windowBits < ZLIB_MIN_WINDOW_BITS || windowBits > ZLIB_MAX_WINDOW_BITS) { | |
Anders Johnsen
2014/01/27 12:27:45
Move last test to next line, as well as 2 places b
vicb
2014/01/27 15:14:19
fixed
| |
531 throw new ArgumentError("'windowBits' must be in range " | |
532 "${ZLIB_MIN_WINDOW_BITS}..${ZLIB_MAX_WINDOW_BITS}"); | |
533 } | |
534 } | |
535 | |
536 void validateZLibeLevel(int level) { | |
537 if (level is! int || | |
538 level < ZLIB_MIN_LEVEL || level > ZLIB_MAX_LEVEL) { | |
539 throw new ArgumentError("'level' must be in range ${ZLIB_MIN_LEVEL}.." | |
540 "${ZLIB_MAX_LEVEL}"); | |
541 } | |
542 } | |
543 | |
544 void validateZLibMemLevel(int memLevel) { | |
545 if (memLevel is! int || | |
546 memLevel < ZLIB_MIN_MEM_LEVEL || memLevel > ZLIB_MAX_MEM_LEVEL) { | |
547 throw new ArgumentError("'memLevel' must be in range " | |
548 "${ZLIB_MIN_MEM_LEVEL}..${ZLIB_MAX_MEM_LEVEL}"); | |
549 } | |
550 } | |
551 | |
552 void validateZLibStrategy(int strategy) { | |
553 var strategies = <int>[ZLIB_STRATEGY_FILTERED, ZLIB_STRATEGY_HUFFMAN_ONLY, | |
554 ZLIB_STRATEGY_RLE, ZLIB_STRATEGY_FIXED, ZLIB_STRATEGY_DEFAULT]; | |
555 if (strategies.indexOf(strategy) == -1) { | |
556 throw new ArgumentError("Unsupported 'strategy'"); | |
557 } | |
558 } | |
OLD | NEW |