/*
* 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.processors.hadoop.shuffle.direct;
import java.io.EOFException;
import org.apache.ignite.internal.util.GridUnsafe;
import org.apache.ignite.internal.util.typedef.internal.SB;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import static org.apache.ignite.internal.util.GridUnsafe.BYTE_ARR_OFF;
/**
* Hadoop data input used for direct communication.
*/
public class HadoopDirectDataInput extends InputStream implements DataInput {
/** Data buffer. */
private final byte[] buf;
/** Position. */
private int pos;
/**
* Constructor.
*
* @param buf Buffer.
*/
public HadoopDirectDataInput(byte[] buf) {
this.buf = buf;
}
/** {@inheritDoc} */
@Override public int read() throws IOException {
return (int)readByte() & 0xFF;
}
/** {@inheritDoc} */
@Override public void readFully(@NotNull byte[] b) throws IOException {
readFully(b, 0, b.length);
}
/** {@inheritDoc} */
@Override public void readFully(@NotNull byte[] b, int off, int len) throws IOException {
checkRange(len);
System.arraycopy(buf, pos, b, off, len);
pos += len;
}
/** {@inheritDoc} */
@Override public int skipBytes(int n) throws IOException {
if (n < 0)
throw new IllegalArgumentException();
assert pos <= buf.length;
int toSkip = Math.min(buf.length - pos, n);
pos += toSkip;
return toSkip;
}
/** {@inheritDoc} */
@Override public boolean readBoolean() throws IOException {
return readByte() == 1;
}
/** {@inheritDoc} */
@Override public byte readByte() throws IOException {
checkRange(1);
byte res = GridUnsafe.getByte(buf, BYTE_ARR_OFF + pos);
pos += 1;
return res;
}
/** {@inheritDoc} */
@Override public int readUnsignedByte() throws IOException {
return readByte() & 0xff;
}
/** {@inheritDoc} */
@Override public short readShort() throws IOException {
checkRange(2);
short res = GridUnsafe.getShort(buf, BYTE_ARR_OFF + pos);
pos += 2;
return res;
}
/** {@inheritDoc} */
@Override public int readUnsignedShort() throws IOException {
return readShort() & 0xffff;
}
/** {@inheritDoc} */
@Override public char readChar() throws IOException {
checkRange(2);
char res = GridUnsafe.getChar(buf, BYTE_ARR_OFF + pos);
pos += 2;
return res;
}
/** {@inheritDoc} */
@Override public int readInt() throws IOException {
checkRange(4);
int res = GridUnsafe.getInt(buf, BYTE_ARR_OFF + pos);
pos += 4;
return res;
}
/** {@inheritDoc} */
@Override public long readLong() throws IOException {
checkRange(8);
long res = GridUnsafe.getLong(buf, BYTE_ARR_OFF + pos);
pos += 8;
return res;
}
/** {@inheritDoc} */
@Override public float readFloat() throws IOException {
checkRange(4);
float res = GridUnsafe.getFloat(buf, BYTE_ARR_OFF + pos);
pos += 4;
return res;
}
/** {@inheritDoc} */
@Override public double readDouble() throws IOException {
checkRange(8);
double res = GridUnsafe.getDouble(buf, BYTE_ARR_OFF + pos);
pos += 8;
return res;
}
/** {@inheritDoc} */
@Override public String readLine() throws IOException {
if (pos == buf.length)
return null;
SB sb = new SB();
while (pos < buf.length) {
char c = (char)readByte();
switch (c) {
case '\n':
return sb.toString();
case '\r':
if (pos == buf.length)
return sb.toString();
c = (char)readByte();
if (c == '\n')
return sb.toString();
else
pos--;
return sb.toString();
default:
sb.a(c);
}
}
return sb.toString();
}
/** {@inheritDoc} */
@NotNull @Override public String readUTF() throws IOException {
byte[] bytes = new byte[readShort()];
if (bytes.length != 0)
readFully(bytes);
return new String(bytes, StandardCharsets.UTF_8);
}
/**
* Ensures the position is still within the buffer.
*
* @throws EOFException if an attempt is made to read beyond the buffer end.
*/
private void checkRange(int bytesToRead) throws EOFException {
assert bytesToRead > 0;
if (pos + bytesToRead - 1 >= buf.length)
throw new EOFException("Attempt to read beyond the end of buffer: " + (pos + bytesToRead - 1)
+ " >= " + buf.length);
}
}