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

Side by Side Diff: tool/input_sdk/lib/convert/line_splitter.dart

Issue 1965563003: Update dart:convert and dart:core Uri. (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 7 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
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.
8 const int _LF = 10;
9 const int _CR = 13;
10
7 /** 11 /**
8 * This class splits [String] values into individual lines. 12 * A [Converter] that splits a [String] into individual lines.
13 *
14 * A line is terminated by either a CR (U+000D), a LF (U+000A), a
15 * CR+LF sequence (DOS line ending),
16 * and a final non-empty line can be ended by the end of the string.
17 *
18 * The returned lines do not contain the line terminators.
9 */ 19 */
10 class LineSplitter extends Converter<String, List<String>> { 20 class LineSplitter extends
21 ChunkedConverter<String, List<String>, String, String> {
11 22
12 const LineSplitter(); 23 const LineSplitter();
13 24
25 /// Split [lines] into individual lines.
26 ///
27 /// If [start] and [end] are provided, only split the contents of
28 /// `lines.substring(start, end)`. The [start] and [end] values must
29 /// specify a valid sub-range of [lines]
30 /// (`0 <= start <= end <= lines.length`).
31 static Iterable<String> split(String lines, [int start = 0, int end]) sync* {
32 end = RangeError.checkValidRange(start, end, lines.length);
33 int sliceStart = start;
34 int char = 0;
35 for (int i = start; i < end; i++) {
36 int previousChar = char;
37 char = lines.codeUnitAt(i);
38 if (char != _CR) {
39 if (char != _LF) continue;
40 if (previousChar == _CR) {
41 sliceStart = i + 1;
42 continue;
43 }
44 }
45 yield lines.substring(sliceStart, i);
46 sliceStart = i + 1;
47 }
48 if (sliceStart < end) {
49 yield lines.substring(sliceStart, end);
50 }
51 }
52
14 List<String> convert(String data) { 53 List<String> convert(String data) {
15 var lines = new List<String>(); 54 List<String> lines = <String>[];
16 55 int end = data.length;
17 _LineSplitterSink._addSlice(data, 0, data.length, true, lines.add); 56 int sliceStart = 0;
18 57 int char = 0;
58 for (int i = 0; i < end; i++) {
59 int previousChar = char;
60 char = data.codeUnitAt(i);
61 if (char != _CR) {
62 if (char != _LF) continue;
63 if (previousChar == _CR) {
64 sliceStart = i + 1;
65 continue;
66 }
67 }
68 lines.add(data.substring(sliceStart, i));
69 sliceStart = i + 1;
70 }
71 if (sliceStart < end) {
72 lines.add(data.substring(sliceStart, end));
73 }
19 return lines; 74 return lines;
20 } 75 }
21 76
22 StringConversionSink startChunkedConversion(Sink<dynamic> sink) { 77 StringConversionSink startChunkedConversion(Sink<String> sink) {
23 if (sink is! StringConversionSink) { 78 if (sink is! StringConversionSink) {
24 sink = new StringConversionSink.from(sink); 79 sink = new StringConversionSink.from(sink);
25 } 80 }
26 return new _LineSplitterSink(sink); 81 return new _LineSplitterSink(sink);
27 } 82 }
28 } 83 }
29 84
30 // TODO(floitsch): deal with utf8. 85 // TODO(floitsch): deal with utf8.
31 class _LineSplitterSink extends StringConversionSinkBase { 86 class _LineSplitterSink extends StringConversionSinkBase {
32 static const int _LF = 10;
33 static const int _CR = 13;
34
35 final StringConversionSink _sink; 87 final StringConversionSink _sink;
36 88
89 /// The carry-over from the previous chunk.
90 ///
91 /// If the previous slice ended in a line without a line terminator,
92 /// then the next slice may continue the line.
37 String _carry; 93 String _carry;
38 94
95 /// Whether to skip a leading LF character from the next slice.
96 ///
97 /// If the previous slice ended on a CR character, a following LF
98 /// would be part of the same line termination, and should be ignored.
99 ///
100 /// Only `true` when [_carry] is `null`.
101 bool _skipLeadingLF = false;
102
39 _LineSplitterSink(this._sink); 103 _LineSplitterSink(this._sink);
40 104
41 void addSlice(String chunk, int start, int end, bool isLast) { 105 void addSlice(String chunk, int start, int end, bool isLast) {
106 end = RangeError.checkValidRange(start, end, chunk.length);
107 // If the chunk is empty, it's probably because it's the last one.
108 // Handle that here, so we know the range is non-empty below.
109 if (start >= end) {
110 if (isLast) close();
111 return;
112 }
42 if (_carry != null) { 113 if (_carry != null) {
114 assert(!_skipLeadingLF);
43 chunk = _carry + chunk.substring(start, end); 115 chunk = _carry + chunk.substring(start, end);
44 start = 0; 116 start = 0;
45 end = chunk.length; 117 end = chunk.length;
46 _carry = null; 118 _carry = null;
119 } else if (_skipLeadingLF) {
120 if (chunk.codeUnitAt(start) == _LF) {
121 start += 1;
122 }
123 _skipLeadingLF = false;
47 } 124 }
48 _carry = _addSlice(chunk, start, end, isLast, _sink.add); 125 _addLines(chunk, start, end);
49 if (isLast) _sink.close(); 126 if (isLast) close();
50 } 127 }
51 128
52 void close() { 129 void close() {
53 addSlice('', 0, 0, true); 130 if (_carry != null) {
131 _sink.add(_carry);
132 _carry = null;
133 }
134 _sink.close();
54 } 135 }
55 136
56 static String _addSlice(String chunk, int start, int end, bool isLast, 137 void _addLines(String lines, int start, int end) {
57 void adder(String val)) { 138 int sliceStart = start;
58 139 int char = 0;
59 int pos = start; 140 for (int i = start; i < end; i++) {
60 while (pos < end) { 141 int previousChar = char;
61 int skip = 0; 142 char = lines.codeUnitAt(i);
62 int char = chunk.codeUnitAt(pos); 143 if (char != _CR) {
63 if (char == _LF) { 144 if (char != _LF) continue;
64 skip = 1; 145 if (previousChar == _CR) {
65 } else if (char == _CR) { 146 sliceStart = i + 1;
66 skip = 1; 147 continue;
67 if (pos + 1 < end) {
68 if (chunk.codeUnitAt(pos + 1) == _LF) {
69 skip = 2;
70 }
71 } else if (!isLast) {
72 return chunk.substring(start, end);
73 } 148 }
74 } 149 }
75 if (skip > 0) { 150 _sink.add(lines.substring(sliceStart, i));
76 adder(chunk.substring(start, pos)); 151 sliceStart = i + 1;
77 start = pos = pos + skip;
78 } else {
79 pos++;
80 }
81 } 152 }
82 if (pos != start) { 153 if (sliceStart < end) {
83 var carry = chunk.substring(start, pos); 154 _carry = lines.substring(sliceStart, end);
84 if (isLast) { 155 } else {
85 // Add remaining 156 _skipLeadingLF = (char == _CR);
86 adder(carry);
87 } else {
88 return carry;
89 }
90 } 157 }
91 return null;
92 } 158 }
93 } 159 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698