1*055d4590SKeyi Gui /* 2*055d4590SKeyi Gui * Copyright (C) 2011 The Android Open Source Project 3*055d4590SKeyi Gui * 4*055d4590SKeyi Gui * Licensed under the Apache License, Version 2.0 (the "License"); 5*055d4590SKeyi Gui * you may not use this file except in compliance with the License. 6*055d4590SKeyi Gui * You may obtain a copy of the License at 7*055d4590SKeyi Gui * 8*055d4590SKeyi Gui * http://www.apache.org/licenses/LICENSE-2.0 9*055d4590SKeyi Gui * 10*055d4590SKeyi Gui * Unless required by applicable law or agreed to in writing, software 11*055d4590SKeyi Gui * distributed under the License is distributed on an "AS IS" BASIS, 12*055d4590SKeyi Gui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*055d4590SKeyi Gui * See the License for the specific language governing permissions and 14*055d4590SKeyi Gui * limitations under the License. 15*055d4590SKeyi Gui */ 16*055d4590SKeyi Gui 17*055d4590SKeyi Gui package com.android.dex; 18*055d4590SKeyi Gui 19*055d4590SKeyi Gui import com.android.dex.util.ByteInput; 20*055d4590SKeyi Gui import com.android.dex.util.ByteOutput; 21*055d4590SKeyi Gui 22*055d4590SKeyi Gui /** 23*055d4590SKeyi Gui * Read and write {@code encoded_value} primitives. 24*055d4590SKeyi Gui */ 25*055d4590SKeyi Gui public final class EncodedValueCodec { EncodedValueCodec()26*055d4590SKeyi Gui private EncodedValueCodec() { 27*055d4590SKeyi Gui } 28*055d4590SKeyi Gui 29*055d4590SKeyi Gui /** 30*055d4590SKeyi Gui * Writes a signed integral to {@code out}. 31*055d4590SKeyi Gui */ writeSignedIntegralValue(ByteOutput out, int type, long value)32*055d4590SKeyi Gui public static void writeSignedIntegralValue(ByteOutput out, int type, long value) { 33*055d4590SKeyi Gui /* 34*055d4590SKeyi Gui * Figure out how many bits are needed to represent the value, 35*055d4590SKeyi Gui * including a sign bit: The bit count is subtracted from 65 36*055d4590SKeyi Gui * and not 64 to account for the sign bit. The xor operation 37*055d4590SKeyi Gui * has the effect of leaving non-negative values alone and 38*055d4590SKeyi Gui * unary complementing negative values (so that a leading zero 39*055d4590SKeyi Gui * count always returns a useful number for our present 40*055d4590SKeyi Gui * purpose). 41*055d4590SKeyi Gui */ 42*055d4590SKeyi Gui int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63)); 43*055d4590SKeyi Gui 44*055d4590SKeyi Gui // Round up the requiredBits to a number of bytes. 45*055d4590SKeyi Gui int requiredBytes = (requiredBits + 0x07) >> 3; 46*055d4590SKeyi Gui 47*055d4590SKeyi Gui /* 48*055d4590SKeyi Gui * Write the header byte, which includes the type and 49*055d4590SKeyi Gui * requiredBytes - 1. 50*055d4590SKeyi Gui */ 51*055d4590SKeyi Gui out.writeByte(type | ((requiredBytes - 1) << 5)); 52*055d4590SKeyi Gui 53*055d4590SKeyi Gui // Write the value, per se. 54*055d4590SKeyi Gui while (requiredBytes > 0) { 55*055d4590SKeyi Gui out.writeByte((byte) value); 56*055d4590SKeyi Gui value >>= 8; 57*055d4590SKeyi Gui requiredBytes--; 58*055d4590SKeyi Gui } 59*055d4590SKeyi Gui } 60*055d4590SKeyi Gui 61*055d4590SKeyi Gui /** 62*055d4590SKeyi Gui * Writes an unsigned integral to {@code out}. 63*055d4590SKeyi Gui */ writeUnsignedIntegralValue(ByteOutput out, int type, long value)64*055d4590SKeyi Gui public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) { 65*055d4590SKeyi Gui // Figure out how many bits are needed to represent the value. 66*055d4590SKeyi Gui int requiredBits = 64 - Long.numberOfLeadingZeros(value); 67*055d4590SKeyi Gui if (requiredBits == 0) { 68*055d4590SKeyi Gui requiredBits = 1; 69*055d4590SKeyi Gui } 70*055d4590SKeyi Gui 71*055d4590SKeyi Gui // Round up the requiredBits to a number of bytes. 72*055d4590SKeyi Gui int requiredBytes = (requiredBits + 0x07) >> 3; 73*055d4590SKeyi Gui 74*055d4590SKeyi Gui /* 75*055d4590SKeyi Gui * Write the header byte, which includes the type and 76*055d4590SKeyi Gui * requiredBytes - 1. 77*055d4590SKeyi Gui */ 78*055d4590SKeyi Gui out.writeByte(type | ((requiredBytes - 1) << 5)); 79*055d4590SKeyi Gui 80*055d4590SKeyi Gui // Write the value, per se. 81*055d4590SKeyi Gui while (requiredBytes > 0) { 82*055d4590SKeyi Gui out.writeByte((byte) value); 83*055d4590SKeyi Gui value >>= 8; 84*055d4590SKeyi Gui requiredBytes--; 85*055d4590SKeyi Gui } 86*055d4590SKeyi Gui } 87*055d4590SKeyi Gui 88*055d4590SKeyi Gui /** 89*055d4590SKeyi Gui * Writes a right-zero-extended value to {@code out}. 90*055d4590SKeyi Gui */ writeRightZeroExtendedValue(ByteOutput out, int type, long value)91*055d4590SKeyi Gui public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) { 92*055d4590SKeyi Gui // Figure out how many bits are needed to represent the value. 93*055d4590SKeyi Gui int requiredBits = 64 - Long.numberOfTrailingZeros(value); 94*055d4590SKeyi Gui if (requiredBits == 0) { 95*055d4590SKeyi Gui requiredBits = 1; 96*055d4590SKeyi Gui } 97*055d4590SKeyi Gui 98*055d4590SKeyi Gui // Round up the requiredBits to a number of bytes. 99*055d4590SKeyi Gui int requiredBytes = (requiredBits + 0x07) >> 3; 100*055d4590SKeyi Gui 101*055d4590SKeyi Gui // Scootch the first bits to be written down to the low-order bits. 102*055d4590SKeyi Gui value >>= 64 - (requiredBytes * 8); 103*055d4590SKeyi Gui 104*055d4590SKeyi Gui /* 105*055d4590SKeyi Gui * Write the header byte, which includes the type and 106*055d4590SKeyi Gui * requiredBytes - 1. 107*055d4590SKeyi Gui */ 108*055d4590SKeyi Gui out.writeByte(type | ((requiredBytes - 1) << 5)); 109*055d4590SKeyi Gui 110*055d4590SKeyi Gui // Write the value, per se. 111*055d4590SKeyi Gui while (requiredBytes > 0) { 112*055d4590SKeyi Gui out.writeByte((byte) value); 113*055d4590SKeyi Gui value >>= 8; 114*055d4590SKeyi Gui requiredBytes--; 115*055d4590SKeyi Gui } 116*055d4590SKeyi Gui } 117*055d4590SKeyi Gui 118*055d4590SKeyi Gui /** 119*055d4590SKeyi Gui * Read a signed integer. 120*055d4590SKeyi Gui * 121*055d4590SKeyi Gui * @param zwidth byte count minus one 122*055d4590SKeyi Gui */ readSignedInt(ByteInput in, int zwidth)123*055d4590SKeyi Gui public static int readSignedInt(ByteInput in, int zwidth) { 124*055d4590SKeyi Gui int result = 0; 125*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 126*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 127*055d4590SKeyi Gui } 128*055d4590SKeyi Gui result >>= (3 - zwidth) * 8; 129*055d4590SKeyi Gui return result; 130*055d4590SKeyi Gui } 131*055d4590SKeyi Gui 132*055d4590SKeyi Gui /** 133*055d4590SKeyi Gui * Read an unsigned integer. 134*055d4590SKeyi Gui * 135*055d4590SKeyi Gui * @param zwidth byte count minus one 136*055d4590SKeyi Gui * @param fillOnRight true to zero fill on the right; false on the left 137*055d4590SKeyi Gui */ readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight)138*055d4590SKeyi Gui public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) { 139*055d4590SKeyi Gui int result = 0; 140*055d4590SKeyi Gui if (!fillOnRight) { 141*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 142*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 143*055d4590SKeyi Gui } 144*055d4590SKeyi Gui result >>>= (3 - zwidth) * 8; 145*055d4590SKeyi Gui } else { 146*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 147*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xff) << 24); 148*055d4590SKeyi Gui } 149*055d4590SKeyi Gui } 150*055d4590SKeyi Gui return result; 151*055d4590SKeyi Gui } 152*055d4590SKeyi Gui 153*055d4590SKeyi Gui /** 154*055d4590SKeyi Gui * Read a signed long. 155*055d4590SKeyi Gui * 156*055d4590SKeyi Gui * @param zwidth byte count minus one 157*055d4590SKeyi Gui */ readSignedLong(ByteInput in, int zwidth)158*055d4590SKeyi Gui public static long readSignedLong(ByteInput in, int zwidth) { 159*055d4590SKeyi Gui long result = 0; 160*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 161*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 162*055d4590SKeyi Gui } 163*055d4590SKeyi Gui result >>= (7 - zwidth) * 8; 164*055d4590SKeyi Gui return result; 165*055d4590SKeyi Gui } 166*055d4590SKeyi Gui 167*055d4590SKeyi Gui /** 168*055d4590SKeyi Gui * Read an unsigned long. 169*055d4590SKeyi Gui * 170*055d4590SKeyi Gui * @param zwidth byte count minus one 171*055d4590SKeyi Gui * @param fillOnRight true to zero fill on the right; false on the left 172*055d4590SKeyi Gui */ readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight)173*055d4590SKeyi Gui public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) { 174*055d4590SKeyi Gui long result = 0; 175*055d4590SKeyi Gui if (!fillOnRight) { 176*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 177*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 178*055d4590SKeyi Gui } 179*055d4590SKeyi Gui result >>>= (7 - zwidth) * 8; 180*055d4590SKeyi Gui } else { 181*055d4590SKeyi Gui for (int i = zwidth; i >= 0; i--) { 182*055d4590SKeyi Gui result = (result >>> 8) | ((in.readByte() & 0xffL) << 56); 183*055d4590SKeyi Gui } 184*055d4590SKeyi Gui } 185*055d4590SKeyi Gui return result; 186*055d4590SKeyi Gui } 187*055d4590SKeyi Gui } 188