blob: e94f30d51d0cedbf8949252779384bd914ff8fb5 [file] [log] [blame]
// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import com.android.tools.r8.dex.DexReader;
import com.android.tools.r8.dex.DexOutputBuffer;
public class EncodedValueUtils {
public static long parseSigned(DexReader dexReader, int numberOfBytes) {
assert numberOfBytes > 0;
long result = 0;
int shift = 0;
for (int i = 1; i < numberOfBytes; i++) {
result |= ((long) (dexReader.get() & 0xFF)) << shift;
shift += 8;
}
// Let the last byte sign-extend into any remaining bytes.
return result | (((long) dexReader.get()) << shift);
}
// Inspired by com.android.dex.EncodedValueCodec
public static int putSigned(DexOutputBuffer outputBuffer, long value, int expectedSize) {
int bit_size = Long.SIZE + 1 - Long.numberOfLeadingZeros(value ^ (value >> (Long.SIZE - 1)));
int size = Math.max((bit_size + Byte.SIZE - 1) / Byte.SIZE, 1);
assert size > 0 && size <= expectedSize;
for (int i = 0; i < size; i++) {
outputBuffer.putByte((byte) value);
value >>= Byte.SIZE;
}
return size;
}
// Inspired by com.android.dex.EncodedValueCodec
public static byte[] encodeSigned(long value) {
int bit_size = Long.SIZE + 1 - Long.numberOfLeadingZeros(value ^ (value >> (Long.SIZE - 1)));
int size = Math.max((bit_size + Byte.SIZE - 1) / Byte.SIZE, 1);
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
result[i] = (byte) value;
value >>= Byte.SIZE;
}
return result;
}
public static long parseUnsigned(DexReader dexReader, int numberOfBytes) {
assert numberOfBytes > 0;
long result = 0;
int shift = 0;
for (int i = 0; i < numberOfBytes; i++) {
result |= ((long) (dexReader.get() & 0xFF)) << shift;
shift += 8;
}
return result;
}
// Inspired by com.android.dex.EncodedValueCodec
public static int putUnsigned(DexOutputBuffer outputBuffer, long value,
int expectedSize) {
int bit_size = Long.SIZE - Long.numberOfLeadingZeros(value);
int size = Math.max((bit_size + Byte.SIZE - 1) / Byte.SIZE, 1);
assert size > 0 && size <= expectedSize;
for (int i = 0; i < size; i++) {
outputBuffer.putByte((byte) value);
value >>= Byte.SIZE;
}
return size;
}
public static byte[] encodeUnsigned(long value) {
int bit_size = Long.SIZE - Long.numberOfLeadingZeros(value);
int size = Math.max((bit_size + Byte.SIZE - 1) / Byte.SIZE, 1);
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
result[i] = (byte) value;
value >>= Byte.SIZE;
}
return result;
}
public static int putBitsFromRightZeroExtended(DexOutputBuffer outputBuffer, long value,
int expectedSize) {
int bit_size = Long.SIZE - Long.numberOfTrailingZeros(value);
int size = (bit_size - 1) / Byte.SIZE + 1;
assert size > 0 && size <= expectedSize;
value >>= Long.SIZE - (size * Byte.SIZE); // shift trailing zeros.
for (int i = 0; i < size; i++) {
outputBuffer.putByte((byte) value);
value >>= Byte.SIZE;
}
return size;
}
private static byte[] encodeBitsFromRightZeroExtended(long value) {
int bit_size = Long.SIZE - Long.numberOfTrailingZeros(value);
int size = (bit_size - 1) / Byte.SIZE + 1;
value >>= Long.SIZE - (size * Byte.SIZE); // shift trailing zeros.
byte[] result = new byte[size];
for (int i = 0; i < size; i++) {
result[i] = (byte) value;
value >>= Byte.SIZE;
}
return result;
}
public static float parseFloat(DexReader dexReader, int numberOfBytes) {
long bits =
parseUnsigned(dexReader, numberOfBytes) << ((Float.BYTES - numberOfBytes) * Byte.SIZE);
return Float.intBitsToFloat((int) bits);
}
public static int putFloat(DexOutputBuffer outputBuffer, float value) {
long bits = ((long) Float.floatToIntBits(value)) << 32;
return EncodedValueUtils.putBitsFromRightZeroExtended(outputBuffer, bits, Float.BYTES);
}
public static byte[] encodeFloat(float value) {
long tmp = ((long) Float.floatToIntBits(value)) << 32;
byte[] result = EncodedValueUtils.encodeBitsFromRightZeroExtended(tmp);
assert result.length <= Float.BYTES;
return result;
}
public static double parseDouble(DexReader dexReader, int numberOfBytes) {
long bits =
parseUnsigned(dexReader, numberOfBytes) << ((Double.BYTES - numberOfBytes) * Byte.SIZE);
return Double.longBitsToDouble(bits);
}
public static int putDouble(DexOutputBuffer outputBuffer, double value) {
long bits = Double.doubleToLongBits(value);
return EncodedValueUtils.putBitsFromRightZeroExtended(outputBuffer, bits, Double.BYTES);
}
public static byte[] encodeDouble(double value) {
long tmp = Double.doubleToLongBits(value);
byte[] result = EncodedValueUtils.encodeBitsFromRightZeroExtended(tmp);
assert result.length <= Double.BYTES;
return result;
}
}