added Leb128
This commit is contained in:
76
src/main/java/net/woggioni/jwo/Leb128.java
Normal file
76
src/main/java/net/woggioni/jwo/Leb128.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package net.woggioni.jwo;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class Leb128 {
|
||||
|
||||
public static long reverse(long n) {
|
||||
long res = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
long b = (n & (0xFFL << (i * 8))) >>> (i * 8);
|
||||
res |= b << ((7 - i) * 8);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public static int encode(OutputStream os, double input) {
|
||||
return encode(os, reverse(Double.doubleToLongBits(input)));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static int encode(OutputStream os, long input) {
|
||||
int bytes_written = 0;
|
||||
long number = input >= 0 ? (input << 1) : (-(input + 1)) << 1 | 1;
|
||||
while((number & 127L) != number) {
|
||||
os.write((int) (number & 127) | 128);
|
||||
bytes_written++;
|
||||
number >>>= 7;
|
||||
}
|
||||
os.write((int) number);
|
||||
return ++bytes_written;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static class Leb128Decoder {
|
||||
@Getter
|
||||
private int bytesRead = 0;
|
||||
|
||||
private final InputStream is;
|
||||
|
||||
public byte decodeByte() {
|
||||
return (byte) decode();
|
||||
}
|
||||
|
||||
public short decodeShort() {
|
||||
return (short) decode();
|
||||
}
|
||||
|
||||
public int decodeInt() {
|
||||
return (int) decode();
|
||||
}
|
||||
|
||||
public double decodeDouble() {
|
||||
return Double.longBitsToDouble(reverse(decode()));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public long decode() {
|
||||
long res = 0;
|
||||
for(int i = 0; i < (8 * 8 + 6) / 7; i++) {
|
||||
int c = is.read();
|
||||
bytesRead++;
|
||||
if(c < 0) {
|
||||
throw new IllegalArgumentException("Unexpected end of file");
|
||||
}
|
||||
res |= ((long)(c & 127)) << (i * 7);
|
||||
if((byte) c >= 0) break;
|
||||
}
|
||||
return (res & 1) != 0 ? - (res >>> 1) - 1 : (res >>> 1);
|
||||
}
|
||||
}
|
||||
}
|
@@ -13,7 +13,15 @@ public class MutableTuple2<T, U> {
|
||||
public T _1;
|
||||
public U _2;
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>> Comparator<MutableTuple2<X, Y>> getComparator(Class<X> cls1, Class<Y> cls2) {
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>>
|
||||
Comparator<MutableTuple2<X, Y>> getComparator(Class<X> cls1, Class<Y> cls2) {
|
||||
return Comparator
|
||||
.comparing((MutableTuple2<X, Y> t) -> t._1)
|
||||
.thenComparing((MutableTuple2<X, Y> t) -> t._2);
|
||||
}
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>>
|
||||
Comparator<MutableTuple2<X, Y>> getComparator(MutableTuple2<X, Y> tuple) {
|
||||
return Comparator
|
||||
.comparing((MutableTuple2<X, Y> t) -> t._1)
|
||||
.thenComparing((MutableTuple2<X, Y> t) -> t._2);
|
||||
|
@@ -14,7 +14,16 @@ public class MutableTuple3<T, U, V> {
|
||||
public U _2;
|
||||
public V _3;
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>> Comparator<MutableTuple3<X, Y, Z>> getComparator(Class<X> cls1, Class<Y> cls2, Class<Z> cls3) {
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>>
|
||||
Comparator<MutableTuple3<X, Y, Z>> getComparator(Class<X> cls1, Class<Y> cls2, Class<Z> cls3) {
|
||||
return Comparator
|
||||
.comparing((MutableTuple3<X, Y, Z> t) -> t._1)
|
||||
.thenComparing((MutableTuple3<X, Y, Z> t) -> t._2)
|
||||
.thenComparing((MutableTuple3<X, Y, Z> t) -> t._3);
|
||||
}
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>>
|
||||
Comparator<MutableTuple3<X, Y, Z>> getComparator(MutableTuple3<X, Y, Z> tuple) {
|
||||
return Comparator
|
||||
.comparing((MutableTuple3<X, Y, Z> t) -> t._1)
|
||||
.thenComparing((MutableTuple3<X, Y, Z> t) -> t._2)
|
||||
|
@@ -16,4 +16,10 @@ public class Tuple2<T, U> {
|
||||
.comparing((Tuple2<X, Y> t) -> t._1)
|
||||
.thenComparing((Tuple2<X, Y> t) -> t._2);
|
||||
}
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>> Comparator<Tuple2<X, Y>> getComparator(Tuple2<X, Y> tuple) {
|
||||
return Comparator
|
||||
.comparing((Tuple2<X, Y> t) -> t._1)
|
||||
.thenComparing((Tuple2<X, Y> t) -> t._2);
|
||||
}
|
||||
}
|
||||
|
@@ -12,10 +12,19 @@ public class Tuple3<T, U, V> {
|
||||
public final U _2;
|
||||
public final V _3;
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>> Comparator<Tuple3<X, Y, Z>> getComparator(Class<X> cls1, Class<Y> cls2, Class<Z> cls3) {
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>>
|
||||
Comparator<Tuple3<X, Y, Z>> getComparator(Class<X> cls1, Class<Y> cls2, Class<Z> cls3) {
|
||||
return Comparator
|
||||
.comparing((Tuple3<X, Y, Z> t) -> t._1)
|
||||
.thenComparing((Tuple3<X, Y, Z> t) -> t._2)
|
||||
.thenComparing((Tuple3<X, Y, Z> t) -> t._3);
|
||||
}
|
||||
|
||||
public static <X extends Comparable<X>, Y extends Comparable<Y>, Z extends Comparable<Z>>
|
||||
Comparator<Tuple3<X, Y, Z>> getComparator(Tuple3<X, Y, Z> tuple) {
|
||||
return Comparator
|
||||
.comparing((Tuple3<X, Y, Z> t) -> t._1)
|
||||
.thenComparing((Tuple3<X, Y, Z> t) -> t._2)
|
||||
.thenComparing((Tuple3<X, Y, Z> t) -> t._3);
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,10 @@
|
||||
package net.woggioni.jwo.utils;
|
||||
package net.woggioni.jwo;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import net.woggioni.jwo.Chronometer;
|
||||
import net.woggioni.jwo.JWO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
61
src/test/java/net/woggioni/jwo/Leb128Test.java
Normal file
61
src/test/java/net/woggioni/jwo/Leb128Test.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package net.woggioni.jwo;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Leb128Test {
|
||||
|
||||
@Test
|
||||
public void testLong() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
List<Long> numbers = Arrays.asList(0L, 1L, -3L, 5L, 7L, 8L, 125L, 255L, 10325L, -2000L, 1024L * 1024L * 1024L * 12L);
|
||||
|
||||
numbers.forEach(n -> Leb128.encode(baos, n));
|
||||
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
Leb128.Leb128Decoder decoder = new Leb128.Leb128Decoder(new ByteArrayInputStream(bytes));
|
||||
numbers.forEach(n -> Assert.assertEquals((long) n, decoder.decode()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDouble() {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
List<Double> numbers = Arrays.asList(
|
||||
0.0, 1.5, -3.0, 0.5, 2.5, 8.25, -125.0, 255.0, 10325.0, -2000.0, 1024.0 * 1024 * 1024 * 12,
|
||||
-122.42200352825247, 37.80848009696725);
|
||||
|
||||
numbers.forEach(n -> Leb128.encode(baos, n));
|
||||
|
||||
byte[] bytes = baos.toByteArray();
|
||||
|
||||
Leb128.Leb128Decoder decoder = new Leb128.Leb128Decoder(new ByteArrayInputStream(bytes));
|
||||
numbers.forEach(n -> Assert.assertEquals(n, decoder.decodeDouble(), 0.0));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void reverseTest() {
|
||||
long n = 101325;
|
||||
Assert.assertEquals(n, Leb128.reverse(Leb128.reverse(n)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void reverseTestDouble() {
|
||||
double n = 0.25;
|
||||
long doubleLong = Double.doubleToLongBits(n);
|
||||
long reverse = Leb128.reverse(doubleLong);
|
||||
try(ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
Leb128.encode(os, reverse);
|
||||
byte[] bytes = os.toByteArray();
|
||||
Assert.assertEquals(3, bytes.length);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package net.woggioni.jwo.utils.io;
|
||||
package net.woggioni.jwo.io;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import net.woggioni.jwo.io.CircularBuffer;
|
@@ -1,11 +1,7 @@
|
||||
package net.woggioni.jwo.utils.tree;
|
||||
package net.woggioni.jwo.tree;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.woggioni.jwo.tree.StackContext;
|
||||
import net.woggioni.jwo.tree.TreeNode;
|
||||
import net.woggioni.jwo.tree.TreeNodeVisitor;
|
||||
import net.woggioni.jwo.tree.TreeWalker;
|
||||
import net.woggioni.jwo.tuple.Tuple2;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
Reference in New Issue
Block a user