Chromium Code Reviews| 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 dart.convert; | 5 part of dart.convert; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * An instance of the default implementation of the [AsciiCodec]. | 8 * An instance of the default implementation of the [AsciiCodec]. |
| 9 * | 9 * |
| 10 * This instance provides a convenient access to the most common ASCII | 10 * This instance provides a convenient access to the most common ASCII |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 53 */ | 53 */ |
| 54 String decode(List<int> bytes, { bool allowInvalid }) { | 54 String decode(List<int> bytes, { bool allowInvalid }) { |
| 55 if (allowInvalid == null) allowInvalid = _allowInvalid; | 55 if (allowInvalid == null) allowInvalid = _allowInvalid; |
| 56 if (allowInvalid) { | 56 if (allowInvalid) { |
| 57 return const AsciiDecoder(allowInvalid: true).convert(bytes); | 57 return const AsciiDecoder(allowInvalid: true).convert(bytes); |
| 58 } else { | 58 } else { |
| 59 return const AsciiDecoder(allowInvalid: false).convert(bytes); | 59 return const AsciiDecoder(allowInvalid: false).convert(bytes); |
| 60 } | 60 } |
| 61 } | 61 } |
| 62 | 62 |
| 63 Converter<String, List<int>> get encoder => const AsciiEncoder(); | 63 AsciiEncoder get encoder => const AsciiEncoder(); |
| 64 | 64 |
| 65 Converter<List<int>, String> get decoder => | 65 AsciiDecoder get decoder => |
| 66 _allowInvalid ? const AsciiDecoder(allowInvalid: true) | 66 _allowInvalid ? const AsciiDecoder(allowInvalid: true) |
| 67 : const AsciiDecoder(allowInvalid: false); | 67 : const AsciiDecoder(allowInvalid: false); |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Superclass for [AsciiEncoder] and [Latin1Encoder]. | 70 // Superclass for [AsciiEncoder] and [Latin1Encoder]. |
| 71 // Generalizes common operations that only differ by a mask; | 71 // Generalizes common operations that only differ by a mask; |
| 72 class _UnicodeSubsetEncoder extends Converter<String, List<int>> { | 72 class _UnicodeSubsetEncoder extends Converter<String, List<int>> { |
| 73 final int _subsetMask; | 73 final int _subsetMask; |
| 74 | 74 |
| 75 const _UnicodeSubsetEncoder(this._subsetMask); | 75 const _UnicodeSubsetEncoder(this._subsetMask); |
| 76 | 76 |
| 77 List<int> convert(String string) { | 77 List<int> convert(String string, [int start = 0, int end]) { |
|
Søren Gjesse
2014/11/20 10:41:41
Where are the new arguments documented?
Lasse Reichstein Nielsen
2014/11/20 12:46:22
Ack, documenting.
| |
| 78 List result = new Uint8List(string.length); | 78 int stringLength = string.length; |
|
Søren Gjesse
2014/11/20 10:41:41
Maybe factor out argument checking.
Lasse Reichstein Nielsen
2014/11/20 12:46:22
Funny you should say that - I'm already doing that
| |
| 79 for (int i = 0; i < string.length; i++) { | 79 if (start < 0 || start > stringLength) { |
| 80 var codeUnit = string.codeUnitAt(i); | 80 throw new RangeError.range(start, 0, stringLength, "start"); |
| 81 } | |
| 82 if (end == null) { | |
| 83 end = stringLength; | |
| 84 } else { | |
| 85 if (end < start || end > stringLength) { | |
| 86 throw new RangeError.range(end, start, stringLength, "end"); | |
| 87 } | |
| 88 } | |
| 89 int length = end - start; | |
| 90 List result = new Uint8List(length); | |
| 91 for (int i = 0; i < length; i++) { | |
| 92 var codeUnit = string.codeUnitAt(start + i); | |
| 81 if ((codeUnit & ~_subsetMask) != 0) { | 93 if ((codeUnit & ~_subsetMask) != 0) { |
| 82 throw new ArgumentError("String contains invalid characters."); | 94 throw new ArgumentError("String contains invalid characters."); |
| 83 } | 95 } |
| 84 result[i] = codeUnit; | 96 result[i] = codeUnit; |
| 85 } | 97 } |
| 86 return result; | 98 return result; |
| 87 } | 99 } |
| 88 | 100 |
| 89 /** | 101 /** |
| 90 * Starts a chunked conversion. | 102 * Starts a chunked conversion. |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 164 * [_ASCII_MASK] for ASCII (7-bit). | 176 * [_ASCII_MASK] for ASCII (7-bit). |
| 165 * | 177 * |
| 166 * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the | 178 * If [_allowInvalid] is `true`, [convert] replaces invalid bytes with the |
| 167 * Unicode Replacement character `U+FFFD` (�). | 179 * Unicode Replacement character `U+FFFD` (�). |
| 168 * Otherwise it throws a [FormatException]. | 180 * Otherwise it throws a [FormatException]. |
| 169 */ | 181 */ |
| 170 const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask); | 182 const _UnicodeSubsetDecoder(this._allowInvalid, this._subsetMask); |
| 171 | 183 |
| 172 /** | 184 /** |
| 173 * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the | 185 * Converts the [bytes] (a list of unsigned 7- or 8-bit integers) to the |
| 174 * corresponding string. | 186 * corresponding string. |
|
Søren Gjesse
2014/11/20 10:41:41
Add documentation.
| |
| 175 */ | 187 */ |
| 176 String convert(List<int> bytes) { | 188 String convert(List<int> bytes, [int start = 0, int end]) { |
| 177 for (int i = 0; i < bytes.length; i++) { | 189 int byteCount = bytes.length; |
| 190 if (start < 0 || start > byteCount) { | |
| 191 throw new RangeError.range(start, 0, byteCount, "start"); | |
| 192 } | |
| 193 if (end == null) { | |
| 194 end = byteCount; | |
| 195 } else { | |
| 196 if (end < start || end > byteCount) { | |
| 197 throw new RangeError.range(end, start, byteCount, "end"); | |
| 198 } | |
| 199 } | |
| 200 int length = end - start; | |
| 201 | |
| 202 for (int i = start; i < end; i++) { | |
| 178 int byte = bytes[i]; | 203 int byte = bytes[i]; |
| 179 if ((byte & ~_subsetMask) != 0) { | 204 if ((byte & ~_subsetMask) != 0) { |
| 180 if (!_allowInvalid) { | 205 if (!_allowInvalid) { |
| 181 throw new FormatException("Invalid value in input: $byte"); | 206 throw new FormatException("Invalid value in input: $byte"); |
| 182 } | 207 } |
| 183 return _convertInvalid(bytes); | 208 return _convertInvalid(bytes, start, end); |
| 184 } | 209 } |
| 185 } | 210 } |
| 186 return new String.fromCharCodes(bytes); | 211 return new String.fromCharCodes(bytes, start, end); |
| 187 } | 212 } |
| 188 | 213 |
| 189 String _convertInvalid(List<int> bytes) { | 214 String _convertInvalid(List<int> bytes, int start, int end) { |
| 190 StringBuffer buffer = new StringBuffer(); | 215 StringBuffer buffer = new StringBuffer(); |
| 191 for (int i = 0; i < bytes.length; i++) { | 216 for (int i = start; i < end; i++) { |
| 192 int value = bytes[i]; | 217 int value = bytes[i]; |
| 193 if ((value & ~_subsetMask) != 0) value = 0xFFFD; | 218 if ((value & ~_subsetMask) != 0) value = 0xFFFD; |
| 194 buffer.writeCharCode(value); | 219 buffer.writeCharCode(value); |
| 195 } | 220 } |
| 196 return buffer.toString(); | 221 return buffer.toString(); |
| 197 } | 222 } |
| 198 | 223 |
| 199 /** | 224 /** |
| 200 * Starts a chunked conversion. | 225 * Starts a chunked conversion. |
| 201 * | 226 * |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 299 } | 324 } |
| 300 if (start < end) { | 325 if (start < end) { |
| 301 if (start != 0 || end != length) { | 326 if (start != 0 || end != length) { |
| 302 source = source.sublist(start, end); | 327 source = source.sublist(start, end); |
| 303 } | 328 } |
| 304 add(source); | 329 add(source); |
| 305 } | 330 } |
| 306 if (isLast) close(); | 331 if (isLast) close(); |
| 307 } | 332 } |
| 308 } | 333 } |
| OLD | NEW |