1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.util;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.Arrays;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Simple (mostly) fixed-size list of objects, which may be made immutable.
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class FixedSizeList
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        extends MutabilityControl implements ToHuman {
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@code non-null;} array of elements */
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Object[] arr;
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Constructs an instance. All indices initially contain {@code null}.
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param size the size of the list
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public FixedSizeList(int size) {
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        super(size != 0);
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            arr = new Object[size];
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (NegativeArraySizeException ex) {
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Translate the exception.
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IllegalArgumentException("size < 0");
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public boolean equals(Object other) {
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (this == other) {
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Easy out.
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return true;
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if ((other == null) || (getClass() != other.getClass())) {
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Another easy out.
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        FixedSizeList list = (FixedSizeList) other;
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return Arrays.equals(arr, list.arr);
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public int hashCode() {
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return Arrays.hashCode(arr);
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** {@inheritDoc} */
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    @Override
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toString() {
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        String name = getClass().getName();
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return toString0(name.substring(name.lastIndexOf('.') + 1) + '{',
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         ", ",
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         "}",
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         false);
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * {@inheritDoc}
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * This method will only work if every element of the list
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * implements {@link ToHuman}.
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toHuman() {
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        String name = getClass().getName();
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return toString0(name.substring(name.lastIndexOf('.') + 1) + '{',
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         ", ",
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         "}",
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                         true);
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets a customized string form for this instance.
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param prefix {@code null-ok;} prefix for the start of the result
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param separator {@code null-ok;} separator to insert between each item
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param suffix {@code null-ok;} suffix for the end of the result
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the custom string
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toString(String prefix, String separator, String suffix) {
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return toString0(prefix, separator, suffix, false);
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets a customized human string for this instance. This method will
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * only work if every element of the list implements {@link
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * ToHuman}.
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param prefix {@code null-ok;} prefix for the start of the result
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param separator {@code null-ok;} separator to insert between each item
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param suffix {@code null-ok;} suffix for the end of the result
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the custom string
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public String toHuman(String prefix, String separator, String suffix) {
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return toString0(prefix, separator, suffix, true);
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the number of elements in this list.
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public final int size() {
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return arr.length;
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Shrinks this instance to fit, by removing any unset
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * ({@code null}) elements, leaving the remaining elements in
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * their original order.
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public void shrinkToFit() {
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int sz = arr.length;
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int newSz = 0;
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < sz; i++) {
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (arr[i] != null) {
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                newSz++;
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sz == newSz) {
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return;
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        throwIfImmutable();
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Object[] newa = new Object[newSz];
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int at = 0;
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < sz; i++) {
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Object one = arr[i];
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (one != null) {
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                newa[at] = one;
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                at++;
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        arr = newa;
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (newSz == 0) {
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            setImmutable();
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the indicated element. It is an error to call this with the
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * index for an element which was never set; if you do that, this
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * will throw {@code NullPointerException}. This method is
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * protected so that subclasses may offer a safe type-checked
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * public interface to their clients.
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param n {@code >= 0, < size();} which element
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the indicated element
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected final Object get0(int n) {
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Object result = arr[n];
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (result == null) {
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                throw new NullPointerException("unset: " + n);
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return result;
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (ArrayIndexOutOfBoundsException ex) {
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Translate the exception.
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return throwIndex(n);
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Gets the indicated element, allowing {@code null}s to be
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * returned. This method is protected so that subclasses may
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * (optionally) offer a safe type-checked public interface to
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * their clients.
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param n {@code >= 0, < size();} which element
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code null-ok;} the indicated element
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected final Object getOrNull0(int n) {
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return arr[n];
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Sets the element at the given index, but without doing any type
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * checks on the element. This method is protected so that
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * subclasses may offer a safe type-checked public interface to
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * their clients.
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param n {@code >= 0, < size();} which element
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param obj {@code null-ok;} the value to store
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    protected final void set0(int n, Object obj) {
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        throwIfImmutable();
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        try {
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            arr[n] = obj;
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } catch (ArrayIndexOutOfBoundsException ex) {
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Translate the exception.
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throwIndex(n);
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Throws the appropriate exception for the given index value.
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param n the index value
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return never
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @throws IndexOutOfBoundsException always thrown
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Object throwIndex(int n) {
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (n < 0) {
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            throw new IndexOutOfBoundsException("n < 0");
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        throw new IndexOutOfBoundsException("n >= size()");
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Helper for {@link #toString} and {@link #toHuman}, which both of
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * those call to pretty much do everything.
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param prefix {@code null-ok;} prefix for the start of the result
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param separator {@code null-ok;} separator to insert between each item
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param suffix {@code null-ok;} suffix for the end of the result
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param human whether the output is to be human
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return {@code non-null;} the custom string
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private String toString0(String prefix, String separator, String suffix,
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                             boolean human) {
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int len = arr.length;
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        StringBuffer sb = new StringBuffer(len * 10 + 10);
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (prefix != null) {
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(prefix);
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < len; i++) {
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if ((i != 0) && (separator != null)) {
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(separator);
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (human) {
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(((ToHuman) arr[i]).toHuman());
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                sb.append(arr[i]);
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (suffix != null) {
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            sb.append(suffix);
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        return sb.toString();
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
277