1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.util;
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.DataInputStream;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
2499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * Wrapper for a {@code byte[]}, which provides read-only access and
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can "reveal" a partial slice of the underlying array.
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <b>Note:</b> Multibyte accessors all use big-endian order.
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class ByteArray {
3099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code non-null;} underlying array */
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final byte[] bytes;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= 0}; start index of the slice (inclusive) */
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int start;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code >= 0, <= bytes.length}; size computed as
3799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code end - start} (in the constructor) */
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private final int size;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs an instance.
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
4399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param bytes {@code non-null;} the underlying array
4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param start {@code >= 0;} start index of the slice (inclusive)
4599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param end {@code >= start, <= bytes.length;} end index of
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the slice (exclusive)
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ByteArray(byte[] bytes, int start, int end) {
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bytes == null) {
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException("bytes == null");
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start < 0) {
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("start < 0");
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (end < start) {
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("end < start");
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (end > bytes.length) {
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("end > bytes.length");
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.bytes = bytes;
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.start = start;
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.size = end - start;
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Constructs an instance from an entire {@code byte[]}.
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
7399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param bytes {@code non-null;} the underlying array
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ByteArray(byte[] bytes) {
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this(bytes, 0, bytes.length);
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the size of the array, in bytes.
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
8299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code >= 0;} the size
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int size() {
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return size;
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns a slice (that is, a sub-array) of this instance.
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
9199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param start {@code >= 0;} start index of the slice (inclusive)
9299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param end {@code >= start, <= size();} end index of
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the slice (exclusive)
9499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} the slice
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ByteArray slice(int start, int end) {
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(start, end);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new ByteArray(bytes, start + this.start, end + this.start);
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the offset into the given array represented by the given
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * offset into this instance.
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param offset offset into this instance
10699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param bytes {@code non-null;} (alleged) underlying array
10799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return corresponding offset into {@code bytes}
10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @throws IllegalArgumentException thrown if {@code bytes} is
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * not the underlying array of this instance
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int underlyingOffset(int offset, byte[] bytes) {
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bytes != this.bytes) {
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("wrong bytes");
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return start + offset;
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
12099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code signed byte} value at a particular offset.
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
12299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < size();} offset to fetch
12399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code signed byte} at that offset
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getByte(int off) {
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 1);
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getByte0(off);
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
13199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code signed short} value at a particular offset.
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
13399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < (size() - 1);} offset to fetch
13499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code signed short} at that offset
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getShort(int off) {
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 2);
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (getByte0(off) << 8) | getUnsignedByte0(off + 1);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
14299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code signed int} value at a particular offset.
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
14499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < (size() - 3);} offset to fetch
14599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code signed int} at that offset
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getInt(int off) {
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 4);
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (getByte0(off) << 24) |
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 1) << 16) |
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 2) << 8) |
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getUnsignedByte0(off + 3);
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
15699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code signed long} value at a particular offset.
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
15899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < (size() - 7);} offset to fetch
15999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code signed int} at that offset
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public long getLong(int off) {
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 8);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int part1 = (getByte0(off) << 24) |
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 1) << 16) |
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 2) << 8) |
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getUnsignedByte0(off + 3);
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int part2 = (getByte0(off + 4) << 24) |
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 5) << 16) |
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            (getUnsignedByte0(off + 6) << 8) |
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            getUnsignedByte0(off + 7);
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (part2 & 0xffffffffL) | ((long) part1) << 32;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
17699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code unsigned byte} value at a particular offset.
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
17899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < size();} offset to fetch
17999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code unsigned byte} at that offset
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getUnsignedByte(int off) {
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 1);
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getUnsignedByte0(off);
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code unsigned short} value at a particular offset.
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
18999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param off {@code >= 0, < (size() - 1);} offset to fetch
19099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code unsigned short} at that offset
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int getUnsignedShort(int off) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        checkOffsets(off, off + 2);
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (getUnsignedByte0(off) << 8) | getUnsignedByte0(off + 1);
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Copies the contents of this instance into the given raw
19999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code byte[]} at the given offset. The given array must be
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * large enough.
201de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
20299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param out {@code non-null;} array to hold the output
20399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param offset {@code non-null;} index into {@code out} for the first
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * byte of output
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void getBytes(byte[] out, int offset) {
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((out.length - offset) < size) {
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IndexOutOfBoundsException("(out.length - offset) < " +
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                                "size()");
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(bytes, start, out, offset, size);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Checks a range of offsets for validity, throwing if invalid.
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param s start offset (inclusive)
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param e end offset (exclusive)
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void checkOffsets(int s, int e) {
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((s < 0) || (e < s) || (e > size)) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("bad range: " + s + ".." + e +
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                               "; actual size " + size);
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
22999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code signed byte} value at the given offset,
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without doing any argument checking.
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param off offset to fetch
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return byte at that offset
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getByte0(int off) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytes[start + off];
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
24099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the {@code unsigned byte} value at the given offset,
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * without doing any argument checking.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param off offset to fetch
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return byte at that offset
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int getUnsignedByte0(int off) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return bytes[start + off] & 0xff;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
25199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets a {@code DataInputStream} that reads from this instance,
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with the cursor starting at the beginning of this instance's data.
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if needed.
255de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
25699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed
25799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code DataInputStream} instance
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public MyDataInputStream makeDataInputStream() {
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new MyDataInputStream(makeInputStream());
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
26499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets a {@code InputStream} that reads from this instance,
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with the cursor starting at the beginning of this instance's data.
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <b>Note:</b> The returned instance may be cast to {@link #GetCursor}
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * if needed.
268de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
26999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} an appropriately-constructed
27099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code InputStream} instancex
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public MyInputStream makeInputStream() {
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return new MyInputStream();
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper interface that allows one to get the cursor (of a stream).
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public interface GetCursor {
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /**
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Gets the current cursor.
282de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro         *
28399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * @return {@code 0..size();} the cursor
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int getCursor();
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
287de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper class for {@link #makeInputStream}, which implements the
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * stream functionality.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public class MyInputStream extends InputStream {
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** 0..size; the cursor */
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int cursor;
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /** 0..size; the mark */
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private int mark;
298de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public MyInputStream() {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cursor = 0;
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mark = 0;
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read() throws IOException {
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (cursor >= size) {
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return -1;
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int result = getUnsignedByte0(cursor);
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cursor++;
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return result;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int read(byte[] arr, int offset, int length) {
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((offset + length) > arr.length) {
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                length = arr.length - offset;
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
318de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int maxLength = size - cursor;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (length > maxLength) {
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                length = maxLength;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
324508a92917e983723cd94915592d837a114b69110Jesse Wilson            System.arraycopy(bytes, cursor + start, arr, offset, length);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cursor += length;
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return length;
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public int available() {
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return size - cursor;
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void mark(int reserve) {
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            mark = cursor;
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public void reset() {
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cursor = mark;
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public boolean markSupported() {
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Helper class for {@link #makeDataInputStream}. This is used
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * simply so that the cursor of a wrapped {@link #MyInputStream}
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * instance may be easily determined.
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3514b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein    public static class MyDataInputStream extends DataInputStream {
35299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        /** {@code non-null;} the underlying {@link #MyInputStream} */
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        private final MyInputStream wrapped;
354de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public MyDataInputStream(MyInputStream wrapped) {
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            super(wrapped);
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.wrapped = wrapped;
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
362