blob: cc9ad943527479f6286d5f4e38f1357fb4c3140f [file] [log] [blame]
// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
part of dart.convert;
/**
* This class splits [String] values into individual lines.
*/
class LineSplitter extends Converter<String, List<String>> {
List<String> convert(String data) {
var lines = new List<String>();
_LineSplitterSink._addSlice(data, 0, data.length, true, lines.add);
return lines;
}
StringConversionSink startChunkedConversion(
ChunkedConversionSink<String> sink) {
if (sink is! StringConversionSink) {
sink = new StringConversionSink.from(sink);
}
return new _LineSplitterSink(sink);
}
}
// TODO(floitsch): deal with utf8.
class _LineSplitterSink extends StringConversionSinkBase {
static const int _LF = 10;
static const int _CR = 13;
final StringConversionSink _sink;
String _carry;
_LineSplitterSink(this._sink);
void addSlice(String chunk, int start, int end, bool isLast) {
if(_carry != null) {
chunk = _carry + chunk.substring(start, end);
start = 0;
end = chunk.length;
_carry = null;
}
_carry = _addSlice(chunk, start, end, isLast, _sink.add);
if(isLast) _sink.close();
}
void close() {
addSlice('', 0, 0, true);
}
static String _addSlice(String chunk, int start, int end, bool isLast, void adder(String val)) {
int pos = start;
while (pos < end) {
int skip = 0;
int char = chunk.codeUnitAt(pos);
if (char == _LF) {
skip = 1;
} else if (char == _CR) {
skip = 1;
if (pos + 1 < end) {
if (chunk.codeUnitAt(pos + 1) == _LF) {
skip = 2;
}
} else if (!isLast) {
return chunk.substring(start, end);
}
}
if (skip > 0) {
adder(chunk.substring(start, pos));
start = pos = pos + skip;
} else {
pos++;
}
}
if (pos != start) {
var carry = chunk.substring(start, pos);
if(isLast) {
// Add remaining
adder(carry);
} else {
return carry;
}
}
return null;
}
}