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