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

Unified Diff: runtime/bin/string_stream.dart

Issue 9653026: Add writeString method to OutputStream (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 8 years, 9 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 | « runtime/bin/stream_util.dart ('k') | samples/chat/chat_server_lib.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/string_stream.dart
diff --git a/runtime/bin/string_stream.dart b/runtime/bin/string_stream.dart
index bedbc55a2fca1b44890fd88ed4224e4f676422ba..536eda1b56551c943506b744e69a2c396c91f803 100644
--- a/runtime/bin/string_stream.dart
+++ b/runtime/bin/string_stream.dart
@@ -28,6 +28,21 @@ interface _StringDecoder {
}
+class _StringDecoders {
+ static _StringDecoder decoder(Encoding encoding) {
+ if (encoding == Encoding.UTF_8) {
+ return new _UTF8Decoder();
+ } else if (encoding == Encoding.ISO_8859_1) {
+ return new _Latin1Decoder();
+ } else if (encoding == Encoding.ASCII) {
+ return new _AsciiDecoder();
+ } else {
+ throw new StreamException("Unsupported encoding ${encoding.name}");
+ }
+ }
+}
+
+
class DecoderException implements Exception {
const DecoderException([String this.message]);
String toString() => "DecoderException: $message";
@@ -142,6 +157,47 @@ class _StringDecoderBase implements _StringDecoder {
}
+// Utility class for decoding UTF-8 from data delivered as a stream of
+// bytes.
+class _UTF8Decoder extends _StringDecoderBase {
+ // Process the next UTF-8 encoded character.
+ bool _processNext() {
+ // Peek the next byte to calculate the number of bytes required for
+ // the next character.
+ int value = _bufferList.peek() & 0xFF;
+ if ((value & 0x80) == 0x80) {
+ int additionalBytes;
+ if ((value & 0xe0) == 0xc0) { // 110xxxxx
+ value = value & 0x1F;
+ additionalBytes = 1;
+ } else if ((value & 0xf0) == 0xe0) { // 1110xxxx
+ value = value & 0x0F;
+ additionalBytes = 2;
+ } else { // 11110xxx
+ value = value & 0x07;
+ additionalBytes = 3;
+ }
+ // Check if there are enough bytes to decode the character. Otherwise
+ // return false.
+ if (_bufferList.length < additionalBytes + 1) {
+ return false;
+ }
+ // Remove the value peeked from the buffer list.
+ _bufferList.next();
+ for (int i = 0; i < additionalBytes; i++) {
+ int byte = _bufferList.next();
+ value = value << 6 | (byte & 0x3F);
+ }
+ } else {
+ // Remove the value peeked from the buffer list.
+ _bufferList.next();
+ }
+ addChar(value);
+ return true;
+ }
+}
+
+
// Utility class for decoding ascii data delivered as a stream of
// bytes.
class _AsciiDecoder extends _StringDecoderBase {
@@ -173,62 +229,121 @@ class _Latin1Decoder extends _StringDecoderBase {
}
-// Utility class for decoding UTF-8 from data delivered as a stream of
-// bytes.
-class _UTF8Decoder extends _StringDecoderBase {
- // Process the next UTF-8 encoded character.
- bool _processNext() {
- // Peek the next byte to calculate the number of bytes required for
- // the next character.
- int value = _bufferList.peek() & 0xFF;
- if ((value & 0x80) == 0x80) {
+// Interface for encoders encoding string data into binary data.
+interface _StringEncoder {
+ List<int> encodeString(String string);
+}
+
+
+// Utility class for encoding a string into UTF-8 byte stream.
+class _UTF8Encoder implements _StringEncoder {
+ List<int> encodeString(String string) {
+ int size = _encodingSize(string);
+ ByteArray result = new ByteArray(size);
+ _encodeString(string, result);
+ return result;
+ }
+
+ static int _encodingSize(String string) => _encodeString(string, null);
+
+ static int _encodeString(String string, List<int> buffer) {
+ int pos = 0;
+ int length = string.length;
+ for (int i = 0; i < length; i++) {
int additionalBytes;
- if ((value & 0xe0) == 0xc0) { // 110xxxxx
- value = value & 0x1F;
+ int charCode = string.charCodeAt(i);
+ if (charCode <= 0x007F) {
+ additionalBytes = 0;
+ if (buffer != null) buffer[pos] = charCode;
+ } else if (charCode <= 0x07FF) {
+ // 110xxxxx (xxxxx is top 5 bits).
+ if (buffer != null) buffer[pos] = ((charCode >> 6) & 0x1F) | 0xC0;
additionalBytes = 1;
- } else if ((value & 0xf0) == 0xe0) { // 1110xxxx
- value = value & 0x0F;
+ } else if (charCode <= 0xFFFF) {
+ // 1110xxxx (xxxx is top 4 bits)
+ if (buffer != null) buffer[pos] = ((charCode >> 12) & 0x0F)| 0xE0;
additionalBytes = 2;
- } else { // 11110xxx
- value = value & 0x07;
+ } else {
+ // 11110xxx (xxx is top 3 bits)
+ if (buffer != null) buffer[pos] = ((charCode >> 18) & 0x07) | 0xF0;
additionalBytes = 3;
}
- // Check if there are enough bytes to decode the character. Otherwise
- // return false.
- if (_bufferList.length < additionalBytes + 1) {
- return false;
+ pos++;
+ if (buffer != null) {
+ for (int i = additionalBytes; i > 0; i--) {
+ // 10xxxxxx (xxxxxx is next 6 bits from the top).
+ buffer[pos++] = ((charCode >> (6 * (i - 1))) & 0x3F) | 0x80;
+ }
+ } else {
+ pos += additionalBytes;
}
- // Remove the value peeked from the buffer list.
- _bufferList.next();
- for (int i = 0; i < additionalBytes; i++) {
- int byte = _bufferList.next();
- value = value << 6 | (byte & 0x3F);
+ }
+ return pos;
+ }
+}
+
+
+// Utility class for encoding a string into a Latin1 byte stream.
+class _Latin1Encoder implements _StringEncoder {
+ List<int> encodeString(String string) {
+ ByteArray result = new ByteArray(string.length);
+ for (int i = 0; i < string.length; i++) {
+ int charCode = string.charCodeAt(i);
+ if (charCode > 255) {
+ throw new EncoderException(
+ "No ISO_8859_1 encoding for code point $charCode");
}
- } else {
- // Remove the value peeked from the buffer list.
- _bufferList.next();
+ result[i] = charCode;
}
- addChar(value);
- return true;
+ return result;
}
}
-class _StringInputStream implements StringInputStream {
- _StringInputStream(InputStream this._input, [String encoding])
- : _encoding = encoding {
- if (_encoding === null) {
- _encoding = "UTF-8";
+// Utility class for encoding a string into an ASCII byte stream.
+class _AsciiEncoder implements _StringEncoder {
+ List<int> encodeString(String string) {
+ ByteArray result = new ByteArray(string.length);
+ for (int i = 0; i < string.length; i++) {
+ int charCode = string.charCodeAt(i);
+ if (charCode > 127) {
+ throw new EncoderException(
+ "No ASCII encoding for code point $charCode");
+ }
+ result[i] = charCode;
}
- if (_encoding == "UTF-8") {
- _decoder = new _UTF8Decoder();
- } else if (_encoding == "ISO-8859-1") {
- _decoder = new _Latin1Decoder();
- } else if (_encoding == "ASCII") {
- _decoder = new _AsciiDecoder();
+ return result;
+ }
+}
+
+
+class _StringEncoders {
+ static _StringEncoder encoder(Encoding encoding) {
+ if (encoding == Encoding.UTF_8) {
+ return new _UTF8Encoder();
+ } else if (encoding == Encoding.ISO_8859_1) {
+ return new _Latin1Encoder();
+ } else if (encoding == Encoding.ASCII) {
+ return new _AsciiEncoder();
} else {
- throw new StreamException("Unsupported encoding $_encoding");
+ throw new StreamException("Unsupported encoding ${encoding.name}");
}
+ }
+}
+
+
+class EncoderException implements Exception {
+ const EncoderException([String this.message]);
+ String toString() => "EncoderException: $message";
+ final String message;
+}
+
+
+class _StringInputStream implements StringInputStream {
+ _StringInputStream(InputStream this._input,
+ [Encoding encoding = Encoding.UTF_8])
+ : _encoding = encoding {
+ _decoder = _StringDecoders.decoder(encoding);
_input.onData = _onData;
_input.onClosed = _onClosed;
}
@@ -257,7 +372,7 @@ class _StringInputStream implements StringInputStream {
int available() => _decoder.available();
- String get encoding() => _encoding;
+ Encoding get encoding() => _encoding;
bool get closed() => _inputClosed && _decoder.isEmpty();
@@ -390,7 +505,7 @@ class _StringInputStream implements StringInputStream {
}
InputStream _input;
- String _encoding;
+ Encoding _encoding;
_StringDecoder _decoder;
bool _inputClosed = false; // Is the underlying input stream closed?
bool _closed = false; // Is this stream closed.
« no previous file with comments | « runtime/bin/stream_util.dart ('k') | samples/chat/chat_server_lib.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698