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