org.eclipse.mat.parser.io.BufferedRandomAccessInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of haha Show documentation
Show all versions of haha Show documentation
Java library to automate the analysis of Android heap dumps.
/**
* ****************************************************************************
* Copyright (c) 2008 SAP AG.
* 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
*
* Contributors:
* SAP AG - initial API and implementation
* *****************************************************************************
*/
package org.eclipse.mat.parser.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.lang.ref.SoftReference;
import org.eclipse.mat.collect.HashMapLongObject;
public class BufferedRandomAccessInputStream extends InputStream {
RandomAccessFile raf;
private class Page {
long real_pos_start;
byte[] buffer;
int buf_end;
public Page() {
buffer = new byte[bufsize];
}
}
int bufsize;
long fileLength;
long real_pos;
long reported_pos;
HashMapLongObject> pages = new HashMapLongObject>();
Page current;
public BufferedRandomAccessInputStream(RandomAccessFile in) throws IOException {
this(in, 1024);
}
public BufferedRandomAccessInputStream(RandomAccessFile in, int bufsize) throws IOException {
this.bufsize = bufsize;
this.raf = in;
this.fileLength = in.length();
}
public final int read() throws IOException {
if (reported_pos == fileLength) return -1;
if (current == null || (reported_pos - current.real_pos_start) >= current.buf_end) {
current = getPage(reported_pos);
}
return current.buffer[((int) (reported_pos++ - current.real_pos_start))] & 0xff;
}
@Override public int read(byte[] b, int off, int len) throws IOException {
if (b == null) {
throw new NullPointerException();
} else if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off
+ len) < 0)) {
throw new IndexOutOfBoundsException();
} else if (len == 0) {
return 0;
}
if (reported_pos == fileLength) return -1;
int copied = 0;
while (copied < len) {
if (reported_pos == fileLength) return copied;
if (current == null || (reported_pos - current.real_pos_start) >= current.buf_end) {
current = getPage(reported_pos);
}
int buf_pos = (int) (reported_pos - current.real_pos_start);
int length = Math.min(len - copied, current.buf_end - buf_pos);
System.arraycopy(current.buffer, buf_pos, b, off + copied, length);
reported_pos += length;
copied += length;
}
return copied;
}
private Page getPage(long pos) throws IOException {
long key = pos / bufsize;
SoftReference r = pages.get(key);
Page p = r == null ? null : r.get();
if (p != null) return p;
long page_start = key * bufsize;
if (page_start != real_pos) {
raf.seek(page_start);
real_pos = page_start;
}
p = new Page();
int n = raf.read(p.buffer);
if (n >= 0) {
p.real_pos_start = real_pos;
p.buf_end = n;
real_pos += n;
}
pages.put(key, new SoftReference(p));
return p;
}
public boolean markSupported() {
return false;
}
public void close() throws IOException {
raf.close();
}
/**
* @throws IOException
*/
public void seek(long pos) throws IOException {
reported_pos = pos;
current = null;
}
public long getFilePointer() {
return reported_pos;
}
}