OLD | NEW |
| (Empty) |
1 part of dart.convert; | |
2 const AsciiCodec ASCII = const AsciiCodec(); | |
3 const int _ASCII_MASK = 0x7F; | |
4 class AsciiCodec extends Encoding {final bool _allowInvalid; | |
5 const AsciiCodec({ | |
6 bool allowInvalid : false} | |
7 ) : _allowInvalid = allowInvalid; | |
8 String get name => "us-ascii"; | |
9 String decode(List<int> bytes, { | |
10 bool allowInvalid} | |
11 ) { | |
12 if (allowInvalid == null) allowInvalid = _allowInvalid; | |
13 if (allowInvalid) { | |
14 return const AsciiDecoder(allowInvalid: true).convert(bytes); | |
15 } | |
16 else { | |
17 return const AsciiDecoder(allowInvalid: false).convert(bytes); | |
18 } | |
19 } | |
20 AsciiEncoder get encoder => const AsciiEncoder(); | |
21 AsciiDecoder get decoder => _allowInvalid ? const AsciiDecoder(allowInvalid: tr
ue) : const AsciiDecoder(allowInvalid: false); | |
22 } | |
23 class _UnicodeSubsetEncoder extends Converter<String, List<int>> {final int _su
bsetMask; | |
24 const _UnicodeSubsetEncoder(this._subsetMask); | |
25 List<int> convert(String string, [int start = 0, int end]) { | |
26 int stringLength = string.length; | |
27 RangeError.checkValidRange(start, end, stringLength); | |
28 if (end == null) end = stringLength; | |
29 int length = end - start; | |
30 List result = new Uint8List(length); | |
31 for (int i = 0; i < length; i++) { | |
32 var codeUnit = string.codeUnitAt(start + i); | |
33 if ((codeUnit & ~_subsetMask) != 0) { | |
34 throw new ArgumentError("String contains invalid characters."); | |
35 } | |
36 result[i] = codeUnit; | |
37 } | |
38 return DEVC$RT.cast(result, DEVC$RT.type((List<dynamic> _) { | |
39 } | |
40 ), DEVC$RT.type((List<int> _) { | |
41 } | |
42 ), "CompositeCast", """line 96, column 12 of dart:convert/ascii.dart: """, resul
t is List<int>, false); | |
43 } | |
44 StringConversionSink startChunkedConversion(Sink<List<int>> sink) { | |
45 if (sink is! ByteConversionSink) { | |
46 sink = new ByteConversionSink.from(sink); | |
47 } | |
48 return new _UnicodeSubsetEncoderSink(_subsetMask, DEVC$RT.cast(sink, DEVC$RT.ty
pe((Sink<List<int>> _) { | |
49 } | |
50 ), ByteConversionSink, "ImplicitCast", """line 109, column 55 of dart:convert/as
cii.dart: """, sink is ByteConversionSink, true)); | |
51 } | |
52 Stream<List<int>> bind(Stream<String> stream) => super.bind(stream); | |
53 } | |
54 class AsciiEncoder extends _UnicodeSubsetEncoder {const AsciiEncoder() : super(
_ASCII_MASK); | |
55 } | |
56 class _UnicodeSubsetEncoderSink extends StringConversionSinkBase {final ByteCon
versionSink _sink; | |
57 final int _subsetMask; | |
58 _UnicodeSubsetEncoderSink(this._subsetMask, this._sink); | |
59 void close() { | |
60 _sink.close(); | |
61 } | |
62 void addSlice(String source, int start, int end, bool isLast) { | |
63 RangeError.checkValidRange(start, end, source.length); | |
64 for (int i = start; i < end; i++) { | |
65 int codeUnit = source.codeUnitAt(i); | |
66 if ((codeUnit & ~_subsetMask) != 0) { | |
67 throw new ArgumentError("Source contains invalid character with code point: $cod
eUnit."); | |
68 } | |
69 } | |
70 _sink.add(source.codeUnits.sublist(start, end)); | |
71 if (isLast) { | |
72 close(); | |
73 } | |
74 } | |
75 } | |
76 abstract class _UnicodeSubsetDecoder extends Converter<List<int>, String> {fina
l bool _allowInvalid; | |
77 final int _subsetMask; | |
78 const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask); | |
79 String convert(List<int> bytes, [int start = 0, int end]) { | |
80 int byteCount = bytes.length; | |
81 RangeError.checkValidRange(start, end, byteCount); | |
82 if (end == null) end = byteCount; | |
83 int length = end - start; | |
84 for (int i = start; i < end; i++) { | |
85 int byte = bytes[i]; | |
86 if ((byte & ~_subsetMask) != 0) { | |
87 if (!_allowInvalid) { | |
88 throw new FormatException("Invalid value in input: $byte"); | |
89 } | |
90 return _convertInvalid(bytes, start, end); | |
91 } | |
92 } | |
93 return new String.fromCharCodes(bytes, start, end); | |
94 } | |
95 String _convertInvalid(List<int> bytes, int start, int end) { | |
96 StringBuffer buffer = new StringBuffer(); | |
97 for (int i = start; i < end; i++) { | |
98 int value = bytes[i]; | |
99 if ((value & ~_subsetMask) != 0) value = 0xFFFD; | |
100 buffer.writeCharCode(value); | |
101 } | |
102 return buffer.toString(); | |
103 } | |
104 ByteConversionSink startChunkedConversion(Sink<String> sink); | |
105 Stream<String> bind(Stream<List<int>> stream) => super.bind(stream); | |
106 } | |
107 class AsciiDecoder extends _UnicodeSubsetDecoder {const AsciiDecoder({ | |
108 bool allowInvalid : false} | |
109 ) : super(allowInvalid, _ASCII_MASK); | |
110 ByteConversionSink startChunkedConversion(Sink<String> sink) { | |
111 StringConversionSink stringSink; | |
112 if (sink is StringConversionSink) { | |
113 stringSink = sink; | |
114 } | |
115 else { | |
116 stringSink = new StringConversionSink.from(sink); | |
117 } | |
118 if (_allowInvalid) { | |
119 return new _ErrorHandlingAsciiDecoderSink(stringSink.asUtf8Sink(false)); | |
120 } | |
121 else { | |
122 return new _SimpleAsciiDecoderSink(stringSink); | |
123 } | |
124 } | |
125 } | |
126 class _ErrorHandlingAsciiDecoderSink extends ByteConversionSinkBase {ByteConver
sionSink _utf8Sink; | |
127 _ErrorHandlingAsciiDecoderSink(this._utf8Sink); | |
128 void close() { | |
129 _utf8Sink.close(); | |
130 } | |
131 void add(List<int> source) { | |
132 addSlice(source, 0, source.length, false); | |
133 } | |
134 void addSlice(List<int> source, int start, int end, bool isLast) { | |
135 RangeError.checkValidRange(start, end, source.length); | |
136 for (int i = start; i < end; i++) { | |
137 if ((source[i] & ~_ASCII_MASK) != 0) { | |
138 if (i > start) _utf8Sink.addSlice(source, start, i, false); | |
139 _utf8Sink.add(const <int> [0xEF, 0xBF, 0xBD]); | |
140 start = i + 1; | |
141 } | |
142 } | |
143 if (start < end) { | |
144 _utf8Sink.addSlice(source, start, end, isLast); | |
145 } | |
146 else if (isLast) { | |
147 close(); | |
148 } | |
149 } | |
150 } | |
151 class _SimpleAsciiDecoderSink extends ByteConversionSinkBase {Sink _sink; | |
152 _SimpleAsciiDecoderSink(this._sink); | |
153 void close() { | |
154 _sink.close(); | |
155 } | |
156 void add(List<int> source) { | |
157 for (int i = 0; i < source.length; i++) { | |
158 if ((source[i] & ~_ASCII_MASK) != 0) { | |
159 throw new FormatException("Source contains non-ASCII bytes."); | |
160 } | |
161 } | |
162 _sink.add(new String.fromCharCodes(source)); | |
163 } | |
164 void addSlice(List<int> source, int start, int end, bool isLast) { | |
165 final int length = source.length; | |
166 RangeError.checkValidRange(start, end, length); | |
167 if (start < end) { | |
168 if (start != 0 || end != length) { | |
169 source = source.sublist(start, end); | |
170 } | |
171 add(source); | |
172 } | |
173 if (isLast) close(); | |
174 } | |
175 } | |
OLD | NEW |