| Index: lib/src/base64/decoder_sink.dart
|
| diff --git a/lib/src/base64/decoder_sink.dart b/lib/src/base64/decoder_sink.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f660f341ed206c83ecc4162e360d737b589903c0
|
| --- /dev/null
|
| +++ b/lib/src/base64/decoder_sink.dart
|
| @@ -0,0 +1,51 @@
|
| +// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| +// for details. All rights reserved. Use of this source code is governed by a
|
| +// BSD-style license that can be found in the LICENSE file.
|
| +
|
| +library crypto.base64.decoder_sink;
|
| +
|
| +import 'dart:convert';
|
| +
|
| +import 'decoder.dart';
|
| +
|
| +/// A [ChunkedConversionSink] for decoding chunks of Base64 strings to data.
|
| +class Base64DecoderSink extends ChunkedConversionSink<String> {
|
| + /// The encoder used to decode each chunk.
|
| + final Base64Decoder _decoder = new Base64Decoder();
|
| +
|
| + /// The underlying sink to which to emit the decoded strings.
|
| + final ChunkedConversionSink<List<int>> _outSink;
|
| +
|
| + /// The as-yet-unconverted text.
|
| + ///
|
| + /// This is used to handle text stopping partway through a four-character
|
| + /// 32-bit chunk.
|
| + String _unconverted = "";
|
| +
|
| + Base64DecoderSink(this._outSink);
|
| +
|
| + void add(String chunk) {
|
| + if (chunk.isEmpty) return;
|
| + if (_unconverted.isNotEmpty) chunk = _unconverted + chunk;
|
| + chunk = chunk.replaceAll("%3D", "=");
|
| +
|
| + // The decodable length is the length of the initial substring comprising
|
| + // full four-character 32-bit chunks. Any leftovers are handled when [add]
|
| + // or [close] are next called.
|
| + var decodableLength = chunk.length;
|
| + if (chunk.length > 3 && chunk.contains("%", chunk.length - 2)) {
|
| + decodableLength = chunk.lastIndexOf("%");
|
| + }
|
| + decodableLength -= decodableLength % 4;
|
| +
|
| + _unconverted = chunk.substring(decodableLength);
|
| + if (decodableLength > 0) {
|
| + _outSink.add(_decoder.convert(chunk.substring(0, decodableLength)));
|
| + }
|
| + }
|
| +
|
| + void close() {
|
| + if (_unconverted.isNotEmpty) _outSink.add(_decoder.convert(_unconverted));
|
| + _outSink.close();
|
| + }
|
| +}
|
|
|