All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.mat.parser.io.BufferedRandomAccessInputStream Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * 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;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy