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

Side by Side Diff: sdk/lib/convert/utf.dart

Issue 736583008: Make Utf8Decoder and Utf8Encoder's convert methods take start and end too. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Make UTF8.encoder/decoder return types be Utf8Encoder,Utf8Decoder, not just Converter<..> Created 6 years, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/lib/convert/utf8_encode_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 /** The Unicode Replacement character `U+FFFD` (�). */ 7 /** The Unicode Replacement character `U+FFFD` (�). */
8 const int UNICODE_REPLACEMENT_CHARACTER_RUNE = 0xFFFD; 8 const int UNICODE_REPLACEMENT_CHARACTER_RUNE = 0xFFFD;
9 9
10 /** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */ 10 /** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 * `U+FFFD` (�). Otherwise it throws a [FormatException]. 59 * `U+FFFD` (�). Otherwise it throws a [FormatException].
60 * 60 *
61 * If [allowMalformed] is not given, it defaults to the `allowMalformed` that 61 * If [allowMalformed] is not given, it defaults to the `allowMalformed` that
62 * was used to instantiate `this`. 62 * was used to instantiate `this`.
63 */ 63 */
64 String decode(List<int> codeUnits, { bool allowMalformed }) { 64 String decode(List<int> codeUnits, { bool allowMalformed }) {
65 if (allowMalformed == null) allowMalformed = _allowMalformed; 65 if (allowMalformed == null) allowMalformed = _allowMalformed;
66 return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits); 66 return new Utf8Decoder(allowMalformed: allowMalformed).convert(codeUnits);
67 } 67 }
68 68
69 Converter<String, List<int>> get encoder => new Utf8Encoder(); 69 Utf8Encoder get encoder => new Utf8Encoder();
70 Converter<List<int>, String> get decoder { 70 Utf8Decoder get decoder {
71 return new Utf8Decoder(allowMalformed: _allowMalformed); 71 return new Utf8Decoder(allowMalformed: _allowMalformed);
72 } 72 }
73 } 73 }
74 74
75 /** 75 /**
76 * This class converts strings to their UTF-8 code units (a list of 76 * This class converts strings to their UTF-8 code units (a list of
77 * unsigned 8-bit integers). 77 * unsigned 8-bit integers).
78 */ 78 */
79 class Utf8Encoder extends Converter<String, List<int>> { 79 class Utf8Encoder extends Converter<String, List<int>> {
80 80
81 const Utf8Encoder(); 81 const Utf8Encoder();
82 82
83 /** 83 /**
84 * Converts [string] to its UTF-8 code units (a list of 84 * Converts [string] to its UTF-8 code units (a list of
85 * unsigned 8-bit integers). 85 * unsigned 8-bit integers).
86 *
87 * If [start] and [end] are provided, only the substring
88 * `string.substring(start, end)` is converted.
86 */ 89 */
87 List<int> convert(String string) { 90 List<int> convert(String string, [int start = 0, int end]) {
Søren Gjesse 2014/11/19 13:53:28 Should these be named arguments? Otherwise we are
91 int stringLength = string.length;
92 if (start < 0 || start > stringLength) {
93 throw new RangeError.range(start, 0, stringLength, "start");
94 }
95 if (end == null) {
96 end = stringLength;
97 } else if (end < start || end > stringLength) {
98 throw new RangeError.range(end, start, stringLength, "end");
99 }
100 int length = end - start;
101 if (length == 0) return new Uint8List(0);
88 // Create a new encoder with a length that is guaranteed to be big enough. 102 // Create a new encoder with a length that is guaranteed to be big enough.
89 // A single code unit uses at most 3 bytes. Two code units at most 4. 103 // A single code unit uses at most 3 bytes, a surrogate pair at most 4.
90 _Utf8Encoder encoder = new _Utf8Encoder.withBufferSize(string.length * 3); 104 _Utf8Encoder encoder = new _Utf8Encoder.withBufferSize(length * 3);
91 int endPosition = encoder._fillBuffer(string, 0, string.length); 105 int endPosition = encoder._fillBuffer(string, start, end);
92 assert(endPosition >= string.length - 1); 106 assert(endPosition >= end - 1);
93 if (endPosition != string.length) { 107 if (endPosition != end) {
94 int lastCodeUnit = string.codeUnitAt(string.length - 1); 108 // Encoding skipped the last code unit.
109 // That can only happen if the last code unit is a leadsurrogate.
110 // Force encoding of the lead surrogate by itself.
111 int lastCodeUnit = string.codeUnitAt(end - 1);
95 assert(_isLeadSurrogate(lastCodeUnit)); 112 assert(_isLeadSurrogate(lastCodeUnit));
96 // We use a non-surrogate as `nextUnit` so that _writeSurrogate just 113 // We use a non-surrogate as `nextUnit` so that _writeSurrogate just
97 // writes the lead-surrogate. 114 // writes the lead-surrogate.
98 bool wasCombined = encoder._writeSurrogate(lastCodeUnit, 0); 115 bool wasCombined = encoder._writeSurrogate(lastCodeUnit, 0);
99 assert(!wasCombined); 116 assert(!wasCombined);
100 } 117 }
101 return encoder._buffer.sublist(0, encoder._bufferIndex); 118 return encoder._buffer.sublist(0, encoder._bufferIndex);
102 } 119 }
103 120
104 /** 121 /**
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise 323 * sequences with the Unicode Replacement character `U+FFFD` (�). Otherwise
307 * it throws a [FormatException]. 324 * it throws a [FormatException].
308 */ 325 */
309 const Utf8Decoder({ bool allowMalformed: false }) 326 const Utf8Decoder({ bool allowMalformed: false })
310 : this._allowMalformed = allowMalformed; 327 : this._allowMalformed = allowMalformed;
311 328
312 /** 329 /**
313 * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the 330 * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the
314 * corresponding string. 331 * corresponding string.
315 * 332 *
333 * Uses the code units from [start] to, but no including, [end].
334 * If [end] is omitted, it defaults to `codeUnits.length`.
Søren Gjesse 2014/11/19 13:53:28 Maybe add some more information on invalid encodin
335 *
316 * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this 336 * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this
317 * character is discarded. 337 * character is discarded.
318 */ 338 */
319 String convert(List<int> codeUnits) { 339 String convert(List<int> codeUnits, [int start = 0, int end]) {
340 int length = codeUnits.length;
341 if (start < 0 || start > length) {
342 throw new RangeError.range(start, 0, length, "start");
343 }
344 if (end == null) {
345 end = length;
346 } else if (end < start || end > length) {
347 throw new RangeError.range(end, start, length, "end");
348 }
320 StringBuffer buffer = new StringBuffer(); 349 StringBuffer buffer = new StringBuffer();
321 _Utf8Decoder decoder = new _Utf8Decoder(buffer, _allowMalformed); 350 _Utf8Decoder decoder = new _Utf8Decoder(buffer, _allowMalformed);
322 decoder.convert(codeUnits, 0, codeUnits.length); 351 decoder.convert(codeUnits, start, end);
323 decoder.close(); 352 decoder.close();
324 return buffer.toString(); 353 return buffer.toString();
325 } 354 }
326 355
327 /** 356 /**
328 * Starts a chunked conversion. 357 * Starts a chunked conversion.
329 * 358 *
330 * The converter works more efficiently if the given [sink] is a 359 * The converter works more efficiently if the given [sink] is a
331 * [StringConversionSink]. 360 * [StringConversionSink].
332 */ 361 */
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 } 567 }
539 break loop; 568 break loop;
540 } 569 }
541 if (expectedUnits > 0) { 570 if (expectedUnits > 0) {
542 _value = value; 571 _value = value;
543 _expectedUnits = expectedUnits; 572 _expectedUnits = expectedUnits;
544 _extraUnits = extraUnits; 573 _extraUnits = extraUnits;
545 } 574 }
546 } 575 }
547 } 576 }
OLDNEW
« no previous file with comments | « no previous file | tests/lib/convert/utf8_encode_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698