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 T _1;
|
||||||
public U _2;
|
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
|
return Comparator
|
||||||
.comparing((MutableTuple2<X, Y> t) -> t._1)
|
.comparing((MutableTuple2<X, Y> t) -> t._1)
|
||||||
.thenComparing((MutableTuple2<X, Y> t) -> t._2);
|
.thenComparing((MutableTuple2<X, Y> t) -> t._2);
|
||||||
|
@@ -14,7 +14,16 @@ public class MutableTuple3<T, U, V> {
|
|||||||
public U _2;
|
public U _2;
|
||||||
public V _3;
|
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
|
return Comparator
|
||||||
.comparing((MutableTuple3<X, Y, Z> t) -> t._1)
|
.comparing((MutableTuple3<X, Y, Z> t) -> t._1)
|
||||||
.thenComparing((MutableTuple3<X, Y, Z> t) -> t._2)
|
.thenComparing((MutableTuple3<X, Y, Z> t) -> t._2)
|
||||||
|
@@ -16,4 +16,10 @@ public class Tuple2<T, U> {
|
|||||||
.comparing((Tuple2<X, Y> t) -> t._1)
|
.comparing((Tuple2<X, Y> t) -> t._1)
|
||||||
.thenComparing((Tuple2<X, Y> t) -> t._2);
|
.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,7 +12,16 @@ public class Tuple3<T, U, V> {
|
|||||||
public final U _2;
|
public final U _2;
|
||||||
public final V _3;
|
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
|
return Comparator
|
||||||
.comparing((Tuple3<X, Y, Z> t) -> t._1)
|
.comparing((Tuple3<X, Y, Z> t) -> t._1)
|
||||||
.thenComparing((Tuple3<X, Y, Z> t) -> t._2)
|
.thenComparing((Tuple3<X, Y, Z> t) -> t._2)
|
||||||
|
@@ -1,14 +1,10 @@
|
|||||||
package net.woggioni.jwo.utils;
|
package net.woggioni.jwo;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.woggioni.jwo.Chronometer;
|
|
||||||
import net.woggioni.jwo.JWO;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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 lombok.SneakyThrows;
|
||||||
import net.woggioni.jwo.io.CircularBuffer;
|
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.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
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 net.woggioni.jwo.tuple.Tuple2;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
Reference in New Issue
Block a user