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

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: fix dictionary memory management 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 /// Minimal value for [windowBits]
9 const int ZLIB_MIN_WINDOW_BITS = 8;
Anders Johnsen 2014/02/04 12:30:45 Talking with lrn@ about this, can you create a new
Lasse Reichstein Nielsen 2014/02/04 13:11:57 I think it is better with an abstract ZLib class c
vicb 2014/02/04 19:55:14 This is what I did first before reverting. I'll re
vicb 2014/02/04 19:55:14 Changed for ZLibConst + DEFAULT_
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;
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Maybe DFT -> DEFAULT (if that's what it stands for
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/02/04 12:30:45 The problem here is that ZLIB is now wrong coding
Lasse Reichstein Nielsen 2014/02/04 13:11:57 I don't *really* mind having ZLIB be a non-const v
vicb 2014/02/04 19:55:14 ZLIB is "almost constant" as the class has no stat
vicb 2014/02/04 19:55:14 done
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
Lasse Reichstein Nielsen 2014/02/04 13:11:57 long line.
vicb 2014/02/04 19:55:14 fixed
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);
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
Lasse Reichstein Nielsen 2014/02/04 13:11:57 long line.
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))
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Indent by four spaces and put an empty line before
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
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Use full names (ZLIB_*) for constants. Use either
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.
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,
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Arguably, I'd indent the lines so that "this" matc
vicb 2014/02/04 19:55:14 I prefer to let my IDE decide and not reindent by
205 this.memLevel: ZLIB_DFT_MEM_LEVEL,
206 this.strategy: ZLIB_STRATEGY_DEFAULT,
207 this.dictionary: null,
208 this.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);
Lasse Reichstein Nielsen 2014/02/04 13:11:57 You can do the same const default constructor tric
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
Lasse Reichstein Nielsen 2014/02/04 13:11:57 long line.
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))
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Block-quote this.
vicb 2014/02/04 19:55:14 fixed
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
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Full constant references [ZLIB_STRATEGY_DEFAULT] (
vicb 2014/02/04 19:55:14 fixed
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 * When true, deflate generates raw data with no zlib header or trailer, and
289 * will not compute an adler32 check value
290 */
291 final bool raw;
292
293 ZLibEncoder({this.gzip: false,
294 this.level: ZLIB_DFT_LEVEL,
295 this.windowBits: ZLIB_DFT_WINDOW_BITS,
296 this.memLevel: ZLIB_DFT_MEM_LEVEL,
297 this.strategy: ZLIB_STRATEGY_DEFAULT,
298 this.dictionary: null,
299 this.raw: false}) {
300 validateZLibeLevel(level);
301 validateZLibMemLevel(memLevel);
302 validateZLibStrategy(strategy);
303 validateZLibWindowBits(windowBits);
304 }
305
306 /**
307 * Convert a list of bytes using the options given to the ZLibEncoder
109 * constructor. 308 * constructor.
110 */ 309 */
111 List<int> convert(List<int> bytes) { 310 List<int> convert(List<int> bytes) {
112 _BufferSink sink = new _BufferSink(); 311 _BufferSink sink = new _BufferSink();
113 startChunkedConversion(sink) 312 startChunkedConversion(sink)
114 ..add(bytes) 313 ..add(bytes)
115 ..close(); 314 ..close();
116 return sink.builder.takeBytes(); 315 return sink.builder.takeBytes();
117 } 316 }
118 317
119 /** 318 /**
120 * Start a chunked conversion using the options given to the [ZLibEncoder] 319 * Start a chunked conversion using the options given to the ZLibEncoder
Lasse Reichstein Nielsen 2014/02/04 13:11:57 No need to remove '[' and ']'. If you don't want a
vicb 2014/02/04 19:55:14 fixed
121 * constructor. While it accepts any [ChunkedConversionSink] taking 320 * constructor. While it accepts any [ChunkedConversionSink] taking
122 * [List<int>]'s, the optimal sink to be passed as [sink] is a 321 * [List<int>]'s, the optimal sink to be passed as [sink] is a
123 * [ByteConversionSink]. 322 * [ByteConversionSink].
124 */ 323 */
125 ByteConversionSink startChunkedConversion( 324 ByteConversionSink startChunkedConversion(
126 ChunkedConversionSink<List<int>> sink) { 325 ChunkedConversionSink<List<int>> sink) {
127 if (sink is! ByteConversionSink) { 326 if (sink is! ByteConversionSink) {
128 sink = new ByteConversionSink.from(sink); 327 sink = new ByteConversionSink.from(sink);
129 } 328 }
130 return new _ZLibEncoderSink(sink, gzip, level); 329
330 return new _ZLibEncoderSink(sink, gzip, level, windowBits, memLevel,
331 strategy, dictionary, raw);
131 } 332 }
132 } 333 }
133 334
134 335
135 /** 336 /**
136 * The [ZLibDecoder] is the decoder used by [ZLibCodec] and [GZipCodec] to 337 * The ZLibDecoder is used by [ZLibCodec] and [GZipCodec] to decompress data.
137 * decompress data.
138 */ 338 */
139 class ZLibDecoder extends Converter<List<int>, List<int>> { 339 class ZLibDecoder extends Converter<List<int>, List<int>> {
340 /**
341 * Base two logarithm of the window size (the size of the history buffer). It
342 * should be in the range 8..15. Larger values result in better compression at
343 * the expense of memory usage. The default value is 15
344 */
345 final int windowBits;
140 346
141 /** 347 /**
142 * Create a new [ZLibEncoder] converter. 348 * Initial compression dictionary.
143 */ 349 *
144 const ZLibDecoder(); 350 * It should consist of strings (byte sequences) that are likely to be
351 * encountered later in the data to be compressed, with the most commonly used
352 * strings preferably put towards the end of the dictionary. Using a dictionary
353 * is most useful when the data to be compressed is short and can be predicted
354 * with good accuracy; the data can then be compressed better than with the
355 * default empty dictionary.
356 */
357 final List<int> dictionary;
358
359 /**
360 * When true, deflate generates raw data with no zlib header or trailer, and
361 * will not compute an adler32 check value
362 */
363 final bool raw;
364
365 ZLibDecoder({this.windowBits: ZLIB_DFT_WINDOW_BITS, this.dictionary: null,
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Could have const default constructor too.
366 this.raw: false}) {
367 validateZLibWindowBits(windowBits);
368 }
145 369
146 /** 370 /**
147 * Convert a list of bytes using the options given to the [ZLibDecoder] 371 * Convert a list of bytes using the options given to the [ZLibDecoder]
148 * constructor. 372 * constructor.
149 */ 373 */
150 List<int> convert(List<int> bytes) { 374 List<int> convert(List<int> bytes) {
151 _BufferSink sink = new _BufferSink(); 375 _BufferSink sink = new _BufferSink();
152 startChunkedConversion(sink) 376 startChunkedConversion(sink)
153 ..add(bytes) 377 ..add(bytes)
154 ..close(); 378 ..close();
155 return sink.builder.takeBytes(); 379 return sink.builder.takeBytes();
156 } 380 }
157 381
158 /** 382 /**
159 * Start a chunked conversion. While it accepts any [ChunkedConversionSink] 383 * Start a chunked conversion. While it accepts any [ChunkedConversionSink]
160 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a 384 * taking [List<int>]'s, the optimal sink to be passed as [sink] is a
161 * [ByteConversionSink]. 385 * [ByteConversionSink].
162 */ 386 */
163 ByteConversionSink startChunkedConversion( 387 ByteConversionSink startChunkedConversion(
164 ChunkedConversionSink<List<int>> sink) { 388 ChunkedConversionSink<List<int>> sink) {
165 if (sink is! ByteConversionSink) { 389 if (sink is! ByteConversionSink) {
166 sink = new ByteConversionSink.from(sink); 390 sink = new ByteConversionSink.from(sink);
167 } 391 }
168 return new _ZLibDecoderSink(sink); 392 return new _ZLibDecoderSink(sink, windowBits, dictionary, raw);
169 } 393 }
170 } 394 }
171 395
172 396
173 class _BufferSink extends ByteConversionSink { 397 class _BufferSink extends ByteConversionSink {
174 final BytesBuilder builder = new BytesBuilder(); 398 final BytesBuilder builder = new BytesBuilder();
175 399
176 void add(List<int> chunk) { 400 void add(List<int> chunk) {
177 builder.add(chunk); 401 builder.add(chunk);
178 } 402 }
179 403
180 void addSlice(List<int> chunk, int start, int end, bool isLast) { 404 void addSlice(List<int> chunk, int start, int end, bool isLast) {
181 if (chunk is Uint8List) { 405 if (chunk is Uint8List) {
182 Uint8List list = chunk; 406 Uint8List list = chunk;
183 builder.add(new Uint8List.view(list.buffer, start, end - start)); 407 builder.add(new Uint8List.view(list.buffer, start, end - start));
184 } else { 408 } else {
185 builder.add(chunk.sublist(start, end)); 409 builder.add(chunk.sublist(start, end));
186 } 410 }
187 } 411 }
188 412
189 void close() {} 413 void close() {}
190 } 414 }
191 415
192 416
193 class _ZLibEncoderSink extends _FilterSink { 417 class _ZLibEncoderSink extends _FilterSink {
194 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level) 418 _ZLibEncoderSink(ByteConversionSink sink, bool gzip, int level,
195 : super(sink, _Filter.newZLibDeflateFilter(gzip, level)); 419 int windowBits, int memLevel, int strategy,
420 List<int> dictionary, bool raw)
421 : super(sink, _Filter.newZLibDeflateFilter(gzip, level, windowBits,
422 memLevel, strategy,
423 dictionary, raw));
424 }
425
426 class _ZLibDecoderSink extends _FilterSink {
427 _ZLibDecoderSink(ByteConversionSink sink, int windowBits,
428 List<int> dictionary, bool raw)
429 : super(sink, _Filter.newZLibInflateFilter(windowBits, dictionary, raw));
196 } 430 }
197 431
198 432
199 class _ZLibDecoderSink extends _FilterSink {
200 _ZLibDecoderSink(ByteConversionSink sink)
201 : super(sink, _Filter.newZLibInflateFilter());
202 }
203
204
205 class _FilterSink extends ByteConversionSink { 433 class _FilterSink extends ByteConversionSink {
206 final _Filter _filter; 434 final _Filter _filter;
207 final ByteConversionSink _sink; 435 final ByteConversionSink _sink;
208 bool _closed = false; 436 bool _closed = false;
209 bool _empty = true; 437 bool _empty = true;
210 438
211 _FilterSink(ByteConversionSink this._sink, _Filter this._filter); 439 _FilterSink(this._sink, this._filter);
212 440
213 void add(List<int> data) { 441 void add(List<int> data) {
214 addSlice(data, 0, data.length, false); 442 addSlice(data, 0, data.length, false);
215 } 443 }
216 444
217 void addSlice(List<int> data, int start, int end, bool isLast) { 445 void addSlice(List<int> data, int start, int end, bool isLast) {
218 if (_closed) return; 446 if (_closed) return;
219 if (start < 0 || start > data.length) { 447 if (start < 0 || start > data.length) {
220 throw new ArgumentError("Invalid start position"); 448 throw new ArgumentError("Invalid start position");
221 } 449 }
(...skipping 29 matching lines...) Expand all
251 _closed = true; 479 _closed = true;
252 throw e; 480 throw e;
253 } 481 }
254 if (!_closed) _filter.end(); 482 if (!_closed) _filter.end();
255 _closed = true; 483 _closed = true;
256 _sink.close(); 484 _sink.close();
257 } 485 }
258 } 486 }
259 487
260 488
261
262 /** 489 /**
263 * Private helper-class to handle native filters. 490 * Private helper-class to handle native filters.
264 */ 491 */
265 abstract class _Filter { 492 abstract class _Filter {
266 /** 493 /**
267 * Call to process a chunk of data. A call to [process] should only be made 494 * Call to process a chunk of data. A call to [process] should only be made
268 * when [processed] returns [:null:]. 495 * when [processed] returns [:null:].
269 */ 496 */
270 void process(List<int> data, int start, int end); 497 void process(List<int> data, int start, int end);
271 498
272 /** 499 /**
273 * Get a chunk of processed data. When there are no more data available, 500 * 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 501 * [processed] will return [:null:]. Set [flush] to [:false:] for non-final
275 * calls to improve performance of some filters. 502 * calls to improve performance of some filters.
276 * 503 *
277 * The last call to [processed] should have [end] set to [:true:]. This will m ake 504 * 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. 505 * sure a 'end' packet is written on the stream.
279 */ 506 */
280 List<int> processed({bool flush: true, bool end: false}); 507 List<int> processed({bool flush: true, bool end: false});
281 508
282 /** 509 /**
283 * Mark the filter as closed. Always call this method for any filter created 510 * 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 511 * to avoid leaking resources. [end] can be called at any time, but any
285 * successive calls to [process] or [processed] will fail. 512 * successive calls to [process] or [processed] will fail.
286 */ 513 */
287 void end(); 514 void end();
288 515
289 external static _Filter newZLibDeflateFilter(bool gzip, int level); 516 external static _Filter newZLibDeflateFilter(bool gzip, int level,
290 external static _Filter newZLibInflateFilter(); 517 int windowBits, int memLevel,
518 int strategy,
519 List<int> dictionary, bool raw);
520
521 external static _Filter newZLibInflateFilter(int windowBits,
522 List<int> dictionary, bool raw);
291 } 523 }
524
525 void validateZLibWindowBits(int windowBits) {
526 if (windowBits is! int ||
Lasse Reichstein Nielsen 2014/02/04 13:11:57 I wouldn't test for int-ness here. The type annota
vicb 2014/02/04 19:55:14 Good to know, fixed
527 windowBits < ZLIB_MIN_WINDOW_BITS ||
528 windowBits > ZLIB_MAX_WINDOW_BITS) {
529 throw new ArgumentError("'windowBits' must be in range "
Lasse Reichstein Nielsen 2014/02/04 13:11:57 You can also use new RangeError.range(windowBit
vicb 2014/02/04 19:55:14 Thanks for the tip
530 "${ZLIB_MIN_WINDOW_BITS}..${ZLIB_MAX_WINDOW_BITS}");
531 }
532 }
533
534 void validateZLibeLevel(int level) {
535 if (level is! int ||
536 level < ZLIB_MIN_LEVEL ||
537 level > ZLIB_MAX_LEVEL) {
538 throw new ArgumentError("'level' must be in range ${ZLIB_MIN_LEVEL}.."
539 "${ZLIB_MAX_LEVEL}");
540 }
541 }
542
543 void validateZLibMemLevel(int memLevel) {
544 if (memLevel is! int ||
545 memLevel < ZLIB_MIN_MEM_LEVEL ||
546 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,
Lasse Reichstein Nielsen 2014/02/04 13:11:57 Maybe make this list const. No need to allocate a
vicb 2014/02/04 19:55:14 done
554 ZLIB_STRATEGY_RLE, ZLIB_STRATEGY_FIXED, ZLIB_STRATEGY_DEFAULT];
555 if (strategies.indexOf(strategy) == -1) {
556 throw new ArgumentError("Unsupported 'strategy'");
557 }
558 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698