Simplify DefaultExtractorInput

This commit is contained in:
Oliver Woodman 2015-12-17 12:15:09 +00:00
parent cf13280590
commit b9607321fe

View file

@ -51,13 +51,23 @@ public final class DefaultExtractorInput implements ExtractorInput {
@Override @Override
public int read(byte[] target, int offset, int length) throws IOException, InterruptedException { public int read(byte[] target, int offset, int length) throws IOException, InterruptedException {
return internalRead(target, offset, length, true, false, false); int bytesRead = readFromPeekBuffer(target, offset, length);
if (bytesRead == 0) {
bytesRead = readFromDataSource(target, offset, length, 0, true);
}
commitBytesRead(bytesRead);
return bytesRead;
} }
@Override @Override
public boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput) public boolean readFully(byte[] target, int offset, int length, boolean allowEndOfInput)
throws IOException, InterruptedException { throws IOException, InterruptedException {
return internalReadFully(target, offset, length, allowEndOfInput, false); int bytesRead = readFromPeekBuffer(target, offset, length);
while (bytesRead < length && bytesRead != C.RESULT_END_OF_INPUT) {
bytesRead = readFromDataSource(target, offset, length, bytesRead, allowEndOfInput);
}
commitBytesRead(bytesRead);
return bytesRead != C.RESULT_END_OF_INPUT;
} }
@Override @Override
@ -68,14 +78,24 @@ public final class DefaultExtractorInput implements ExtractorInput {
@Override @Override
public int skip(int length) throws IOException, InterruptedException { public int skip(int length) throws IOException, InterruptedException {
return internalRead(null, 0, Math.min(SCRATCH_SPACE.length + peekBufferLength, length), true, int bytesSkipped = skipFromPeekBuffer(length);
true, false); if (bytesSkipped == 0) {
bytesSkipped = readFromDataSource(SCRATCH_SPACE, 0, length, 0, true);
}
commitBytesRead(bytesSkipped);
return bytesSkipped;
} }
@Override @Override
public boolean skipFully(final int length, boolean allowEndOfInput) public boolean skipFully(int length, boolean allowEndOfInput)
throws IOException, InterruptedException { throws IOException, InterruptedException {
return internalReadFully(null, 0, length, allowEndOfInput, true); int bytesSkipped = skipFromPeekBuffer(length);
while (bytesSkipped < length && bytesSkipped != C.RESULT_END_OF_INPUT) {
bytesSkipped = readFromDataSource(SCRATCH_SPACE, -bytesSkipped,
Math.min(length, bytesSkipped + SCRATCH_SPACE.length), bytesSkipped, allowEndOfInput);
}
commitBytesRead(bytesSkipped);
return bytesSkipped != C.RESULT_END_OF_INPUT;
} }
@Override @Override
@ -94,10 +114,9 @@ public final class DefaultExtractorInput implements ExtractorInput {
public void advancePeekPosition(int length) throws IOException, InterruptedException { public void advancePeekPosition(int length) throws IOException, InterruptedException {
ensureSpaceForPeek(length); ensureSpaceForPeek(length);
peekBufferPosition += length; peekBufferPosition += length;
if (peekBufferPosition > peekBufferLength) { while (peekBufferPosition > peekBufferLength) {
readFromDataSource(peekBuffer, peekBufferLength, peekBufferPosition - peekBufferLength, peekBufferLength = readFromDataSource(peekBuffer, 0, peekBufferPosition, peekBufferLength,
false, false, 0, true); false);
peekBufferLength = peekBufferPosition;
} }
} }
@ -127,6 +146,36 @@ public final class DefaultExtractorInput implements ExtractorInput {
} }
} }
/**
* Skips from the peek buffer.
*
* @param length The maximum number of bytes to skip from the peek buffer.
* @return The number of bytes skipped.
*/
private int skipFromPeekBuffer(int length) {
int bytesSkipped = Math.min(peekBufferLength, length);
updatePeekBuffer(bytesSkipped);
return bytesSkipped;
}
/**
* Reads from the peek buffer
*
* @param target A target array into which data should be written.
* @param offset The offset into the target array at which to write.
* @param length The maximum number of bytes to read from the peek buffer.
* @return The number of bytes read.
*/
private int readFromPeekBuffer(byte[] target, int offset, int length) {
if (peekBufferLength == 0) {
return 0;
}
int peekBytes = Math.min(peekBufferLength, length);
System.arraycopy(peekBuffer, 0, target, offset, peekBytes);
updatePeekBuffer(peekBytes);
return peekBytes;
}
/** /**
* Updates the peek buffer's length, position and contents after consuming data. * Updates the peek buffer's length, position and contents after consuming data.
* *
@ -139,100 +188,47 @@ public final class DefaultExtractorInput implements ExtractorInput {
} }
/** /**
* Internal read method. * Starts or continues a read from the data source.
*
* @see #internalRead(byte[], int, int, boolean, boolean, boolean)
*/
private boolean internalReadFully(byte[] target, int offset, int length, boolean allowEndOfInput,
boolean skip) throws InterruptedException, IOException {
return internalRead(target, offset, length, allowEndOfInput, skip, true)
!= C.RESULT_END_OF_INPUT;
}
/**
* Internal read method.
*
* @see #readFromPeekBuffer(byte[], int, int, boolean)
* @see #readFromDataSource(byte[], int, int, boolean, boolean, int, boolean)
*/
private int internalRead(byte[] target, int offset, int length, boolean allowEndOfInput,
boolean skip, boolean readFully) throws InterruptedException, IOException {
int totalBytesRead = readFromPeekBuffer(target, offset, length, skip);
totalBytesRead = readFromDataSource(target, offset, length, allowEndOfInput, skip,
totalBytesRead, readFully);
if (totalBytesRead != C.RESULT_END_OF_INPUT) {
position += totalBytesRead;
}
return totalBytesRead;
}
/**
* Reads from the peek buffer
* *
* @param target A target array into which data should be written. * @param target A target array into which data should be written.
* @param offset The offset into the target array at which to write. * @param offset The offset into the target array at which to write.
* @param length The maximum number of bytes to read from the input. * @param length The maximum number of bytes to read from the input.
* @param skip If true, instead of reading skip the data * @param bytesAlreadyRead The number of bytes already read from the input.
* @return The number of bytes read * @param allowEndOfInput True if encountering the end of the input having read no data is
*/ * allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it
private int readFromPeekBuffer(byte[] target, int offset, int length, boolean skip) { * should be considered an error, causing an {@link EOFException} to be thrown.
if (peekBufferLength == 0) { * @return The total number of bytes read so far, or {@link C#RESULT_END_OF_INPUT} if
return 0; * {@code allowEndOfInput} is true and the input has ended having read no bytes.
} * @throws EOFException If the end of input was encountered having partially satisfied the read
* (i.e. having read at least one byte, but fewer than {@code length}), or if no bytes were
int peekBytes = Math.min(peekBufferLength, length); * read and {@code allowEndOfInput} is false.
if (!skip) {
System.arraycopy(peekBuffer, 0, target, offset, peekBytes);
}
updatePeekBuffer(peekBytes);
return peekBytes;
}
/**
* Reads from the data source
*
* @param target A target array into which data should be written.
* @param offset The offset into the target array at which to write.
* @param length The maximum number of bytes to read from the input.
* @param returnEOIifNoReadBytes If true on encountering the end of the input having read no data
* should result in {@link C#RESULT_END_OF_INPUT} being returned.
* @param skip If true, instead of reading skip the data
* @param totalBytesRead Number of bytes read until now for the external request
* @param readFully If true reads the requested {@code length} in full.
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the input has ended.
* @throws EOFException If the end of input was encountered.
* @throws IOException If an error occurs reading from the input. * @throws IOException If an error occurs reading from the input.
* @throws InterruptedException If the thread is interrupted. * @throws InterruptedException If the thread is interrupted.
*/ */
private int readFromDataSource(byte[] target, int offset, int length, private int readFromDataSource(byte[] target, int offset, int length, int bytesAlreadyRead,
boolean returnEOIifNoReadBytes, boolean skip, int totalBytesRead, boolean readFully) boolean allowEndOfInput) throws InterruptedException, IOException {
throws InterruptedException, IOException { if (Thread.interrupted()) {
while (totalBytesRead < length) { throw new InterruptedException();
if (Thread.interrupted()) { }
throw new InterruptedException(); int bytesRead = dataSource.read(target, offset + bytesAlreadyRead, length - bytesAlreadyRead);
} if (bytesRead == C.RESULT_END_OF_INPUT) {
if (bytesAlreadyRead == 0 && allowEndOfInput) {
int bytesRead = !skip return C.RESULT_END_OF_INPUT;
? dataSource.read(target, offset + totalBytesRead, length - totalBytesRead) }
: dataSource.read(SCRATCH_SPACE, 0, throw new EOFException();
Math.min(SCRATCH_SPACE.length, length - totalBytesRead)); }
return bytesAlreadyRead + bytesRead;
if (bytesRead == C.RESULT_END_OF_INPUT) { }
if (returnEOIifNoReadBytes && totalBytesRead == 0) {
return C.RESULT_END_OF_INPUT; /**
} * Advances the position by the specified number of bytes read.
if (readFully) { *
throw new EOFException(); * @param bytesRead The number of bytes read.
} */
} else { private void commitBytesRead(int bytesRead) {
totalBytesRead += bytesRead; if (bytesRead != C.RESULT_END_OF_INPUT) {
} position += bytesRead;
if (!readFully) {
break;
}
} }
return totalBytesRead;
} }
} }