blob: 46aa03da2c7b620fb77da759d9a89c0cf41c9711 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.binary.streams;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.internal.util.GridUnsafe;
import static org.apache.ignite.internal.util.GridUnsafe.BIG_ENDIAN;
/**
* Binary abstract input stream.
*/
public abstract class BinaryAbstractInputStream extends BinaryAbstractStream
implements BinaryInputStream {
/** Length of data inside array. */
protected int len;
/** {@inheritDoc} */
@Override public byte readByte() {
ensureEnoughData(1);
return readByteAndShift();
}
/** {@inheritDoc} */
@Override public byte[] readByteArray(int cnt) {
ensureEnoughData(cnt);
byte[] res = new byte[cnt];
copyAndShift(res, GridUnsafe.BYTE_ARR_OFF, cnt);
return res;
}
/** {@inheritDoc} */
@Override public boolean readBoolean() {
return readByte() == BYTE_ONE;
}
/** {@inheritDoc} */
@Override public boolean[] readBooleanArray(int cnt) {
ensureEnoughData(cnt);
boolean[] res = new boolean[cnt];
copyAndShift(res, GridUnsafe.BOOLEAN_ARR_OFF, cnt);
return res;
}
/** {@inheritDoc} */
@Override public short readShort() {
ensureEnoughData(2);
short res = readShortFast();
shift(2);
return res;
}
/** {@inheritDoc} */
@Override public short[] readShortArray(int cnt) {
int len = cnt << 1;
ensureEnoughData(len);
short[] res = new short[cnt];
copyAndShift(res, GridUnsafe.SHORT_ARR_OFF, len);
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++)
res[i] = Short.reverseBytes(res[i]);
}
return res;
}
/** {@inheritDoc} */
@Override public char readChar() {
ensureEnoughData(2);
char res = readCharFast();
shift(2);
return res;
}
/** {@inheritDoc} */
@Override public char[] readCharArray(int cnt) {
int len = cnt << 1;
ensureEnoughData(len);
char[] res = new char[cnt];
copyAndShift(res, GridUnsafe.CHAR_ARR_OFF, len);
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++)
res[i] = Character.reverseBytes(res[i]);
}
return res;
}
/** {@inheritDoc} */
@Override public int readInt() {
ensureEnoughData(4);
int res = readIntFast();
shift(4);
return res;
}
/** {@inheritDoc} */
@Override public int[] readIntArray(int cnt) {
int len = cnt << 2;
ensureEnoughData(len);
int[] res = new int[cnt];
copyAndShift(res, GridUnsafe.INT_ARR_OFF, len);
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++)
res[i] = Integer.reverseBytes(res[i]);
}
return res;
}
/** {@inheritDoc} */
@Override public byte readBytePositioned(int pos) {
int delta = pos + 1 - this.pos;
if (delta > 0)
ensureEnoughData(delta);
return readBytePositioned0(pos);
}
/** {@inheritDoc} */
@Override public short readShortPositioned(int pos) {
int delta = pos + 2 - this.pos;
if (delta > 0)
ensureEnoughData(delta);
return readShortPositioned0(pos);
}
/** {@inheritDoc} */
@Override public int readIntPositioned(int pos) {
int delta = pos + 4 - this.pos;
if (delta > 0)
ensureEnoughData(delta);
return readIntPositioned0(pos);
}
/** {@inheritDoc} */
@Override public float readFloat() {
return Float.intBitsToFloat(readInt());
}
/** {@inheritDoc} */
@Override public float[] readFloatArray(int cnt) {
int len = cnt << 2;
ensureEnoughData(len);
float[] res = new float[cnt];
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++) {
int x = readIntFast();
shift(4);
res[i] = Float.intBitsToFloat(x);
}
}
else
copyAndShift(res, GridUnsafe.FLOAT_ARR_OFF, len);
return res;
}
/** {@inheritDoc} */
@Override public long readLong() {
ensureEnoughData(8);
long res = readLongFast();
shift(8);
return res;
}
/** {@inheritDoc} */
@Override public long[] readLongArray(int cnt) {
int len = cnt << 3;
ensureEnoughData(len);
long[] res = new long[cnt];
copyAndShift(res, GridUnsafe.LONG_ARR_OFF, len);
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++)
res[i] = Long.reverseBytes(res[i]);
}
return res;
}
/** {@inheritDoc} */
@Override public double readDouble() {
return Double.longBitsToDouble(readLong());
}
/** {@inheritDoc} */
@Override public double[] readDoubleArray(int cnt) {
int len = cnt << 3;
ensureEnoughData(len);
double[] res = new double[cnt];
if (BIG_ENDIAN) {
for (int i = 0; i < res.length; i++) {
long x = readLongFast();
shift(8);
res[i] = Double.longBitsToDouble(x);
}
}
else
copyAndShift(res, GridUnsafe.DOUBLE_ARR_OFF, len);
return res;
}
/** {@inheritDoc} */
@Override public int read(byte[] arr, int off, int len) {
if (len > remaining())
len = remaining();
copyAndShift(arr, GridUnsafe.BYTE_ARR_OFF + off, len);
return len;
}
/** {@inheritDoc} */
@Override public void position(int pos) {
if (remaining() + this.pos < pos)
throw new BinaryObjectException("Position is out of bounds: " + pos);
else
this.pos = pos;
}
/** {@inheritDoc} */
@Override public long offheapPointer() {
return 0;
}
/** {@inheritDoc} */
@Override public long rawOffheapPointer() {
return 0;
}
/**
* Ensure that there is enough data.
*
* @param cnt Length.
*/
protected void ensureEnoughData(int cnt) {
if (remaining() < cnt)
throw new BinaryObjectException("Not enough data to read the value [position=" + pos +
", requiredBytes=" + cnt + ", remainingBytes=" + remaining() + ']');
}
/**
* Read next byte from the stream and perform shift.
*
* @return Next byte.
*/
protected abstract byte readByteAndShift();
/**
* Copy data to target object shift position afterwards.
*
* @param target Target.
* @param off Offset.
* @param len Length.
*/
protected abstract void copyAndShift(Object target, long off, int len);
/**
* Read short value (fast path).
*
* @return Short value.
*/
protected abstract short readShortFast();
/**
* Read char value (fast path).
*
* @return Char value.
*/
protected abstract char readCharFast();
/**
* Read int value (fast path).
*
* @return Int value.
*/
protected abstract int readIntFast();
/**
* Read long value (fast path).
*
* @return Long value.
*/
protected abstract long readLongFast();
/**
* Internal routine for positioned byte value read.
*
* @param pos Position.
* @return Int value.
*/
protected abstract byte readBytePositioned0(int pos);
/**
* Internal routine for positioned short value read.
*
* @param pos Position.
* @return Int value.
*/
protected abstract short readShortPositioned0(int pos);
/**
* Internal routine for positioned int value read.
*
* @param pos Position.
* @return Int value.
*/
protected abstract int readIntPositioned0(int pos);
}