149 lines
3.6 KiB
Java
149 lines
3.6 KiB
Java
package nl.sanderhautvast.contiguous;
|
|
|
|
import java.nio.ByteBuffer;
|
|
|
|
/**
|
|
* Writes integers to byte representation like Sqlite's putVarint64
|
|
* not threadsafe (take out B8 and B9 if you need that)
|
|
*/
|
|
final class Varint {
|
|
|
|
//reuse the byte buffers => do not multithread
|
|
private static final byte[] B8 = new byte[8];
|
|
private static final byte[] B9 = new byte[9];
|
|
//TODO remove them now!
|
|
private Varint() {
|
|
}
|
|
|
|
public static byte[] write(long v) {
|
|
if ((v & ((0xff000000L) << 32)) != 0) {
|
|
byte[] result = B9;
|
|
result[8] = (byte) v;
|
|
v >>= 8;
|
|
for (int i = 7; i >= 0; i--) {
|
|
result[i] = (byte) ((v & 0x7f) | 0x80);
|
|
v >>= 7;
|
|
}
|
|
return result;
|
|
} else {
|
|
int n;
|
|
byte[] buf = B8;
|
|
for (n = 0; v != 0; n++, v >>= 7) {
|
|
buf[n] = (byte) ((v & 0x7f) | 0x80);
|
|
}
|
|
buf[0] &= 0x7f;
|
|
byte[] result = new byte[n];
|
|
for (int i = 0, j = n - 1; j >= 0; j--, i++) {
|
|
result[i] = buf[j];
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* read a long value from a variable nr of bytes in varint format
|
|
*
|
|
* copied from the sqlite source, with some java specifics, most notably the addition of
|
|
* &0xFF for the right conversion from byte => signed in java, but to be interpreted as unsigned,
|
|
* to long
|
|
*
|
|
* Does not have the issue that the read(byte[] bytes) method has. The nr of bytes read is determined
|
|
* by the varint64 format.
|
|
*/
|
|
public static long read(ByteBuffer buffer) {
|
|
int SLOT_2_0 = 0x001fc07f;
|
|
int SLOT_4_2_0 = 0xf01fc07f;
|
|
|
|
long a = buffer.get() & 0xFF;
|
|
if ((a & 0x80) == 0) {
|
|
return a;
|
|
}
|
|
|
|
long b = buffer.get() & 0xFF;
|
|
if ((b & 0x80) == 0) {
|
|
a &= 0x7F;
|
|
a = a << 7;
|
|
a |= b;
|
|
return a;
|
|
}
|
|
|
|
a = a << 14;
|
|
a |= (buffer.get() & 0xFF);
|
|
if ((a & 0x80) == 0) {
|
|
a &= SLOT_2_0;
|
|
b &= 0x7F;
|
|
b = b << 7;
|
|
a |= b;
|
|
return a;
|
|
}
|
|
|
|
a &= SLOT_2_0;
|
|
b = b << 14;
|
|
b |= (buffer.get() & 0xFF);
|
|
if ((b & 0x80) == 0) {
|
|
b &= SLOT_2_0;
|
|
a = a << 7;
|
|
a |= b;
|
|
return a;
|
|
}
|
|
|
|
b &= SLOT_2_0;
|
|
long s = a;
|
|
a = a << 14;
|
|
int m = buffer.get() & 0xFF;
|
|
a |= m;
|
|
if ((a & 0x80) == 0) {
|
|
b = b << 7;
|
|
a |= b;
|
|
s = s >> 18;
|
|
return (s << 32) | a;
|
|
}
|
|
|
|
s = s << 7;
|
|
s |= b;
|
|
b = b << 14;
|
|
b |= (buffer.get() & 0xFF);
|
|
if ((b & 0x80) == 0) {
|
|
a &= SLOT_2_0;
|
|
a = a << 7;
|
|
a |= b;
|
|
s = s >> 18;
|
|
return (s << 32) | a;
|
|
}
|
|
|
|
a = a << 14;
|
|
a |= (buffer.get() & 0xFF);
|
|
if ((a & 0x80) == 0) {
|
|
a &= SLOT_4_2_0;
|
|
b &= SLOT_2_0;
|
|
b = b << 7;
|
|
a |= b;
|
|
s = s >> 11;
|
|
return (s << 32) | a;
|
|
}
|
|
|
|
a &= SLOT_2_0;
|
|
b = b << 14;
|
|
b |= (buffer.get() & 0xFF);
|
|
if ((b & 0x80) == 0) {
|
|
b &= SLOT_4_2_0;
|
|
a = a << 7;
|
|
a |= b;
|
|
s = s >> 4;
|
|
return (s << 32) | a;
|
|
}
|
|
|
|
a = a << 15;
|
|
a |= (buffer.get() & 0xFF);
|
|
b &= SLOT_2_0;
|
|
|
|
b = b << 8;
|
|
a |= b;
|
|
s = s << 4;
|
|
b = m;
|
|
b &= 0x7F;
|
|
b = b >> 3;
|
|
s |= b;
|
|
return (s << 32) | a;
|
|
}
|
|
}
|