OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 class GrowableObjectArray<T> implements Array<T> { | |
6 ObjectArray<T> backingArray; | |
7 | |
8 void copyFrom(List<Object> src, int srcStart, int dstStart, int count) { | |
9 Arrays.copy(src, srcStart, this, dstStart, count); | |
10 } | |
11 | |
12 void setRange(int start, int length, List<T> from, [int startFrom = 0]) { | |
13 if (length < 0) { | |
14 throw new IllegalArgumentException("negative length $length"); | |
15 } | |
16 Arrays.copy(from, startFrom, this, start, length); | |
17 } | |
18 | |
19 void removeRange(int start, int length) { | |
20 if (length == 0) { | |
21 return; | |
22 } | |
23 if (length < 0) { | |
24 throw new IllegalArgumentException("negative length $length"); | |
25 } | |
26 if (start < 0 || start >= this.length) { | |
27 throw new IndexOutOfRangeException(start); | |
28 } | |
29 if (start + length > this.length) { | |
30 throw new IndexOutOfRangeException(start + length); | |
31 } | |
32 Arrays.copy(backingArray, | |
33 start + length, | |
34 backingArray, | |
35 start, | |
36 this.length - length - start); | |
37 this.length = this.length - length; | |
38 } | |
39 | |
40 void insertRange(int start, int length, [T initialValue = null]) { | |
41 if (length == 0) { | |
42 return; | |
43 } | |
44 if (length < 0) { | |
45 throw new IllegalArgumentException("negative length $length"); | |
46 } | |
47 if (start < 0 || start > this.length) { | |
48 throw new IndexOutOfRangeException(start); | |
49 } | |
50 if (this.length + length >= backingArray.length) { | |
51 grow(backingArray.length + length); | |
52 } | |
53 Arrays.copy(backingArray, | |
54 start, | |
55 backingArray, | |
56 start + length, | |
57 this.length - start); | |
58 if (initialValue !== null) { | |
59 for (int i = start; i < start + length; i++) { | |
60 backingArray[i] = initialValue; | |
61 } | |
62 } | |
63 this.length = this.length + length; | |
64 } | |
65 | |
66 List<T> getRange(int start, int length) { | |
67 if (length == 0) return []; | |
68 Arrays.rangeCheck(this, start, length); | |
69 return new List<T>.fromList(this, start, start + length); | |
70 } | |
71 | |
72 // The length of this growable array. It is always less than the | |
73 // length of the backing array. | |
74 int _length; | |
75 // Constant used by indexOf and lastIndexOf when the element given | |
76 // is not in the array. | |
77 static final int ABSENT = -1; | |
78 | |
79 GrowableObjectArray() | |
80 : _length = 0, backingArray = new ObjectArray<T>(4) {} | |
81 | |
82 GrowableObjectArray.withCapacity(int capacity) { | |
83 _length = 0; | |
84 if (capacity <= 0) { | |
85 capacity = 4; | |
86 } | |
87 backingArray = new ObjectArray<T>(capacity); | |
88 } | |
89 | |
90 GrowableObjectArray._usingArray(Array<T> array) { | |
91 backingArray = array; | |
92 _length = array.length; | |
93 if (_length == 0) { | |
94 grow(4); | |
95 } | |
96 } | |
97 | |
98 factory GrowableObjectArray.from(Collection<T> other) { | |
99 Array result = new GrowableObjectArray(); | |
100 result.addAll(other); | |
101 return result; | |
102 } | |
103 | |
104 int get length() { | |
105 return _length; | |
106 } | |
107 | |
108 void set length(int new_length) { | |
109 if (new_length >= backingArray.length) { | |
110 grow(new_length); | |
111 } else { | |
112 for (int i = new_length; i < _length; i++) { | |
113 backingArray[i] = null; | |
114 } | |
115 } | |
116 _length = new_length; | |
117 } | |
118 | |
119 T operator [](int index) { | |
120 if (index >= _length) { | |
121 throw new IndexOutOfRangeException(index); | |
122 } | |
123 return backingArray[index]; | |
124 } | |
125 | |
126 void operator []=(int index, T value) { | |
127 if (index >= _length) { | |
128 throw new IndexOutOfRangeException(index); | |
129 } | |
130 backingArray[index] = value; | |
131 } | |
132 | |
133 void grow(int capacity) { | |
134 ObjectArray<T> newArray = new ObjectArray<T>(capacity); | |
135 int length = backingArray.length; | |
136 for (int i = 0; i < length; i++) { | |
137 newArray[i] = backingArray[i]; | |
138 } | |
139 backingArray = newArray; | |
140 } | |
141 | |
142 int add(T value) { | |
143 if (_length == backingArray.length) { | |
144 grow(_length * 2); | |
145 } | |
146 backingArray[_length] = value; | |
147 return ++_length; | |
148 } | |
149 | |
150 void addLast(T element) { | |
151 add(element); | |
152 } | |
153 | |
154 void addAll(Collection<T> collection) { | |
155 for (T elem in collection) { | |
156 add(elem); | |
157 } | |
158 } | |
159 | |
160 T removeLast() { | |
161 _length--; | |
162 return backingArray[_length]; | |
163 } | |
164 | |
165 T last() { | |
166 if (_length === 0) { | |
167 throw new IndexOutOfRangeException(-1); | |
168 } | |
169 return backingArray[_length - 1]; | |
170 } | |
171 | |
172 int indexOf(T element, int startIndex) { | |
173 return Arrays.indexOf(backingArray, element, startIndex, _length); | |
174 } | |
175 | |
176 int lastIndexOf(T element, int startIndex) { | |
177 return Arrays.lastIndexOf(backingArray, element, startIndex); | |
178 } | |
179 | |
180 /** | |
181 * Collection interface. | |
182 */ | |
183 | |
184 void forEach(f(T element)) { | |
185 // TODO(srdjan): Use Collections.forEach(this, f); | |
186 // Using backingArray directly improves DeltaBlue performance by 25%. | |
187 for (int i = 0; i < _length; i++) { | |
188 f(backingArray[i]); | |
189 } | |
190 } | |
191 | |
192 Collection<T> filter(bool f(T element)) { | |
193 return Collections.filter(this, new GrowableObjectArray<T>(), f); | |
194 } | |
195 | |
196 bool every(bool f(T element)) { | |
197 return Collections.every(this, f); | |
198 } | |
199 | |
200 bool some(bool f(T element)) { | |
201 return Collections.some(this, f); | |
202 } | |
203 | |
204 bool isEmpty() { | |
205 return this.length === 0; | |
206 } | |
207 | |
208 void clear() { | |
209 this.length = 0; | |
210 } | |
211 | |
212 void sort(int compare(T a, T b)) { | |
213 DualPivotQuicksort.sort(this, compare); | |
214 } | |
215 | |
216 Iterator<T> iterator() { | |
217 return new VariableSizeArrayIterator<T>(this); | |
218 } | |
219 } | |
220 | |
221 | |
222 // Iterator for arrays with variable size. | |
223 class VariableSizeArrayIterator<T> implements Iterator<T> { | |
224 VariableSizeArrayIterator(GrowableObjectArray<T> array) | |
225 : _array = array, _pos = 0 { | |
226 } | |
227 | |
228 bool hasNext() { | |
229 return _array._length > _pos; | |
230 } | |
231 | |
232 T next() { | |
233 if (!hasNext()) { | |
234 throw const NoMoreElementsException(); | |
235 } | |
236 return _array[_pos++]; | |
237 } | |
238 | |
239 final GrowableObjectArray<T> _array; | |
240 int _pos; | |
241 } | |
242 | |
OLD | NEW |