added Leb128

This commit is contained in:
2019-12-12 00:20:58 +00:00
parent 22646254b1
commit 4a5bcea903
9 changed files with 175 additions and 14 deletions

View 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);
}
}
}

View File

@@ -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);

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;

View 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);
}
}
}

View File

@@ -1,4 +1,4 @@
package net.woggioni.jwo.utils.io;
package net.woggioni.jwo.io;
import lombok.SneakyThrows;
import net.woggioni.jwo.io.CircularBuffer;

View File

@@ -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;