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