/* * Copyright (C) 2014 Indeed Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package com.indeed.imhotep.io; import com.google.common.io.ByteStreams; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; /** * @author jsgroth */ public final class SubInputStream extends InputStream { private static final int INITIAL_BUFFER_SIZE = 65536; private final InputStream is; private byte[] bytes; private int currentIndex; private int currentBlockSize; private boolean done; public SubInputStream(InputStream is) { this.is = is; bytes = new byte[INITIAL_BUFFER_SIZE]; } @Override public int read() throws IOException { if (done) return -1; if (currentIndex == currentBlockSize) { currentBlockSize = Streams.readInt(is); currentIndex = 0; if (currentBlockSize == -1) { throw new EOFException("unexpected end of stream"); } else if (currentBlockSize == 0) { done = true; return -1; } if (bytes.length < currentBlockSize) { bytes = new byte[Math.max(currentBlockSize, bytes.length*2)]; } ByteStreams.readFully(is, bytes, 0, currentBlockSize); } return bytes[currentIndex++] & 0xFF; } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @Override public int read(byte[] b, int off, int len) throws IOException { if (done) return -1; int count = 0; while (len > 0) { int x = read(); if (x == -1) { return count; } b[off++] = (byte)x; --len; ++count; } return count; } }