Path: blob/master/debugtools/DDR_VM/src/com/ibm/j9ddr/libraries/SlidingImageInputStream.java
6005 views
/*******************************************************************************1* Copyright (c) 1991, 2014 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122package com.ibm.j9ddr.libraries;2324//sliding image input stream to present a portion of a file as a complete file in itself2526import java.io.File;27import java.io.IOException;2829import javax.imageio.stream.FileImageInputStream;30import javax.imageio.stream.ImageInputStream;31import javax.imageio.stream.ImageInputStreamImpl;3233public class SlidingImageInputStream extends ImageInputStreamImpl {34private final ImageInputStream stream;35private long length;36private long start;37private final static int BUFFER_SIZE = 4096;38private final byte[] buffer = new byte[BUFFER_SIZE];39private int bytesAvailable = 0;40private boolean EOF = false;41private int bufferPos = 0;42private long bytesRead = 0;43private boolean hasBufferRefreshed = false;44private long markBytesRead = 0;45private long markFilePos = 0;46private long bufferStartPos = 0;4748public SlidingImageInputStream(File raf, long start, long length) throws IOException {49stream = new FileImageInputStream(raf);50init(start, length);51}5253public SlidingImageInputStream(ImageInputStream iis, long start, long length) throws IOException {54stream = iis;55init(start, length);56}5758private void init(long start, long length) throws IOException {59stream.seek(start);60checkBuffer();61this.length = length;62this.start = start;63markFilePos = stream.getStreamPosition();64}6566@Override67public int read() throws IOException {68if(EOF) return -1; //end of file69if(bytesRead == length) {70EOF = true;71return -1;72}73checkBuffer();74bytesRead++;75return 0xFF & buffer[bufferPos++]; //return and increment buffer pointer76}7778@Override79public int read(byte[] b, int off, int len) throws IOException {80if(EOF) return -1; //end of file already set81if(bytesRead == length) { //sliding window over the file is exhausted so treat as EOF82EOF = true;83return -1;84}85if((len + off) > b.length) { //check that destination array is big enough86String msg = String.format("The array is too small to copy %d bytes starting at offset %d", len, off);87throw new IndexOutOfBoundsException(msg);88}89if(len < (bytesAvailable - bufferPos)) { //this request can be satisfied entirely from the buffer90int tocopy = (int) Math.min(len, length - bytesRead); //see which is smaller, amount requested or amount left in window91System.arraycopy(buffer, bufferPos, b, off, tocopy);92bufferPos += tocopy;93bytesRead += tocopy;94return tocopy;95}96//this request needs to be satisfied from one or more buffer fills97int copiedBytes = 0;98while(!EOF && (copiedBytes < len) && (bytesRead < length)){99int tocopy = (int) Math.min(bytesAvailable - bufferPos, length - bytesRead); //see which is smaller, amount left in buffer or amount left in window100tocopy = Math.min(tocopy, len - copiedBytes); //then see which is smaller the proposed copy amount or the amount left to fulfill the request101System.arraycopy(buffer, bufferPos, b, copiedBytes, tocopy);102bufferPos += tocopy;103bytesRead += tocopy;104copiedBytes += tocopy;105checkBuffer();106}107return copiedBytes;108}109110private void checkBuffer() throws IOException {111if(bytesAvailable == bufferPos) { //see if need to refill the buffer112bufferStartPos = bytesRead; //the start of this buffer is the number of bytes read113hasBufferRefreshed = true; //indicate that the buffer has been refreshed114bytesAvailable = stream.read(buffer);115if(bytesAvailable == -1) {116EOF = true;117}118bufferPos = 0;119}120}121122@Override123public long length() {124return length;125}126127@Override128public void mark() {129hasBufferRefreshed = false;130markBytesRead = bytesRead;131super.mark();132}133134@Override135public void reset() throws IOException {136super.reset();137long resetCount = bytesRead - markBytesRead; //how many bytes to rewind by138bytesRead -= resetCount; //update the bytes read count with the rewind139if(hasBufferRefreshed) { //cannot reset back within the buffer so we will need to throw away the current contents140bufferPos = 0;141bytesAvailable = 0;142stream.seek(markFilePos - resetCount); //reset underlying stream position143} else {144bufferPos -= resetCount; //reset within the buffer145}146}147148@Override149public void seek(long pos) throws IOException {150if((pos < bufferStartPos) || (pos >= (bufferStartPos + BUFFER_SIZE))) { //move outside of the current buffer151stream.seek(start + pos); //move the underlying stream152bufferPos = 0; //throw away the current buffer contents153bytesAvailable = 0;154bytesRead = pos;155checkBuffer(); //flag the invalidated buffer156super.seek(pos);157} else { //seek within current buffer158int diff = (int)(pos - bufferStartPos); //how far in ?159bytesRead = bufferStartPos + diff;160bufferPos = diff;161}162}163164@Override165public long getStreamPosition() throws IOException {166return bytesRead;167}168169170171}172173174