/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.android.camera; /* * This file derives from the Apache version of the BufferedInputStream. * Mods to support passing in the buffer rather than creating one directly. */ import java.io.InputStream; import java.io.FilterInputStream; import java.io.IOException; public class BufferedInputStream extends FilterInputStream { protected byte[] buf; protected int count; protected int marklimit; protected int markpos = -1; protected int pos; private boolean closed = false; public BufferedInputStream(InputStream in, byte [] buffer) { super(in); buf = buffer; if (buf == null) { throw new java.security.InvalidParameterException(); } } @Override public synchronized int available() throws IOException { return count - pos + in.available(); } @Override public synchronized void close() throws IOException { if (null != in) { super.close(); in = null; } buf = null; closed = true; } private int fillbuf() throws IOException { if (markpos == -1 || (pos - markpos >= marklimit)) { /* Mark position not set or exceeded readlimit */ int result = in.read(buf); if (result > 0) { markpos = -1; pos = 0; count = result == -1 ? 0 : result; } return result; } if (markpos == 0 && marklimit > buf.length) { /* Increase buffer size to accomodate the readlimit */ int newLength = buf.length * 2; if (newLength > marklimit) { newLength = marklimit; } byte[] newbuf = new byte[newLength]; System.arraycopy(buf, 0, newbuf, 0, buf.length); buf = newbuf; } else if (markpos > 0) { System.arraycopy(buf, markpos, buf, 0, buf.length - markpos); } /* Set the new position and mark position */ pos -= markpos; count = markpos = 0; int bytesread = in.read(buf, pos, buf.length - pos); count = bytesread <= 0 ? pos : pos + bytesread; return bytesread; } @Override public synchronized void mark(int readlimit) { marklimit = readlimit; markpos = pos; } @Override public boolean markSupported() { return true; } @Override public synchronized int read() throws IOException { if (in == null) { // K0059=Stream is closed throw new IOException(); //$NON-NLS-1$ } /* Are there buffered bytes available? */ if (pos >= count && fillbuf() == -1) { return -1; /* no, fill buffer */ } /* Did filling the buffer fail with -1 (EOF)? */ if (count - pos > 0) { return buf[pos++] & 0xFF; } return -1; } @Override public synchronized int read(byte[] buffer, int offset, int length) throws IOException { if (closed) { // K0059=Stream is closed throw new IOException(); //$NON-NLS-1$ } // avoid int overflow if (offset > buffer.length - length || offset < 0 || length < 0) { throw new IndexOutOfBoundsException(); } if (length == 0) { return 0; } if (null == buf) { throw new IOException(); //$NON-NLS-1$ } int required; if (pos < count) { /* There are bytes available in the buffer. */ int copylength = count - pos >= length ? length : count - pos; System.arraycopy(buf, pos, buffer, offset, copylength); pos += copylength; if (copylength == length || in.available() == 0) { return copylength; } offset += copylength; required = length - copylength; } else { required = length; } while (true) { int read; /* * If we're not marked and the required size is greater than the * buffer, simply read the bytes directly bypassing the buffer. */ if (markpos == -1 && required >= buf.length) { read = in.read(buffer, offset, required); if (read == -1) { return required == length ? -1 : length - required; } } else { if (fillbuf() == -1) { return required == length ? -1 : length - required; } read = count - pos >= required ? required : count - pos; System.arraycopy(buf, pos, buffer, offset, read); pos += read; } required -= read; if (required == 0) { return length; } if (in.available() == 0) { return length - required; } offset += read; } } @Override public synchronized void reset() throws IOException { if (closed) { // K0059=Stream is closed throw new IOException(); //$NON-NLS-1$ } if (-1 == markpos) { // K005a=Mark has been invalidated. throw new IOException(); //$NON-NLS-1$ } pos = markpos; } @Override public synchronized long skip(long amount) throws IOException { if (null == in) { // K0059=Stream is closed throw new IOException(); //$NON-NLS-1$ } if (amount < 1) { return 0; } if (count - pos >= amount) { pos += amount; return amount; } long read = count - pos; pos = count; if (markpos != -1) { if (amount <= marklimit) { if (fillbuf() == -1) { return read; } if (count - pos >= amount - read) { pos += amount - read; return amount; } // Couldn't get all the bytes, skip what we read read += (count - pos); pos = count; return read; } markpos = -1; } return read + in.skip(amount - read); } }