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 public 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 */ computeNewCapacity(int currentSize, int requested)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 */ ByteArray()59 public ByteArray() { 60 this(10); 61 } 62 63 /** 64 * Creates an empty ByteArray with the specified initial capacity. 65 */ ByteArray(@ntRangefrom = 0) int initialCapacity)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 */ resize(@ntRangefrom = 0) int newSize)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 */ append(byte value)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 */ ensureCapacity(@ntRange int count)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 */ clear()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 */ clearWithReleasingLargeArray()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 */ get(@ntRangefrom = 0) int index)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 */ set(@ntRangefrom = 0) int index, byte value)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 */ size()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 */ getRawArray()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 */ IntArray()168 public IntArray() { 169 this(10); 170 } 171 172 /** 173 * Creates an empty IntArray with the specified initial capacity. 174 */ IntArray(@ntRangefrom = 0) int initialCapacity)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 */ resize(@ntRangefrom = 0) int newSize)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 */ append(int value)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 */ ensureCapacity(@ntRangefrom = 0) int count)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 */ clear()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 */ clearWithReleasingLargeArray()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 */ get(@ntRangefrom = 0) int index)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 */ set(@ntRangefrom = 0) int index, int value)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 */ size()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 */ getRawArray()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 */ FloatArray()277 public FloatArray() { 278 this(10); 279 } 280 281 /** 282 * Creates an empty FloatArray with the specified initial capacity. 283 */ FloatArray(@ntRangefrom = 0) int initialCapacity)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 */ resize(@ntRangefrom = 0) int newSize)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 */ append(float value)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 */ ensureCapacity(int count)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 */ clear()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 */ clearWithReleasingLargeArray()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 */ get(@ntRangefrom = 0) int index)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 */ set(@ntRangefrom = 0) int index, float value)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 */ size()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 */ getRawArray()370 public @NonNull float[] getRawArray() { 371 return mValues; 372 } 373 } 374 } 375