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

Unified Diff: sdk/lib/convert/byte_conversion.dart

Issue 19883003: Add chunked conversion to converters. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Improve some typse. Created 7 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | sdk/lib/convert/chunked_conversion.dart » ('j') | sdk/lib/convert/chunked_conversion.dart » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/convert/byte_conversion.dart
diff --git a/sdk/lib/convert/byte_conversion.dart b/sdk/lib/convert/byte_conversion.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9eb834115b0cfcd3d1a2c9cccbbbc93e72982b44
--- /dev/null
+++ b/sdk/lib/convert/byte_conversion.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2013, 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.
+
+part of dart.convert;
+
+/**
+ * This class represents the [ByteConversionSink] interface. It is
+ * accessed through [ByteConversionSink.INTERFACE] or as instance field
+ * `interface` from [ByteConversionSink]s.
+ */
+class _ByteInterface extends ChunkedConversionInterface {
+ const _ByteInterface();
+
+ ByteConversionSink adapt(ChunkedConversionSink sink) {
+ if (sink.interface == _ByteInterface) return sink;
Søren Gjesse 2013/07/24 09:26:41 _ByteInterface => ByteConvertionSink.INTERFACE
floitsch 2013/07/24 18:31:15 Done.
+ // Common denominator is ChunkedConversionSink.
+ return new _ByteAdapterSink(sink);
+ }
+}
+
+/**
+ * The [ByteConversionSink] provides an interface for converters to
+ * efficiently transmit byte data.
+ *
+ * Instead of limiting the interface to one non-chunked list of bytes it
+ * accepts its input in chunks (themselves being lists of bytes).
+ */
+abstract class ByteConversionSink
+ extends ChunkedConversionSink<List<int>, List<int>> {
+
+ /** The Interface that represents the [ByteConversionSink]. */
+ static const ChunkedConversionInterface INTERFACE = const _ByteInterface();
+
+ ByteConversionSink();
+ /**
+ * Creates a [ByteConversionSink] with a callback.
+ *
+ * The [callback] is invoked with the accumulated data when the sink is
+ * closed (which automatically happens when it receives data through
+ * [addNonChunked]).
+ */
+ factory ByteConversionSink.withCallback(void callback(List<int> list)) =
+ _ByteConversionCallbackSink;
Søren Gjesse 2013/07/24 09:26:41 How about also having a ByteConvertionSink.withFu
floitsch 2013/07/24 18:31:15 Removed that constructor during removal of addNonC
+
+ /**
+ * Adds the next [chunk] to `this`.
+ *
+ * Adds the substring defined by [start] and [end]-exclusive to `this`.
+ *
+ * If [isLast] is `true` closes `this`.
+ *
+ * The given [chunk] is not hold onto. Once the method returns, it is safe to
+ * overwrite the data in it.
+ */
+ void addSlice(List<int> chunk, int start, int end, bool isLast);
+
+ // TODO(floitsch): add more methods:
+ // - iterateBytes.
+
+ ChunkedConversionInterface get interface => INTERFACE;
+}
+
+/**
+ * The [StringConversionSinkBase] provides a base-class for converters that
+ * need to accept byte inputs.
+ */
+abstract class ByteConversionSinkBase extends ByteConversionSink {
+
+ void add(List<int> chunk);
+ void close();
+
+ void addNonChunked(List<int> list) {
+ add(list);
+ close();
+ }
+
+ void addSlice(List<int> chunk, int start, int end, bool isLast) {
+ if (start != 0 || end != chunk.length) {
+ add(chunk.sublist(start, end));
+ } else {
+ add(chunk);
+ }
+ if (isLast) close();
+ }
+
+ ChunkedConversionInterface get interface => ByteConversionSink.INTERFACE;
+}
+
+/**
+ * A [ByteConversionSink] accumulates all chunks and gives it to
+ * the wrapped sink in one go (using `addNonChunked`).
+ *
+ * This class can be used to terminate a chunked conversion.
+ */
+class _ByteAdapterSink extends ByteConversionSinkBase {
+ static const _INITIAL_BUFFER_SIZE = 1024;
+ final ChunkedConversionSink _otherSink;
+ // TODO(11971, floitsch): use Uint8List instead of normal lists.
+ final List<int> _buffer = new List<int>(_INITIAL_BUFFER_SIZE);
+ int _bufferIndex = 0;
+
+ _ByteAdapterSink(this._otherSink);
+
+ void add(Iterable<int> chunk) {
+ int freeCount = _buffer.length - _bufferIndex;
+ if (chunk.length > freeCount) {
+ // Grow the buffer.
+ int oldLength = _buffer.length;
+ int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2;
+ // TODO(11971, floitsch): use Uint8List instead of normal lists.
+ List<int> grown = new List<int>(newLength);
+ grown.setRange(0, _buffer.length, _buffer);
+ }
+ _buffer.setRange(_bufferIndex, _bufferIndex + chunk.length, chunk);
+ _bufferIndex += chunk.length;
+ }
+
+ static int _roundToPowerOf2(int v) {
Søren Gjesse 2013/07/24 09:26:41 This is not the first time I have seen this code.
floitsch 2013/07/24 18:31:15 Filed http://dartbug.com/12008.
+ assert(v > 0);
+ v--;
+ v |= v >> 1;
+ v |= v >> 2;
+ v |= v >> 4;
+ v |= v >> 8;
+ v |= v >> 16;
+ v++;
+ return v;
+ }
+
+ void close() {
+ _otherSink.addNonChunked(_buffer.sublist(0, _bufferIndex));
+ }
+
+ void addNonChunked(List<int> list) => _otherSink.addNonChunked(list);
+}
+
+/**
+ * A [ByteConversionSink] accumulating all chunks and invoking a
+ * callback when the sink is closed.
+ */
+class _ByteConversionCallbackSink extends ByteConversionSinkBase {
+ final _ChunkedConversionCallback<List<int>> _callback;
+ // TODO(floitsch): use typed lists.
+ final List<int> _accumulated = <int>[];
+
+ _ByteConversionCallbackSink(this._callback);
+
+ void add(Iterable<int> chunk) { _accumulated.addAll(chunk); }
+ void close() { _callback(_accumulated); }
+
+ void addNonChunked(List<int> list) => _callback(list);
+}
« no previous file with comments | « no previous file | sdk/lib/convert/chunked_conversion.dart » ('j') | sdk/lib/convert/chunked_conversion.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698