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 * Reads an signed integer from {@code in}. 53 */ readSignedLeb128(ByteInput in)54 public static int readSignedLeb128(ByteInput in) { 55 int result = 0; 56 int cur; 57 int count = 0; 58 int signBits = -1; 59 60 do { 61 cur = in.readByte() & 0xff; 62 result |= (cur & 0x7f) << (count * 7); 63 signBits <<= 7; 64 count++; 65 } while (((cur & 0x80) == 0x80) && count < 5); 66 67 if ((cur & 0x80) == 0x80) { 68 throw new DexException("invalid LEB128 sequence"); 69 } 70 71 // Sign extend if appropriate 72 if (((signBits >> 1) & result) != 0 ) { 73 result |= signBits; 74 } 75 76 return result; 77 } 78 79 /** 80 * Reads an unsigned integer from {@code in}. 81 */ readUnsignedLeb128(ByteInput in)82 public static int readUnsignedLeb128(ByteInput in) { 83 int result = 0; 84 int cur; 85 int count = 0; 86 87 do { 88 cur = in.readByte() & 0xff; 89 result |= (cur & 0x7f) << (count * 7); 90 count++; 91 } while (((cur & 0x80) == 0x80) && count < 5); 92 93 if ((cur & 0x80) == 0x80) { 94 throw new DexException("invalid LEB128 sequence"); 95 } 96 97 return result; 98 } 99 100 /** 101 * Writes {@code value} as an unsigned integer to {@code out}, starting at 102 * {@code offset}. Returns the number of bytes written. 103 */ writeUnsignedLeb128(ByteOutput out, int value)104 public static void writeUnsignedLeb128(ByteOutput out, int value) { 105 int remaining = value >>> 7; 106 107 while (remaining != 0) { 108 out.writeByte((byte) ((value & 0x7f) | 0x80)); 109 value = remaining; 110 remaining >>>= 7; 111 } 112 113 out.writeByte((byte) (value & 0x7f)); 114 } 115 116 /** 117 * Writes {@code value} as a signed integer to {@code out}, starting at 118 * {@code offset}. Returns the number of bytes written. 119 */ writeSignedLeb128(ByteOutput out, int value)120 public static void writeSignedLeb128(ByteOutput out, int value) { 121 int remaining = value >> 7; 122 boolean hasMore = true; 123 int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; 124 125 while (hasMore) { 126 hasMore = (remaining != end) 127 || ((remaining & 1) != ((value >> 6) & 1)); 128 129 out.writeByte((byte) ((value & 0x7f) | (hasMore ? 0x80 : 0))); 130 value = remaining; 131 remaining >>= 7; 132 } 133 } 134 } 135