in imagepipeline/src/main/java/com/facebook/imagepipeline/decoder/ProgressiveJpegParser.java [140:228]
private boolean doParseMoreData(final InputStream inputStream) {
final int oldBestScanNumber = mBestScanNumber;
try {
int nextByte;
while (mParserState != NOT_A_JPEG && (nextByte = inputStream.read()) != -1) {
mBytesParsed++;
if (mEndMarkerRead) {
// There should be no more data after the EOI marker, just in case there is lets
// bail out instead of trying to parse the unknown data
mParserState = NOT_A_JPEG;
mEndMarkerRead = false;
return false;
}
switch (mParserState) {
case READ_FIRST_JPEG_BYTE:
if (nextByte == JfifUtil.MARKER_FIRST_BYTE) {
mParserState = READ_SECOND_JPEG_BYTE;
} else {
mParserState = NOT_A_JPEG;
}
break;
case READ_SECOND_JPEG_BYTE:
if (nextByte == JfifUtil.MARKER_SOI) {
mParserState = READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA;
} else {
mParserState = NOT_A_JPEG;
}
break;
case READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA:
if (nextByte == JfifUtil.MARKER_FIRST_BYTE) {
mParserState = READ_MARKER_SECOND_BYTE;
}
break;
case READ_MARKER_SECOND_BYTE:
if (nextByte == JfifUtil.MARKER_FIRST_BYTE) {
mParserState = READ_MARKER_SECOND_BYTE;
} else if (nextByte == JfifUtil.MARKER_ESCAPE_BYTE) {
mParserState = READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA;
} else if (nextByte == JfifUtil.MARKER_EOI) {
mEndMarkerRead = true;
newScanOrImageEndFound(mBytesParsed - 2);
// There should be no data after the EOI marker, but in case there is, let's process
// the next byte as a first marker byte.
mParserState = READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA;
} else {
if (nextByte == JfifUtil.MARKER_SOS) {
newScanOrImageEndFound(mBytesParsed - 2);
}
if (doesMarkerStartSegment(nextByte)) {
mParserState = READ_SIZE_FIRST_BYTE;
} else {
mParserState = READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA;
}
}
break;
case READ_SIZE_FIRST_BYTE:
mParserState = READ_SIZE_SECOND_BYTE;
break;
case READ_SIZE_SECOND_BYTE:
final int size = (mLastByteRead << 8) + nextByte;
// We need to jump after the end of the segment - skip size-2 next bytes.
// We might want to skip more data than is available to read, in which case we will
// consume entire data in inputStream and exit this function before entering another
// iteration of the loop.
final int bytesToSkip = size - 2;
StreamUtil.skip(inputStream, bytesToSkip);
mBytesParsed += bytesToSkip;
mParserState = READ_MARKER_FIRST_BYTE_OR_ENTROPY_DATA;
break;
case NOT_A_JPEG:
default:
Preconditions.checkState(false);
}
mLastByteRead = nextByte;
}
} catch (IOException ioe) {
// does not happen, input stream returned by pooled byte buffer does not throw IOExceptions
Throwables.propagate(ioe);
}
return mParserState != NOT_A_JPEG && mBestScanNumber != oldBestScanNumber;
}