org.opendaylight.controller.cluster.io.ChunkedInputStream Maven / Gradle / Ivy
/*
* Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.controller.cluster.io;
import static java.util.Objects.requireNonNull;
import java.io.InputStream;
import java.util.Iterator;
final class ChunkedInputStream extends InputStream {
private final Iterator remainingChunks;
private byte[] currentChunk;
private int currentLimit;
private int currentOffset;
private int available;
ChunkedInputStream(final int size, final Iterator iterator) {
remainingChunks = requireNonNull(iterator);
currentChunk = remainingChunks.next();
currentLimit = currentChunk.length;
available = size;
}
@Override
public int available() {
return available;
}
@Override
public int read() {
if (currentChunk == null) {
return -1;
}
int ret = currentChunk[currentOffset] & 0xff;
consumeBytes(1);
return ret;
}
@Override
@SuppressWarnings("checkstyle:ParameterName")
public int read(final byte[] b) {
return read(b, 0, b.length);
}
@Override
@SuppressWarnings("checkstyle:ParameterName")
public int read(final byte[] b, final int off, final int len) {
if (len < 0) {
throw new IndexOutOfBoundsException();
}
if (currentChunk == null) {
return -1;
}
final int result = Math.min(available, len);
int toOffset = off;
int toCopy = result;
while (toCopy != 0) {
final int count = currentBytes(toCopy);
System.arraycopy(currentChunk, currentOffset, b, toOffset, count);
consumeBytes(count);
toOffset += count;
toCopy -= count;
}
return result;
}
@Override
@SuppressWarnings("checkstyle:ParameterName")
public long skip(final long n) {
final int result = (int) Math.min(available, n);
int toSkip = result;
while (toSkip != 0) {
final int count = currentBytes(toSkip);
consumeBytes(count);
toSkip -= count;
}
return result;
}
private int currentBytes(final int desired) {
return Math.min(desired, currentLimit - currentOffset);
}
private void consumeBytes(final int count) {
currentOffset += count;
available -= count;
if (currentOffset == currentLimit) {
if (remainingChunks.hasNext()) {
currentChunk = remainingChunks.next();
currentLimit = currentChunk.length;
} else {
currentChunk = null;
currentLimit = 0;
}
currentOffset = 0;
}
}
}