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