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

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

Powered by Google App Engine
This is Rietveld 408576698