| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of utf; | 5 part of utf; |
| 6 | 6 |
| 7 // TODO(floitsch): make this transformer reusable. |
| 7 abstract class _StringDecoder | 8 abstract class _StringDecoder |
| 8 extends StreamEventTransformer<List<int>, String> { | 9 implements StreamTransformer<List<int>, String>, EventSink<List<int>> { |
| 9 List<int> _carry; | 10 List<int> _carry; |
| 10 List<int> _buffer; | 11 List<int> _buffer; |
| 11 int _replacementChar; | 12 int _replacementChar; |
| 12 | 13 |
| 14 EventSink<String> _outSink; |
| 15 |
| 13 _StringDecoder(int this._replacementChar); | 16 _StringDecoder(int this._replacementChar); |
| 14 | 17 |
| 15 void handleData(List<int> bytes, EventSink<String> sink) { | 18 Stream<String> bind(Stream<List<int>> stream) { |
| 19 return new Stream.eventTransformed( |
| 20 stream, |
| 21 (EventSink<String> sink) { |
| 22 if (_outSink != null) { |
| 23 throw new StateError("String decoder already used"); |
| 24 } |
| 25 _outSink = sink; |
| 26 return this; |
| 27 }); |
| 28 } |
| 29 |
| 30 void add(List<int> bytes) { |
| 16 try { | 31 try { |
| 17 _buffer = <int>[]; | 32 _buffer = <int>[]; |
| 18 List<int> carry = _carry; | 33 List<int> carry = _carry; |
| 19 _carry = null; | 34 _carry = null; |
| 20 int pos = 0; | 35 int pos = 0; |
| 21 int available = bytes.length; | 36 int available = bytes.length; |
| 22 // If we have carry-over data, start from negative index, indicating carry | 37 // If we have carry-over data, start from negative index, indicating carry |
| 23 // index. | 38 // index. |
| 24 int goodChars = 0; | 39 int goodChars = 0; |
| 25 if (carry != null) pos = -carry.length; | 40 if (carry != null) pos = -carry.length; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 48 break; | 63 break; |
| 49 } else { | 64 } else { |
| 50 // Invalid byte at position pos - 1 | 65 // Invalid byte at position pos - 1 |
| 51 _buffer.length = goodChars; | 66 _buffer.length = goodChars; |
| 52 _addChar(-1); | 67 _addChar(-1); |
| 53 goodChars = _buffer.length; | 68 goodChars = _buffer.length; |
| 54 } | 69 } |
| 55 } | 70 } |
| 56 if (_buffer.length > 0) { | 71 if (_buffer.length > 0) { |
| 57 // Limit to 'goodChars', if lower than actual charCodes in the buffer. | 72 // Limit to 'goodChars', if lower than actual charCodes in the buffer. |
| 58 sink.add(new String.fromCharCodes(_buffer)); | 73 _outSink.add(new String.fromCharCodes(_buffer)); |
| 59 } | 74 } |
| 60 _buffer = null; | 75 _buffer = null; |
| 61 } catch (e) { | 76 } catch (e, stackTrace) { |
| 62 sink.addError(e); | 77 _outSink.addError(e, stackTrace); |
| 63 } | 78 } |
| 64 } | 79 } |
| 65 | 80 |
| 66 void handleDone(EventSink<String> sink) { | 81 void addError(Object error, [StackTrace stackTrace]) { |
| 82 _outSink.addError(error, stackTrace); |
| 83 } |
| 84 |
| 85 void close() { |
| 67 if (_carry != null) { | 86 if (_carry != null) { |
| 68 if (_replacementChar != null) { | 87 if (_replacementChar != null) { |
| 69 sink.add(new String.fromCharCodes( | 88 _outSink.add(new String.fromCharCodes( |
| 70 new List.filled(_carry.length, _replacementChar))); | 89 new List.filled(_carry.length, _replacementChar))); |
| 71 } else { | 90 } else { |
| 72 throw new ArgumentError('Invalid codepoint'); | 91 throw new ArgumentError('Invalid codepoint'); |
| 73 } | 92 } |
| 74 } | 93 } |
| 75 sink.close(); | 94 _outSink.close(); |
| 76 } | 95 } |
| 77 | 96 |
| 78 int _processBytes(int getNext()); | 97 int _processBytes(int getNext()); |
| 79 | 98 |
| 80 void _addChar(int char) { | 99 void _addChar(int char) { |
| 81 void error() { | 100 void error() { |
| 82 if (_replacementChar != null) { | 101 if (_replacementChar != null) { |
| 83 char = _replacementChar; | 102 char = _replacementChar; |
| 84 } else { | 103 } else { |
| 85 throw new ArgumentError('Invalid codepoint'); | 104 throw new ArgumentError('Invalid codepoint'); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 _addChar(value); | 162 _addChar(value); |
| 144 return 1 + additionalBytes; | 163 return 1 + additionalBytes; |
| 145 } | 164 } |
| 146 _addChar(value); | 165 _addChar(value); |
| 147 return 1; | 166 return 1; |
| 148 } | 167 } |
| 149 } | 168 } |
| 150 | 169 |
| 151 | 170 |
| 152 abstract class _StringEncoder | 171 abstract class _StringEncoder |
| 153 extends StreamEventTransformer<String, List<int>> { | 172 implements StreamTransformer<String, List<int>>, EventSink<String> { |
| 154 | 173 |
| 155 void handleData(String data, EventSink<List<int>> sink) { | 174 EventSink<List<int>> _outSink; |
| 156 sink.add(_processString(data)); | 175 |
| 176 Stream<List<int>> bind(Stream<String> stream) { |
| 177 return new Stream.eventTransformed( |
| 178 stream, |
| 179 (EventSink<List<int>> sink) { |
| 180 if (_outSink != null) { |
| 181 throw new StateError("String encoder already used"); |
| 182 } |
| 183 _outSink = sink; |
| 184 return this; |
| 185 }); |
| 157 } | 186 } |
| 158 | 187 |
| 188 void add(String data) { |
| 189 _outSink.add(_processString(data)); |
| 190 } |
| 191 |
| 192 void addError(Object error, [StackTrace stackTrace]) { |
| 193 _outSink.addError(error, stackTrace); |
| 194 } |
| 195 |
| 196 void close() { _outSink.close(); } |
| 197 |
| 159 List<int> _processString(String string); | 198 List<int> _processString(String string); |
| 160 } | 199 } |
| 161 | 200 |
| 162 /** | 201 /** |
| 163 * StringTransformer that UTF-8 encodes a stream of strings. | 202 * StringTransformer that UTF-8 encodes a stream of strings. |
| 164 */ | 203 */ |
| 165 class Utf8EncoderTransformer extends _StringEncoder { | 204 class Utf8EncoderTransformer extends _StringEncoder { |
| 166 List<int> _processString(String string) { | 205 List<int> _processString(String string) { |
| 167 var bytes = []; | 206 var bytes = []; |
| 168 int pos = 0; | 207 int pos = 0; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 189 } | 228 } |
| 190 for (int i = additionalBytes; i > 0; i--) { | 229 for (int i = additionalBytes; i > 0; i--) { |
| 191 // 10xxxxxx (xxxxxx is next 6 bits from the top). | 230 // 10xxxxxx (xxxxxx is next 6 bits from the top). |
| 192 bytes.add(((charCode >> (6 * (i - 1))) & 0x3F) | 0x80); | 231 bytes.add(((charCode >> (6 * (i - 1))) & 0x3F) | 0x80); |
| 193 } | 232 } |
| 194 pos += additionalBytes + 1; | 233 pos += additionalBytes + 1; |
| 195 } | 234 } |
| 196 return bytes; | 235 return bytes; |
| 197 } | 236 } |
| 198 } | 237 } |
| OLD | NEW |