1 /*
2  * Copyright (C) 2009 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 dex.reader;
18 
19 import java.io.BufferedInputStream;
20 import java.io.ByteArrayOutputStream;
21 import java.io.FileInputStream;
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 
26 public final class DexBuffer {
27 
28     private ByteBuffer b;
29 
DexBuffer(String fileName)30     public DexBuffer(String fileName) throws IOException {
31 
32         // FIXME channel? allocate fix size?
33         FileInputStream fis = null;
34         try {
35             fis = new FileInputStream(fileName);
36 
37             BufferedInputStream bis = new BufferedInputStream(fis);
38             ByteArrayOutputStream bos = new ByteArrayOutputStream();
39             byte[] buf = new byte[1024];
40             int len;
41             while ((len = bis.read(buf)) > 0) {
42                 bos.write(buf, 0, len);
43             }
44             byte[] bytes = bos.toByteArray();
45             initialize(ByteBuffer.wrap(bytes));
46         } finally {
47             if (fis != null) {
48                 fis.close();
49             }
50         }
51     }
52 
DexBuffer(byte[] bytes)53     public DexBuffer(byte[] bytes) {
54         initialize(ByteBuffer.wrap(bytes));
55     }
56 
DexBuffer(ByteBuffer slice)57     private DexBuffer(ByteBuffer slice) {
58         initialize(slice);
59     }
60 
initialize(ByteBuffer buffer)61     private void initialize(ByteBuffer buffer) {
62         b = buffer.asReadOnlyBuffer();
63         b.clear();
64         b.order(ByteOrder.LITTLE_ENDIAN);
65     }
66 
setPosition(int offset)67     public void setPosition(int offset) {
68         b.position(offset);
69     }
70 
readBytes(byte[] dst)71     public void readBytes(byte[] dst) {
72         b.get(dst, 0, dst.length);
73     }
74 
75     /**
76      * FIXME make endian dependent
77      */
readUleb128()78     public int readUleb128() {
79         int endValue = 0;
80         int value = 0;
81         int nr = 0;
82         do {
83             value = (b.get() & 0xFF);
84             endValue |= ((value & 0x7F) << 7 * nr);// cut away left most bit
85             nr++;
86         } while ((value & 0x80) != 0); // highest bit set?
87         return endValue;
88     }
89 
90     /**
91      * pre 0 < nBytes <=4
92      */
readInt(int nBytes)93     public int readInt(int nBytes) {
94         int endValue = 0;
95         int tmp = 0;
96         for (int i = 0; i < nBytes; i++) {
97             tmp = b.get() & 0xFF;
98             endValue |= (tmp << i * 8);
99         }
100         return endValue;
101     }
102 
103     /**
104      * pre 0 < nBytes <=1 FIXME: Sign extension
105      */
readShort(int nBytes)106     public short readShort(int nBytes) {
107         short endValue = 0;
108         int tmp = 0;
109         for (int i = 0; i < nBytes; i++) {
110             tmp = b.get() & 0xFF;
111             endValue |= (tmp << i * 8);
112         }
113         return endValue;
114     }
115 
116     /**
117      * pre 0 < nBytes <=1
118      */
readChar(int nBytes)119     public char readChar(int nBytes) {
120         char endValue = 0;
121         int tmp = 0;
122         for (int i = 0; i < nBytes; i++) {
123             tmp = b.get() & 0xFF;
124             endValue |= (tmp << i * 8);
125         }
126         return endValue;
127     }
128 
129     /**
130      * pre 0 < nBytes <=7 FIXME: Sign extension
131      */
readLong(int nBytes)132     public long readLong(int nBytes) {
133         long endValue = 0;
134         int tmp = 0;
135         for (int i = 0; i < nBytes; i++) {
136             tmp = b.get() & 0xFF;
137             endValue |= (tmp << i * 8);
138         }
139         return endValue;
140     }
141 
142     /**
143      * pre 0 < nBytes <=4
144      */
readFloat(int nBytes)145     public float readFloat(int nBytes) {
146         int bits = readInt(nBytes);
147         int bytesToMove = (4 - nBytes) * 8;
148         bits <<= bytesToMove;
149         return Float.intBitsToFloat(bits);
150     }
151 
152     // returns int form current position
readUInt()153     public int readUInt() {
154         int value = b.getInt();
155         // assert value >= 0;
156         return value;
157     }
158 
readUShort()159     public int readUShort() {
160         return b.getShort() & 0xFFFF;
161     }
162 
163     // returns byte form current position
readUByte()164     public byte readUByte() {
165         return b.get();
166     }
167 
createCopy()168     public DexBuffer createCopy() {
169         return new DexBuffer(b.duplicate());
170     }
171 
readDouble(int nBytes)172     public double readDouble(int nBytes) {
173         long bits = readLong(nBytes);
174         int bytesToMove = (8 - nBytes) * 8;
175         bits <<= bytesToMove;
176         return Double.longBitsToDouble(bits);
177     }
178 
skip(int nBytes)179     public void skip(int nBytes) {
180         b.position(b.position() + nBytes);
181     }
182 }
183