Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove empty tail segment (1.x branch) #687

Merged
merged 1 commit into from
Dec 11, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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