/** * Skips a set amount of bytes such that reading can be stopped and started again later if not * enough bytes are available. * * <p>Returns {@link #READ_RESULT_CONTINUE} if all bytes have been skipped. Reset {@link * #bytesState} to {@code 0} before calling to indicate a new set of bytes should be skipped. * * @param inputStream The input stream from which bytes should be skipped * @param totalBytes The total size of bytes to be skipped * @return One of the {@code RESULT_*} flags defined in this class */ private int skipBytesInternal(NonBlockingInputStream inputStream, int totalBytes) { if (bytesState >= totalBytes) { return READ_RESULT_CONTINUE; } int remainingBytes = totalBytes - bytesState; int additionalBytesRead = inputStream.skip(remainingBytes); return updateBytesState(additionalBytesRead, totalBytes); }
/** * Reads a set amount of bytes into a {@link ByteBuffer} such that reading can be stopped and * started again later if not enough bytes are available. * * <p>Returns {@link #READ_RESULT_CONTINUE} if all bytes have been read. Reset {@link #bytesState} * to {@code 0} before calling to indicate a new set of bytes should be read. * * @param inputStream The input stream from which bytes should be read * @param byteBuffer The {@link ByteBuffer} into which bytes should be read * @param totalBytes The total size of bytes to be read * @return One of the {@code RESULT_*} flags defined in this class */ private int readBytesInternal( NonBlockingInputStream inputStream, ByteBuffer byteBuffer, int totalBytes) { if (bytesState == STATE_BEGIN_READING && totalBytes > byteBuffer.capacity()) { throw new IllegalArgumentException("Byte buffer not large enough"); } if (bytesState >= totalBytes) { return READ_RESULT_CONTINUE; } int remainingBytes = totalBytes - bytesState; int additionalBytesRead = inputStream.read(byteBuffer, remainingBytes); return updateBytesState(additionalBytesRead, totalBytes); }
/** * Reads a set amount of bytes into a {@code byte[]} such that reading can be stopped and started * again later if not enough bytes are available. * * <p>Returns {@link #READ_RESULT_CONTINUE} if all bytes have been read. Reset {@link #bytesState} * to {@code 0} before calling to indicate a new set of bytes should be read. * * @param inputStream The input stream from which bytes should be read * @param byteArray The {@code byte[]} into which bytes should be read * @param totalBytes The total size of bytes to be read * @return One of the {@code RESULT_*} flags defined in this class */ private int readBytesInternal( NonBlockingInputStream inputStream, byte[] byteArray, int totalBytes) { if (bytesState == STATE_BEGIN_READING && totalBytes > byteArray.length) { throw new IllegalArgumentException("Byte array not large enough"); } if (bytesState >= totalBytes) { return READ_RESULT_CONTINUE; } int remainingBytes = totalBytes - bytesState; int additionalBytesRead = inputStream.read(byteArray, bytesState, remainingBytes); return updateBytesState(additionalBytesRead, totalBytes); }
@Override public int read(NonBlockingInputStream inputStream) throws ParserException { Assertions.checkState(eventHandler != null); while (true) { while (!masterElementsStack.isEmpty() && bytesRead >= masterElementsStack.peek().elementEndOffsetBytes) { eventHandler.onMasterElementEnd(masterElementsStack.pop().elementId); return READ_RESULT_CONTINUE; } if (state == STATE_BEGIN_READING) { int idResult = readElementId(inputStream); if (idResult != READ_RESULT_CONTINUE) { return idResult; } int sizeResult = readElementContentSize(inputStream); if (sizeResult != READ_RESULT_CONTINUE) { return sizeResult; } state = STATE_READ_CONTENTS; bytesState = 0; } int type = eventHandler.getElementType(elementId); switch (type) { case TYPE_MASTER: int masterHeaderSize = (int) (bytesRead - elementOffset); // Header size is 12 bytes max. masterElementsStack.add(new MasterElement(elementId, bytesRead + elementContentSize)); eventHandler.onMasterElementStart( elementId, elementOffset, masterHeaderSize, elementContentSize); prepareForNextElement(); return READ_RESULT_CONTINUE; case TYPE_UNSIGNED_INT: if (elementContentSize > MAX_INTEGER_ELEMENT_SIZE_BYTES) { throw new IllegalStateException("Invalid integer size " + elementContentSize); } int intResult = readBytesInternal(inputStream, tempByteArray, (int) elementContentSize); if (intResult != READ_RESULT_CONTINUE) { return intResult; } long intValue = getTempByteArrayValue((int) elementContentSize, false); eventHandler.onIntegerElement(elementId, intValue); prepareForNextElement(); return READ_RESULT_CONTINUE; case TYPE_FLOAT: if (elementContentSize != VALID_FLOAT32_ELEMENT_SIZE_BYTES && elementContentSize != VALID_FLOAT64_ELEMENT_SIZE_BYTES) { throw new IllegalStateException("Invalid float size " + elementContentSize); } int floatResult = readBytesInternal(inputStream, tempByteArray, (int) elementContentSize); if (floatResult != READ_RESULT_CONTINUE) { return floatResult; } long valueBits = getTempByteArrayValue((int) elementContentSize, false); double floatValue; if (elementContentSize == VALID_FLOAT32_ELEMENT_SIZE_BYTES) { floatValue = Float.intBitsToFloat((int) valueBits); } else { floatValue = Double.longBitsToDouble(valueBits); } eventHandler.onFloatElement(elementId, floatValue); prepareForNextElement(); return READ_RESULT_CONTINUE; case TYPE_STRING: if (elementContentSize > Integer.MAX_VALUE) { throw new IllegalStateException( "String element size " + elementContentSize + " is larger than MAX_INT"); } if (stringBytes == null) { stringBytes = new byte[(int) elementContentSize]; } int stringResult = readBytesInternal(inputStream, stringBytes, (int) elementContentSize); if (stringResult != READ_RESULT_CONTINUE) { return stringResult; } String stringValue = new String(stringBytes, Charset.forName(C.UTF8_NAME)); stringBytes = null; eventHandler.onStringElement(elementId, stringValue); prepareForNextElement(); return READ_RESULT_CONTINUE; case TYPE_BINARY: if (elementContentSize > Integer.MAX_VALUE) { throw new IllegalStateException( "Binary element size " + elementContentSize + " is larger than MAX_INT"); } if (inputStream.getAvailableByteCount() < elementContentSize) { return READ_RESULT_NEED_MORE_DATA; } int binaryHeaderSize = (int) (bytesRead - elementOffset); // Header size is 12 bytes max. boolean consumed = eventHandler.onBinaryElement( elementId, elementOffset, binaryHeaderSize, (int) elementContentSize, inputStream); if (consumed) { long expectedBytesRead = elementOffset + binaryHeaderSize + elementContentSize; if (expectedBytesRead != bytesRead) { throw new IllegalStateException( "Incorrect total bytes read. Expected " + expectedBytesRead + " but actually " + bytesRead); } prepareForNextElement(); } return READ_RESULT_CONTINUE; case TYPE_UNKNOWN: if (elementContentSize > Integer.MAX_VALUE) { throw new IllegalStateException( "Unknown element size " + elementContentSize + " is larger than MAX_INT"); } int skipResult = skipBytesInternal(inputStream, (int) elementContentSize); if (skipResult != READ_RESULT_CONTINUE) { return skipResult; } prepareForNextElement(); break; default: throw new IllegalStateException("Invalid element type " + type); } } }