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
82
83
84
85
86 public AutoLFOutputStream(OutputStream out) {
87 this(out, true);
88 }
89
90
91
92
93
94
95
96
97
98
99
100 public AutoLFOutputStream(OutputStream out, boolean detectBinary) {
101 this.out = out;
102 this.detectBinary = detectBinary;
103 }
104
105
106 @Override
107 public void write(int b) throws IOException {
108 onebytebuf[0] = (byte) b;
109 write(onebytebuf, 0, 1);
110 }
111
112
113 @Override
114 public void write(byte[] b) throws IOException {
115 int overflow = buffer(b, 0, b.length);
116 if (overflow > 0) {
117 write(b, b.length - overflow, overflow);
118 }
119 }
120
121
122 @Override
123 public void write(byte[] b, int startOff, int startLen)
124 throws IOException {
125 final int overflow = buffer(b, startOff, startLen);
126 if (overflow < 0) {
127 return;
128 }
129 final int off = startOff + startLen - overflow;
130 final int len = overflow;
131 if (len == 0) {
132 return;
133 }
134 int lastw = off;
135 if (isBinary) {
136 out.write(b, off, len);
137 return;
138 }
139 for (int i = off; i < off + len; ++i) {
140 final byte c = b[i];
141 if (c == '\r') {
142
143 if (lastw < i) {
144 out.write(b, lastw, i - lastw);
145 }
146 lastw = i + 1;
147 buf = '\r';
148 } else if (c == '\n') {
149 if (buf == '\r') {
150 out.write('\n');
151 lastw = i + 1;
152 buf = -1;
153 } else {
154 if (lastw < i + 1) {
155 out.write(b, lastw, i + 1 - lastw);
156 }
157 lastw = i + 1;
158 }
159 } else {
160 if (buf == '\r') {
161 out.write('\r');
162 lastw = i;
163 }
164 buf = -1;
165 }
166 }
167 if (lastw < off + len) {
168 out.write(b, lastw, off + len - lastw);
169 }
170 }
171
172 private int buffer(byte[] b, int off, int len) throws IOException {
173 if (binbufcnt > binbuf.length) {
174 return len;
175 }
176 int copy = Math.min(binbuf.length - binbufcnt, len);
177 System.arraycopy(b, off, binbuf, binbufcnt, copy);
178 binbufcnt += copy;
179 int remaining = len - copy;
180 if (remaining > 0) {
181 decideMode();
182 }
183 return remaining;
184 }
185
186 private void decideMode() throws IOException {
187 if (detectBinary) {
188 isBinary = RawText.isBinary(binbuf, binbufcnt);
189 detectBinary = false;
190 }
191 int cachedLen = binbufcnt;
192 binbufcnt = binbuf.length + 1;
193 write(binbuf, 0, cachedLen);
194 }
195
196
197 @Override
198 public void flush() throws IOException {
199 if (binbufcnt <= binbuf.length) {
200 decideMode();
201 }
202 out.flush();
203 }
204
205
206 @Override
207 public void close() throws IOException {
208 flush();
209 if (buf == '\r') {
210 out.write(buf);
211 buf = -1;
212 }
213 out.close();
214 }
215 }