1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // https://developers.google.com/protocol-buffers/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf; 32 33 import static com.google.protobuf.Internal.checkNotNull; 34 35 import com.google.protobuf.Internal.FloatList; 36 import java.util.Arrays; 37 import java.util.Collection; 38 import java.util.RandomAccess; 39 40 /** 41 * An implementation of {@link FloatList} on top of a primitive array. 42 * 43 * @author dweis@google.com (Daniel Weis) 44 */ 45 final class FloatArrayList extends AbstractProtobufList<Float> 46 implements FloatList, RandomAccess, PrimitiveNonBoxingCollection { 47 48 private static final FloatArrayList EMPTY_LIST = new FloatArrayList(new float[0], 0); 49 static { EMPTY_LIST.makeImmutable()50 EMPTY_LIST.makeImmutable(); 51 } 52 emptyList()53 public static FloatArrayList emptyList() { 54 return EMPTY_LIST; 55 } 56 57 /** The backing store for the list. */ 58 private float[] array; 59 60 /** 61 * The size of the list distinct from the length of the array. That is, it is the number of 62 * elements set in the list. 63 */ 64 private int size; 65 66 /** Constructs a new mutable {@code FloatArrayList} with default capacity. */ FloatArrayList()67 FloatArrayList() { 68 this(new float[DEFAULT_CAPACITY], 0); 69 } 70 71 /** 72 * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}. 73 */ FloatArrayList(float[] other, int size)74 private FloatArrayList(float[] other, int size) { 75 array = other; 76 this.size = size; 77 } 78 79 @Override removeRange(int fromIndex, int toIndex)80 protected void removeRange(int fromIndex, int toIndex) { 81 ensureIsMutable(); 82 if (toIndex < fromIndex) { 83 throw new IndexOutOfBoundsException("toIndex < fromIndex"); 84 } 85 86 System.arraycopy(array, toIndex, array, fromIndex, size - toIndex); 87 size -= (toIndex - fromIndex); 88 modCount++; 89 } 90 91 @Override equals(Object o)92 public boolean equals(Object o) { 93 if (this == o) { 94 return true; 95 } 96 if (!(o instanceof FloatArrayList)) { 97 return super.equals(o); 98 } 99 FloatArrayList other = (FloatArrayList) o; 100 if (size != other.size) { 101 return false; 102 } 103 104 final float[] arr = other.array; 105 for (int i = 0; i < size; i++) { 106 if (Float.floatToIntBits(array[i]) != Float.floatToIntBits(arr[i])) { 107 return false; 108 } 109 } 110 111 return true; 112 } 113 114 @Override hashCode()115 public int hashCode() { 116 int result = 1; 117 for (int i = 0; i < size; i++) { 118 result = (31 * result) + Float.floatToIntBits(array[i]); 119 } 120 return result; 121 } 122 123 @Override mutableCopyWithCapacity(int capacity)124 public FloatList mutableCopyWithCapacity(int capacity) { 125 if (capacity < size) { 126 throw new IllegalArgumentException(); 127 } 128 return new FloatArrayList(Arrays.copyOf(array, capacity), size); 129 } 130 131 @Override get(int index)132 public Float get(int index) { 133 return getFloat(index); 134 } 135 136 @Override getFloat(int index)137 public float getFloat(int index) { 138 ensureIndexInRange(index); 139 return array[index]; 140 } 141 142 @Override indexOf(Object element)143 public int indexOf(Object element) { 144 if (!(element instanceof Float)) { 145 return -1; 146 } 147 float unboxedElement = (Float) element; 148 int numElems = size(); 149 for (int i = 0; i < numElems; i++) { 150 if (array[i] == unboxedElement) { 151 return i; 152 } 153 } 154 return -1; 155 } 156 157 @Override contains(Object element)158 public boolean contains(Object element) { 159 return indexOf(element) != -1; 160 } 161 162 @Override size()163 public int size() { 164 return size; 165 } 166 167 @Override set(int index, Float element)168 public Float set(int index, Float element) { 169 return setFloat(index, element); 170 } 171 172 @Override setFloat(int index, float element)173 public float setFloat(int index, float element) { 174 ensureIsMutable(); 175 ensureIndexInRange(index); 176 float previousValue = array[index]; 177 array[index] = element; 178 return previousValue; 179 } 180 181 @Override add(Float element)182 public boolean add(Float element) { 183 addFloat(element); 184 return true; 185 } 186 187 @Override add(int index, Float element)188 public void add(int index, Float element) { 189 addFloat(index, element); 190 } 191 192 /** Like {@link #add(Float)} but more efficient in that it doesn't box the element. */ 193 @Override addFloat(float element)194 public void addFloat(float element) { 195 ensureIsMutable(); 196 if (size == array.length) { 197 // Resize to 1.5x the size 198 int length = ((size * 3) / 2) + 1; 199 float[] newArray = new float[length]; 200 201 System.arraycopy(array, 0, newArray, 0, size); 202 array = newArray; 203 } 204 205 array[size++] = element; 206 } 207 208 /** Like {@link #add(int, Float)} but more efficient in that it doesn't box the element. */ addFloat(int index, float element)209 private void addFloat(int index, float element) { 210 ensureIsMutable(); 211 if (index < 0 || index > size) { 212 throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); 213 } 214 215 if (size < array.length) { 216 // Shift everything over to make room 217 System.arraycopy(array, index, array, index + 1, size - index); 218 } else { 219 // Resize to 1.5x the size 220 int length = ((size * 3) / 2) + 1; 221 float[] newArray = new float[length]; 222 223 // Copy the first part directly 224 System.arraycopy(array, 0, newArray, 0, index); 225 226 // Copy the rest shifted over by one to make room 227 System.arraycopy(array, index, newArray, index + 1, size - index); 228 array = newArray; 229 } 230 231 array[index] = element; 232 size++; 233 modCount++; 234 } 235 236 @Override addAll(Collection<? extends Float> collection)237 public boolean addAll(Collection<? extends Float> collection) { 238 ensureIsMutable(); 239 240 checkNotNull(collection); 241 242 // We specialize when adding another FloatArrayList to avoid boxing elements. 243 if (!(collection instanceof FloatArrayList)) { 244 return super.addAll(collection); 245 } 246 247 FloatArrayList list = (FloatArrayList) collection; 248 if (list.size == 0) { 249 return false; 250 } 251 252 int overflow = Integer.MAX_VALUE - size; 253 if (overflow < list.size) { 254 // We can't actually represent a list this large. 255 throw new OutOfMemoryError(); 256 } 257 258 int newSize = size + list.size; 259 if (newSize > array.length) { 260 array = Arrays.copyOf(array, newSize); 261 } 262 263 System.arraycopy(list.array, 0, array, size, list.size); 264 size = newSize; 265 modCount++; 266 return true; 267 } 268 269 @Override remove(Object o)270 public boolean remove(Object o) { 271 ensureIsMutable(); 272 for (int i = 0; i < size; i++) { 273 if (o.equals(array[i])) { 274 System.arraycopy(array, i + 1, array, i, size - i - 1); 275 size--; 276 modCount++; 277 return true; 278 } 279 } 280 return false; 281 } 282 283 @Override remove(int index)284 public Float remove(int index) { 285 ensureIsMutable(); 286 ensureIndexInRange(index); 287 float value = array[index]; 288 if (index < size - 1) { 289 System.arraycopy(array, index + 1, array, index, size - index - 1); 290 } 291 size--; 292 modCount++; 293 return value; 294 } 295 296 /** 297 * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an 298 * {@link IndexOutOfBoundsException} if it is not. 299 * 300 * @param index the index to verify is in range 301 */ ensureIndexInRange(int index)302 private void ensureIndexInRange(int index) { 303 if (index < 0 || index >= size) { 304 throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); 305 } 306 } 307 makeOutOfBoundsExceptionMessage(int index)308 private String makeOutOfBoundsExceptionMessage(int index) { 309 return "Index:" + index + ", Size:" + size; 310 } 311 } 312