ByteArrayInput.java revision bba8645009131cbc0c596ca1fdb26f7c848e6795
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
175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compackage org.jf.dexlib.Util;
185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com/**
205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * Implementation of {@link Input} which reads the data from a
215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * <code>byte[]</code> instance.
225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com *
235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * <p><b>Note:</b> As per the {@link Input } interface, multi-byte
245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com * reads all use little-endian order.</p>
255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com */
265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.compublic class ByteArrayInput
275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    implements Input {
285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** non-null; the data itself */
305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private byte[] data;
315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** &gt;= 0; current read cursor */
335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private int cursor;
345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Constructs an instance with the given data
375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     *
385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @param data non-null; data array to use for input
395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public ByteArrayInput(byte[] data) {
415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (data == null) {
425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new NullPointerException("data == null");
435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.data = data;
465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.cursor = 0;
475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Gets the underlying <code>byte[]</code> of this instance
515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     *
525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * @return non-null; the <code>byte[]</code>
535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte[] getArray() {
555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return data;
565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int getCursor() {
605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return cursor;
615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void setCursor(int cursor) {
655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (cursor < 0 || cursor >= data.length)
665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new IndexOutOfBoundsException("The provided cursor value " +
675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    "is not within the bounds of this instance's data array");
685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        this.cursor = cursor;
695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void assertCursor(int expectedCursor) {
735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (cursor != expectedCursor) {
745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throw new ExceptionWithContext("expected cursor " +
755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    expectedCursor + "; actual value: " + cursor);
765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte readByte() {
81bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return data[cursor++];
825867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
845867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readShort() {
865867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
87bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        int result = ((data[readAt++] & 0xff) +
88bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 8));
89bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
90bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
915867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readInt() {
955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
96bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        int result = (data[readAt++] & 0xff) +
97bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 8) +
98bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 16) +
99bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                     ((data[readAt++] & 0xff) << 24);
100bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
101bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
1025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1045867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public long readLong() {
1065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int readAt = cursor;
1075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
108bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        long result = (data[readAt++] & 0xffL) |
109bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 8) |
110bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 16) |
111bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 24) |
112bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 32) |
113bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 40) |
114bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 48) |
115bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com                      ((data[readAt++] & 0xffL) << 58);
116bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = readAt;
117bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        return result;
1185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readUnsignedOrSignedLeb128() {
1235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
1245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
1255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
1265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
1285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result > 0x7f) {
1295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
1305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
1315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue > 0x7f) {
1325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
1335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
1345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue > 0x7f) {
1355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
1365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
1375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue > 0x7f) {
1385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
1395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
1405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
1415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
1425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
1435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
1445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
1455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
1465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        } else {
1475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            cursor = end;
1485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return result;
1495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
1525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //If the last byte is 0, then this was an unsigned value (incorrectly) written in a signed format
1545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //The caller wants to know if this is the case, so we'll return the negated value instead
1555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //If there was only a single byte that had a value of 0, then we would have returned in the above
1565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //"else"
1575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (data[end-1] == 0) {
1585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            return ~result;
1595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
1615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readUnsignedLeb128() {
1685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
1695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
1705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
1715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
1735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result > 0x7f) {
1745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
1755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
1765867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue > 0x7f) {
1775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
1785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
1795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue > 0x7f) {
1805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
1815867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
1825867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue > 0x7f) {
1835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
1845867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
1855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
1865867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
1875867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
1885867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
1895867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
1905867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
1915867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
1925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
1945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
1955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
1965867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
1975867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
1985867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public int readSignedLeb128() {
1995867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor;
2005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int currentByteValue;
2015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int result;
2025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        result = data[end++] & 0xff;
2045867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (result <= 0x7f) {
2055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result << 25) >> 25;
2065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        } else {
2075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            currentByteValue = data[end++] & 0xff;
2085867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            result = (result & 0x7f) | ((currentByteValue & 0x7f) << 7);
2095867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            if (currentByteValue <= 0x7f) {
2105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result = (result << 18) >> 18;
2115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            } else {
2125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                currentByteValue = data[end++] & 0xff;
2135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                result |= (currentByteValue & 0x7f) << 14;
2145867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                if (currentByteValue <= 0x7f) {
2155867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result = (result << 11) >> 11;
2165867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                } else {
2175867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    currentByteValue = data[end++] & 0xff;
2185867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    result |= (currentByteValue & 0x7f) << 21;
2195867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    if (currentByteValue <= 0x7f) {
2205867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result = (result << 4) >> 4;
2215867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    } else {
2225867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        currentByteValue = data[end++] & 0xff;
2235867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        if (currentByteValue > 0x0f) {
2245867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                            throwInvalidLeb();
2255867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        }
2265867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                        result |= currentByteValue << 28;
2275867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                    }
2285867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com                }
2295867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            }
2305867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2315867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2325867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2335867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
2345867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2355867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2365867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2375867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void read(byte[] bytes, int offset, int length) {
2385867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2395867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2405867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2415867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2425867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2435867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2445867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, bytes, offset, length);
2455867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2465867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2475867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2485867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2495867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void read(byte[] bytes) {
2505867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int length = bytes.length;
2515867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2525867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2535867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2545867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2555867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2565867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2575867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, bytes, 0, length);
2585867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2595867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2605867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2615867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2625867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public byte[] readBytes(int length) {
2635867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int end = cursor + length;
2645867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2655867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        if (end > data.length) {
2665867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            throwBounds();
2675867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2685867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2695867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        byte[] result = new byte[length];
2705867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        System.arraycopy(data, cursor, result, 0, length);
2715867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor = end;
2725867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        return result;
2735867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2745867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2755867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2761f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com    public String realNullTerminatedUtf8String() {
2775867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int startPosition = cursor;
2785867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        while (data[cursor] != 0) {
2795867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com            cursor++;
2805867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        }
2815867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        int byteCount = cursor - startPosition;
2821f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com
2835867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        //skip the terminating null
2845867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        cursor++;
2855867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2861f29ee7351fd7fb48bb093b39b5f9ffddb34a3eaJesusFreke@JesusFreke.com        return Utf8Utils.utf8BytesToString(data, startPosition, byteCount);
2875867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2885867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2895867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2905867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void skipBytes(int count) {
291bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor += count;
2925867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2935867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2945867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /** {@inheritDoc} */
2955867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    public void alignTo(int alignment) {
296bba8645009131cbc0c596ca1fdb26f7c848e6795JesusFreke@JesusFreke.com        cursor = AlignmentUtils.alignOffset(cursor, alignment);
2975867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
2985867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
2995867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
3005867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Throws the excpetion for when an attempt is made to read past the
3015867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * end of the instance.
3025867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
3035867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private static void throwBounds() {
3045867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        throw new IndexOutOfBoundsException("attempt to read past the end");
3055867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3065867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com
3075867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    /**
3085867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     * Throws the exception for when an invalid LEB128 value is encountered
3095867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com     */
3105867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    private static void throwInvalidLeb() {
3115867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com        throw new RuntimeException("invalid LEB128 integer encountered");
3125867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com    }
3135867263eb588f4671400895d1e6b01c01535061bJesusFreke@JesusFreke.com}
314