blob: e428377a0a313484bd77181a9415f937ed758cad [file] [log] [blame]
Seigo Nonakaf1644f72017-11-27 22:09:49 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.text;
18
19import android.annotation.IntRange;
20import android.annotation.NonNull;
21
22import com.android.internal.util.ArrayUtils;
23
24import libcore.util.EmptyArray;
25
26/**
27 * Implements a growing array of int primitives.
28 *
29 * These arrays are NOT thread safe.
30 *
31 * @hide
32 */
33public final class AutoGrowArray {
34 private static final int MIN_CAPACITY_INCREMENT = 12;
35 private static final int MAX_CAPACITY_TO_BE_KEPT = 10000;
36
37 /**
38 * Returns next capacity size.
39 *
40 * The returned capacity is larger than requested capacity.
41 */
42 private static int computeNewCapacity(int currentSize, int requested) {
43 final int targetCapacity = currentSize + (currentSize < (MIN_CAPACITY_INCREMENT / 2)
44 ? MIN_CAPACITY_INCREMENT : currentSize >> 1);
45 return targetCapacity > requested ? targetCapacity : requested;
46 }
47
48 /**
49 * An auto growing byte array.
50 */
51 public static class ByteArray {
52
53 private @NonNull byte[] mValues;
54 private @IntRange(from = 0) int mSize;
55
56 /**
57 * Creates an empty ByteArray with the default initial capacity.
58 */
59 public ByteArray() {
60 this(10);
61 }
62
63 /**
64 * Creates an empty ByteArray with the specified initial capacity.
65 */
66 public ByteArray(@IntRange(from = 0) int initialCapacity) {
67 if (initialCapacity == 0) {
68 mValues = EmptyArray.BYTE;
69 } else {
70 mValues = ArrayUtils.newUnpaddedByteArray(initialCapacity);
71 }
72 mSize = 0;
73 }
74
75 /**
76 * Changes the size of this ByteArray. If this ByteArray is shrinked, the backing array
77 * capacity is unchanged.
78 */
79 public void resize(@IntRange(from = 0) int newSize) {
80 if (newSize > mValues.length) {
81 ensureCapacity(newSize - mSize);
82 }
83 mSize = newSize;
84 }
85
86 /**
87 * Appends the specified value to the end of this array.
88 */
89 public void append(byte value) {
90 ensureCapacity(1);
91 mValues[mSize++] = value;
92 }
93
94 /**
95 * Ensures capacity to append at least <code>count</code> values.
96 */
97 private void ensureCapacity(@IntRange int count) {
98 final int requestedSize = mSize + count;
99 if (requestedSize >= mValues.length) {
100 final int newCapacity = computeNewCapacity(mSize, requestedSize);
101 final byte[] newValues = ArrayUtils.newUnpaddedByteArray(newCapacity);
102 System.arraycopy(mValues, 0, newValues, 0, mSize);
103 mValues = newValues;
104 }
105 }
106
107 /**
108 * Removes all values from this array.
109 */
110 public void clear() {
111 mSize = 0;
112 }
113
114 /**
115 * Removes all values from this array and release the internal array object if it is too
116 * large.
117 */
118 public void clearWithReleasingLargeArray() {
119 clear();
120 if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
121 mValues = EmptyArray.BYTE;
122 }
123 }
124
125 /**
126 * Returns the value at the specified position in this array.
127 */
128 public byte get(@IntRange(from = 0) int index) {
129 return mValues[index];
130 }
131
132 /**
133 * Sets the value at the specified position in this array.
134 */
135 public void set(@IntRange(from = 0) int index, byte value) {
136 mValues[index] = value;
137 }
138
139 /**
140 * Returns the number of values in this array.
141 */
142 public @IntRange(from = 0) int size() {
143 return mSize;
144 }
145
146 /**
147 * Returns internal raw array.
148 *
149 * Note that this array may have larger size than you requested.
150 * Use size() instead for getting the actual array size.
151 */
152 public @NonNull byte[] getRawArray() {
153 return mValues;
154 }
155 }
156
157 /**
158 * An auto growing int array.
159 */
160 public static class IntArray {
161
162 private @NonNull int[] mValues;
163 private @IntRange(from = 0) int mSize;
164
165 /**
166 * Creates an empty IntArray with the default initial capacity.
167 */
168 public IntArray() {
169 this(10);
170 }
171
172 /**
173 * Creates an empty IntArray with the specified initial capacity.
174 */
175 public IntArray(@IntRange(from = 0) int initialCapacity) {
176 if (initialCapacity == 0) {
177 mValues = EmptyArray.INT;
178 } else {
179 mValues = ArrayUtils.newUnpaddedIntArray(initialCapacity);
180 }
181 mSize = 0;
182 }
183
184 /**
185 * Changes the size of this IntArray. If this IntArray is shrinked, the backing array
186 * capacity is unchanged.
187 */
188 public void resize(@IntRange(from = 0) int newSize) {
189 if (newSize > mValues.length) {
190 ensureCapacity(newSize - mSize);
191 }
192 mSize = newSize;
193 }
194
195 /**
196 * Appends the specified value to the end of this array.
197 */
198 public void append(int value) {
199 ensureCapacity(1);
200 mValues[mSize++] = value;
201 }
202
203 /**
204 * Ensures capacity to append at least <code>count</code> values.
205 */
206 private void ensureCapacity(@IntRange(from = 0) int count) {
207 final int requestedSize = mSize + count;
208 if (requestedSize >= mValues.length) {
209 final int newCapacity = computeNewCapacity(mSize, requestedSize);
210 final int[] newValues = ArrayUtils.newUnpaddedIntArray(newCapacity);
211 System.arraycopy(mValues, 0, newValues, 0, mSize);
212 mValues = newValues;
213 }
214 }
215
216 /**
217 * Removes all values from this array.
218 */
219 public void clear() {
220 mSize = 0;
221 }
222
223 /**
224 * Removes all values from this array and release the internal array object if it is too
225 * large.
226 */
227 public void clearWithReleasingLargeArray() {
228 clear();
229 if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
230 mValues = EmptyArray.INT;
231 }
232 }
233
234 /**
235 * Returns the value at the specified position in this array.
236 */
237 public int get(@IntRange(from = 0) int index) {
238 return mValues[index];
239 }
240
241 /**
242 * Sets the value at the specified position in this array.
243 */
244 public void set(@IntRange(from = 0) int index, int value) {
245 mValues[index] = value;
246 }
247
248 /**
249 * Returns the number of values in this array.
250 */
251 public @IntRange(from = 0) int size() {
252 return mSize;
253 }
254
255 /**
256 * Returns internal raw array.
257 *
258 * Note that this array may have larger size than you requested.
259 * Use size() instead for getting the actual array size.
260 */
261 public @NonNull int[] getRawArray() {
262 return mValues;
263 }
264 }
265
266 /**
267 * An auto growing float array.
268 */
269 public static class FloatArray {
270
271 private @NonNull float[] mValues;
272 private @IntRange(from = 0) int mSize;
273
274 /**
275 * Creates an empty FloatArray with the default initial capacity.
276 */
277 public FloatArray() {
278 this(10);
279 }
280
281 /**
282 * Creates an empty FloatArray with the specified initial capacity.
283 */
284 public FloatArray(@IntRange(from = 0) int initialCapacity) {
285 if (initialCapacity == 0) {
286 mValues = EmptyArray.FLOAT;
287 } else {
288 mValues = ArrayUtils.newUnpaddedFloatArray(initialCapacity);
289 }
290 mSize = 0;
291 }
292
293 /**
294 * Changes the size of this FloatArray. If this FloatArray is shrinked, the backing array
295 * capacity is unchanged.
296 */
297 public void resize(@IntRange(from = 0) int newSize) {
298 if (newSize > mValues.length) {
299 ensureCapacity(newSize - mSize);
300 }
301 mSize = newSize;
302 }
303
304 /**
305 * Appends the specified value to the end of this array.
306 */
307 public void append(float value) {
308 ensureCapacity(1);
309 mValues[mSize++] = value;
310 }
311
312 /**
313 * Ensures capacity to append at least <code>count</code> values.
314 */
315 private void ensureCapacity(int count) {
316 final int requestedSize = mSize + count;
317 if (requestedSize >= mValues.length) {
318 final int newCapacity = computeNewCapacity(mSize, requestedSize);
319 final float[] newValues = ArrayUtils.newUnpaddedFloatArray(newCapacity);
320 System.arraycopy(mValues, 0, newValues, 0, mSize);
321 mValues = newValues;
322 }
323 }
324
325 /**
326 * Removes all values from this array.
327 */
328 public void clear() {
329 mSize = 0;
330 }
331
332 /**
333 * Removes all values from this array and release the internal array object if it is too
334 * large.
335 */
336 public void clearWithReleasingLargeArray() {
337 clear();
338 if (mValues.length > MAX_CAPACITY_TO_BE_KEPT) {
339 mValues = EmptyArray.FLOAT;
340 }
341 }
342
343 /**
344 * Returns the value at the specified position in this array.
345 */
346 public float get(@IntRange(from = 0) int index) {
347 return mValues[index];
348 }
349
350 /**
351 * Sets the value at the specified position in this array.
352 */
353 public void set(@IntRange(from = 0) int index, float value) {
354 mValues[index] = value;
355 }
356
357 /**
358 * Returns the number of values in this array.
359 */
360 public @IntRange(from = 0) int size() {
361 return mSize;
362 }
363
364 /**
365 * Returns internal raw array.
366 *
367 * Note that this array may have larger size than you requested.
368 * Use size() instead for getting the actual array size.
369 */
370 public @NonNull float[] getRawArray() {
371 return mValues;
372 }
373 }
374}