All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.activej.serializer.BinaryInput Maven / Gradle / Ivy

Go to download

Extremely fast and space-efficient serializers. Implemented using bytecode engineering.

There is a newer version: 6.0-rc2
Show newest version
/*
 * Copyright (C) 2020 ActiveJ LLC.
 *
 * 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 io.activej.serializer;

import org.jetbrains.annotations.Nullable;

import java.util.concurrent.atomic.AtomicReference;

import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * Provides methods for reading primitives
 * and Strings from byte arrays
 */
@SuppressWarnings({"unused", "WeakerAccess", "DuplicatedCode", "SpellCheckingInspection"})
public final class BinaryInput {
	public final byte[] array;
	public int pos;

	public static final AtomicReference BUF = new AtomicReference<>(new char[256]);

	public BinaryInput(byte[] array) {
		this.array = array;
	}

	public BinaryInput(byte[] array, int pos) {
		this.array = array;
		this.pos = pos;
	}

	public byte[] array() {
		return array;
	}

	public int pos() {
		return pos;
	}

	public void pos(int pos) {
		this.pos = pos;
	}

	public void move(int delta) {
		this.pos += delta;
	}

	public int read(byte[] b) {
		return read(b, 0, b.length);
	}

	public int read(byte[] b, int off, int len) {
		System.arraycopy(this.array, pos, b, off, len);
		pos += len;
		return len;
	}

	public byte readByte() {
		return array[pos++];
	}

	public boolean readBoolean() {
		return readByte() != 0;
	}

	public short readShort() {
		short result = (short) ((array[pos] & 0xFF) << 8 | array[pos + 1] & 0xFF);
		pos += 2;
		return result;
	}

	public short readShortLE() {
		short result = (short) (array[pos] & 0xFF | (array[pos + 1] & 0xFF) << 8);
		pos += 2;
		return result;
	}

	public char readChar() {
		char c = (char) ((array[pos] & 0xFF) << 8 | array[pos + 1] & 0xFF);
		pos += 2;
		return c;
	}

	public char readCharLE() {
		char c = (char) (array[pos] & 0xFF | (array[pos + 1] & 0xFF) << 8);
		pos += 2;
		return c;
	}

	public int readInt() {
		int result =
			(array[pos] & 0xFF) << 24 |
			(array[pos + 1] & 0xFF) << 16 |
			(array[pos + 2] & 0xFF) << 8 |
			array[pos + 3] & 0xFF;
		pos += 4;
		return result;
	}

	public int readIntLE() {
		int result =
			(array[pos] & 0xFF) |
			(array[pos + 1] & 0xFF) << 8 |
			(array[pos + 2] & 0xFF) << 16 |
			(array[pos + 3] & 0xFF) << 24;
		pos += 4;
		return result;
	}

	public long readLong() {
		long result =
			(long) (array[pos] & 0xFF) << 56 |
			(long) (array[pos + 1] & 0xFF) << 48 |
			(long) (array[pos + 2] & 0xFF) << 40 |
			(long) (array[pos + 3] & 0xFF) << 32 |
			(long) (array[pos + 4] & 0xFF) << 24 |
			(long) (array[pos + 5] & 0xFF) << 16 |
			(long) (array[pos + 6] & 0xFF) << 8 |
			(long) (array[pos + 7] & 0xFF);
		pos += 8;
		return result;
	}

	public long readLongLE() {
		long result =
			(long) (array[pos] & 0xFF) |
			(long) (array[pos + 1] & 0xFF) << 8 |
			(long) (array[pos + 2] & 0xFF) << 16 |
			(long) (array[pos + 3] & 0xFF) << 24 |
			(long) (array[pos + 4] & 0xFF) << 32 |
			(long) (array[pos + 5] & 0xFF) << 40 |
			(long) (array[pos + 6] & 0xFF) << 48 |
			(long) (array[pos + 7] & 0xFF) << 56;
		pos += 8;
		return result;
	}

