• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.google.protobuf.Internal.DoubleList;
34 
35 import java.util.Arrays;
36 import java.util.Collection;
37 import java.util.RandomAccess;
38 
39 /**
40  * An implementation of {@link DoubleList} on top of a primitive array.
41  *
42  * @author dweis@google.com (Daniel Weis)
43  */
44 final class DoubleArrayList
45     extends AbstractProtobufList<Double>
46     implements DoubleList, RandomAccess {
47 
48   private static final DoubleArrayList EMPTY_LIST = new DoubleArrayList();
49   static {
EMPTY_LIST.makeImmutable()50     EMPTY_LIST.makeImmutable();
51   }
52 
emptyList()53   public static DoubleArrayList emptyList() {
54     return EMPTY_LIST;
55   }
56 
57   /**
58    * The backing store for the list.
59    */
60   private double[] array;
61 
62   /**
63    * The size of the list distinct from the length of the array. That is, it is the number of
64    * elements set in the list.
65    */
66   private int size;
67 
68   /**
69    * Constructs a new mutable {@code DoubleArrayList} with default capacity.
70    */
DoubleArrayList()71   DoubleArrayList() {
72     this(new double[DEFAULT_CAPACITY], 0);
73   }
74 
75   /**
76    * Constructs a new mutable {@code DoubleArrayList}
77    * containing the same elements as {@code other}.
78    */
DoubleArrayList(double[] other, int size)79   private DoubleArrayList(double[] other, int size) {
80     array = other;
81     this.size = size;
82   }
83 
84   @Override
equals(Object o)85   public boolean equals(Object o) {
86     if (this == o) {
87       return true;
88     }
89     if (!(o instanceof DoubleArrayList)) {
90       return super.equals(o);
91     }
92     DoubleArrayList other = (DoubleArrayList) o;
93     if (size != other.size) {
94       return false;
95     }
96 
97     final double[] arr = other.array;
98     for (int i = 0; i < size; i++) {
99       if (array[i] != arr[i]) {
100         return false;
101       }
102     }
103 
104     return true;
105   }
106 
107   @Override
hashCode()108   public int hashCode() {
109     int result = 1;
110     for (int i = 0; i < size; i++) {
111       long bits = Double.doubleToLongBits(array[i]);
112       result = (31 * result) + Internal.hashLong(bits);
113     }
114     return result;
115   }
116 
117   @Override
mutableCopyWithCapacity(int capacity)118   public DoubleList mutableCopyWithCapacity(int capacity) {
119     if (capacity < size) {
120       throw new IllegalArgumentException();
121     }
122     return new DoubleArrayList(Arrays.copyOf(array, capacity), size);
123   }
124 
125   @Override
get(int index)126   public Double get(int index) {
127     return getDouble(index);
128   }
129 
130   @Override
getDouble(int index)131   public double getDouble(int index) {
132     ensureIndexInRange(index);
133     return array[index];
134   }
135 
136   @Override
size()137   public int size() {
138     return size;
139   }
140 
141   @Override
set(int index, Double element)142   public Double set(int index, Double element) {
143     return setDouble(index, element);
144   }
145 
146   @Override
setDouble(int index, double element)147   public double setDouble(int index, double element) {
148     ensureIsMutable();
149     ensureIndexInRange(index);
150     double previousValue = array[index];
151     array[index] = element;
152     return previousValue;
153   }
154 
155   @Override
add(int index, Double element)156   public void add(int index, Double element) {
157     addDouble(index, element);
158   }
159 
160   /**
161    * Like {@link #add(Double)} but more efficient in that it doesn't box the element.
162    */
163   @Override
addDouble(double element)164   public void addDouble(double element) {
165     addDouble(size, element);
166   }
167 
168   /**
169    * Like {@link #add(int, Double)} but more efficient in that it doesn't box the element.
170    */
addDouble(int index, double element)171   private void addDouble(int index, double element) {
172     ensureIsMutable();
173     if (index < 0 || index > size) {
174       throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
175     }
176 
177     if (size < array.length) {
178       // Shift everything over to make room
179       System.arraycopy(array, index, array, index + 1, size - index);
180     } else {
181       // Resize to 1.5x the size
182       int length = ((size * 3) / 2) + 1;
183       double[] newArray = new double[length];
184 
185       // Copy the first part directly
186       System.arraycopy(array, 0, newArray, 0, index);
187 
188       // Copy the rest shifted over by one to make room
189       System.arraycopy(array, index, newArray, index + 1, size - index);
190       array = newArray;
191     }
192 
193     array[index] = element;
194     size++;
195     modCount++;
196   }
197 
198   @Override
addAll(Collection<? extends Double> collection)199   public boolean addAll(Collection<? extends Double> collection) {
200     ensureIsMutable();
201 
202     if (collection == null) {
203       throw new NullPointerException();
204     }
205 
206     // We specialize when adding another DoubleArrayList to avoid boxing elements.
207     if (!(collection instanceof DoubleArrayList)) {
208       return super.addAll(collection);
209     }
210 
211     DoubleArrayList list = (DoubleArrayList) collection;
212     if (list.size == 0) {
213       return false;
214     }
215 
216     int overflow = Integer.MAX_VALUE - size;
217     if (overflow < list.size) {
218       // We can't actually represent a list this large.
219       throw new OutOfMemoryError();
220     }
221 
222     int newSize = size + list.size;
223     if (newSize > array.length) {
224       array = Arrays.copyOf(array, newSize);
225     }
226 
227     System.arraycopy(list.array, 0, array, size, list.size);
228     size = newSize;
229     modCount++;
230     return true;
231   }
232 
233   @Override
remove(Object o)234   public boolean remove(Object o) {
235     ensureIsMutable();
236     for (int i = 0; i < size; i++) {
237       if (o.equals(array[i])) {
238         System.arraycopy(array, i + 1, array, i, size - i);
239         size--;
240         modCount++;
241         return true;
242       }
243     }
244     return false;
245   }
246 
247   @Override
remove(int index)248   public Double remove(int index) {
249     ensureIsMutable();
250     ensureIndexInRange(index);
251     double value = array[index];
252     System.arraycopy(array, index + 1, array, index, size - index);
253     size--;
254     modCount++;
255     return value;
256   }
257 
258   /**
259    * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an
260    * {@link IndexOutOfBoundsException} if it is not.
261    *
262    * @param index the index to verify is in range
263    */
ensureIndexInRange(int index)264   private void ensureIndexInRange(int index) {
265     if (index < 0 || index >= size) {
266       throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index));
267     }
268   }
269 
makeOutOfBoundsExceptionMessage(int index)270   private String makeOutOfBoundsExceptionMessage(int index) {
271     return "Index:" + index + ", Size:" + size;
272   }
273 }
274