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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sdk/lib/convert/line_splitter.dart ('k') | sdk/lib/convert/utf.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sdk/lib/convert/string_converter.dart
diff --git a/sdk/lib/convert/string_converter.dart b/sdk/lib/convert/string_converter.dart
new file mode 100644
index 0000000000000000000000000000000000000000..9847f9dc70edd9fa84fb61d8197897915a4691cb
--- /dev/null
+++ b/sdk/lib/convert/string_converter.dart
@@ -0,0 +1,370 @@
+// 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;
+
+class _StringInterface extends ChunkedConversionInterface {
+ const _StringInterface();
+
+ StringConversionSink adapt(ChunkedConversionSink sink) {
+ if (sink.interface == StringConversionSink.INTERFACE) return sink;
+ // Common interface is ChunkedConversionSink.
+ return new _StringAdapterSink(sink);
+ }
+
+ StringConversionSink adaptEventSink(EventSink sink) {
+ return new _EventSinkStringAdapterSink(sink);
+ }
+}
+
+abstract class StringConversionSink
+ extends ChunkedConversionSink<String>
+ implements StringSink {
+
+ StringConversionSink();
+ factory StringConversionSink.withStringSink(StringSink sink) =
+ _StringSinkConversionSink;
+
+ void addString(String str, bool isLast);
+ void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast);
+ void addRunes(List<int> runes, int start, int end, bool isLast);
+ void addUtf8(List<int> utf8Units, int start, int end, bool isLast);
+ void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast);
+ void addAscii(List<int> codeUnits, int start, int end, bool isLast);
+ void iterateCodeUnits(StringIterator iterator, bool isLast);
+ void iterateRunes(StringIterator iterator, bool isLast);
+ void iterateUtf8(StringIterator iterator, bool isLast);
+ void iterateIsoLatin1(StringIterator iterator, bool isLast);
+ void iterateAscii(StringIterator iterator, bool isLast);
+ void close(); // Equivalent to addString("", true);
+
+ static const ChunkedConversionInterface INTERFACE = const _StringInterface();
+}
+
+class _StringSinkConversionSink extends StringConversionSinkBase {
+ StringSink _sink;
+ _StringSinkConversionSink(StringSink this._sink);
+
+ void add(String str) => write(str);
+ void close() { /* do nothing */ }
+
+ void write(Object o) => _sink.write(o);
+ void writeln([Object o]) => _sink.writeln(o);
+ void writeCharCode(int charCode) => _sink.writeCharCode(charCode);
+ void writeAll(Iterable objects, [String separator = ""])
+ => _sink.writeAll(objects, separator);
+}
+
+class _StringAdapterSink extends StringConversionSinkBase {
+ final ChunkedConversionSink _otherSink;
+ final StringBuffer _buffer = new StringBuffer();
+
+ _StringAdapterSink(this._otherSink);
+
+ void addNonChunked(String str) => _otherSink.addNonChunked(str);
+
+ void add(String str) => _buffer.write(str);
+ void close() => _otherSink.addNonChunked(_buffer.toString());
+
+ void write(Object o) => _buffer.write(o);
+ void writeln([Object o]) => _buffer.writeln(o);
+ void writeCharCode(int charCode) => _buffer.writeCharCode(charCode);
+ void writeAll(Iterable objects, [String separator = ""])
+ => _buffer.writeAll(objects, separator);
+}
+
+class _EventSinkStringAdapterSink extends StringConversionSinkBase {
+ final EventSink _sink;
+
+ _EventSinkStringAdapterSink(this._sink);
+
+ void add(String str) => _sink.add(str);
+ void close() => _sink.close();
+}
+
+abstract class _StringMultiStringConversionSinkBase
+ extends ChunkedConversionSink {
+ var _handler = null;
+
+ void add(String str);
+
+ void addString(String str, bool isLast) {
+ add(str);
+ if (isLast) close();
+ }
+
+ List<int> _sublist(List<int> list, int start, int end) {
+ if (start != 0 || end != list.length) return list.sublist(start, end);
+ return list;
+ }
+ void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast) {
+ addString(new String.fromCharCodes(_sublist(codeUnits, start, end)),
+ isLast);
+ }
+ void addRunes(List<int> runes, int start, int end, bool isLast) {
+ addString(new String.fromCharCodes(_sublist(runes, start, end)), isLast);
+ }
+ void addUtf8(List<int> utf8Units, int start, int end, bool isLast) {
+ if (_handler == null) {
+ _handler = new Utf8Handler();
+ } else if (_handler is! Utf8Handler) {
+ throw new UnimplementedError("Switching handlers");
+ }
+ Utf8Handler handler = _handler;
+ String string = handler.convert(utf8Units, start, end);
+ bool isDone = isLast && !handler.hasPartialInput;
+ addString(string, isDone);
+ if (isLast && handler.hasPartialInput) {
+ throw new StateError("Bad input");
+ }
+ }
+ void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast) {
+ addRunes(codeUnits, start, end, isLast);
+ }
+ void addAscii(List<int> codeUnits, int start, int end, bool isLast) {
+ addIsoLatin1(codeUnits, start, end, isLast);
+ }
+ void iterateCodeUnits(StringIterator iterator, bool isLast) {
+ addString(iterator.convertToString(), isLast);
+ }
+ void iterateRunes(StringIterator iterator, bool isLast) {
+ addString(iterator.convertToString(), isLast);
+ }
+ void iterateUtf8(StringIterator iterator, bool isLast) {
+ addString(iterator.convertToString(), isLast);
+ }
+ void iterateIsoLatin1(StringIterator iterator, bool isLast) {
+ addString(iterator.convertToString(), isLast);
+ }
+ void iterateAscii(StringIterator iterator, bool isLast) {
+ addString(iterator.convertToString(), isLast);
+ }
+
+ void write(Object o) { addString(o.toString(), false); }
+ void writeln([Object o]) {
+ if (o != null) {
+ addString(o.toString(), false);
+ }
+ addString("\n", false);
+ }
+ void writeCharCode(int charCode) {
+ addString(new String.fromCharCode(charCode), false);
+ }
+ void writeAll(Iterable objects, [String separator = ""]) {
+ addString(objects.join(separator), false);
+ }
+
+ ChunkedConversionInterface get interface => StringConversionSink.INTERFACE;
+}
+
+abstract class StringConversionSinkBase
+ extends _StringMultiStringConversionSinkBase
+ implements StringConversionSink {
+
+ void addNonChunked(String str) => addString(str, true);
+
+ close() => addString("", true);
+}
+
+class Utf8Handler {
+ int _value = 0;
+ int _expectedUnits = 0;
+ int _extraUnits = 0;
+
+ bool get hasPartialInput => _expectedUnits > 0;
+
+ // Limits of one through four byte encodings.
+ static const List<int> _LIMITS = const <int>[
+ _ONE_BYTE_LIMIT,
+ _TWO_BYTE_LIMIT,
+ _THREE_BYTE_LIMIT,
+ _FOUR_BYTE_LIMIT ];
+
+ /**
+ * This method will call _partialState for unfinished unicode sequences.
+ */
+ String convert(List<int> codeUnits, int startIndex, int endIndex) {
+ StringBuffer buffer = new StringBuffer();
+ convertToSink(codeUnits, startIndex, endIndex, buffer);
+ return buffer.toString();
+ }
+
+ /**
+ * This method will call _partialState for unfinished unicode sequences.
+ */
+ void convertToSink(List<int> codeUnits, int startIndex, int endIndex,
+ StringSink sink) {
+ int value = _value;
+ int expectedUnits = _expectedUnits;
+ int extraUnits = _extraUnits;
+ _value = 0;
+ _expectedUnits = 0;
+ _extraUnits = 0;
+
+ int i = startIndex;
+ loop: while (true) {
+ multibyte: if (expectedUnits > 0) {
+ do {
+ if (i == endIndex) {
+ break loop;
+ }
+ int unit = codeUnits[i];
+ if ((unit & 0xC0) != 0x80) {
+ int partialValue = value;
+ value = expectedUnits = 0;
+ if (!_onError(partialValue)) break loop;
+ break multibyte;
+ } else {
+ value = (value << 6) | (unit & 0x3f);
+ expectedUnits--;
+ i++;
+ }
+ } while (expectedUnits > 0);
+ if (value <= _LIMITS[extraUnits - 1]) {
+ // Overly long encoding. The value could be encoded with a shorter
+ // encoding.
+ if (!_onError(value)) break loop;
+ }
+ sink.writeCharCode(value);
+ }
+
+ while (i < endIndex) {
+ int unit = codeUnits[i++];
+ if (unit <= _ONE_BYTE_LIMIT) {
+ sink.writeCharCode(unit);
+ } else {
+ if ((unit & 0xE0) == 0xC0) {
+ value = unit & 0x1F;
+ expectedUnits = extraUnits = 1;
+ continue loop;
+ }
+ if ((unit & 0xF0) == 0xE0) {
+ value = unit & 0x0F;
+ expectedUnits = extraUnits = 2;
+ continue loop;
+ }
+ if ((unit & 0xF8) == 0xF0) {
+ value = unit & 0x07;
+ expectedUnits = extraUnits = 3;
+ continue loop;
+ }
+ if (!_onError(unit)) {
+ break loop;
+ }
+ }
+ }
+ break loop;
+ }
+ if (expectedUnits > 0) {
+ _value = value;
+ _expectedUnits = expectedUnits;
+ _extraUnits = extraUnits;
+ }
+ }
+
+ bool _onError(int unexpectedByte) {
+ throw new StateError
+ ("Unexpected byte 0x${unexpectedByte.toRadixString(16)}.");
+ }
+}
+
+abstract class StringIterator extends Iterator {
+ /**
+ * Fills [list] at position [startIndex] up to [endIndex] (exclusive) with
+ * the next elements. Returns the next unwritten index.
+ */
+ int fill(List<int> list, int startIndex, int endIndex);
+
+ /**
+ * Returns the string representation of the full content of this iterator.
+ */
+ String convertToString();
+
+ StringIterator asRunes();
+ StringIterator asCodeUnits();
+ StringIterator asUtf8();
+}
+
+
+class _MultiStringInterface extends ChunkedConversionInterface {
+ const _MultiStringInterface();
+
+ MultiStringConversionSink adapt(ChunkedConversionSink sink) {
+ if (sink.interface == MultiStringConversionSink.INTERFACE) return sink;
+ // Common interface is ChunkedConversionSink.
+ return new _MultiStringAdapterSink(sink);
+ }
+
+ MultiStringConversionSink adaptEventSink(EventSink sink) {
+ return new _EventSinkMultiStringAdapterSink(sink);
+ }
+}
+
+abstract class MultiStringConversionSink
+ extends ChunkedConversionSink<List<String>>
+ implements StringSink {
+
+ MultiStringConversionSink();
+
+ void addString(String str, bool isLast);
+ void addCodeUnits(List<int> codeUnits, int start, int end, bool isLast);
+ void addRunes(List<int> runes, int start, int end, bool isLast);
+ void addUtf8(List<int> utf8Units, int start, int end, bool isLast);
+ void addIsoLatin1(List<int> codeUnits, int start, int end, bool isLast);
+ void addAscii(List<int> codeUnits, int start, int end, bool isLast);
+ void iterateCodeUnits(StringIterator iterator, bool isLast);
+ void iterateRunes(StringIterator iterator, bool isLast);
+ void iterateUtf8(StringIterator iterator, bool isLast);
+ void iterateIsoLatin1(StringIterator iterator, bool isLast);
+ void iterateAscii(StringIterator iterator, bool isLast);
+ void close();
+
+ static const ChunkedConversionInterface INTERFACE =
+ const _MultiStringInterface();
+}
+
+abstract class MultiStringConversionSinkBase
+ extends _StringMultiStringConversionSinkBase
+ implements MultiStringConversionSink {
+
+ void addNonChunked(List<String> list) {
+ for (int i = 0; i < list.length - 1; i++) {
+ addString(list[i], false);
+ }
+ if (!list.isEmpty) {
+ addString(list.last, true);
+ } else {
+ close();
+ }
+ }
+
+ ChunkedConversionInterface get interface =>
+ MultiStringConversionSink.INTERFACE;
+}
+
+
+class _MultiStringAdapterSink extends MultiStringConversionSinkBase
+ implements MultiStringConversionSink {
+ final ChunkedConversionSink _otherSink;
+ final List<String> _accumulator = <String>[];
+
+ _MultiStringAdapterSink(this._otherSink);
+
+ void addNonChunked(List<String> list) {
+ _otherSink.addNonChunked(list.join("\n"));
+ }
+
+ void add(String str) => _accumulator.add(str);
+ void close() { _otherSink.addNonChunked(_accumulator); }
+}
+
+class _EventSinkMultiStringAdapterSink extends MultiStringConversionSinkBase
+ implements MultiStringConversionSink {
+ final EventSink _sink;
+
+ _EventSinkMultiStringAdapterSink(this._sink);
+
+ void add(String str) => _sink.add(str);
+ void close() { _sink.close(); }
+}
« 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