
com.bigdata.io.DataInputBuffer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bigdata-core Show documentation
Show all versions of bigdata-core Show documentation
Blazegraph(TM) DB Core Platform. It contains all Blazegraph DB dependencies other than Blueprints.
/**
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;
}
}