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

com.bigdata.io.DataInputBuffer Maven / Gradle / Ivy

Go to download

Blazegraph(TM) DB Core Platform. It contains all Blazegraph DB dependencies other than Blueprints.

There is a newer version: 2.1.4
Show newest version
/**

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     licenses@blazegraph.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/*
 * Created on Apr 9, 2007
 */

package com.bigdata.io;

import it.unimi.dsi.fastutil.io.RepositionableStream;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;

/**
 * A fast implementation of DataInput designed to read from a byte[].
 * 
 * @see DataOutputBuffer
 * 
 * @see DataInputStream
 * 
 * @author Bryan Thompson
 * @version $Id$
 */
public class DataInputBuffer extends InputStream implements DataInput,
        RepositionableStream {

    /**
     * The buffer whose contents are being read.
     */
    private byte[] buf;
    
    /**
     * The original value of {@link #off}.
     */
    private int origin;
    
    /**
     * The current offset in the buffer.  This is incremented each time
     * any data is read from the buffer.
     */
    private int off;

    /**
     * The exclusive index of the last byte in the buffer having valid data (up
     * to limit-1 is valid).
     */
    private int limit;

    /**
     * Prepare for reading from the byte[].
     * 
     * @param buf
     *            The source data.
     */
    public DataInputBuffer(final byte[] buf) {

        if (buf == null)
            throw new IllegalArgumentException();

        this.buf = buf;
        
        this.off = this.origin = 0;
        
        this.limit = buf.length;
        
    }
    
    /**
     * Prepare for reading from the byte[].
     * 
     * @param buf
     *            The source data.
     * @param off
     *            The offset of the first byte to be read.
     * @param len
     *            The #of bytes available.
     */
    public DataInputBuffer(final byte[] buf, final int off, final int len) {

        if (buf == null)
            throw new IllegalArgumentException();
        
        assert off >= 0;

        assert len >= 0;
        
        assert off + len <= buf.length;
        
        this.buf = buf;
        
        this.off = this.origin = off;
        
        this.limit = off + len;
        
    }

    /**
     * Prepare for reading from the buffer. The bytes between the
     * {@link ByteArrayBuffer#pos()} and the {@link ByteArrayBuffer#limit()}
     * will be read.
     * 
     * @param buf
     *            The buffer.
     */
    public DataInputBuffer(final ByteArrayBuffer buf) {
        
        if (buf == null)
            throw new IllegalArgumentException();
        
        this.buf = buf.array();
        
        this.off = this.origin = buf.pos;
        
        this.limit = buf.limit;
        
    }
    
    /**
     * Replaces the buffer and resets the offset to zero (0).
     * 
     * @param buf
     *            The new buffer.
     */
    public void setBuffer(final byte[] buf) {

        if (buf == null)
            throw new IllegalArgumentException();

        setBuffer(buf, 0, buf.length);

    }
    
    /**
     * Return the backing buffer.
     */
    public byte[] getBuffer() {
        
        return buf;
        
    }
    
    /**
     * Replaces the buffer and reset the offset and length to the specified
     * values.
     * 
     * @param buf
     *            The new buffer.
     * @param off
     * @param len
     */
    public void setBuffer(final byte[] buf, final int off, final int len) {

        if (buf == null)
            throw new IllegalArgumentException();

        if (off + len > buf.length)
            throw new IllegalArgumentException();

        this.buf = buf;

        this.off = this.origin = off;

        this.limit = off + len;
        
    }
    
    /**
     * Replaces the buffer reference with {@link ByteArrayBuffer#array()} and
     * resets the offset and length to the {@link ByteArrayBuffer#pos()} and the
     * {@link ByteArrayBuffer#limit()} respectively.
     * 
     * @param buf
     *            The buffer.
     */
    public void setBuffer(final ByteArrayBuffer buf) {
        
        if (buf == null)
            throw new IllegalArgumentException();

        setBuffer(buf.array(), buf.pos, buf.limit);
        
    }
    
    /**
     * The origin (original offset) associated with the backing buffer.
     */
    public int getOrigin() {
        
        return origin;
        
    }
    
    /*
     * DataInput
     */
    
    public boolean readBoolean() throws IOException {

        if (off >= limit)
            throw new EOFException();

        return buf[off++] == 0 ? false : true;

    }

    @Override
    public int read() throws IOException {

        if (off >= limit)
            return -1; // EOF
        
        return 0xff & buf[off++];
        
    }
    
    public byte readByte() throws IOException {

        if (off >= limit)
            throw new EOFException();
        
        return buf[off++];
        
    }

    public char readChar() throws IOException {

        if (off + 2 > limit)
            throw new EOFException();

        final int ch1 = buf[off++];

        final int ch2 = buf[off++];
        
        return (char) ((ch1 << 8) + (ch2 << 0));
        
    }

    public double readDouble() throws IOException {

        return Double.longBitsToDouble(readLong());

    }

    public float readFloat() throws IOException {

        return Float.intBitsToFloat(readInt());
        
    }

    final public void readFully(final byte[] b) throws IOException {

        readFully(b, 0, b.length);
        
    }

    final public void readFully(final byte[] a, final int aoff, final int alen)
            throws IOException {

        if (this.off + alen > this.limit)
            throw new EOFException();
        
        System.arraycopy(buf/* src */, this.off/* srcPos */, a/* dest */,
                aoff/* destPos */, alen/* len */);
        
        this.off += alen;
        
    }

    /**
     * Overridden for more efficiency.
     */
    final public int read(final byte[] a, final int aoff, final int alen)
            throws IOException {

        if (alen == 0) {

            // Read request length is zero, so return 0 (per API).
            return 0;

        }
        
        final int remaining = limit - off;

        if (remaining == 0) {

            // EOF (per API).
            return -1;
        
        }

        // #of bytes to read.
        final int n = remaining < alen ? remaining : alen;

        System.arraycopy(buf/* src */, this.off/* srcPos */, a/* dest */,
                aoff/* destPos */, n/* len */);

        this.off += n;

        return n;

    }

    public int readInt() throws IOException {

        if (off + 4 > limit)
            throw new EOFException();
        
        int v = 0;
        
        // big-endian.
        v += (0xff & buf[off++]) << 24;
        v += (0xff & buf[off++]) << 16;
        v += (0xff & buf[off++]) <<  8;
        v += (0xff & buf[off++]) <<  0;
        
        return v;

    }

    public String readLine() throws IOException {
        
        throw new UnsupportedOperationException();
        
    }

    public long readLong() throws IOException {

        if (off + 8 > limit)
            throw new EOFException();

        long v = 0L;

        // big-endian.
        v += (0xffL & buf[off++]) << 56;
        v += (0xffL & buf[off++]) << 48;
        v += (0xffL & buf[off++]) << 40;
        v += (0xffL & buf[off++]) << 32;
        v += (0xffL & buf[off++]) << 24;
        v += (0xffL & buf[off++]) << 16;
        v += (0xffL & buf[off++]) <<  8;
        v += (0xffL & buf[off++]) <<  0;
        
        return v;
 
    }

    public short readShort() throws IOException {
        
        if (off + 2 > limit)
            throw new EOFException();

        final int ch1 = buf[off++];

        final int ch2 = buf[off++];
        
        return (short) ((ch1 << 8) + (ch2 << 0));
        
    }

    public String readUTF() throws IOException {

        return DataInputStream.readUTF(this);
        
    }

    /**
     * Variant of {@link #readUTF()} which wraps the {@link IOException}.
     */
    public String readUTF2() {

        try {

            return DataInputStream.readUTF(this);

        } catch (IOException e) {

            throw new RuntimeException(e);

        }
        
    }

    public int readUnsignedByte() throws IOException {
        
        if (off >= limit)
            throw new EOFException();
        
        return buf[off++];
        
    }

    public int readUnsignedShort() throws IOException {

        if (off + 2 > limit)
            throw new EOFException();

        int a = buf[off++];

        int b = buf[off++];
        
        return (((a & 0xff) << 8) | (b & 0xff));

//        return ((ch1 << 8) + (ch2 << 0));
        
    }

    public int skipBytes(final int n) throws IOException {

        off += n;

        if (off > limit)
            throw new IOException();

        return n;
        
    }

    /*
     * unpack unsigned long integer.
     */

    /**
     * Convenience method unpacks long and throws an exception if the value
     * exceeds {@link Integer#MAX_VALUE}.
     * 
     * @return The integer value.
     * 
     * @throws IOException
     */
    final public int unpackInt() throws IOException {
        
        final long v = unpackLong();

        if (v > Integer.MAX_VALUE)
            throw new IOException();

        return (int) v;

    }

    /**
     * Unpack a long value from the current buffer position.
     * 
     * @return The long value.
     * 
     * @throws IOException
     */
    final public long unpackLong() throws IOException {
        if (off + 1 > limit)
            throw new EOFException();
        int b = buf[off++];
        int nbytes;
        long l;
        if ((b & 0x80) != 0) {
            // high bit is set.
            nbytes = 8; // use 8 bytes (this one plus the next 7).
            l = b & 0x7f; // clear the high bit - the rest of the byte is the
                            // start value.
        } else {
            // high bit is clear.
            nbytes = b >> 4; // nbytes is the upper nibble. (right shift one
                                // nibble).
            l = b & 0x0f; // starting value is lower nibble (clear the upper
                            // nibble).
        }
        if (off + nbytes - 1 > limit)
            throw new EOFException();
        for (int i = 1; i < nbytes; i++) {
            // Read the next byte.
            b = buf[off++];
            // Shift the existing value one byte left and add into the low
            // (unsigned) byte.
            l = (l << 8) + (0xff & b);
        }
        return l;
    }

    /*
     * unpack unsigned short integer.
     */
    
    /**
     * Unpack a non-negative short value from the input stream.
     * 
     * @param is
     *            The input stream.
     * 
     * @return The short value.
     * 
     * @throws IOException
     */
    final public short unpackShort() throws IOException {
        if (off + 1 > limit)
            throw new EOFException();
        short b = (short) buf[off++];
        short v;
        if ((b & 0x80) != 0) { // high bit is set.
            /*
             * clear the high bit and shift over one byte.
             */
            v = (short) ((b & 0x7f) << 8);
            if (off + 1 > limit)
                throw new EOFException();
            b = buf[off++]; // read the next byte.
            v |= (b & 0xff); // and combine it together with the high byte.
        } else {
            // high bit is clear.
            v = b; // interpret the byte as a short value.
        }
        return (short) v;
    }

    /*
     * RepositionableStream.
     * 
     * Note: This interface allows us to use InputBitStream and reset the
     * position to zero (0L) so that we can reuse the buffer, e.g., to serialize
     * nodes in the B+Tree.
     */

    /**
     * Report the position of the stream within its slice (relative to the
     * original offset for the backing buffer)
     */
    public long position() throws IOException {

        return off - origin;

    }

    /**
     * Reposition the stream within its slice (relative to the original offset
     * for the backing buffer).
     */
    public void position(final long v) throws IOException {

//        if (v < origin || v > limit) {
//
//            throw new IOException();
//
//        }

        this.off = origin + (int) Math.min(v, limit);// origin + (int) v;

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy