Clean up some DataSource implementations

- Make read return 0 if readLength==0
- Return RESULT_END_OF_INPUT properly in the case that
  bytesRemaining is unset (this was broken previously,
  but only applies for assets > 2^31 bytes, so it's
  unlikely anyone ever hit this issue)

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=135136541
This commit is contained in:
olly 2016-10-04 12:15:28 -07:00 committed by Oliver Woodman
parent 7838a16dd8
commit f8ed4cfdee
7 changed files with 118 additions and 82 deletions

View File

@ -338,17 +338,21 @@ public class OkHttpDataSource implements HttpDataSource {
* @throws IOException If an error occurs reading from the source. * @throws IOException If an error occurs reading from the source.
*/ */
private int readInternal(byte[] buffer, int offset, int readLength) throws IOException { private int readInternal(byte[] buffer, int offset, int readLength) throws IOException {
readLength = bytesToRead == C.LENGTH_UNSET ? readLength
: (int) Math.min(readLength, bytesToRead - bytesRead);
if (readLength == 0) { if (readLength == 0) {
// We've read all of the requested data. return 0;
return C.RESULT_END_OF_INPUT; }
if (bytesToRead != C.LENGTH_UNSET) {
long bytesRemaining = bytesToRead - bytesRead;
if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
readLength = (int) Math.min(readLength, bytesRemaining);
} }
int read = responseByteStream.read(buffer, offset, readLength); int read = responseByteStream.read(buffer, offset, readLength);
if (read == -1) { if (read == -1) {
if (bytesToRead != C.LENGTH_UNSET && bytesToRead != bytesRead) { if (bytesToRead != C.LENGTH_UNSET) {
// The server closed the connection having not sent sufficient data. // End of stream reached having not read sufficient data.
throw new EOFException(); throw new EOFException();
} }
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;

View File

@ -104,29 +104,35 @@ public final class AssetDataSource implements DataSource {
@Override @Override
public int read(byte[] buffer, int offset, int readLength) throws AssetDataSourceException { public int read(byte[] buffer, int offset, int readLength) throws AssetDataSourceException {
if (bytesRemaining == 0) { if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else {
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new AssetDataSourceException(e);
}
if (bytesRead > 0) {
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
}
return bytesRead;
} }
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new AssetDataSourceException(e);
}
if (bytesRead == -1) {
if (bytesRemaining != C.LENGTH_UNSET) {
// End of stream reached having not read sufficient data.
throw new AssetDataSourceException(new EOFException());
}
return C.RESULT_END_OF_INPUT;
}
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead;
} }
@Override @Override

View File

@ -54,15 +54,18 @@ public final class ByteArrayDataSource implements DataSource {
} }
@Override @Override
public int read(byte[] buffer, int offset, int length) throws IOException { public int read(byte[] buffer, int offset, int readLength) throws IOException {
if (bytesRemaining == 0) { if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} }
length = Math.min(length, bytesRemaining);
System.arraycopy(data, readPosition, buffer, offset, length); readLength = Math.min(readLength, bytesRemaining);
readPosition += length; System.arraycopy(data, readPosition, buffer, offset, readLength);
bytesRemaining -= length; readPosition += readLength;
return length; bytesRemaining -= readLength;
return readLength;
} }
@Override @Override

View File

@ -103,29 +103,35 @@ public final class ContentDataSource implements DataSource {
@Override @Override
public int read(byte[] buffer, int offset, int readLength) throws ContentDataSourceException { public int read(byte[] buffer, int offset, int readLength) throws ContentDataSourceException {
if (bytesRemaining == 0) { if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else {
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new ContentDataSourceException(e);
}
if (bytesRead > 0) {
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
}
return bytesRead;
} }
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new ContentDataSourceException(e);
}
if (bytesRead == -1) {
if (bytesRemaining != C.LENGTH_UNSET) {
// End of stream reached having not read sufficient data.
throw new ContentDataSourceException(new EOFException());
}
return C.RESULT_END_OF_INPUT;
}
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead;
} }
@Override @Override

View File

@ -55,14 +55,18 @@ public interface DataSource {
/** /**
* Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at * Reads up to {@code length} bytes of data and stores them into {@code buffer}, starting at
* index {@code offset}. Blocks until at least one byte of data can be read, the end of the opened * index {@code offset}.
* range is detected, or an exception is thrown. * <p>
* If {@code length} is zero then 0 is returned. Otherwise, if no data is available because the
* end of the opened range has been reached, then {@link C#RESULT_END_OF_INPUT} is returned.
* Otherwise, the call will block until at least one byte of data has been read and the number of
* bytes read is returned.
* *
* @param buffer The buffer into which the read data should be stored. * @param buffer The buffer into which the read data should be stored.
* @param offset The start offset into {@code buffer} at which data should be written. * @param offset The start offset into {@code buffer} at which data should be written.
* @param readLength The maximum number of bytes to read. * @param readLength The maximum number of bytes to read.
* @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if the end of the opened * @return The number of bytes read, or {@link C#RESULT_END_OF_INPUT} if no data is avaliable
* range is reached. * because the end of the opened range has been reached.
* @throws IOException If an error occurs reading from the source. * @throws IOException If an error occurs reading from the source.
*/ */
int read(byte[] buffer, int offset, int readLength) throws IOException; int read(byte[] buffer, int offset, int readLength) throws IOException;

View File

@ -550,11 +550,18 @@ public class DefaultHttpDataSource implements HttpDataSource {
if (readLength == 0) { if (readLength == 0) {
return 0; return 0;
} }
if (bytesToRead != C.LENGTH_UNSET) {
long bytesRemaining = bytesToRead - bytesRead;
if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT;
}
readLength = (int) Math.min(readLength, bytesRemaining);
}
int read = inputStream.read(buffer, offset, readLength); int read = inputStream.read(buffer, offset, readLength);
if (read == -1) { if (read == -1) {
if (bytesToRead != C.LENGTH_UNSET && bytesToRead != bytesRead) { if (bytesToRead != C.LENGTH_UNSET) {
// The server closed the connection having not sent sufficient data. // End of stream reached having not read sufficient data.
throw new EOFException(); throw new EOFException();
} }
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;

View File

@ -132,29 +132,35 @@ public final class RawResourceDataSource implements DataSource {
@Override @Override
public int read(byte[] buffer, int offset, int readLength) throws RawResourceDataSourceException { public int read(byte[] buffer, int offset, int readLength) throws RawResourceDataSourceException {
if (bytesRemaining == 0) { if (readLength == 0) {
return 0;
} else if (bytesRemaining == 0) {
return C.RESULT_END_OF_INPUT; return C.RESULT_END_OF_INPUT;
} else {
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new RawResourceDataSourceException(e);
}
if (bytesRead > 0) {
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
}
return bytesRead;
} }
int bytesRead;
try {
int bytesToRead = bytesRemaining == C.LENGTH_UNSET ? readLength
: (int) Math.min(bytesRemaining, readLength);
bytesRead = inputStream.read(buffer, offset, bytesToRead);
} catch (IOException e) {
throw new RawResourceDataSourceException(e);
}
if (bytesRead == -1) {
if (bytesRemaining != C.LENGTH_UNSET) {
// End of stream reached having not read sufficient data.
throw new RawResourceDataSourceException(new EOFException());
}
return C.RESULT_END_OF_INPUT;
}
if (bytesRemaining != C.LENGTH_UNSET) {
bytesRemaining -= bytesRead;
}
if (listener != null) {
listener.onBytesTransferred(this, bytesRead);
}
return bytesRead;
} }
@Override @Override