All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.kolibrifx.plovercrest.server.internal.protocol.SizeLimitedByteBufferReader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010-2017, KolibriFX AS. Licensed under the Apache License, version 2.0.
 */

package com.kolibrifx.plovercrest.server.internal.protocol;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;

/**
 * A helper class for reading a limited amount of data from an underlying channel into a
 * {@link ByteBuffer}. The buffer can have a smaller capacity than the total amount of data, but not
 * smaller than the size passed to {@link #readSlice(int)}. Slices returned are invalidated by the
 * next read* call.
 * 

* While the reader is in use, the underlying {@link ByteBuffer} should not be accessed directly. */ public class SizeLimitedByteBufferReader { private final ByteBuffer buffer; private final ReadableByteChannel channel; private int unreadByteCount; public SizeLimitedByteBufferReader(final ByteBuffer buffer, final int totalSize, final ReadableByteChannel channel) { this.buffer = buffer; this.channel = channel; this.unreadByteCount = totalSize; // initialize the buffer so that the first read call should trigger readAsMuchAsPossible() buffer.position(0); buffer.limit(0); } private void readAsMuchAsPossible() throws IOException, EndOfStreamDuringRead { final int remainingCapacity = buffer.capacity() - buffer.position(); final int bytesToRead = Math.min(remainingCapacity, unreadByteCount); buffer.limit(buffer.position() + bytesToRead); while (buffer.hasRemaining()) { final int readCount = channel.read(buffer); if (readCount < 0) { throw new EndOfStreamDuringRead(); } assert readCount > 0; // blocking channel guarantee } buffer.flip(); unreadByteCount -= bytesToRead; assert unreadByteCount >= 0; } private void bufferAtLeast(final int byteCount) throws IOException, EndOfStreamDuringRead { if (buffer.remaining() >= byteCount) { return; } if (byteCount > remaining()) { throw new ProtocolError("Cannot buffer up " + byteCount + " bytes, buffer.remaining()=" + buffer.remaining() + " remainingToRead=" + unreadByteCount); } buffer.compact(); readAsMuchAsPossible(); // The following should only happen if byteCount > buffer.capacity() if (buffer.remaining() < byteCount) { throw new ProtocolError("Failed to buffer up " + byteCount + " bytes, remaining after read is " + buffer.remaining()); } } public int readInt() throws IOException, EndOfStreamDuringRead { bufferAtLeast(4); return buffer.getInt(); } public long readLong() throws IOException, EndOfStreamDuringRead { bufferAtLeast(8); return buffer.getLong(); } public ByteBuffer readSlice(final int size) throws IOException, EndOfStreamDuringRead { bufferAtLeast(size); final int oldLimit = buffer.limit(); final int endOfSlice = buffer.position() + size; buffer.limit(endOfSlice); final ByteBuffer slice = buffer.slice(); buffer.limit(oldLimit); buffer.position(endOfSlice); return slice; } public int remaining() { return unreadByteCount + buffer.remaining(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy