• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.dx.util;
18 
19 /**
20  * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3
21  * section 7.6.
22  */
23 public final class Leb128Utils {
24     /**
25      * This class is uninstantiable.
26      */
Leb128Utils()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      */
unsignedLeb128Size(int value)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      */
signedLeb128Size(int value)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      */
readSignedLeb128(ByteInput in)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      */
readUnsignedLeb128(ByteInput in)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      */
writeUnsignedLeb128(ByteOutput out, int value)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      */
writeSignedLeb128(ByteOutput out, int value)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