1c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei/*
2c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Copyright (C) 2013 The Android Open Source Project
3c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
4c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Licensed under the Apache License, Version 2.0 (the "License");
5c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * you may not use this file except in compliance with the License.
6c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * You may obtain a copy of the License at
7c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
8c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *      http://www.apache.org/licenses/LICENSE-2.0
9c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
10c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Unless required by applicable law or agreed to in writing, software
11c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * distributed under the License is distributed on an "AS IS" BASIS,
12c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * See the License for the specific language governing permissions and
14c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * limitations under the License.
15c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei */
16c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
17c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weipackage com.android.ex.photo.util;
18c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
19c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weiimport android.util.Log;
20c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
21c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weiimport java.io.IOException;
22c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weiimport java.io.InputStream;
23c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weiimport java.util.Arrays;
24c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
25c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei/**
26c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Wrapper for {@link InputStream} that allows you to read bytes from it like a byte[]. An
27c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * internal buffer is kept as small as possible to avoid large unnecessary allocations.
28c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
29c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <p/>
30c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Care must be taken so that the internal buffer is kept small. The best practice is to
31c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * precalculate the maximum buffer size that you will need. For example,
32c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * say you have a loop that reads bytes from index <code>0</code> to <code>10</code>,
33c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * skips to index <code>N</code>, reads from index <code>N</code> to <code>N+10</code>, etc. Then
34c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * you know that the internal buffer can have a maximum size of <code>10</code>,
35c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * and you should set the <code>bufferSize</code> parameter to <code>10</code> in the constructor.
36c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
37c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <p/>
38c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * Use {@link #advanceTo(int)} to declare that you will not need to access lesser indexes. This
39c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * helps to keep the internal buffer small. In the above example, after reading bytes from index
40c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <code>0</code> to <code>10</code>, you should call <code>advanceTo(N)</code> so that internal
41c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * buffer becomes filled with bytes from index <code>N</code> to <code>N+10</code>.
42c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
43c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <p/>
44c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * If you know that you are reading bytes from a <strong>strictly</strong> increasing or equal
45c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * index, then you should set the <code>autoAdvance</code> parameter to <code>true</code> in the
46c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * constructor. For complicated access patterns, or when you prefer to control the internal
47c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * buffer yourself, set <code>autoAdvance</code> to <code>false</code>. When
48c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <code>autoAdvance</code> is enabled, every time an index is beyond the buffer length,
49c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * the buffer will be shifted forward such that the index requested becomes the first element in
50c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * the buffer.
51c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei *
52c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * <p/>
53c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * All public methods with parameter <code>index</code> are absolute indexed. The index is from
54c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei * the beginning of the wrapped input stream.
55c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei */
56c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Weipublic class InputStreamBuffer {
57c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
58c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private static final boolean DEBUG = false;
59c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private static final int DEBUG_MAX_BUFFER_SIZE = 80;
60c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private static final String TAG = "InputStreamBuffer";
61c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
62c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private InputStream mInputStream;
63c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private byte[] mBuffer;
64c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private boolean mAutoAdvance;
65c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /** Byte count the buffer is offset by. */
66c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private int mOffset = 0;
67c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /** Number of bytes filled in the buffer. */
68c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private int mFilled = 0;
69c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
70c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
71c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Construct a new wrapper for an InputStream.
72c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
73c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
74c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * If <code>autoAdvance</code> is true, behavior is undefined if you call {@link #get(int)}
75c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * or {@link #has(int)} with an index N, then some arbitrary time later call {@link #get(int)}
76c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * or {@link #has(int)} with an index M < N. The wrapper may return the right value,
77c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * if the buffer happens to still contain index M, but more likely it will throw an
78c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * {@link IllegalStateException}.
79c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
80c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
81c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * If <code>autoAdvance</code> is false, you must be diligent and call {@link #advanceTo(int)}
82c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * at the appropriate times to ensure that the internal buffer is not unnecessarily resized
83c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * and reallocated.
84c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
85c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param inputStream The input stream to wrap. The input stream will not be closed by the
86c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    wrapper.
87c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param bufferSize  The initial size for the internal buffer. The buffer size should be
88c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    carefully chosen to avoid resizing and reallocating the internal buffer.
89c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    The internal buffer size used will be the least power of two greater
90c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    than this parameter.
91c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param autoAdvance Determines the behavior when you need to read an index that is beyond
92c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    the internal buffer size. If true, the internal buffer will shift so
93c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    that the requested index becomes the first element. If false,
94c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    the internal buffer size will grow to the smallest power of 2 which is
95c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *                    greater than the requested index.
96c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
97c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public InputStreamBuffer(final InputStream inputStream, int bufferSize,
98c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            final boolean autoAdvance) {
99c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        mInputStream = inputStream;
100c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (bufferSize <= 0) {
101c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            throw new IllegalArgumentException(
102c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    String.format("Buffer size %d must be positive.", bufferSize));
103c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
104c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        bufferSize = leastPowerOf2(bufferSize);
105c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        mBuffer = new byte[bufferSize];
106c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        mAutoAdvance = autoAdvance;
107c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
108c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
109c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
110c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Attempt to get byte at the requested index from the wrapped input stream. If the internal
111c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * buffer contains the requested index, return immediately. If the index is less than the
112c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * head of the buffer, or the index is greater or equal to the size of the wrapped input stream,
113c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * a runtime exception is thrown.
114c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
115c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
116c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * If the index is not in the internal buffer, but it can be requested from the input stream,
117c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * {@link #fill(int)} will be called first, and the byte at the index returned.
118c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
119c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
120c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * You should always call {@link #has(int)} with the same index, unless you are sure that no
121c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * exceptions will be thrown as described above.
122c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
123c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
124c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Consider calling {@link #advanceTo(int)} if you know that you will never request a lesser
125c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * index in the future.
126c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param index The requested index.
127c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @return The byte at that index.
128c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
129c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public byte get(final int index) throws IllegalStateException, IndexOutOfBoundsException {
130c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.beginSection("get");
131c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (has(index)) {
132c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            final int i = index - mOffset;
133c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
134c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            return mBuffer[i];
135c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } else {
136c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
137c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            throw new IndexOutOfBoundsException(
138c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    String.format("Index %d beyond length.", index));
139c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
140c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
141c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
142c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
143c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Attempt to return whether the requested index is within the size of the wrapped input
144c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * stream. One side effect is {@link #fill(int)} will be called.
145c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
146c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
147c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * If this method returns true, it is guaranteed that {@link #get(int)} with the same index
148c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * will not fail. That means that if the requested index is within the size of the wrapped
149c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * input stream, but the index is less than the head of the internal buffer,
150c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * a runtime exception is thrown.
151c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
152c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
153c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * See {@link #get(int)} for caveats. A lot of the same warnings about exceptions and
154c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <code>advanceTo()</code> apply.
155c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param index The requested index.
156c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @return True if requested index is within the size of the wrapped input stream. False if
157c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * the index is beyond the size.
158c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
159c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public boolean has(final int index) throws IllegalStateException, IndexOutOfBoundsException {
160c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.beginSection("has");
161c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (index < mOffset) {
162c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
163c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            throw new IllegalStateException(
164c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    String.format("Index %d is before buffer %d", index, mOffset));
165c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
166c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
167c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        final int i = index - mOffset;
168c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
169c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        // Requested index not in internal buffer.
170c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (i >= mFilled || i >= mBuffer.length) {
171c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
172c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            return fill(index);
173c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
174c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
175c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.endSection();
176c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        return true;
177c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
178c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
179c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
180c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Attempts to advance the head of the buffer to the requested index. If the index is less
181c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * than the head of the buffer, the internal state will not be changed.
182c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
183c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
184c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Advancing does not fill the internal buffer. The next {@link #get(int)} or
185c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * {@link #has(int)} call will fill the buffer.
186c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
187c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public void advanceTo(final int index) throws IllegalStateException, IndexOutOfBoundsException {
188c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.beginSection("advance to");
189c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        final int i = index - mOffset;
190c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (i <= 0) {
191c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            // noop
192c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
193c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            return;
194c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } else if (i < mFilled) {
195c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            // Shift elements starting at i to position 0.
196c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            shiftToBeginning(i);
197c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mOffset = index;
198c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mFilled = mFilled - i;
199c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } else if (mInputStream != null) {
200c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            // Burn some bytes from the input stream to match the new index.
201c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            int burn = i - mFilled;
202c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            boolean empty = false;
203c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            int fails = 0;
204c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            try {
205c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                while (burn > 0) {
206c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    final long burned = mInputStream.skip(burn);
207c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    if (burned <= 0) {
208c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        fails++;
209c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    } else {
210c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        burn -= burned;
211c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    }
212c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
213c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    if (fails >= 5) {
214c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        empty = true;
215c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        break;
216c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    }
217c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                }
218c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            } catch (IOException ignored) {
219c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                empty = true;
220c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            }
221c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
222c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            if (empty) {
223c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                //Mark input stream as consumed.
224c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                mInputStream = null;
225c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            }
226c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
227c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mOffset = index - burn;
228c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mFilled = 0;
229c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } else {
230c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            // Advancing beyond the input stream.
231c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mOffset = index;
232c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mFilled = 0;
233c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
234c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
235c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Log.d(TAG, String.format("advanceTo %d buffer: %s", i, this));
236c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.endSection();
237c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
238c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
239c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
240c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Attempt to fill the internal buffer fully. The buffer will be modified such that the
241c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * requested index will always be in the buffer. If the index is less
242c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * than the head of the buffer, a runtime exception is thrown.
243c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
244c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
245c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * If the requested index is already in bounds of the buffer, then the buffer will just be
246c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * filled.
247c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     *
248c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <p/>
249c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Otherwise, if <code>autoAdvance</code> was set to true in the constructor,
250c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * {@link #advanceTo(int)} will be called with the requested index,
251c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * and then the buffer filled. If <code>autoAdvance</code> was set to false,
252c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * we allocate a single larger buffer of a least multiple-of-two size that can contain the
253c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * requested index. The elements in the old buffer are copied over to the head of the new
254c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * buffer. Then the entire buffer is filled.
255c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param index The requested index.
256c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @return True if the byte at the requested index has been filled. False if the wrapped
257c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * input stream ends before we reach the index.
258c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
259c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private boolean fill(final int index) {
260c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.beginSection("fill");
261c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (index < mOffset) {
262c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
263c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            throw new IllegalStateException(
264c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    String.format("Index %d is before buffer %d", index, mOffset));
265c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
266c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
267c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        int i = index - mOffset;
268c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        // Can't fill buffer anymore if input stream is consumed.
269c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (mInputStream == null) {
270c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            Trace.endSection();
271c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            return false;
272c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
273c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
274c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        // Increase buffer size if necessary.
275c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        int length = i + 1;
276c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (length > mBuffer.length) {
277c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            if (mAutoAdvance) {
278c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                advanceTo(index);
279c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                i = index - mOffset;
280c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            } else {
281c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                length = leastPowerOf2(length);
282c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                Log.w(TAG, String.format(
283c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        "Increasing buffer length from %d to %d. Bad buffer size chosen, "
284c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                                + "or advanceTo() not called.",
285c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                        mBuffer.length, length));
286c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                mBuffer = Arrays.copyOf(mBuffer, length);
287c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            }
288c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
289c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
290c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        // Read from input stream to fill buffer.
291c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        int read = -1;
292c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        try {
293c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            read = mInputStream.read(mBuffer, mFilled, mBuffer.length - mFilled);
294c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } catch (IOException ignored) {
295c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
296c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
297c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (read != -1) {
298c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mFilled = mFilled + read;
299c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        } else {
300c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            // Mark input stream as consumed.
301c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mInputStream = null;
302c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
303c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
304c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Log.d(TAG, String.format("fill %d      buffer: %s", i, this));
305c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
306c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.endSection();
307c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        return i < mFilled;
308c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
309c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
310c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
311c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Modify the internal buffer so that all the bytes are shifted towards the head by
312c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <code>i</code>. In other words, the byte at index <code>i</code> will now be at index
313c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * <code>0</code>. Bytes from a lesser index are tossed.
314c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * @param i How much to shift left.
315c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
316c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private void shiftToBeginning(final int i) {
317c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (i >= mBuffer.length) {
318c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            throw new IndexOutOfBoundsException(
319c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                    String.format("Index %d out of bounds. Length %d", i, mBuffer.length));
320c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
321c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        for (int j = 0; j + i < mFilled; j++) {
322c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            mBuffer[j] = mBuffer[j + i];
323c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
324c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
325c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
326c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    @Override
327c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public String toString() {
328c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (DEBUG) {
329c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            return toDebugString();
330c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
331c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        return String.format("+%d+%d [%d]", mOffset, mBuffer.length, mFilled);
332c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
333c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
334c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    public String toDebugString() {
335c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.beginSection("to debug string");
336c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        final StringBuilder sb = new StringBuilder();
337c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        sb.append("+").append(mOffset);
338c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        sb.append("+").append(mBuffer.length);
339c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        sb.append(" [");
340c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        for (int i = 0; i < mBuffer.length && i < DEBUG_MAX_BUFFER_SIZE; i++) {
341c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            if (i > 0) {
342c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                sb.append(",");
343c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            }
344c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            if (i < mFilled) {
345c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                sb.append(String.format("%02X", mBuffer[i]));
346c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            } else {
347c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei                sb.append("__");
348c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            }
349c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
350c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        if (mInputStream != null) {
351c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei            sb.append("...");
352c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        }
353c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        sb.append("]");
354c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
355c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        Trace.endSection();
356c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        return sb.toString();
357c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
358c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei
359c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    /**
360c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     * Calculate the least power of two greater than or equal to the input.
361c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei     */
362c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    private static int leastPowerOf2(int n) {
363c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n--;
364c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n |= n >> 1;
365c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n |= n >> 2;
366c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n |= n >> 4;
367c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n |= n >> 8;
368c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n |= n >> 16;
369c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        n++;
370c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei        return n;
371c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei    }
372c631b5a4b1f19f84a70b772bc879fae7c92fd4a8Mark Wei}
373