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

Side by Side 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: Address comments. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.convert;
6
7 /**
8 * This class represents the [ByteConversionSink] interface. It is
9 * accessed through [ByteConversionSink.INTERFACE] or as instance field
10 * `interface` from [ByteConversionSink]s.
11 */
12 class _ByteInterface extends ChunkedConversionInterface {
13 const _ByteInterface();
14
15 ByteConversionSink adapt(ChunkedConversionSink sink) {
16 if (sink.interface == ByteConversionSink.INTERFACE) return sink;
17 return new _ByteAdapterSink(sink);
18 }
19
20 /**
21 * Creates a [ByteConversionSink] with a callback.
22 *
23 * The [callback] is invoked with the accumulated data when the sink is
24 * closed.
25 */
26 ByteConversionSink createSink(void callback(List<int> accumulated)) {
27 return new _ByteCallbackSink(callback);
28 }
29 }
30
31 /**
32 * The [ByteConversionSink] provides an interface for converters to
33 * efficiently transmit byte data.
34 *
35 * Instead of limiting the interface to one non-chunked list of bytes it
36 * accepts its input in chunks (themselves being lists of bytes).
37 */
38 abstract class ByteConversionSink extends ChunkedConversionSink<List<int>> {
39
40 /** The Interface that represents the [ByteConversionSink]. */
41 static const ChunkedConversionInterface INTERFACE = const _ByteInterface();
42
43 ByteConversionSink();
44
45 /**
46 * Adds the next [chunk] to `this`.
47 *
48 * Adds the substring defined by [start] and [end]-exclusive to `this`.
Søren Gjesse 2013/07/25 08:07:00 substring -> bytes
floitsch 2013/07/25 12:57:24 Done.
49 *
50 * If [isLast] is `true` closes `this`.
51 *
52 * The given [chunk] is not hold onto. Once the method returns, it is safe to
Søren Gjesse 2013/07/25 08:07:00 hold -> held (I think).
floitsch 2013/07/25 12:57:24 Done.
53 * overwrite the data in it.
54 */
55 void addSlice(List<int> chunk, int start, int end, bool isLast);
56
57 // TODO(floitsch): add more methods:
58 // - iterateBytes.
59
60 ChunkedConversionInterface get interface => INTERFACE;
61 }
62
63 /**
64 * The [StringConversionSinkBase] provides a base-class for converters that
65 * need to accept byte inputs.
66 */
67 abstract class ByteConversionSinkBase extends ByteConversionSink {
68
69 void add(List<int> chunk);
70 void close();
71
72 void addSlice(List<int> chunk, int start, int end, bool isLast) {
73 if (start != 0 || end != chunk.length) {
74 add(chunk.sublist(start, end));
75 } else {
76 add(chunk);
77 }
78 if (isLast) close();
79 }
80
81 ChunkedConversionInterface get interface => ByteConversionSink.INTERFACE;
82 }
83
84 /**
85 * This class adapts a simple [ChunkedConversionSink] to a [ByteConversionSink].
86 *
87 * All additional methods of the [ByteConversionSink] (compared to the
88 * ChunkedConversionSink) are redirected to the `add` method.
89 */
90 class _ByteAdapterSink extends ByteConversionSinkBase {
91 final ChunkedConversionSink<List<int>> _sink;
92
93 _ByteAdapterSink(this._sink);
94
95 void add(List<int> chunk) => _sink.add(chunk);
96 void close() => _sink.close();
97 }
98
99 /**
100 * This class accumulates all chunks into one list of bytes
101 * and invokes a callback when the sink is closed.
102 *
103 * This class can be used to terminate a chunked conversion.
104 */
105 class _ByteCallbackSink extends ByteConversionSinkBase {
106 static const _INITIAL_BUFFER_SIZE = 1024;
107
108 final _ChunkedConversionCallback<List<int>> _callback;
109 // TODO(11971, floitsch): use Uint8List instead of normal lists.
110 List<int> _buffer = new List<int>(_INITIAL_BUFFER_SIZE);
111 int _bufferIndex = 0;
112
113 _ByteCallbackSink(void callback(List<int> accumulated))
114 : this._callback = callback;
115
116 void add(Iterable<int> chunk) {
117 int freeCount = _buffer.length - _bufferIndex;
118 if (chunk.length > freeCount) {
119 // Grow the buffer.
120 int oldLength = _buffer.length;
121 int newLength = _roundToPowerOf2(chunk.length + oldLength) * 2;
122 // TODO(11971, floitsch): use Uint8List instead of normal lists.
Søren Gjesse 2013/07/25 08:07:00 We have the class BytesBuilder in dart:io which do
floitsch 2013/07/25 12:57:24 I think we want to add growable typed lists to typ
123 List<int> grown = new List<int>(newLength);
124 grown.setRange(0, _buffer.length, _buffer);
125 _buffer = grown;
126 }
127 _buffer.setRange(_bufferIndex, _bufferIndex + chunk.length, chunk);
128 _bufferIndex += chunk.length;
129 }
130
131 static int _roundToPowerOf2(int v) {
132 assert(v > 0);
133 v--;
134 v |= v >> 1;
135 v |= v >> 2;
136 v |= v >> 4;
137 v |= v >> 8;
138 v |= v >> 16;
139 v++;
140 return v;
141 }
142
143 void close() {
144 _callback(_buffer.sublist(0, _bufferIndex));
145 }
146 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/convert/chunked_conversion.dart » ('j') | sdk/lib/convert/string_conversion.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698