15867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com/*
2a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * Copyright (C) 2007 The Android Open Source Project
35867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
4a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * Licensed under the Apache License, Version 2.0 (the "License");
5a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * you may not use this file except in compliance with the License.
6a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * You may obtain a copy of the License at
75867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
8a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com *      http://www.apache.org/licenses/LICENSE-2.0
9a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com *
10a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * Unless required by applicable law or agreed to in writing, software
11a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * distributed under the License is distributed on an "AS IS" BASIS,
12a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * See the License for the specific language governing permissions and
14a7139f6586c9bb8452e4c648ce582f8fbc626740JesusFreke@JesusFreke.com * limitations under the License.
155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com */
165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
17128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com/*
18128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com * As per the Apache license requirements, this file has been modified
19128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com * from its original state.
20128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com *
21128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com * Such modifications are Copyright (C) 2010 Ben Gruver, and are released
22128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com * under the original license
23128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com */
24128e8279c3cf44cc1d1c8f263035ba8e4044d5c6JesusFreke@JesusFreke.com
255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compackage org.jf.dexlib.Util;
265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com/**
285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * Implementation of {@link Input} which reads the data from a
295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * <code>byte[]</code> instance.
305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * <p><b>Note:</b> As per the {@link Input } interface, multi-byte
325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * reads all use little-endian order.</p>
335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com */
345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compublic class ByteArrayInput
355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    implements Input {
365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** non-null; the data itself */
385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private byte[] data;
395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** &gt;= 0; current read cursor */
415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private int cursor;
425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Constructs an instance with the given data
455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     *
465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param data non-null; data array to use for input
475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public ByteArrayInput(byte[] data) {
495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (data == null) {
505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new NullPointerException("data == null");
515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.data = data;
545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.cursor = 0;
555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Gets the underlying <code>byte[]</code> of this instance
595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     *
605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @return non-null; the <code>byte[]</code>
615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte[] getArray() {
635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return data;
645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int getCursor() {
685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return cursor;
695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void setCursor(int cursor) {
735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (cursor < 0 || cursor >= data.length)
745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new IndexOutOfBoundsException("The provided cursor value " +
755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    "is not within the bounds of this instance's data array");
765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.cursor = cursor;
775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void assertCursor(int expectedCursor) {
815867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (cursor != expectedCursor) {
825867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new ExceptionWithContext("expected cursor " +
835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    expectedCursor + "; actual value: " + cursor);
845867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
865867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
875867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
885867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte readByte() {
89bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return data[cursor++];
905867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
915867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readShort() {
945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
95bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        int result = ((data[readAt++] & 0xff) +
96bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 8));
97bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
98bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
995867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readInt() {
1035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
104bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        int result = (data[readAt++] & 0xff) +
105bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 8) +
106bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 16) +
107bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 24);
108bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
109bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
1105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public long readLong() {
1145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
1155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
116bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        long result = (data[readAt++] & 0xffL) |
117bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 8) |
118bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 16) |
119bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 24) |
120bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 32) |
121bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 40) |
122bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 48) |
1237ed253b78bd28abb0a56463ca26bb26c1c07302cjesusfreke@jesusfreke.com                      ((data[readAt++] & 0xffL) << 56);
124bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
125bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
1265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readUnsignedOrSignedLeb128() {
1315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
1325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
1335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
1345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
1365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result > 0x7f) {
1375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
1385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
1395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue > 0x7f) {
1405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
1415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
1425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue > 0x7f) {
1435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
1445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
1455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue > 0x7f) {
1465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
1475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
1485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
1495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
1505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
1515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
1525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
1535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
1545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        } else {
1555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            cursor = end;
1565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return result;
1575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
1605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //If the last byte is 0, then this was an unsigned value (incorrectly) written in a signed format
1625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //The caller wants to know if this is the case, so we'll return the negated value instead
1635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //If there was only a single byte that had a value of 0, then we would have returned in the above
1645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //"else"
1655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (data[end-1] == 0) {
1665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return ~result;
1675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
1695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readUnsignedLeb128() {
1765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
1775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
1785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
1795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
1815867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result > 0x7f) {
1825867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
1835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
1845867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue > 0x7f) {
1855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
1865867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
1875867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue > 0x7f) {
1885867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
1895867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
1905867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue > 0x7f) {
1915867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
1925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
1935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
1945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
1955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
1965867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
1975867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
1985867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
1995867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
2035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2045867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readSignedLeb128() {
2075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
2085867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
2095867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
2105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
2125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result <= 0x7f) {
2135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result << 25) >> 25;
2145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        } else {
2155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
2165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
2175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue <= 0x7f) {
2185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result = (result << 18) >> 18;
2195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            } else {
2205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
2215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
2225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue <= 0x7f) {
2235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result = (result << 11) >> 11;
2245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                } else {
2255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
2265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
2275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue <= 0x7f) {
2285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result = (result << 4) >> 4;
2295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    } else {
2305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
2315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
2325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
2335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
2345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
2355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
2365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
2375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
2385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
2425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void read(byte[] bytes, int offset, int length) {
2465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, bytes, offset, length);
2535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void read(byte[] bytes) {
2585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int length = bytes.length;
2595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, bytes, 0, length);
2665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte[] readBytes(int length) {
2715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        byte[] result = new byte[length];
2785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, result, 0, length);
2795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
2815867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2825867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2841f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com    public String realNullTerminatedUtf8String() {
2855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int startPosition = cursor;
2865867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        while (data[cursor] != 0) {
2875867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            cursor++;
2885867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2895867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int byteCount = cursor - startPosition;
2901f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com
2915867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //skip the terminating null
2925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor++;
2935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2941f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com        return Utf8Utils.utf8BytesToString(data, startPosition, byteCount);
2955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2965867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2975867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2985867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void skipBytes(int count) {
299bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor += count;
3005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
3025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
3035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void alignTo(int alignment) {
304bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = AlignmentUtils.alignOffset(cursor, alignment);
3055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
3075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
3085867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Throws the excpetion for when an attempt is made to read past the
3095867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * end of the instance.
3105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
3115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private static void throwBounds() {
3125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        throw new IndexOutOfBoundsException("attempt to read past the end");
3135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
3155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
3165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Throws the exception for when an invalid LEB128 value is encountered
3175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
3185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private static void throwInvalidLeb() {
3195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        throw new RuntimeException("invalid LEB128 integer encountered");
3205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com}
322