	public int readVarInt() {
		byte b;
		if ((b = array[pos]) >= 0) {
			pos += 1;
			return b;
		}
		int result = b & 0x7f;
		if ((b = array[pos + 1]) >= 0) {
			pos += 2;
			return result | b << 7;
		}
		result |= (b & 0x7f) << 7;
		if ((b = array[pos + 2]) >= 0) {
			pos += 3;
			return result | b << 14;
		}
		result |= (b & 0x7f) << 14;
		if ((b = array[pos + 3]) >= 0) {
			pos += 4;
			return result | b << 21;
		}
		result = result | (b & 0x7f) << 21 | array[pos + 4] << 28;
		pos += 5;
		return result;
	}

	public long readVarLong() {
		byte b;
		b = array[pos++];
		if (b >= 0) {
			return b;
		}
		long result = b & 0x7F;
		for (int offset = 7; offset < 64; offset += 7) {
			b = array[pos++];
			if (b >= 0)
				return result | (long) b << offset;
			result |= (long) (b & 0x7F) << offset;
		}
		throw new CorruptedDataException("Read varlong was too long");
	}

	public float readFloat() {
		return Float.intBitsToFloat(readInt());
	}

	public double readDouble() {
		return Double.longBitsToDouble(readLong());
	}

	public String readUTF8() {
		int length = readVarInt();
		String s = new String(array, pos, length, UTF_8);
		pos += length;
		return s;
	}

	public @Nullable String readUTF8Nullable() {
		int length = readVarInt();
		if (length == 0) return null;
		length--;
		String s = new String(array, pos, length, UTF_8);
		pos += length;
		return s;
	}

	public String readIso88591() {
		int length = readVarInt();
		String s = new String(array, pos, length, ISO_8859_1);
		pos += length;
		return s;
	}

	public @Nullable String readIso88591Nullable() {
		int length = readVarInt();
		if (length == 0) return null;
		length--;
		String s = new String(array, pos, length, ISO_8859_1);
		pos += length;
		return s;
	}

	public String readUTF16() {
		int length = readVarInt();
		if (length == 0) return "";
		if (length >= 40) return readUTF16buf(length);
		char[] chars = new char[length];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) ((array[pos + i * 2] & 0xFF) << 8 | array[pos + i * 2 + 1] & 0xFF);
		}
		pos += length * 2;
		return new String(chars, 0, length);
	}

	public String readUTF16LE() {
		int length = readVarInt();
		if (length == 0) return "";
		if (length >= 40) return readUTF16LEbuf(length);
		char[] chars = new char[length];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) (array[pos + i * 2] & 0xFF | (array[pos + i * 2 + 1] & 0xFF) << 8);
		}
		pos += length * 2;
		return new String(chars, 0, length);
	}

	public @Nullable String readUTF16Nullable() {
		int length = readVarInt();
		if (length == 0) return null;
		length--;
		if (length == 0) return "";
		if (length >= 40) return readUTF16buf(length);
		char[] chars = new char[length];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) ((array[pos + i * 2] & 0xFF) << 8 | array[pos + i * 2 + 1] & 0xFF);
		}
		pos += length * 2;
		return new String(chars, 0, length);
	}

	public @Nullable String readUTF16NullableLE() {
		int length = readVarInt();
		if (length == 0) return null;
		length--;
		if (length == 0) return "";
		if (length >= 40) return readUTF16LEbuf(length);
		char[] chars = new char[length];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) (array[pos + i * 2] & 0xFF | (array[pos + i * 2 + 1] & 0xFF) << 8);
		}
		pos += length * 2;
		return new String(chars, 0, length);
	}

	private String readUTF16buf(int length) {
		char[] chars = BUF.getAndSet(null);
		if (chars == null || chars.length < length) chars = new char[length + length / 4];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) ((array[pos + i * 2] & 0xFF) << 8 | array[pos + i * 2 + 1] & 0xFF);
		}
		pos += length * 2;
		String s = new String(chars, 0, length);
		BUF.lazySet(chars);
		return s;
	}

	private String readUTF16LEbuf(int length) {
		char[] chars = BUF.getAndSet(null);
		if (chars == null || chars.length < length) chars = new char[length + length / 4];
		for (int i = 0; i < length; i++) {
			chars[i] = (char) (array[pos + i * 2] & 0xFF | (array[pos + i * 2 + 1] & 0xFF) << 8);
		}
		pos += length * 2;
		String s = new String(chars, 0, length);
		BUF.lazySet(chars);
		return s;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy