Skip to content

Commit c07dd96

Browse files
committed
Merge pull request square#67 from square/jw/read-fully-byte-array
Add readFully for byte[].
2 parents c71c72f + 081659a commit c07dd96

File tree

6 files changed

+76
-30
lines changed

6 files changed

+76
-30
lines changed

okio/src/main/java/okio/Buffer.java

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ public byte getByte(long pos) {
368368
return new ByteString(readByteArray());
369369
}
370370

371-
@Override public ByteString readByteString(long byteCount) {
371+
@Override public ByteString readByteString(long byteCount) throws IOException {
372372
return new ByteString(readByteArray(byteCount));
373373
}
374374

@@ -390,15 +390,15 @@ public byte getByte(long pos) {
390390
return readString(size, Util.UTF_8);
391391
}
392392

393-
@Override public String readUtf8(long byteCount) {
393+
@Override public String readUtf8(long byteCount) throws IOException {
394394
return readString(byteCount, Util.UTF_8);
395395
}
396396

397397
@Override public String readString(Charset charset) throws IOException {
398398
return readString(size, charset);
399399
}
400400

401-
@Override public String readString(long byteCount, Charset charset) {
401+
@Override public String readString(long byteCount, Charset charset) throws IOException {
402402
checkOffsetAndCount(size, 0, byteCount);
403403
if (charset == null) throw new IllegalArgumentException("charset == null");
404404
if (byteCount > Integer.MAX_VALUE) {
@@ -440,7 +440,7 @@ public byte getByte(long pos) {
440440
return readUtf8Line(newline);
441441
}
442442

443-
String readUtf8Line(long newline) {
443+
String readUtf8Line(long newline) throws IOException {
444444
if (newline > 0 && getByte(newline - 1) == '\r') {
445445
// Read everything until '\r\n', then skip the '\r\n'.
446446
String result = readUtf8((newline - 1));
@@ -455,47 +455,40 @@ String readUtf8Line(long newline) {
455455
}
456456
}
457457

458-
@Override public byte[] readByteArray() {
458+
@Override public byte[] readByteArray() throws IOException {
459459
return readByteArray(size);
460460
}
461461

462-
@Override public byte[] readByteArray(long byteCount) {
462+
@Override public byte[] readByteArray(long byteCount) throws IOException {
463463
checkOffsetAndCount(this.size, 0, byteCount);
464464
if (byteCount > Integer.MAX_VALUE) {
465465
throw new IllegalArgumentException("byteCount > Integer.MAX_VALUE: " + byteCount);
466466
}
467467

468-
int offset = 0;
469468
byte[] result = new byte[(int) byteCount];
470-
471-
while (offset < byteCount) {
472-
int toCopy = (int) Math.min(byteCount - offset, head.limit - head.pos);
473-
System.arraycopy(head.data, head.pos, result, offset, toCopy);
474-
475-
offset += toCopy;
476-
head.pos += toCopy;
477-
478-
if (head.pos == head.limit) {
479-
Segment toRecycle = head;
480-
head = toRecycle.pop();
481-
SegmentPool.INSTANCE.recycle(toRecycle);
482-
}
483-
}
484-
485-
this.size -= byteCount;
469+
readFully(result);
486470
return result;
487471
}
488472

489473
@Override public int read(byte[] sink) {
490474
return read(sink, 0, sink.length);
491475
}
492476

477+
@Override public void readFully(byte[] sink) throws IOException {
478+
int offset = 0;
479+
while (offset < sink.length) {
480+
int read = read(sink, offset, sink.length - offset);
481+
if (read == -1) throw new EOFException();
482+
offset += read;
483+
}
484+
}
485+
493486
@Override public int read(byte[] sink, int offset, int byteCount) {
494487
checkOffsetAndCount(sink.length, offset, byteCount);
495488

496489
Segment s = this.head;
497490
if (s == null) return -1;
498-
int toCopy = Math.min((int) byteCount, s.limit - s.pos);
491+
int toCopy = Math.min(byteCount, s.limit - s.pos);
499492
System.arraycopy(s.data, s.pos, sink, offset, toCopy);
500493

501494
s.pos += toCopy;
@@ -808,7 +801,7 @@ public long indexOf(byte b, long fromIndex) {
808801
/** For testing. This returns the sizes of the segments in this buffer. */
809802
List<Integer> segmentSizes() {
810803
if (head == null) return Collections.emptyList();
811-
List<Integer> result = new ArrayList<Integer>();
804+
List<Integer> result = new ArrayList<>();
812805
result.add(head.limit - head.pos);
813806
for (Segment s = head.next; s != head; s = s.next) {
814807
result.add(s.limit - s.pos);
@@ -868,8 +861,12 @@ List<Integer> segmentSizes() {
868861
}
869862

870863
if (size <= 16) {
871-
ByteString data = clone().readByteString(size);
872-
return String.format("Buffer[size=%s data=%s]", size, data.hex());
864+
try {
865+
ByteString data = clone().readByteString(size);
866+
return String.format("Buffer[size=%s data=%s]", size, data.hex());
867+
} catch (IOException e) {
868+
throw new AssertionError(e);
869+
}
873870
}
874871

875872
try {

okio/src/main/java/okio/BufferedSource.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ public interface BufferedSource extends Source {
8787
*/
8888
int read(byte[] sink) throws IOException;
8989

90+
/**
91+
* Removes exactly {@code sink.length} bytes from this and copies them into {@code sink}.
92+
* Throws an {@link java.io.EOFException} if the requested number of bytes cannot be read.
93+
*/
94+
void readFully(byte[] sink) throws IOException;
95+
9096
/**
9197
* Removes up to {@code byteCount} bytes from this and copies them into {@code sink} at
9298
* {@code offset}. Returns the number of bytes read, or -1 if this source is exhausted.

okio/src/main/java/okio/RealBufferedSource.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,11 @@ public RealBufferedSource(Source source) {
9797
return read(sink, 0, sink.length);
9898
}
9999

100+
@Override public void readFully(byte[] sink) throws IOException {
101+
require(sink.length);
102+
buffer.readFully(sink);
103+
}
104+
100105
@Override public int read(byte[] sink, int offset, int byteCount) throws IOException {
101106
checkOffsetAndCount(sink.length, offset, byteCount);
102107

okio/src/test/java/okio/BufferTest.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public final class BufferTest {
201201
Segment.SIZE, Segment.SIZE, Segment.SIZE, 1), segmentSizes);
202202
}
203203

204-
private List<Integer> moveBytesBetweenBuffers(String... contents) {
204+
private List<Integer> moveBytesBetweenBuffers(String... contents) throws IOException {
205205
StringBuilder expected = new StringBuilder();
206206
Buffer buffer = new Buffer();
207207
for (String s : contents) {
@@ -674,7 +674,7 @@ private List<Integer> moveBytesBetweenBuffers(String... contents) {
674674
assertEquals(0, buffer.size());
675675
}
676676

677-
@Test public void testWritePrefixToEmptyBuffer() {
677+
@Test public void testWritePrefixToEmptyBuffer() throws IOException {
678678
Buffer sink = new Buffer();
679679
Buffer source = new Buffer();
680680
source.writeUtf8("abcd");
@@ -899,6 +899,24 @@ private List<Integer> moveBytesBetweenBuffers(String... contents) {
899899
assertEquals("Hi", sink.readUtf8());
900900
}
901901

902+
@Test public void readFullyByteArray() throws IOException {
903+
Buffer source = new Buffer().writeUtf8("Hello").writeUtf8(repeat('e', Segment.SIZE));
904+
byte[] expected = source.clone().readByteArray();
905+
byte[] sink = new byte[Segment.SIZE + 5];
906+
source.readFully(sink);
907+
assertByteArraysEquals(expected, sink);
908+
}
909+
910+
@Test public void readFullyByteArrayTooShortThrows() throws IOException {
911+
Buffer source = new Buffer().writeUtf8("Hello");
912+
byte[] sink = new byte[6];
913+
try {
914+
source.readFully(sink);
915+
fail();
916+
} catch (EOFException ignored) {
917+
}
918+
}
919+
902920
/**
903921
* Returns a new buffer containing the data in {@code data}, and a segment
904922
* layout determined by {@code dice}.

okio/src/test/java/okio/InflaterSourceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ private Buffer decodeBase64(String s) {
7878
return new Buffer().write(ByteString.decodeBase64(s));
7979
}
8080

81-
private String readUtf8(Buffer buffer) {
81+
private String readUtf8(Buffer buffer) throws IOException {
8282
return buffer.readUtf8(buffer.size());
8383
}
8484

okio/src/test/java/okio/RealBufferedSourceTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,4 +309,24 @@ public final class RealBufferedSourceTest {
309309
byte[] expected = { 0, 0, 'a', 'b', 'c', 0, 0 };
310310
assertByteArraysEquals(expected, sink);
311311
}
312+
313+
@Test public void readFullyByteArray() throws IOException {
314+
Buffer buffer = new Buffer().writeUtf8("Hello").writeUtf8(repeat('e', Segment.SIZE));
315+
BufferedSource source = Okio.buffer((Source) buffer);
316+
byte[] expected = buffer.clone().readByteArray();
317+
byte[] sink = new byte[Segment.SIZE + 5];
318+
source.readFully(sink);
319+
assertByteArraysEquals(expected, sink);
320+
}
321+
322+
@Test public void readFullyByteArrayTooShortThrows() throws IOException {
323+
Buffer buffer = new Buffer().writeUtf8("Hello");
324+
BufferedSource source = Okio.buffer((Source) buffer);
325+
byte[] sink = new byte[6];
326+
try {
327+
source.readFully(sink);
328+
fail();
329+
} catch (EOFException ignored) {
330+
}
331+
}
312332
}

0 commit comments

Comments
 (0)