13c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller/* 23c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Copyright (C) 2014 Square, Inc. 33c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 43c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 53c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * you may not use this file except in compliance with the License. 63c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * You may obtain a copy of the License at 73c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 83c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 93c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * 103c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * Unless required by applicable law or agreed to in writing, software 113c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 123c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * See the License for the specific language governing permissions and 143c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller * limitations under the License. 153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller */ 163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerpackage okio; 173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.IOException; 193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerimport java.io.OutputStream; 203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fullerfinal class RealBufferedSink implements BufferedSink { 223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public final OkBuffer buffer; 233c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public final Sink sink; 243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller private boolean closed; 253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public RealBufferedSink(Sink sink, OkBuffer buffer) { 273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (sink == null) throw new IllegalArgumentException("sink == null"); 283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this.buffer = buffer; 293c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this.sink = sink; 303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller public RealBufferedSink(Sink sink) { 333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller this(sink, new OkBuffer()); 343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 363c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public OkBuffer buffer() { 373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return buffer; 383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void write(OkBuffer source, long byteCount) 413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller throws IOException { 42c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.write(source, byteCount); 443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller emitCompleteSegments(); 453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink write(ByteString byteString) throws IOException { 48c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.write(byteString); 503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 523c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink writeUtf8(String string) throws IOException { 54c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.writeUtf8(string); 563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink write(byte[] source) throws IOException { 60c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.write(source); 623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink write(byte[] source, int offset, int byteCount) throws IOException { 66c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.write(source, offset, byteCount); 683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink writeByte(int b) throws IOException { 72c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.writeByte(b); 743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink writeShort(int s) throws IOException { 78c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.writeShort(s); 803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 83c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Override public BufferedSink writeShortLe(int s) throws IOException { 84c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 85c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller buffer.writeShortLe(s); 86c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller return emitCompleteSegments(); 87c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 88c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink writeInt(int i) throws IOException { 90c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.writeInt(i); 923c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return emitCompleteSegments(); 933c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 943c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 95c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Override public BufferedSink writeIntLe(int i) throws IOException { 96c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 97c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller buffer.writeIntLe(i); 98c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller return emitCompleteSegments(); 99c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 100c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 101c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Override public BufferedSink writeLong(long v) throws IOException { 102c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 103c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller buffer.writeLong(v); 104c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller return emitCompleteSegments(); 105c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 106c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 107c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller @Override public BufferedSink writeLongLe(long v) throws IOException { 108c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 109c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller buffer.writeLongLe(v); 110c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller return emitCompleteSegments(); 111c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller } 112c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller 1133c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public BufferedSink emitCompleteSegments() throws IOException { 114c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 1153c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller long byteCount = buffer.completeSegmentByteCount(); 1163c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (byteCount > 0) sink.write(buffer, byteCount); 1173c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return this; 1183c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1193c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1203c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public OutputStream outputStream() { 1213c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return new OutputStream() { 1223c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void write(int b) throws IOException { 123c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IOException("closed"); 1243c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.writeByte((byte) b); 1253c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller emitCompleteSegments(); 1263c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1273c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1283c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void write(byte[] data, int offset, int byteCount) throws IOException { 129c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IOException("closed"); 1303c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller buffer.write(data, offset, byteCount); 1313c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller emitCompleteSegments(); 1323c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1333c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1343c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void flush() throws IOException { 1353c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // For backwards compatibility, a flush() on a closed stream is a no-op. 136c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (!closed) { 1373c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RealBufferedSink.this.flush(); 1383c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1393c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1403c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1413c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void close() throws IOException { 1423c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller RealBufferedSink.this.close(); 1433c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1443c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1453c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public String toString() { 1463c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return RealBufferedSink.this + ".outputStream()"; 1473c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1483c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller }; 1493c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1503c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1513c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void flush() throws IOException { 152c6bd683320121544811f481709b3fdbcbe9b3866Neil Fuller if (closed) throw new IllegalStateException("closed"); 1533c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (buffer.size > 0) { 1543c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.write(buffer, buffer.size); 1553c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1563c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.flush(); 1573c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1583c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1593c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public void close() throws IOException { 1603c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (closed) return; 1613c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1623c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // Emit buffered data to the underlying sink. If this fails, we still need 1633c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller // to close the sink; otherwise we risk leaking resources. 1643c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller Throwable thrown = null; 1653c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 1663c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (buffer.size > 0) { 1673c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.write(buffer, buffer.size); 1683c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1693c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (Throwable e) { 1703c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller thrown = e; 1713c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1723c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1733c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller try { 1743c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.close(); 1753c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } catch (Throwable e) { 1763c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (thrown == null) thrown = e; 1773c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1783c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller closed = true; 1793c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1803c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller if (thrown != null) Util.sneakyRethrow(thrown); 1813c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1823c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1833c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public Sink deadline(Deadline deadline) { 1843c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller sink.deadline(deadline); 1853c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return this; 1863c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1873c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller 1883c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller @Override public String toString() { 1893c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller return "buffer(" + sink + ")"; 1903c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller } 1913c938a3f6b61ce5e2dba0d039b03fe73b89fd26cNeil Fuller} 192