Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: sdk/lib/io/data_transformer.dart

Issue 130513003: [ZLIB] Add support for windowBits, memLevel, raw (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: integrate feedback Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698