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

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

Issue 1302283002: Make LineSplitter.split return an Iterable<String>, not Iterable<>. Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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 unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | 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 // Character constants. 7 // Character constants.
8 const int _LF = 10; 8 const int _LF = 10;
9 const int _CR = 13; 9 const int _CR = 13;
10 10
11 /** 11 /**
12 * A [Converter] that splits a [String] into individual lines. 12 * A [Converter] that splits a [String] into individual lines.
13 * 13 *
14 * A line is terminated by either a CR (U+000D), a LF (U+000A), a 14 * A line is terminated by either a CR (U+000D), a LF (U+000A), a
15 * CR+LF sequence (DOS line ending), 15 * CR+LF sequence (DOS line ending),
16 * and a final non-empty line can be ended by the end of the string. 16 * and a final non-empty line can be ended by the end of the string.
17 * 17 *
18 * The returned lines do not contain the line terminators. 18 * The returned lines do not contain the line terminators.
19 */ 19 */
20 class LineSplitter extends Converter<String, List<String>> { 20 class LineSplitter extends Converter<String, List<String>> {
21 21
22 const LineSplitter(); 22 const LineSplitter();
23 23
24 /// Split [lines] into individual lines. 24 /// Split [lines] into individual lines.
25 /// 25 ///
26 /// If [start] and [end] are provided, only split the contents of 26 /// If [start] and [end] are provided, only split the contents of
27 /// `lines.substring(start, end)`. The [start] and [end] values must 27 /// `lines.substring(start, end)`. The [start] and [end] values must
28 /// specify a valid sub-range of [lines] 28 /// specify a valid sub-range of [lines]
29 /// (`0 <= start <= end <= lines.length`). 29 /// (`0 <= start <= end <= lines.length`).
30 static Iterable<String> split(String lines, [int start = 0, int end]) sync* { 30 static Iterable<String> split(String lines, [int start = 0, int end]) {
31 end = RangeError.checkValidRange(start, end, lines.length); 31 end = RangeError.checkValidRange(start, end, lines.length);
32 int sliceStart = start; 32 return new _LineIterable(lines, start, end);
33 int char = 0;
34 for (int i = start; i < end; i++) {
35 int previousChar = char;
36 char = lines.codeUnitAt(i);
37 if (char != _CR) {
38 if (char != _LF) continue;
39 if (previousChar == _CR) {
40 sliceStart = i + 1;
41 continue;
42 }
43 }
44 yield lines.substring(sliceStart, i);
45 sliceStart = i + 1;
46 }
47 if (sliceStart < end) {
48 yield lines.substring(sliceStart, end);
49 }
50 } 33 }
51 34
52 List<String> convert(String data) => split(data).toList(); 35 List<String> convert(String data) => split(data).toList();
53 36
54 StringConversionSink startChunkedConversion(Sink<String> sink) { 37 StringConversionSink startChunkedConversion(Sink<String> sink) {
55 if (sink is! StringConversionSink) { 38 if (sink is! StringConversionSink) {
56 sink = new StringConversionSink.from(sink); 39 sink = new StringConversionSink.from(sink);
57 } 40 }
58 return new _LineSplitterSink(sink); 41 return new _LineSplitterSink(sink);
59 } 42 }
60 } 43 }
61 44
45 class _LineIterable extends Iterable<String> {
46 final String _string;
47 final int _start;
48 final int _end;
49 _LineIterable(this._string, this._start, this._end);
50 Iterator<String> get iterator => new _LineIterator(_string, _start, _end);
51
52 bool get isEmpty => _start < _end;
53 bool get isNotEmpty => _start >= end;
54 }
55
56 class _LineIterator implements Iterator<String> {
57 final String _string;
58 final int _end;
59 int _index;
60 String _current;
61 _LineIterator(this._string, this._index, this._end);
62
63 String get current => _current;
64
65 bool moveNext() {
66 if (_index < _end) {
67 int terminatorLength = 1;
68 int i = _index;
69 findEnd: {
70 while (i < _end) {
71 int char = _string.codeUnitAt(i++);
72 if (char != _LF) {
73 if (char != _CR) continue;
74 // Break on CR or CR+LF
floitsch 2016/03/08 12:35:34 Finish with "."
75 if (i < _end && _string.codeUnitAt(i) == _LF) {
76 terminatorLength = 2;
77 i++;
78 }
79 }
80 break findEnd;
81 }
82 terminatorLength = 0; // Terminated by the end, not a char.
83 }
84 _current = _string.substring(_index, i - terminatorLength);
85 _index = i;
86 return true;
87 }
88 _current = null;
89 return false;
90 }
91 }
92
62 // TODO(floitsch): deal with utf8. 93 // TODO(floitsch): deal with utf8.
63 class _LineSplitterSink extends StringConversionSinkBase { 94 class _LineSplitterSink extends StringConversionSinkBase {
64 final StringConversionSink _sink; 95 final StringConversionSink _sink;
65 96
66 /// The carry-over from the previous chunk. 97 /// The carry-over from the previous chunk.
67 /// 98 ///
68 /// If the previous slice ended in a line without a line terminator, 99 /// If the previous slice ended in a line without a line terminator,
69 /// then the next slice may continue the line. 100 /// then the next slice may continue the line.
70 String _carry; 101 String _carry;
71 102
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 _sink.add(lines.substring(sliceStart, i)); 158 _sink.add(lines.substring(sliceStart, i));
128 sliceStart = i + 1; 159 sliceStart = i + 1;
129 } 160 }
130 if (sliceStart < end) { 161 if (sliceStart < end) {
131 _carry = lines.substring(sliceStart, end); 162 _carry = lines.substring(sliceStart, end);
132 } else { 163 } else {
133 _skipLeadingLF = (char == _CR); 164 _skipLeadingLF = (char == _CR);
134 } 165 }
135 } 166 }
136 } 167 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698