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

Side by Side Diff: lib/src/cr_lf_remover.dart

Issue 1226083002: Fix several Windows issues. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Created 5 years, 5 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 | lib/src/executable.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS d.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 library pub.cr_lf_remover;
6
7 import 'dart:convert';
8
9 import 'package:charcode/ascii.dart';
10
11 /// A converter that removes CR characters immediately preceding LF characters.
12 ///
13 /// This is useful when piping output from a Dart process on Windows. Due to
14 /// sdk#19334, an extra CR is added before every LF, even if one already
15 /// existed, which can cause data to become corrupted. By converting CR LFs to
16 /// LFs, this class ensures that when the output is emitted through the parent
17 /// process's stdout it will be identical to the output emitted by the child.
18 ///
19 /// Note that this will only work properly for Dart subprocesses, because
20 /// sdk#19334 guarantees that they will *never* emit an LF without a preceding
21 /// CR.
22 class CRLFRemover extends Converter<List<int>, List<int>> {
23 const CRLFRemover();
24
25 List<int> convert(List<int> data) {
26 var result;
27 var sink = startChunkedConversion(
28 new ByteConversionSink.withCallback((result_) => result = result_));
29 sink.add(data);
30 sink.close();
31 return result;
32 }
33
34 ChunkedConversionSink startChunkedConversion(Sink<List<int>> sink) {
35 if (sink is! ByteConversionSink) sink = new ByteConversionSink.from(sink);
Bob Nystrom 2015/07/08 22:12:15 Document this.
nweiz 2015/07/09 00:30:14 Done.
36 return new _CRLFSink(sink);
37 }
38 }
39
40 /// The custom sink used to do chunked removal of CRs.
41 class _CRLFSink extends ByteConversionSink {
42 /// Whether the last chunk ended in CR.
43 ///
44 /// If it did, that CR wasn't printed in case it needs to be removed.
45 var _wasCR = false;
46
47 /// The underlying sink.
48 final ByteConversionSink _sink;
49
50 _CRLFSink(this._sink);
51
52 void add(Iterable<int> chunk) {
53 if (chunk is! List) chunk = chunk.toList();
54 addSlice(chunk, 0, chunk.length, false);
55 }
56
57 void addSlice(List<int> chunk, int start, int end, bool isLast) {
58 var wasCR = _wasCR;
59 var nextSliceStart = start;
60 for (var i = start; i < end; i++) {
61 if (wasCR && chunk[i] == $lf) {
62 if (i != start) {
63 _sink.addSlice(chunk, nextSliceStart, i - 1, false);
64 nextSliceStart = i;
65 }
66 } else if (_wasCR && i == start) {
67 // If the last chunk ended in a CR and this chunk *doesn't* start with
68 // an LF, we need to write the CR from the last chunk.
69 _sink.add([$cr]);
70 }
71
72 wasCR = chunk[i] == $cr;
73 }
74
75 _wasCR = wasCR;
76 var finalSliceEnd = wasCR ? end - 1 : end;
77 _sink.addSlice(chunk, nextSliceStart, finalSliceEnd, isLast);
78 }
79
80 void close() {
81 if (_wasCR) _sink.add([$cr]);
82 _sink.close();
83 }
84 }
OLDNEW
« no previous file with comments | « no previous file | lib/src/executable.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698