/* * This code is released under the * Apache License Version 2.0 http://www.apache.org/licenses/. */ package me.lemire.integercompression; import java.nio.ByteBuffer; import java.nio.IntBuffer; /** * VariableByte with Delta+Zigzag Encoding. * * @author MURAOKA Taro http://github.com/koron */ public class DeltaZigzagVariableByte implements IntegerCODEC { @Override public String toString() { return DeltaZigzagVariableByte.class.getSimpleName(); } @Override public void compress(int[] inBuf, IntWrapper inPos, int inLen, int[] outBuf, IntWrapper outPos) { if (inLen == 0) { return; } ByteBuffer byteBuf = makeBuffer(inLen * 5 + 3); DeltaZigzagEncoding.Encoder ctx = new DeltaZigzagEncoding.Encoder(0); // Delta+Zigzag+VariableByte encoding. int ip = inPos.get(); final int inPosLast = ip + inLen; for (; ip < inPosLast; ++ip) { // Filter with delta+zigzag encoding. int n = ctx.encodeInt(inBuf[ip]); // Variable byte encoding. switch (Integer.numberOfLeadingZeros(n)) { case 0: case 1: case 2: case 3: byteBuf.put((byte) (((n >>> 28) & 0x7F) | 0x80)); // through. //$FALL-THROUGH$ case 4: case 5: case 6: case 7: case 8: case 9: case 10: byteBuf.put((byte) (((n >>> 21) & 0x7F) | 0x80)); // through. //$FALL-THROUGH$ case 11: case 12: case 13: case 14: case 15: case 16: case 17: byteBuf.put((byte) (((n >>> 14) & 0x7F) | 0x80)); // through. //$FALL-THROUGH$ case 18: case 19: case 20: case 21: case 22: case 23: case 24: byteBuf.put((byte) (((n >>> 7) & 0x7F) | 0x80)); // through. //$FALL-THROUGH$ default: byteBuf.put((byte) (n & 0x7F)); } } // Padding buffer to considerable as IntBuffer. for (int i = (4 - (byteBuf.position() % 4)) % 4; i > 0; --i) { byteBuf.put((byte) (0x80)); } int outLen = byteBuf.position() / 4; byteBuf.flip(); IntBuffer intBuf = byteBuf.asIntBuffer(); /* * System.out.println(String.format( * "inLen=%d pos=%d limit=%d outLen=%d outBuf.len=%d", inLen, * intBuf.position(), intBuf.limit(), outLen, outBuf.length)); */ intBuf.get(outBuf, outPos.get(), outLen); inPos.add(inLen); outPos.add(outLen); } @Override public void uncompress(int[] inBuf, IntWrapper inPos, int inLen, int[] outBuf, IntWrapper outPos) { DeltaZigzagEncoding.Decoder ctx = new DeltaZigzagEncoding.Decoder(0); int ip = inPos.get(); int op = outPos.get(); int vbcNum = 0, vbcShift = 24; // Varialbe Byte Context. final int inPosLast = ip + inLen; while (ip < inPosLast) { // Fetch a byte value. int n = (inBuf[ip] >>> vbcShift) & 0xFF; if (vbcShift > 0) { vbcShift -= 8; } else { vbcShift = 24; ip++; } // Decode variable byte and delta+zigzag. vbcNum = (vbcNum << 7) + (n & 0x7F); if ((n & 0x80) == 0) { outBuf[op++] = ctx.decodeInt(vbcNum); vbcNum = 0; } } outPos.set(op); inPos.set(inPosLast); } /** * Creates a new buffer of the requested size. * * In case you need a different way to allocate buffers, you can override this method * with a custom behavior. The default implementation allocates a new Java direct * {@link ByteBuffer} on each invocation. */ protected ByteBuffer makeBuffer(int sizeInBytes) { return ByteBuffer.allocateDirect(sizeInBytes); } }