Leb128Utils.java revision 579d7739c53a2707ad711a2d2cae46d7d782f061
172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com/* 272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Copyright (C) 2008 The Android Open Source Project 372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * 472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Licensed under the Apache License, Version 2.0 (the "License"); 572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * you may not use this file except in compliance with the License. 672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * You may obtain a copy of the License at 772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * 872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * http://www.apache.org/licenses/LICENSE-2.0 972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * 1072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Unless required by applicable law or agreed to in writing, software 1172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * distributed under the License is distributed on an "AS IS" BASIS, 1272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * See the License for the specific language governing permissions and 1472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * limitations under the License. 1572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com */ 1672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 1772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.compackage com.android.dx.util; 1872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 1972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com/** 2072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3 2172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * section 7.6. 2272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com */ 2372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.compublic final class Leb128Utils { 2472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com /** 2572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * This class is uninstantiable. 2672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com */ 2772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com private Leb128Utils() { 2872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com // This space intentionally left blank. 2972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com } 3072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 3172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com /** 3272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Gets the number of bytes in the unsigned LEB128 encoding of the 3372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * given value. 3472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * 3572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * @param value the value in question 3672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * @return its write size, in bytes 3772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com */ 3872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com public static int unsignedLeb128Size(int value) { 3972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com // TODO: This could be much cleverer. 4072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 4172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com int remaining = value >> 7; 4272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com int count = 0; 4372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 4472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com while (remaining != 0) { 4572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com remaining >>= 7; 4672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com count++; 4772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com } 4872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 4972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com return count + 1; 5072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com } 5172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 5272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com /** 5372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * Gets the number of bytes in the signed LEB128 encoding of the 5472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * given value. 5572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * 5672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * @param value the value in question 5772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com * @return its write size, in bytes 5872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com */ 5972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com public static int signedLeb128Size(int value) { 6072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com // TODO: This could be much cleverer. 6172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 6272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com int remaining = value >> 7; 6372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com int count = 0; 6472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com boolean hasMore = true; 6572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1; 6672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 6772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com while (hasMore) { 6872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com hasMore = (remaining != end) 6972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com || ((remaining & 1) != ((value >> 6) & 1)); 7072f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 7172f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com value = remaining; 7272f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com remaining >>= 7; 7372f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com count++; 7472f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com } 7572f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 7672f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com return count; 7772f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com } 7872f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com 7972f428db148f97e97f861b103d7fff1d53032a71kjellander@google.com /** 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