Archived
0

Merge branch 'dev/utils' into dev/world

This commit is contained in:
2021-06-27 05:37:16 +03:00
12 changed files with 362 additions and 2 deletions

1
utils/build.gradle Normal file
View File

@@ -0,0 +1 @@
apply from: rootDir.toPath().resolve('logic.gradle').toFile()

2
utils/gradle.properties Normal file
View File

@@ -0,0 +1,2 @@
# suppress inspection "UnusedProperty" for whole file
module.name=utils

View File

@@ -0,0 +1,23 @@
package mc.utils;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
public class Table<C, R, V> {
private final Map<C, Map<R, V>> map = new HashMap<>();
@Nullable
public V getColumnAndRow(C column, R row) {
if (!map.containsKey(column)) {
return null;
}
return map.get(column).get(row);
}
public void put(C column, R row, V value) {
map.computeIfAbsent(column, c -> new HashMap<>()).put(row, value);
}
}

View File

@@ -0,0 +1,51 @@
package mc.utils.array;
import java.nio.ByteBuffer;
public abstract class AbstractBitBufferArray implements BitArray {
protected int bitPerEntity;
protected int arraySize;
protected long maxEntityValue;
protected ByteBuffer byteBuffer;
protected int writePosition = 0;
protected AbstractBitBufferArray(int bitPerEntity, int arraySize, boolean direct) {
this.bitPerEntity = bitPerEntity;
this.arraySize = arraySize;
this.maxEntityValue = (1L << bitPerEntity) - 1L;
int capaticy = calculateCapacity();
if (direct) {
this.byteBuffer = ByteBuffer.allocateDirect(capaticy);
} else {
this.byteBuffer = ByteBuffer.allocate(capaticy);
}
}
@Override
public void put(int value) {
put(writePosition, value);
writePosition++;
}
@Override
public ByteBuffer byteBuffer() {
return this.byteBuffer;
}
protected void validateIndex(int index) {
if (index < 0 || index > arraySize - 1) {
throw new IllegalArgumentException("Index " + index + " out of range [0;" + arraySize + "]");
}
}
protected void validateValue(int value) {
if ((value | maxEntityValue) > maxEntityValue) {
throw new IllegalArgumentException("Invalide value " + value + ". Value bits: " + Integer.bitCount(value) + ", maximum bits: " + bitPerEntity);
}
}
protected abstract int calculateCapacity();
}

View File

@@ -0,0 +1,13 @@
package mc.utils.array;
import java.nio.ByteBuffer;
public interface BitArray {
void put(int value);
void put(int index, int value);
int get(int index);
ByteBuffer byteBuffer();
}

View File

@@ -0,0 +1,62 @@
package mc.utils.array;
public class BitByteArray extends AbstractBitBufferArray {
public BitByteArray(int bitPerEntity, int arraySize, boolean direct) {
super(bitPerEntity, arraySize, direct);
}
public BitByteArray(int bitPerEntity, int arraySize) {
this(bitPerEntity, arraySize, true);
}
@Override
public void put(int index, int value) {
validateIndex(index);
validateValue(value);
//@formatter:off
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Byte.SIZE;
int var1 = index * bitPerEntity;
int tailValueIndex = var1 / Byte.SIZE;
int offsetValue = var1 % Byte.SIZE;
//@formatter:on
byteBuffer.put(tailValueIndex,
(byte) (byteBuffer.get(tailValueIndex) & ~(maxEntityValue << offsetValue)
| ((byte) value & maxEntityValue) << offsetValue));
if (headValueIndex != tailValueIndex) {
int shift1 = Byte.SIZE - offsetValue;
int shift2 = bitPerEntity - shift1;
byteBuffer.put(headValueIndex,
(byte) (byteBuffer.get(headValueIndex) >>> shift2 << shift2
| ((byte) value & maxEntityValue) >> shift1));
}
}
@Override
public int get(int index) {
validateIndex(index);
//@formatter:off
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Byte.SIZE;
int var1 = index * bitPerEntity;
int tailValueIndex = var1 / Byte.SIZE;
int offsetValue = var1 % Byte.SIZE;
//@formatter:on
if (headValueIndex == tailValueIndex) {
return (int) (byteBuffer.get(tailValueIndex) >>> offsetValue & maxEntityValue);
} else {
return (int) ((byteBuffer.get(tailValueIndex) >>> offsetValue
| byteBuffer.get(headValueIndex) << (Byte.SIZE - offsetValue)) & maxEntityValue);
}
}
@Override
protected int calculateCapacity() {
return (arraySize * bitPerEntity / Byte.SIZE + 1) * Byte.BYTES;
}
}

View File

