/*
* Copyright 2015 the original author or authors.
* @https://github.com/scouter-project/scouter
*
* Licensed 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 scouter.io;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import scouter.lang.pack.MapPack;
import scouter.lang.pack.Pack;
import scouter.lang.pack.PackEnum;
import scouter.lang.step.Step;
import scouter.lang.step.StepEnum;
import scouter.lang.value.Value;
import scouter.lang.value.ValueEnum;
public class DataInputX {
private int offset;
private DataInput inner;
private DataInputStream din;
public DataInputX(byte[] buff) {
this(new ByteArrayInputStream(buff));
}
public DataInputX(byte[] buff, int offset) {
this(new ByteArrayInputStream(buff, offset, buff.length - offset));
}
public DataInputX(ByteArrayInputStream in) {
this(new DataInputStream(in));
}
public DataInputX(BufferedInputStream in) {
this.din = new DataInputStream(in);
this.inner = this.din;
}
public DataInputX(DataInputStream in) {
this.inner = in;
this.din = in;
}
public DataInputX(RandomAccessFile in) {
this.inner = in;
}
public byte[] readIntBytes() throws IOException {
int len = readInt();
return read(len);
}
public byte[] read(int len) throws IOException {
offset += len;
byte[] buff = new byte[len];
this.inner.readFully(buff);
return buff;
}
public byte[] readShortBytes() throws IOException {
int len = readUnsignedShort();
offset += len;
byte[] buff = new byte[len];
this.inner.readFully(buff);
return buff;
}
public byte[] readBlob() throws IOException {
int baselen = readUnsignedByte();
switch (baselen) {
case 255: {
int len = readUnsignedShort();
byte[] buffer = read(len);
return buffer;
}
case 254: {
int len = this.readInt();
byte[] buffer = read(len);
return buffer;
}
case 0: {
return new byte[0];
}
default:
byte[] buffer = read(baselen);
return buffer;
}
}
public int readInt3() throws IOException {
byte[] readBuffer = read(3);
return toInt3(readBuffer, 0);
}
public long readLong5() throws IOException {
byte[] readBuffer =read(5);
return toLong5(readBuffer, 0);
}
public long readDecimal() throws IOException {
byte len = readByte();
switch (len) {
case 0:
return 0;
case 1:
return readByte();
case 2:
return readShort();
case 3:
return readInt3();
case 4:
return readInt();
case 5:
return readLong5();
default:
return readLong();
}
}
public String readText() throws IOException {
byte[] buffer = readBlob();
return new String(buffer, "UTF8");
}
public static boolean toBoolean(byte[] buf, int pos) {
return buf[pos]!=0;
}
public static short toShort(byte[] buf, int pos) {
int ch1 = buf[pos] & 0xff;
int ch2 = buf[pos + 1] & 0xff;
return (short) ((ch1 << 8) + (ch2 << 0));
}
public static int toInt3(byte[] buf, int pos) {
int ch1 = buf[pos] & 0xff;
int ch2 = buf[pos + 1] & 0xff;
int ch3 = buf[pos + 2] & 0xff;
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8)) >> 8;
}
public static int toInt(byte[] buf, int pos) {
int ch1 = buf[pos] & 0xff;
int ch2 = buf[pos + 1] & 0xff;
int ch3 = buf[pos + 2] & 0xff;
int ch4 = buf[pos + 3] & 0xff;
return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
}
public static long toLong(byte[] buf, int pos) {
return (((long) buf[pos] << 56)//
+ ((long) (buf[pos + 1] & 255) << 48) //
+ ((long) (buf[pos + 2] & 255) << 40) //
+ ((long) (buf[pos + 3] & 255) << 32) //
+ ((long) (buf[pos + 4] & 255) << 24) + ((buf[pos + 5] & 255) << 16) //
+ ((buf[pos + 6] & 255) << 8) //
+ ((buf[pos + 7] & 255) << 0));
}
public static long toLong5(byte[] buf, int pos) {
return (((long) buf[pos] << 32) + //
((long) (buf[pos + 1] & 255) << 24) + //
((buf[pos + 2] & 255) << 16) + //
((buf[pos + 3] & 255) << 8) + //
((buf[pos + 4] & 255) << 0));
}
public static float toFloat(byte[] buf, int pos) {
return Float.intBitsToFloat(toInt(buf, pos));
}
public static double toDouble(byte[] buf, int pos) {
return Double.longBitsToDouble(toLong(buf, pos));
}
public static byte[] get(byte[] buf, int pos, int length) {
byte[] out = new byte[length];
System.arraycopy(buf, pos, out, 0, length);
return out;
}
public int[] readDecimalArray(int[] data) throws IOException {
int length = (int) readDecimal();
data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = (int) readDecimal();
}
return data;
}
public long[] readDecimalArray() throws IOException {
int length = (int) readDecimal();
long[] data = new long[length];
for (int i = 0; i < length; i++) {
data[i] = readDecimal();
}
return data;
}
public long[] readArray() throws IOException {
return readArray(new long[0]);
}
public long[] readArray(long[] data) throws IOException {
int length = readShort();
data = new long[length];
for (int i = 0; i < length; i++) {
data[i] = readLong();
}
return data;
}
public int[] readArray(int[] data) throws IOException {
int length = readShort();
data = new int[length];
for (int i = 0; i < length; i++) {
data[i] = readInt();
}
return data;
}
public float[] readArray(float[] data) throws IOException {
int length = readShort();
data = new float[length];
for (int i = 0; i < length; i++) {
data[i] = readFloat();
}
return data;
}
public Value readValue() throws IOException {
this.offset++;
byte type = this.inner.readByte();
return ValueEnum.create(type).read(this);
}
public Step readStep() throws IOException {
this.offset++;
byte type = this.inner.readByte();
return StepEnum.create(type).read(this);
}
public Pack readPack() throws IOException {
this.offset++;
byte type = this.inner.readByte();
return PackEnum.create(type).read(this);
}
public MapPack readMapPack() throws IOException {
return (MapPack)readPack();
}
public void readFully(byte[] b) throws IOException {
this.offset += b.length;
this.inner.readFully(b);
}
public void readFully(byte[] b, int off, int len) throws IOException {
this.offset += len;
this.inner.readFully(b, off, len);
}
public int skipBytes(int n) throws IOException {
this.offset += n;
return this.inner.skipBytes(n);
}
public boolean readBoolean() throws IOException {
this.offset += 1;
return this.inner.readBoolean();
}
public byte readByte() throws IOException {
this.offset += 1;
return this.inner.readByte();
}
public int readUnsignedByte() throws IOException {
this.offset += 1;
return this.inner.readUnsignedByte();
}
public short readShort() throws IOException {
this.offset += 2;
return this.inner.readShort();
}
public int readUnsignedShort() throws IOException {
this.offset += 2;
return this.inner.readUnsignedShort();
}
public char readChar() throws IOException {
this.offset += 2;
return this.inner.readChar();
}
public int readInt() throws IOException {
this.offset += 4;
return this.inner.readInt();
}
public long readLong() throws IOException {
this.offset += 8;
return this.inner.readLong();
}
public float readFloat() throws IOException {
this.offset += 4;
return this.inner.readFloat();
}
public double readDouble() throws IOException {
this.offset += 8;
return this.inner.readDouble();
}
public int available() throws IOException {
return this.din == null ? 0 : this.din.available();
}
public void close() throws IOException {
if (this.inner instanceof RandomAccessFile) {
((RandomAccessFile) this.inner).close();
} else if (this.inner instanceof InputStream) {
((InputStream) this.inner).close();
}
}
public int getOffset() {
return this.offset;
}
public static byte[] read(FileChannel channel, int len) throws IOException {
byte[] buf = new byte[len];
ByteBuffer dst = ByteBuffer.wrap(buf);
channel.read(dst);
return buf;
}
}