Package com.thinkaurelius.titan.graphdb.database.idhandling

Source Code of com.thinkaurelius.titan.graphdb.database.idhandling.VariableLong

package com.thinkaurelius.titan.graphdb.database.idhandling;

import com.thinkaurelius.titan.diskstorage.ReadBuffer;
import com.thinkaurelius.titan.diskstorage.StaticBuffer;
import com.thinkaurelius.titan.diskstorage.WriteBuffer;
import com.thinkaurelius.titan.diskstorage.util.WriteByteBuffer;

/**
* @author Matthias Broecheler (me@matthiasb.com)
*/

public class VariableLong {

    public static int unsignedByte(byte b) {
        return b < 0 ? b + 256 : b;
    }

    //Move stop bit back to front => rewrite prefix variable encoding by custom writing first byte

    private static final byte BIT_MASK = 127;
    private static final byte STOP_MASK = -128;

    private static long readUnsigned(ReadBuffer in) {
        long value = 0;
        byte b;
        do {
            b = in.getByte();
            value = value << 7 | (b & BIT_MASK);
        } while (b >= 0);
        return value;
    }


    private static void writeUnsigned(WriteBuffer out, final long value) {
        writeUnsigned(out, unsignedBlockBitLength(value), value);
    }

    private static void writeUnsigned(WriteBuffer out, int offset, final long value) {
        assert offset % 7 == 0;
        while (offset > 0) {
            offset -= 7;
            byte b = (byte) ((value >>> offset) & BIT_MASK);
            if (offset == 0) {
                b = (byte) (b | STOP_MASK);
            }
            out.putByte(b);
        }
    }

    private static int unsignedBlockBitLength(final long value) {
        return unsignedNumBlocks(value)*7;
    }

    private static int unsignedNumBlocks(final long value) {
        return numVariableBlocks(unsignedBitLength(value));
    }

    private static int numVariableBlocks(final int numBits) {
        assert numBits > 0;
        return (numBits - 1) / 7 + 1;
    }

    public static int unsignedBitLength(final long value) {
        return (value == 0) ? 1 : Long.SIZE - Long.numberOfLeadingZeros(value);
    }

    /* ##################################
          Read and write positive longs
       ################################## */


    public static long readPositive(ReadBuffer in) {
        long value = readUnsigned(in);
        assert value >= 0;
        return value;
    }

    public static void writePositive(WriteBuffer out, final long value) {
        assert value >= 0;
        writeUnsigned(out, value);
    }

    public static StaticBuffer positiveByteBuffer(final long value) {
        WriteBuffer buffer = new WriteByteBuffer(positiveLength(value));
        writePositive(buffer, value);
        return buffer.getStaticBuffer();
    }


    public static StaticBuffer positiveByteBuffer(long[] value) {
        int len = 0;
        for (long aValue : value)
            len += positiveLength(aValue);

        WriteBuffer buffer = new WriteByteBuffer(len);

        for (long aValue : value)
            writePositive(buffer, aValue);

        return buffer.getStaticBuffer();
    }

    public static int positiveLength(long value) {
        assert value >= 0;
        return unsignedNumBlocks(value);
    }

    /* ##################################
      Read and write arbitrary longs
    ################################## */

    private static long convert2Unsigned(final long value) {
        assert value >= 0 || value > Long.MIN_VALUE;
        return Math.abs(value) << 1 | (value < 0 ? 1 : 0);
    }

    private static long convertFromUnsigned(final long value) {
        return ((value & 1) == 1) ? -(value >>> 1) : value >>> 1;
    }

    public static int length(long value) {
        return unsignedNumBlocks(convert2Unsigned(value));
    }

    public static void write(WriteBuffer out, final long value) {
        writeUnsigned(out, convert2Unsigned(value));
    }

    public static long read(ReadBuffer in) {
        return convertFromUnsigned(readUnsigned(in));
    }


    /* ##################################
      Read and write positive longs with a specified binary prefix of fixed length
    ################################## */

    public static void writePositiveWithPrefix(final WriteBuffer out, long value, long prefix, final int prefixBitLen) {
        assert value >= 0;
        assert prefixBitLen > 0 && prefixBitLen < 6 && (prefix < (1L << prefixBitLen));
        //Write first byte
        int deltaLen = 8 - prefixBitLen;
        byte first = (byte)(prefix<<deltaLen);
        int valueLen = unsignedBitLength(value);
        int mod = valueLen%7;
        if (mod<=(deltaLen-1)) {
            int offset = (valueLen-mod);
            first = (byte)(first | (value >>> offset));
            value = value & ((1l<<offset)-1);
            valueLen -= mod;
        } else {
            valueLen += (7-mod);
        }
        if (valueLen==0) {
            //Add stop mask
            first = (byte) ( first | (1<<(deltaLen-1)));
        }
        out.putByte(first);
        if (valueLen>0) {
            //Keep writing
            writeUnsigned(out,valueLen,value);
        }
    }

    public static int positiveWithPrefixLength(final long value, final int prefixBitLen) {
        assert value >= 0;
        assert prefixBitLen > 0 && prefixBitLen < 6;
        return numVariableBlocks(unsignedBitLength(value)+prefixBitLen);
    }

    public static long[] readPositiveWithPrefix(final ReadBuffer in, final int prefixBitLen) {
        assert prefixBitLen > 0 && prefixBitLen < 6;

        int first = unsignedByte(in.getByte());
        int deltaLen = 8 - prefixBitLen;
        long prefix = first>>deltaLen;
        long value =  first & ((1<<(deltaLen-1))-1);
        if ( ((first>>>(deltaLen-1)) & 1) == 0) { //No stop mask
            int deltaPos = in.getPosition();
            long remainder = readUnsigned(in);
            deltaPos = in.getPosition()-deltaPos;
            assert deltaPos > 0;
            value = (value<<(deltaPos*7)) + remainder;
        }
        return new long[]{value, prefix};
    }


    /* ##################################
      Write positive longs so that they can be read backwards
      Use positiveLength() for length
    ################################## */

    public static void writePositiveBackward(WriteBuffer out, long value) {
        assert value >= 0;
        writeUnsignedBackward(out,value);
    }

    public static long readPositiveBackward(ReadBuffer in) {
        return readUnsignedBackward(in);
    }

    /* ##################################
      Write arbitrary longs so that they can be read backwards
      Use length() for length
    ################################## */

    public static void writeBackward(WriteBuffer out, final long value) {
        writeUnsignedBackward(out, convert2Unsigned(value));
    }

    public static long readBackward(ReadBuffer in) {
        return convertFromUnsigned(readUnsignedBackward(in));
    }

    private static void writeUnsignedBackward(WriteBuffer out, long value) {
        boolean first = true;
        do {
            byte b = (byte) (value & BIT_MASK);
            value = value >>> 7;
            if (first) {
                b = (byte) (b | STOP_MASK);
                first = false;
            }
            out.putByte(b);
        } while (value>0);
    }

    private static long readUnsignedBackward(ReadBuffer in) {
        int position = in.getPosition();
        long value = 0;
        int b;
        do {
            b = in.getByte(position);
            value = value << 7 | b & BIT_MASK;
            position--;
        } while (b >= 0);
        in.movePosition(position-in.getPosition());
        return value;
    }


}
TOP

Related Classes of com.thinkaurelius.titan.graphdb.database.idhandling.VariableLong

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.