12bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson/* 22bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Copyright (C) 2011 The Android Open Source Project 32bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 42bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Licensed under the Apache License, Version 2.0 (the "License"); 52bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * you may not use this file except in compliance with the License. 62bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * You may obtain a copy of the License at 72bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 82bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * http://www.apache.org/licenses/LICENSE-2.0 92bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Unless required by applicable law or agreed to in writing, software 112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * distributed under the License is distributed on an "AS IS" BASIS, 122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * See the License for the specific language governing permissions and 142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * limitations under the License. 152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonpackage com.android.dex; 182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport com.android.dex.util.ByteInput; 202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonimport com.android.dex.util.ByteOutput; 212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson/** 232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Read and write {@code encoded_value} primitives. 242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilsonpublic final class EncodedValueCodec { 262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson private EncodedValueCodec() { 272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Writes a signed integral to {@code out}. 312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static void writeSignedIntegralValue(ByteOutput out, int type, long value) { 332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /* 342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Figure out how many bits are needed to represent the value, 352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * including a sign bit: The bit count is subtracted from 65 362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * and not 64 to account for the sign bit. The xor operation 372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * has the effect of leaving non-negative values alone and 382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * unary complementing negative values (so that a leading zero 392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * count always returns a useful number for our present 402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * purpose). 412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63)); 432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Round up the requiredBits to a number of bytes. 452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBytes = (requiredBits + 0x07) >> 3; 462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /* 482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Write the header byte, which includes the type and 492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * requiredBytes - 1. 502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte(type | ((requiredBytes - 1) << 5)); 522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Write the value, per se. 542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson while (requiredBytes > 0) { 552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte((byte) value); 562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson value >>= 8; 572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson requiredBytes--; 582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Writes an unsigned integral to {@code out}. 632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) { 652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Figure out how many bits are needed to represent the value. 662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBits = 64 - Long.numberOfLeadingZeros(value); 672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (requiredBits == 0) { 682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson requiredBits = 1; 692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Round up the requiredBits to a number of bytes. 722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBytes = (requiredBits + 0x07) >> 3; 732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /* 752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Write the header byte, which includes the type and 762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * requiredBytes - 1. 772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte(type | ((requiredBytes - 1) << 5)); 792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Write the value, per se. 812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson while (requiredBytes > 0) { 822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte((byte) value); 832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson value >>= 8; 842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson requiredBytes--; 852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 882bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 892bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Writes a right-zero-extended value to {@code out}. 902bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 912bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) { 922bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Figure out how many bits are needed to represent the value. 932bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBits = 64 - Long.numberOfTrailingZeros(value); 942bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (requiredBits == 0) { 952bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson requiredBits = 1; 962bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 972bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 982bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Round up the requiredBits to a number of bytes. 992bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int requiredBytes = (requiredBits + 0x07) >> 3; 1002bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1012bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Scootch the first bits to be written down to the low-order bits. 1022bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson value >>= 64 - (requiredBytes * 8); 1032bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1042bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /* 1052bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Write the header byte, which includes the type and 1062bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * requiredBytes - 1. 1072bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1082bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte(type | ((requiredBytes - 1) << 5)); 1092bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1102bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson // Write the value, per se. 1112bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson while (requiredBytes > 0) { 1122bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson out.writeByte((byte) value); 1132bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson value >>= 8; 1142bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson requiredBytes--; 1152bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1162bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1172bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1182bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1192bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Read a signed integer. 1202bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 1212bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param zwidth byte count minus one 1222bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1232bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static int readSignedInt(ByteInput in, int zwidth) { 1242bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int result = 0; 1252bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1262bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 1272bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1282bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result >>= (3 - zwidth) * 8; 1292bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 1302bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1312bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1322bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1332bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Read an unsigned integer. 1342bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 1352bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param zwidth byte count minus one 1362bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param fillOnRight true to zero fill on the right; false on the left 1372bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1382bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) { 1392bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson int result = 0; 1402bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (!fillOnRight) { 1412bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1422bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 1432bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1442bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result >>>= (3 - zwidth) * 8; 1452bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } else { 1462bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1472bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 1482bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1492bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1502bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 1512bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1522bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1532bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1542bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Read a signed long. 1552bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 1562bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param zwidth byte count minus one 1572bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1582bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static long readSignedLong(ByteInput in, int zwidth) { 1592bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson long result = 0; 1602bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1612bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 1622bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1632bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result >>= (7 - zwidth) * 8; 1642bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 1652bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1662bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson 1672bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson /** 1682bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * Read an unsigned long. 1692bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * 1702bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param zwidth byte count minus one 1712bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson * @param fillOnRight true to zero fill on the right; false on the left 1722bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson */ 1732bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) { 1742bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson long result = 0; 1752bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson if (!fillOnRight) { 1762bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1772bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 1782bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1792bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result >>>= (7 - zwidth) * 8; 1802bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } else { 1812bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson for (int i = zwidth; i >= 0; i--) { 1822bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 1832bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1842bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1852bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson return result; 1862bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson } 1872bea5ee615b0f4add658d5660bd81c5145a0d05eJesse Wilson} 188