Skip to content

Commit

Permalink
Merge pull request #687 from square/jwilson.1211.empty_tail_segment_1x
Browse files Browse the repository at this point in the history
Remove empty tail segment (1.x branch)
  • Loading branch information
swankjesse authored Dec 11, 2019
2 parents a4aa971 + 94dba1e commit 5c28000
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 1 deletion.
5 changes: 5 additions & 0 deletions okio/src/main/java/okio/Buffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ private void readFrom(InputStream in, long byteCount, boolean forever) throws IO
int maxToCopy = (int) Math.min(byteCount, Segment.SIZE - tail.limit);
int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
if (bytesRead == -1) {
if (tail.pos == tail.limit) {
// We allocated a tail segment, but didn't end up needing it. Recycle!
head = tail.pop();
SegmentPool.recycle(tail);
}
if (forever) return;
throw new EOFException();
}
Expand Down
9 changes: 8 additions & 1 deletion okio/src/main/java/okio/Okio.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,14 @@ private static Source source(final InputStream in, final Timeout timeout) {
Segment tail = sink.writableSegment(1);
int maxToCopy = (int) Math.min(byteCount, Segment.SIZE - tail.limit);
int bytesRead = in.read(tail.data, tail.limit, maxToCopy);
if (bytesRead == -1) return -1;
if (bytesRead == -1) {
if (tail.pos == tail.limit) {
// We allocated a tail segment, but didn't end up needing it. Recycle!
sink.head = tail.pop();
SegmentPool.recycle(tail);
}
return -1;
}
tail.limit += bytesRead;
sink.size += bytesRead;
return bytesRead;
Expand Down
7 changes: 7 additions & 0 deletions okio/src/test/java/okio/BufferTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.junit.Test;

import static java.util.Arrays.asList;
import static okio.TestUtil.assertNoEmptySegments;
import static okio.TestUtil.bufferWithRandomSegmentLayout;
import static okio.TestUtil.repeat;
import static okio.Util.UTF_8;
Expand Down Expand Up @@ -292,6 +293,12 @@ private List<Integer> moveBytesBetweenBuffers(String... contents) throws IOExcep
assertEquals("hello, wor", out);
}

@Test public void readFromDoesNotLeaveEmptyTailSegment() throws IOException {
Buffer buffer = new Buffer();
buffer.readFrom(new ByteArrayInputStream(new byte[Segment.SIZE]));
assertNoEmptySegments(buffer);
}

@Test public void moveAllRequestedBytesWithRead() throws Exception {
Buffer sink = new Buffer();
sink.writeUtf8(repeat('a', 10));
Expand Down
12 changes: 12 additions & 0 deletions okio/src/test/java/okio/OkioTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import static okio.TestUtil.assertNoEmptySegments;
import static okio.TestUtil.repeat;
import static okio.Util.UTF_8;
import static org.junit.Assert.assertEquals;
Expand Down Expand Up @@ -119,6 +120,17 @@ public final class OkioTest {
assertEquals(-1, source.read(sink, 1));
}

@Test public void sourceFromInputStreamWithSegmentSize() throws Exception {
InputStream in = new ByteArrayInputStream(new byte[Segment.SIZE]);
Source source = Okio.source(in);
Buffer sink = new Buffer();

assertEquals(Segment.SIZE, source.read(sink, Segment.SIZE));
assertEquals(-1, source.read(sink, Segment.SIZE));

assertNoEmptySegments(sink);
}

@Test public void sourceFromInputStreamBounds() throws Exception {
Source source = Okio.source(new ByteArrayInputStream(new byte[100]));
try {
Expand Down
7 changes: 7 additions & 0 deletions okio/src/test/java/okio/TestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,19 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;

final class TestUtil {
private TestUtil() {
}

static void assertNoEmptySegments(Buffer buffer) {
for (Integer segmentSize : buffer.segmentSizes()) {
assertNotEquals("Expected all segments to be non-empty", 0, segmentSize.intValue());
}
}

static void assertByteArraysEquals(byte[] a, byte[] b) {
assertEquals(Arrays.toString(a), Arrays.toString(b));
}
Expand Down

0 comments on commit 5c28000

Please sign in to comment.