/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package hivemall.utils.codec; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import javax.annotation.Nonnull; /** * @link https://en.wikipedia.org/wiki/LEB128 */ public final class ZigZagLEB128Codec { private ZigZagLEB128Codec() {} public static int encode(final int n) { return (n << 1) ^ (n >> 31); } public static long encode(final long n) { return (n << 1) ^ (n >> 63); } public static int decode(final int n) { return (n >>> 1) ^ -(n & 1); } public static long decode(final long n) { return (n >>> 1) ^ -(n & 1); } public static void writeSignedInt(final int value, @Nonnull final DataOutput out) throws IOException { writeUnsignedInt(encode(value), out); } public static void writeUnsignedInt(int value, @Nonnull final DataOutput out) throws IOException { while ((value & ~0x7F) != 0L) { out.writeByte((value & 0x7F) | 0x80); value >>>= 7; } out.writeByte(value & 0x7F); } public static void writeSignedLong(final long value, @Nonnull final DataOutput out) throws IOException { writeUnsignedLong(encode(value), out); } private static void writeUnsignedLong(long value, @Nonnull final DataOutput out) throws IOException { while ((value & ~0x7FL) != 0L) { out.writeByte(((int) value & 0x7F) | 0x80); value >>>= 7; } out.writeByte((int) value & 0x7F); } public static int readSignedInt(@Nonnull final DataInput in) throws IOException { int raw = readUnsignedInt(in); int temp = (((raw << 31) >> 31) ^ raw) >> 1; return temp ^ (raw & (1 << 31)); } public static int readUnsignedInt(@Nonnull final DataInput in) throws IOException { int value = 0; int i = 0; int b; while (((b = in.readByte()) & 0x80) != 0) { value |= (b & 0x7F) << i; i += 7; if (i > 35) { throw new IllegalArgumentException("Variable length quantity is too long: " + i); } } return value | (b << i); } public static long readSignedLong(@Nonnull final DataInput in) throws IOException { long raw = readUnsignedLong(in); long temp = (((raw << 63) >> 63) ^ raw) >> 1; return temp ^ (raw & (1L << 63)); } public static long readUnsignedLong(@Nonnull final DataInput in) throws IOException { long value = 0L; int i = 0; long b; while (((b = in.readByte()) & 0x80L) != 0) { value |= (b & 0x7F) << i; i += 7; if (i > 63) { throw new IllegalArgumentException("Variable length quantity is too long: " + i); } } return value | (b << i); } @Deprecated public static void writeFloat(final float value, final DataOutput out) throws IOException { int bits = Float.floatToIntBits(value); writeSignedInt(bits, out); } @Deprecated public static float readFloat(@Nonnull final DataInput in) throws IOException { int bits = readSignedInt(in); return Float.intBitsToFloat(bits); } @Deprecated public static void writeDouble(final double value, final DataOutput out) throws IOException { long bits = Double.doubleToLongBits(value); writeSignedLong(bits, out); } @Deprecated public static double readDouble(@Nonnull final DataInput in) throws IOException { long bits = readSignedLong(in); return Double.longBitsToDouble(bits); } }