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