All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.common.geometry.DlugoszVarLenIntPacker Maven / Gradle / Ivy

package org.opentripplanner.common.geometry;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Variable-length integer encoding. This optimize integer storage when most of the values are
 * small, but few of them can be quite large (as in a geometry). Adapted Dlugosz scheme to support
 * signed int whose average are around 0.
 * 
 * See Dlugosz' variable-length integer encoding (http://www.dlugosz.com/ZIP2/VLI.html).
 * 
 * @author laurent
 * 
 */
public class DlugoszVarLenIntPacker {

    public static byte[] pack(int[] arr) {
        if (arr == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream(arr.length);
        for (int i : arr) {
            if (i >= -64 && i <= 63) {
                // 0xxx xxxx -> 7 bits value
                // i+64 between 0 and 127, 7 bits
                int ui = i + 64;
                baos.write(ui);
            } else if (i >= -8192 && i <= 8191) {
                // 10xx xxxx + 8 -> 14 bits value
                // i+8192 between 0 and 16383
                int ui = i + 8192;
                baos.write(0x80 | (ui >> 8)); // 6b MSB
                baos.write(ui & 0xFF); // 8b LSB
            } else if (i >= -1048576 && i <= 1048575) {
                // 110 xxxx + 2x8 -> 21 bits value
                // i + 1048576 between 0 and 2097151
                int ui = i + 1048576;
                baos.write(0xC0 | (ui >> 16)); // 5b MSB
                baos.write((ui >> 8) & 0xFF); // 8b
                baos.write(ui & 0xFF); // 8b
            } else if (i >= -67108864 && i <= 67108863) {
                // 1110 0xxx + 3x8 -> 27 bits value
                // i + 67108864 between 0 and 134217727
                int ui = i + 67108864;
                baos.write(0xE0 | (ui >> 24)); // 3b MSB
                baos.write((ui >> 16) & 0xFF); // 8b
                baos.write((ui >> 8) & 0xFF); // 8b
                baos.write(ui & 0xFF); // 8b
            } else { // int can't have more than 32 bits
                // 1110 1xxx + 4x8 -> 35 bits value
                // i + 0x80000000 fits in 35 bits for sure
                long ui = (long) i + 2147483648L;
                baos.write((int) (0xE8 | (ui >> 32))); // 3b MSB
                baos.write((int) ((ui >> 24) & 0xFF)); // 8b
                baos.write((int) ((ui >> 16) & 0xFF)); // 8b
                baos.write((int) ((ui >> 8) & 0xFF)); // 8b
                baos.write((int) (ui & 0xFF)); // 8b
            }
        }
        return baos.toByteArray();
    }

    public static int[] unpack(byte[] arr) {
        if (arr == null) {
            return null;
        }
        List retval = new ArrayList(arr.length);
        int i = 0;
        while (i < arr.length) {
            int v1 = arr[i] & 0xFF;
            i++;
            if ((v1 & 0x80) == 0x00) {
                // 0xxx xxxx -> 7 bits value
                int sv = (v1 & 0x7F) - 64;
                retval.add(sv);
            } else if ((v1 & 0xC0) == 0x80) {
                // 10xx xxxx + 8 -> 14 bits value
                int sv = ((v1 & 0x3F) << 8) + (arr[i] & 0xFF) - 8192;
                i++;
                retval.add(sv);
            } else if ((v1 & 0xE0) == 0xC0) {
                // 110 xxxx + 2x8 -> 21 bits value
                int sv = ((v1 & 0x1F) << 16) + ((arr[i] & 0xFF) << 8) + (arr[i + 1] & 0xFF)
                        - 1048576;
                i += 2;
                retval.add(sv);
            } else if ((v1 & 0xF8) == 0xE0) {
                // 1110 0xxx + 3x8 -> 27 bits value
                int sv = ((v1 & 0x1F) << 24) + ((arr[i] & 0xFF) << 16) + ((arr[i + 1] & 0xFF) << 8)
                        + (arr[i + 2] & 0xFF) - 67108864;
                i += 3;
                retval.add(sv);
            } else {
                // 1110 1xxx + 4x8 -> 35 bits value
                long sv = (((long) v1 & 0x1F) << 32) + ((arr[i] & 0xFF) << 24)
                        + ((arr[i + 1] & 0xFF) << 16) + ((arr[i + 2] & 0xFF) << 8)
                        + (arr[i + 3] & 0xFF) - 2147483648L;
                i += 4;
                retval.add((int) sv);
            }
        }
        int[] bufret = new int[retval.size()];
        i = 0;
        for (int v : retval) {
            bufret[i++] = v;
        }
        return bufret;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy