package com.github.hoffart.dmap.util; import java.nio.ByteBuffer; /** * VInt compression taken from WritableUtils in Apache Hadoop 1.0.3! */ public final class CompressionUtils { public static int writeVInt(ByteBuffer bb, int i) { return writeVLong(bb, i); } public static int writeVLong(ByteBuffer bb, long l) { int initPos = bb.position(); if (l >= -112 && l <= 127) { bb.put((byte) l); return 1; } int len = -112; if (l < 0) { l ^= -1L; // take one's complement' len = -120; } long tmp = l; while (tmp != 0) { tmp = tmp >> 8; len--; } bb.put((byte)len); len = (len < -120) ? -(len + 120) : -(len + 112); for (int idx = len; idx != 0; idx--) { int shiftbits = (idx - 1) * 8; long mask = 0xFFL << shiftbits; bb.put((byte) ((l & mask) >> shiftbits)); } return bb.position() - initPos; } public static int readVInt(ByteBuffer bb) { return (int) readVLong(bb); } public static int readVInt(ByteBuffer bb, int len, byte firstByte) { return (int) readVLong(bb, len, firstByte); } public static long readVLong(ByteBuffer bb) { byte firstByte = bb.get(); int len = decodeVNumSize(firstByte); return readVLong(bb, len, firstByte); } public static long readVLong(ByteBuffer bb, int len, byte firstByte) { if (len == 1) { return firstByte; } long l = 0; for (int idx = 0; idx < len-1; idx++) { byte b = bb.get(); l = l << 8; l = l | (b & 0xFF); } return (isNegativeVNum(firstByte) ? ~l : l); } public static boolean isNegativeVNum(byte value) { return value < -120 || (value >= -112 && value < 0); } public static int decodeVNumSize(byte value) { if (value >= -112) { return 1; } else if (value < -120) { return -119 - value; } return -111 - value; } public static int getVNumSize(long i) { if (i >= -112 && i <= 127) { return 1; } if (i < 0) { i ^= -1L; // take one's complement' } // find the number of bytes with non-leading zeros int dataBits = Long.SIZE - Long.numberOfLeadingZeros(i); // find the number of data bytes + length byte return (dataBits + 7) / 8 + 1; } }