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

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

Issue 2698353003: unfork DDC's copy of most SDK libraries (Closed)
Patch Set: revert core_patch Created 3 years, 9 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of dart.convert;
6
7 // Character constants.
8 const int _LF = 10;
9 const int _CR = 13;
10
11 /**
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.
19 */
20 class LineSplitter
21 extends Converter<String, List<String>>/*=Object*/
22 implements Object/*=StreamTransformer<String, String>*/ {
23
24 const LineSplitter();
25
26 /// Split [lines] into individual lines.
27 ///
28 /// If [start] and [end] are provided, only split the contents of
29 /// `lines.substring(start, end)`. The [start] and [end] values must
30 /// specify a valid sub-range of [lines]
31 /// (`0 <= start <= end <= lines.length`).
32 static Iterable<String> split(String lines, [int start = 0, int end]) sync* {
33 end = RangeError.checkValidRange(start, end, lines.length);
34 int sliceStart = start;
35 int char = 0;
36 for (int i = start; i < end; i++) {
37 int previousChar = char;
38 char = lines.codeUnitAt(i);
39 if (char != _CR) {
40 if (char != _LF) continue;
41 if (previousChar == _CR) {
42 sliceStart = i + 1;
43 continue;
44 }
45 }
46 yield lines.substring(sliceStart, i);
47 sliceStart = i + 1;
48 }
49 if (sliceStart < end) {
50 yield lines.substring(sliceStart, end);
51 }
52 }
53
54 List<String> convert(String data) {
55 List<String> lines = <String>[];
56 int end = data.length;
57 int sliceStart = 0;
58 int char = 0;
59 for (int i = 0; i < end; i++) {
60 int previousChar = char;
61 char = data.codeUnitAt(i);
62 if (char != _CR) {
63 if (char != _LF) continue;
64 if (previousChar == _CR) {
65 sliceStart = i + 1;
66 continue;
67 }
68 }
69 lines.add(data.substring(sliceStart, i));
70 sliceStart = i + 1;
71 }
72 if (sliceStart < end) {
73 lines.add(data.substring(sliceStart, end));
74 }
75 return lines;
76 }
77
78 StringConversionSink startChunkedConversion(Sink<String> sink) {
79 if (sink is! StringConversionSink) {
80 sink = new StringConversionSink.from(sink);
81 }
82 return new _LineSplitterSink(sink);
83 }
84
85 Stream/*<String>*/ bind(Stream/*<String>*/ stream) {
86 return new Stream<String>.eventTransformed(
87 stream,
88 (EventSink<String> sink) => new _LineSplitterEventSink(sink));
89 }
90 }
91
92 // TODO(floitsch): deal with utf8.
93 class _LineSplitterSink extends StringConversionSinkBase {
94 final StringConversionSink _sink;
95
96 /// The carry-over from the previous chunk.
97 ///
98 /// If the previous slice ended in a line without a line terminator,
99 /// then the next slice may continue the line.
100 String _carry;
101
102 /// Whether to skip a leading LF character from the next slice.
103 ///
104 /// If the previous slice ended on a CR character, a following LF
105 /// would be part of the same line termination, and should be ignored.
106 ///
107 /// Only `true` when [_carry] is `null`.
108 bool _skipLeadingLF = false;
109
110 _LineSplitterSink(this._sink);
111
112 void addSlice(String chunk, int start, int end, bool isLast) {
113 end = RangeError.checkValidRange(start, end, chunk.length);
114 // If the chunk is empty, it's probably because it's the last one.
115 // Handle that here, so we know the range is non-empty below.
116 if (start >= end) {
117 if (isLast) close();
118 return;
119 }
120 if (_carry != null) {
121 assert(!_skipLeadingLF);
122 chunk = _carry + chunk.substring(start, end);
123 start = 0;
124 end = chunk.length;
125 _carry = null;
126 } else if (_skipLeadingLF) {
127 if (chunk.codeUnitAt(start) == _LF) {
128 start += 1;
129 }
130 _skipLeadingLF = false;
131 }
132 _addLines(chunk, start, end);
133 if (isLast) close();
134 }
135
136 void close() {
137 if (_carry != null) {
138 _sink.add(_carry);
139 _carry = null;
140 }
141 _sink.close();
142 }
143
144 void _addLines(String lines, int start, int end) {
145 int sliceStart = start;
146 int char = 0;
147 for (int i = start; i < end; i++) {
148 int previousChar = char;
149 char = lines.codeUnitAt(i);
150 if (char != _CR) {
151 if (char != _LF) continue;
152 if (previousChar == _CR) {
153 sliceStart = i + 1;
154 continue;
155 }
156 }
157 _sink.add(lines.substring(sliceStart, i));
158 sliceStart = i + 1;
159 }
160 if (sliceStart < end) {
161 _carry = lines.substring(sliceStart, end);
162 } else {
163 _skipLeadingLF = (char == _CR);
164 }
165 }
166 }
167
168 class _LineSplitterEventSink extends _LineSplitterSink
169 implements EventSink<String> {
170 final EventSink<String> _eventSink;
171
172 _LineSplitterEventSink(EventSink<String> eventSink)
173 : _eventSink = eventSink,
174 super(new StringConversionSink.from(eventSink));
175
176 void addError(Object o, [StackTrace stackTrace]) {
177 _eventSink.addError(o, stackTrace);
178 }
179 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698