@@ -0,0 +1,67 @@
package mc.utils.array;
import java.nio.LongBuffer;
public class BitLongArray extends AbstractBitBufferArray {
private final LongBuffer longBuffer;
public BitLongArray(int bitPerEntity, int arraySize, boolean direct) {
super(bitPerEntity, arraySize, direct);
this.longBuffer = this.byteBuffer.asLongBuffer();
}
public BitLongArray(int bitPerEntity, int arraySize) {
this(bitPerEntity, arraySize, true);
}
@Override
public void put(int index, int value) {
validateIndex(index);
validateValue(value);
//@formatter:off
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Long.SIZE;
int var1 = index * bitPerEntity;
int tailValueIndex = var1 / Long.SIZE;
int offsetValue = var1 % Long.SIZE;
//@formatter:on
longBuffer.put(tailValueIndex,
longBuffer.get(tailValueIndex) & ~(maxEntityValue << offsetValue)
| ((long) value & maxEntityValue) << offsetValue);
if (headValueIndex != tailValueIndex) {
int shift1 = Long.SIZE - offsetValue;
int shift2 = bitPerEntity - shift1;
longBuffer.put(headValueIndex,
longBuffer.get(headValueIndex) >>> shift2 << shift2
| ((long) value & maxEntityValue) >> shift1);
}
}
@Override
public int get(int index) {
validateIndex(index);
//@formatter:off
int headValueIndex = ((index + 1) * bitPerEntity - 1) / Long.SIZE;
int var1 = index * bitPerEntity;
int tailValueIndex = var1 / Long.SIZE;
int offsetValue = var1 % Long.SIZE;
//@formatter:on
if (headValueIndex == tailValueIndex) {
return (int) (longBuffer.get(tailValueIndex) >>> offsetValue & maxEntityValue);
} else {
return (int) ((longBuffer.get(tailValueIndex) >>> offsetValue
| longBuffer.get(headValueIndex) << (Long.SIZE - offsetValue)) & maxEntityValue);
}
}
@Override
protected int calculateCapacity() {
return (arraySize * bitPerEntity / Long.SIZE + 1) * Long.BYTES;
}
}

View File

@@ -0,0 +1,80 @@
package mc.utils.array;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import static org.junit.jupiter.api.Assertions.assertEquals;
class BitByteArrayTest {
@Test
void initTest() {
BitArray bitArray = new BitByteArray(4, 1, false);
ByteBuffer byteBuffer = bitArray.byteBuffer();
assertEquals(1, byteBuffer.capacity());
assertEquals(1, byteBuffer.limit());
assertEquals(0, byteBuffer.position());
assertEquals(1, byteBuffer.array().length);
bitArray = new BitByteArray(4, 2);
byteBuffer = bitArray.byteBuffer();
assertEquals(2, byteBuffer.capacity());
assertEquals(2, byteBuffer.limit());
}
@Test
void writeTest1() {
int value = 0b00001001;
int expected = 0b10011001;
BitArray bitArray = new BitByteArray(4, 2);
bitArray.put(value);
bitArray.put(value);
ByteBuffer byteBuffer = bitArray.byteBuffer();
assertEquals(expected, byteBuffer.get(0) & 0xFF); //Unsigned Byte
}
@Test
void writeTest2() {
int value1 = 0b00001001;
int value2 = 0b00001111;
int expected1 = 0b10011001;
int expected2 = 0b11111111;
BitArray bitArray = new BitByteArray(4, 4);
bitArray.put(value1);
bitArray.put(value1);
bitArray.put(value2);
bitArray.put(value2);
ByteBuffer byteBuffer = bitArray.byteBuffer();
assertEquals(expected1, byteBuffer.get(0) & 0xFF); //Unsigned Byte
assertEquals(expected2, byteBuffer.get(1) & 0xFF); //Unsigned Byte
}
@Test
void writeOffsetTest() {
int value = 0b00001001;
int expected = 0b10010000;
BitArray bitArray = new BitByteArray(4, 2);
bitArray.put(1, value);
ByteBuffer byteBuffer = bitArray.byteBuffer();
assertEquals(expected, byteBuffer.get(0) & 0xFF); //Unsigned Byte
}
@Test
void readTest() {
int excepted = 0b00000110;
BitArray bitArray = new BitByteArray(4, 2);
bitArray.put(1, excepted);
assertEquals(excepted, bitArray.get(1));
}
}

View File

@@ -0,0 +1,81 @@
package mc.utils.array;
import org.junit.jupiter.api.Test;
import java.nio.ByteBuffer;
import java.nio.LongBuffer;
import static org.junit.jupiter.api.Assertions.*;
class BitLongArrayTest {
@Test
void initTest() {
BitArray bitArray = new BitLongArray(13, 1, false);
ByteBuffer byteBuffer = bitArray.byteBuffer();
assertEquals(8, byteBuffer.capacity());
assertEquals(8, byteBuffer.limit());
assertEquals(0, byteBuffer.position());
assertEquals(8, byteBuffer.array().length);
bitArray = new BitLongArray(13, 5);
byteBuffer = bitArray.byteBuffer();
assertEquals(16, byteBuffer.capacity());
assertEquals(16, byteBuffer.limit());
}
@Test
void writeTest1() {
int value = 0b00010000_00000011;
long expected = 0b00000000_00000000_00000000_00000000_00000010_00000000_01110000_00000011L;
BitArray bitArray = new BitLongArray(13, 2);
bitArray.put(value);
bitArray.put(value);
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
assertEquals(expected, longBuffer.get(0));
}
@Test
void writeTest2() {
int value = 0b00010000_00000011;
long expected1 = 0b00000000_00111000_00000001_11000000_00001110_00000000_01110000_00000011L;
long expected2 = 0b00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001L;
BitArray bitArray = new BitLongArray(13, 5);
bitArray.put(value);
bitArray.put(value);
bitArray.put(value);
bitArray.put(value);
bitArray.put(value);
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
assertEquals(expected1, longBuffer.get(0));
assertEquals(expected2, longBuffer.get(1));
}
@Test
void writeOffsetTest() {
int value = 0b00010000_00000011;
long expected = 0b00000000_00000000_00000000_00000000_00000010_00000000_01100000_00000000;
BitArray bitArray = new BitLongArray(13, 2);
bitArray.put(1, value);
LongBuffer longBuffer = bitArray.byteBuffer().asLongBuffer();
assertEquals(expected, longBuffer.get(0));
}
@Test
void readTest() {
int excepted = 0b00010000_00000011;
BitArray bitArray = new BitLongArray(13, 2);
bitArray.put(1, excepted);
assertEquals(excepted, bitArray.get(1));
}
}