1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 package org.eclipse.jgit.util.io;
44
45 import java.io.IOException;
46 import java.io.OutputStream;
47
48 import org.eclipse.jgit.diff.RawText;
49
50
51
52
53
54
55
56
57
58
59
60 public class AutoLFOutputStream extends OutputStream {
61
62 static final int BUFFER_SIZE = 8000;
63
64 private final OutputStream out;
65
66 private int buf = -1;
67
68 private byte[] binbuf = new byte[BUFFER_SIZE];
69
70 private byte[] onebytebuf = new byte[1];
71
72 private int binbufcnt = 0;
73
74 private boolean detectBinary;
75
76 private boolean isBinary;
77
78
79
80
81 public AutoLFOutputStream(OutputStream out) {
82 this(out, true);
83 }
84
85
86
87
88
89
90 public AutoLFOutputStream(OutputStream out, boolean detectBinary) {
91 this.out = out;
92 this.detectBinary = detectBinary;
93 }
94
95 @Override
96 public void write(int b) throws IOException {
97 onebytebuf[0] = (byte) b;
98 write(onebytebuf, 0, 1);
99 }
100
101 @Override
102 public void write(byte[] b) throws IOException {
103 int overflow = buffer(b, 0, b.length);
104 if (overflow > 0) {
105 write(b, b.length - overflow, overflow);
106 }
107 }
108
109 @Override
110 public void write(byte[] b, final int startOff, final int startLen)
111 throws IOException {
112 final int overflow = buffer(b, startOff, startLen);
113 if (overflow < 0) {
114 return;
115 }
116 final int off = startOff + startLen - overflow;
117 final int len = overflow;
118 if (len == 0) {
119 return;
120 }
121 int lastw = off;
122 if (isBinary) {
123 out.write(b, off, len);
124 return;
125 }
126 for (int i = off; i < off + len; ++i) {
127 final byte c = b[i];
128 if (c == '\r') {
129
130 if (lastw < i) {
131 out.write(b, lastw, i - lastw);
132 }
133 lastw = i + 1;
134 buf = '\r';
135 } else if (c == '\n') {
136 if (buf == '\r') {
137 out.write('\n');
138 lastw = i + 1;
139 buf = -1;
140 } else {
141 if (lastw < i + 1) {
142 out.write(b, lastw, i + 1 - lastw);
143 }
144 lastw = i + 1;
145 }
146 } else {
147 if (buf == '\r') {
148 out.write('\r');
149 lastw = i;
150 }
151 buf = -1;
152 }
153 }
154 if (lastw < off + len) {
155 out.write(b, lastw, off + len - lastw);
156 }
157 }
158
159 private int buffer(byte[] b, int off, int len) throws IOException {
160 if (binbufcnt > binbuf.length) {
161 return len;
162 }
163 int copy = Math.min(binbuf.length - binbufcnt, len);
164 System.arraycopy(b, off, binbuf, binbufcnt, copy);
165 binbufcnt += copy;
166 int remaining = len - copy;
167 if (remaining > 0) {
168 decideMode();
169 }
170 return remaining;
171 }
172
173 private void decideMode() throws IOException {
174 if (detectBinary) {
175 isBinary = RawText.isBinary(binbuf, binbufcnt);
176 detectBinary = false;
177 }
178 int cachedLen = binbufcnt;
179 binbufcnt = binbuf.length + 1;
180 write(binbuf, 0, cachedLen);
181 }
182
183 @Override
184 public void flush() throws IOException {
185 if (binbufcnt <= binbuf.length) {
186 decideMode();
187 }
188 out.flush();
189 }
190
191 @Override
192 public void close() throws IOException {
193 flush();
194 if (buf == '\r') {
195 out.write(buf);
196 buf = -1;
197 }
198 out.close();
199 }
200 }