| /* |
| * 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); |
| } |