Implement copying a buffer to an output stream.
diff --git a/okio/src/main/java/okio/Buffer.java b/okio/src/main/java/okio/Buffer.java
index 723c398..537c057 100644
--- a/okio/src/main/java/okio/Buffer.java
+++ b/okio/src/main/java/okio/Buffer.java
@@ -118,6 +118,32 @@
}
/**
+ * Write {@code byteCount} bytes from this, starting at {@code offset}, to
+ * {@code out}.
+ */
+ public Buffer copy(OutputStream out, long offset, long byteCount) throws IOException {
+ checkOffsetAndCount(size, offset, byteCount);
+ if (byteCount == 0) return this;
+
+ // Skip segments that we aren't copying from.
+ Segment s = head;
+ for (; offset >= (s.limit - s.pos); s = s.next) {
+ offset -= (s.limit - s.pos);
+ }
+
+ // Copy from one segment at a time.
+ for (; byteCount > 0; s = s.next) {
+ int pos = (int) (s.pos + offset);
+ int toWrite = (int) Math.min(s.limit - pos, byteCount);
+ out.write(s.data, pos, toWrite);
+ byteCount -= toWrite;
+ offset = 0;
+ }
+
+ return this;
+ }
+
+ /**
* Returns the number of bytes in segments that are not writable. This is the
* number of bytes that can be flushed immediately to an underlying sink
* without harming throughput.
@@ -744,7 +770,7 @@
/** Returns a deep copy of this buffer. */
@Override public Buffer clone() {
Buffer result = new Buffer();
- if (size() == 0) return result;
+ if (size == 0) return result;
result.write(head.data, head.pos, head.limit - head.pos);
for (Segment s = head.next; s != head; s = s.next) {
diff --git a/okio/src/test/java/okio/BufferTest.java b/okio/src/test/java/okio/BufferTest.java
index 14b5ef7..916bd9e 100644
--- a/okio/src/test/java/okio/BufferTest.java
+++ b/okio/src/test/java/okio/BufferTest.java
@@ -15,6 +15,7 @@
*/
package okio;
+import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Random;
@@ -247,6 +248,20 @@
assertEquals(Segment.SIZE * 2 - 20, source.size());
}
+ @Test public void copySpanningSegments() throws Exception {
+ Buffer source = new Buffer();
+ source.writeUtf8(repeat('a', Segment.SIZE * 2));
+ source.writeUtf8(repeat('b', Segment.SIZE * 2));
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ source.copy(out, 10, Segment.SIZE * 3);
+
+ assertEquals(repeat('a', Segment.SIZE * 2 - 10) + repeat('b', Segment.SIZE + 10),
+ out.toString());
+ assertEquals(repeat('a', Segment.SIZE * 2) + repeat('b', Segment.SIZE * 2),
+ source.readUtf8(Segment.SIZE * 4));
+ }
+
@Test public void readExhaustedSource() throws Exception {
Buffer sink = new Buffer();
sink.writeUtf8(repeat('a', 10));