1 /* 2 * Copyright (C) 2008 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 * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3 24 * section 7.6. 25 */ 26 public final class Leb128 { Leb128()27 private Leb128() { 28 } 29 30 /** 31 * Gets the number of bytes in the unsigned LEB128 encoding of the 32 * given value. 33 * 34 * @param value the value in question 35 * @return its write size, in bytes 36 */ unsignedLeb128Size(int value)37 public static int unsignedLeb128Size(int value) { 38 // TODO: This could be much cleverer. 39 40 int remaining = value >> 7; 41 int count = 0; 42 43 while (remaining != 0) { 44 remaining >>= 7; 45 count++; 46 } 47 48 return count + 1; 49 } 50 51 /** 52 * Gets the number of bytes in the signed LEB128 encoding of the 53 * given value. 54 * 55 * @param value the value in question 56 * @return its write size, in bytes 57 */ signedLeb128Size(int value)58 public static int signedLeb128Size(int value) { 59 // TODO: This could be much cleverer. 60 61 int remaining = value >> 7; 62 int count = 0; 63 boolean hasMore = true; 64 int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; 65 66 while (hasMore) { 67 hasMore = (remaining != end) 68 || ((remaining & 1) != ((value >> 6) & 1)); 69 70 value = remaining; 71 remaining >>= 7; 72 count++; 73 } 74 75 return count; 76 } 77 78 /** 79 * Reads an signed integer from {@code in}. 80 */ readSignedLeb128(ByteInput in)81 public static int readSignedLeb128(ByteInput in) { 82 int result = 0; 83 int cur; 84 int count = 0; 85 int signBits = -1; 86 87 do { 88 cur = in.readByte() & 0xff; 89 result |= (cur & 0x7f) << (count * 7); 90 signBits <<= 7; 91 count++; 92 } while (((cur & 0x80) == 0x80) && count < 5); 93 94 if ((cur & 0x80) == 0x80) { 95 throw new DexException("invalid LEB128 sequence"); 96 } 97 98 // Sign extend if appropriate 99 if (((signBits >> 1) & result) != 0 ) { 100 result |= signBits; 101 } 102 103 return result; 104 } 105 106 /** 107 * Reads an unsigned integer from {@code in}. 108 */ readUnsignedLeb128(ByteInput in)109 public static int readUnsignedLeb128(ByteInput in) { 110 int result = 0; 111 int cur; 112 int count = 0; 113 114 do { 115 cur = in.readByte() & 0xff; 116 result |= (cur & 0x7f) << (count * 7); 117 count++; 118 } while (((cur & 0x80) == 0x80) && count < 5); 119 120 if ((cur & 0x80) == 0x80) { 121 throw new DexException("invalid LEB128 sequence"); 122 } 123 124 return result; 125 } 126 127 /** 128 * Writes {@code value} as an unsigned integer to {@code out}, starting at 129 * {@code offset}. Returns the number of bytes written. 130 */ writeUnsignedLeb128(ByteOutput out, int value)131 public static void writeUnsignedLeb128(ByteOutput out, int value) { 132 int remaining = value >>> 7; 133 134 while (remaining != 0) { 135 out.writeByte((byte) ((value & 0x7f) | 0x80)); 136 value = remaining; 137 remaining >>>= 7; 138 } 139 140 out.writeByte((byte) (value & 0x7f)); 141 } 142 143 /** 144 * Writes {@code value} as a signed integer to {@code out}, starting at 145 * {@code offset}. Returns the number of bytes written. 146 */ writeSignedLeb128(ByteOutput out, int value)147 public static void writeSignedLeb128(ByteOutput out, int value) { 148 int remaining = value >> 7; 149 boolean hasMore = true; 150 int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; 151 152 while (hasMore) { 153 hasMore = (remaining != end) 154 || ((remaining & 1) != ((value >> 6) & 1)); 155 156 out.writeByte((byte) ((value & 0x7f) | (hasMore ? 0x80 : 0))); 157 value = remaining; 158 remaining >>= 7; 159 } 160 } 161 } 162