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

Side by Side Diff: sdk/lib/convert/string_converter.dart

Issue 17580014: dart:convert library. Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update 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
« no previous file with comments | « sdk/lib/convert/line_splitter.dart ('k') | sdk/lib/convert/utf.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 class _StringInterface extends ChunkedConversionInterface {
8 const _StringInterface();
9
10 StringConversionSink adapt(ChunkedConversionSink sink) {
11 if (sink.interface == StringConversionSink.INTERFACE) return sink;
12 // Common interface is ChunkedConversionSink.
13 return new _StringAdapterSink(sink);
14 }
15
16 StringConversionSink adaptEventSink(EventSink sink) {
17 return new _EventSinkStringAdapterSink(sink);
18 }
19 }
20
21 abstract class StringConversionSink
22 extends ChunkedConversionSink<String>
23 implements StringSink {
24
25 StringConversionSink();
26 factory StringConversionSink.withStringSink(StringSink sink) =
27 _StringSinkConversionSink;
28
29 void addString(String str, bool isLast);
30 void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast);
31 void addRunes(List<int> runes, int start, int end, bool isLast);
32 void addUtf8(List<int> utf8Units, int start, int end, bool isLast);
33 void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast);
34 void addAscii(List<int> codeUnits, int start, int end, bool isLast);
35 void iterateCodeUnits(StringIterator iterator, bool isLast);
36 void iterateRunes(StringIterator iterator, bool isLast);
37 void iterateUtf8(StringIterator iterator, bool isLast);
38 void iterateIsoLatin1(StringIterator iterator, bool isLast);
39 void iterateAscii(StringIterator iterator, bool isLast);
40 void close(); // Equivalent to addString("", true);
41
42 static const ChunkedConversionInterface INTERFACE = const _StringInterface();
43 }
44
45 class _StringSinkConversionSink extends StringConversionSinkBase {
46 StringSink _sink;
47 _StringSinkConversionSink(StringSink this._sink);
48
49 void add(String str) => write(str);
50 void close() { /* do nothing */ }
51
52 void write(Object o) => _sink.write(o);
53 void writeln([Object o]) => _sink.writeln(o);
54 void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
55 void writeAll(Iterable objects, [String separator = ""])
56 => _sink.writeAll(objects, separator);
57 }
58
59 class _StringAdapterSink extends StringConversionSinkBase {
60 final ChunkedConversionSink _otherSink;
61 final StringBuffer _buffer = new StringBuffer();
62
63 _StringAdapterSink(this._otherSink);
64
65 void addNonChunked(String str) => _otherSink.addNonChunked(str);
66
67 void add(String str) => _buffer.write(str);
68 void close() => _otherSink.addNonChunked(_buffer.toString());
69
70 void write(Object o) => _buffer.write(o);
71 void writeln([Object o]) => _buffer.writeln(o);
72 void writeCharCode(int charCode) => _buffer.writeCharCode(charCode);
73 void writeAll(Iterable objects, [String separator = ""])
74 => _buffer.writeAll(objects, separator);
75 }
76
77 class _EventSinkStringAdapterSink extends StringConversionSinkBase {
78 final EventSink _sink;
79
80 _EventSinkStringAdapterSink(this._sink);
81
82 void add(String str) => _sink.add(str);
83 void close() => _sink.close();
84 }
85
86 abstract class _StringMultiStringConversionSinkBase
87 extends ChunkedConversionSink {
88 var _handler = null;
89
90 void add(String str);
91
92 void addString(String str, bool isLast) {
93 add(str);
94 if (isLast) close();
95 }
96
97 List<int> _sublist(List<int> list, int start, int end) {
98 if (start != 0 || end != list.length) return list.sublist(start, end);
99 return list;
100 }
101 void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast) {
102 addString(new String.fromCharCodes(_sublist(codeUnits, start, end)),
103 isLast);
104 }
105 void addRunes(List<int> runes, int start, int end, bool isLast) {
106 addString(new String.fromCharCodes(_sublist(runes, start, end)), isLast);
107 }
108 void addUtf8(List<int> utf8Units, int start, int end, bool isLast) {
109 if (_handler == null) {
110 _handler = new Utf8Handler();
111 } else if (_handler is! Utf8Handler) {
112 throw new UnimplementedError("Switching handlers");
113 }
114 Utf8Handler handler = _handler;
115 String string = handler.convert(utf8Units, start, end);
116 bool isDone = isLast && !handler.hasPartialInput;
117 addString(string, isDone);
118 if (isLast && handler.hasPartialInput) {
119 throw new StateError("Bad input");
120 }
121 }
122 void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast) {
123 addRunes(codeUnits, start, end, isLast);
124 }
125 void addAscii(List<int> codeUnits, int start, int end, bool isLast) {
126 addIsoLatin1(codeUnits, start, end, isLast);
127 }
128 void iterateCodeUnits(StringIterator iterator, bool isLast) {
129 addString(iterator.convertToString(), isLast);
130 }
131 void iterateRunes(StringIterator iterator, bool isLast) {
132 addString(iterator.convertToString(), isLast);
133 }
134 void iterateUtf8(StringIterator iterator, bool isLast) {
135 addString(iterator.convertToString(), isLast);
136 }
137 void iterateIsoLatin1(StringIterator iterator, bool isLast) {
138 addString(iterator.convertToString(), isLast);
139 }
140 void iterateAscii(StringIterator iterator, bool isLast) {
141 addString(iterator.convertToString(), isLast);
142 }
143
144 void write(Object o) { addString(o.toString(), false); }
145 void writeln([Object o]) {
146 if (o != null) {
147 addString(o.toString(), false);
148 }
149 addString("\n", false);
150 }
151 void writeCharCode(int charCode) {
152 addString(new String.fromCharCode(charCode), false);
153 }
154 void writeAll(Iterable objects, [String separator = ""]) {
155 addString(objects.join(separator), false);
156 }
157
158 ChunkedConversionInterface get interface => StringConversionSink.INTERFACE;
159 }
160
161 abstract class StringConversionSinkBase
162 extends _StringMultiStringConversionSinkBase
163 implements StringConversionSink {
164
165 void addNonChunked(String str) => addString(str, true);
166
167 close() => addString("", true);
168 }
169
170 class Utf8Handler {
171 int _value = 0;
172 int _expectedUnits = 0;
173 int _extraUnits = 0;
174
175 bool get hasPartialInput => _expectedUnits > 0;
176
177 // Limits of one through four byte encodings.
178 static const List<int> _LIMITS = const <int>[
179 _ONE_BYTE_LIMIT,
180 _TWO_BYTE_LIMIT,
181 _THREE_BYTE_LIMIT,
182 _FOUR_BYTE_LIMIT ];
183
184 /**
185 * This method will call _partialState for unfinished unicode sequences.
186 */
187 String convert(List<int> codeUnits, int startIndex, int endIndex) {
188 StringBuffer buffer = new StringBuffer();
189 convertToSink(codeUnits, startIndex, endIndex, buffer);
190 return buffer.toString();
191 }
192
193 /**
194 * This method will call _partialState for unfinished unicode sequences.
195 */
196 void convertToSink(List<int> codeUnits, int startIndex, int endIndex,
197 StringSink sink) {
198 int value = _value;
199 int expectedUnits = _expectedUnits;
200 int extraUnits = _extraUnits;
201 _value = 0;
202 _expectedUnits = 0;
203 _extraUnits = 0;
204
205 int i = startIndex;
206 loop: while (true) {
207 multibyte: if (expectedUnits > 0) {
208 do {
209 if (i == endIndex) {
210 break loop;
211 }
212 int unit = codeUnits[i];
213 if ((unit & 0xC0) != 0x80) {
214 int partialValue = value;
215 value = expectedUnits = 0;
216 if (!_onError(partialValue)) break loop;
217 break multibyte;
218 } else {
219 value = (value << 6) | (unit & 0x3f);
220 expectedUnits--;
221 i++;
222 }
223 } while (expectedUnits > 0);
224 if (value <= _LIMITS[extraUnits - 1]) {
225 // Overly long encoding. The value could be encoded with a shorter
226 // encoding.
227 if (!_onError(value)) break loop;
228 }
229 sink.writeCharCode(value);
230 }
231
232 while (i < endIndex) {
233 int unit = codeUnits[i++];
234 if (unit <= _ONE_BYTE_LIMIT) {
235 sink.writeCharCode(unit);
236 } else {
237 if ((unit & 0xE0) == 0xC0) {
238 value = unit & 0x1F;
239 expectedUnits = extraUnits = 1;
240 continue loop;
241 }
242 if ((unit & 0xF0) == 0xE0) {
243 value = unit & 0x0F;
244 expectedUnits = extraUnits = 2;
245 continue loop;
246 }
247 if ((unit & 0xF8) == 0xF0) {
248 value = unit & 0x07;
249 expectedUnits = extraUnits = 3;
250 continue loop;
251 }
252 if (!_onError(unit)) {
253 break loop;
254 }
255 }
256 }
257 break loop;
258 }
259 if (expectedUnits > 0) {
260 _value = value;
261 _expectedUnits = expectedUnits;
262 _extraUnits = extraUnits;
263 }
264 }
265
266 bool _onError(int unexpectedByte) {
267 throw new StateError
268 ("Unexpected byte 0x${unexpectedByte.toRadixString(16)}.");
269 }
270 }
271
272 abstract class StringIterator extends Iterator {
273 /**
274 * Fills [list] at position [startIndex] up to [endIndex] (exclusive) with
275 * the next elements. Returns the next unwritten index.
276 */
277 int fill(List<int> list, int startIndex, int endIndex);
278
279 /**
280 * Returns the string representation of the full content of this iterator.
281 */
282 String convertToString();
283
284 StringIterator asRunes();
285 StringIterator asCodeUnits();
286 StringIterator asUtf8();
287 }
288
289
290 class _MultiStringInterface extends ChunkedConversionInterface {
291 const _MultiStringInterface();
292
293 MultiStringConversionSink adapt(ChunkedConversionSink sink) {
294 if (sink.interface == MultiStringConversionSink.INTERFACE) return sink;
295 // Common interface is ChunkedConversionSink.
296 return new _MultiStringAdapterSink(sink);
297 }
298
299 MultiStringConversionSink adaptEventSink(EventSink sink) {
300 return new _EventSinkMultiStringAdapterSink(sink);
301 }
302 }
303
304 abstract class MultiStringConversionSink
305 extends ChunkedConversionSink<List<String>>
306 implements StringSink {
307
308 MultiStringConversionSink();
309
310 void addString(String str, bool isLast);
311 void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast);
312 void addRunes(List<int> runes, int start, int end, bool isLast);
313 void addUtf8(List<int> utf8Units, int start, int end, bool isLast);
314 void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast);
315 void addAscii(List<int> codeUnits, int start, int end, bool isLast);
316 void iterateCodeUnits(StringIterator iterator, bool isLast);
317 void iterateRunes(StringIterator iterator, bool isLast);
318 void iterateUtf8(StringIterator iterator, bool isLast);
319 void iterateIsoLatin1(StringIterator iterator, bool isLast);
320 void iterateAscii(StringIterator iterator, bool isLast);
321 void close();
322
323 static const ChunkedConversionInterface INTERFACE =
324 const _MultiStringInterface();
325 }
326
327 abstract class MultiStringConversionSinkBase
328 extends _StringMultiStringConversionSinkBase
329 implements MultiStringConversionSink {
330
331 void addNonChunked(List<String> list) {
332 for (int i = 0; i < list.length - 1; i++) {
333 addString(list[i], false);
334 }
335 if (!list.isEmpty) {
336 addString(list.last, true);
337 } else {
338 close();
339 }
340 }
341
342 ChunkedConversionInterface get interface =>
343 MultiStringConversionSink.INTERFACE;
344 }
345
346
347 class _MultiStringAdapterSink extends MultiStringConversionSinkBase
348 implements MultiStringConversionSink {
349 final ChunkedConversionSink _otherSink;
350 final List<String> _accumulator = <String>[];
351
352 _MultiStringAdapterSink(this._otherSink);
353
354 void addNonChunked(List<String> list) {
355 _otherSink.addNonChunked(list.join("\n"));
356 }
357
358 void add(String str) => _accumulator.add(str);
359 void close() { _otherSink.addNonChunked(_accumulator); }
360 }
361
362 class _EventSinkMultiStringAdapterSink extends MultiStringConversionSinkBase
363 implements MultiStringConversionSink {
364 final EventSink _sink;
365
366 _EventSinkMultiStringAdapterSink(this._sink);
367
368 void add(String str) => _sink.add(str);
369 void close() { _sink.close(); }
370 }
OLDNEW
« no previous file with comments | « sdk/lib/convert/line_splitter.dart ('k') | sdk/lib/convert/utf.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698