1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.util;
12
13 import java.util.Arrays;
14 import java.util.Collections;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.NoSuchElementException;
18 import java.util.function.BinaryOperator;
19 import java.util.stream.Collector;
20
21 import org.eclipse.jgit.annotations.Nullable;
22 import org.eclipse.jgit.lib.Ref;
23 import org.eclipse.jgit.lib.RefComparator;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class RefList<T extends Ref> implements Iterable<Ref> {
41 private static final RefList<Ref> EMPTY = new RefList<>(new Ref[0], 0);
42
43
44
45
46
47
48 @SuppressWarnings("unchecked")
49 public static <T extends Ref> RefList<T> emptyList() {
50 return (RefList<T>) EMPTY;
51 }
52
53 final Ref[] list;
54
55 final int cnt;
56
57 RefList(Ref[] list, int cnt) {
58 this.list = list;
59 this.cnt = cnt;
60 }
61
62
63
64
65
66
67
68 protected RefList(RefList<T> src) {
69 this.list = src.list;
70 this.cnt = src.cnt;
71 }
72
73
74 @Override
75 public Iterator<Ref> iterator() {
76 return new Iterator<>() {
77 private int idx;
78
79 @Override
80 public boolean hasNext() {
81 return idx < cnt;
82 }
83
84 @Override
85 public Ref next() {
86 if (idx < cnt)
87 return list[idx++];
88 throw new NoSuchElementException();
89 }
90
91 @Override
92 public void remove() {
93 throw new UnsupportedOperationException();
94 }
95 };
96 }
97
98
99
100
101
102
103 public final List<Ref> asList() {
104 final List<Ref> r = Arrays.asList(list).subList(0, cnt);
105 return Collections.unmodifiableList(r);
106 }
107
108
109
110
111
112
113 public final int size() {
114 return cnt;
115 }
116
117
118
119
120
121
122 public final boolean isEmpty() {
123 return cnt == 0;
124 }
125
126
127
128
129
130
131
132
133
134
135 public final int find(String name) {
136 int high = cnt;
137 if (high == 0)
138 return -1;
139 int low = 0;
140 do {
141 final int mid = (low + high) >>> 1;
142 final int cmp = RefComparator.compareTo(list[mid], name);
143 if (cmp < 0)
144 low = mid + 1;
145 else if (cmp == 0)
146 return mid;
147 else
148 high = mid;
149 } while (low < high);
150 return -(low + 1);
151 }
152
153
154
155
156
157
158
159
160 public final boolean contains(String name) {
161 return 0 <= find(name);
162 }
163
164
165
166
167
168
169
170
171 public final T get(String name) {
172 int idx = find(name);
173 return 0 <= idx ? get(idx) : null;
174 }
175
176
177
178
179
180
181
182
183 @SuppressWarnings("unchecked")
184 public final T get(int idx) {
185 return (T) list[idx];
186 }
187
188
189
190
191
192
193
194
195
196
197
198 public final Builder<T> copy(int n) {
199 Builder<T> r = new Builder<>(Math.max(16, n));
200 r.addAll(list, 0, n);
201 return r;
202 }
203
204
205
206
207
208
209
210
211
212
213
214
215
216 public final RefList<T> set(int idx, T ref) {
217 Ref[] newList = new Ref[cnt];
218 System.arraycopy(list, 0, newList, 0, cnt);
219 newList[idx] = ref;
220 return new RefList<>(newList, cnt);
221 }
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237 public final RefList<T> add(int idx, T ref) {
238 if (idx < 0)
239 idx = -(idx + 1);
240
241 Ref[] newList = new Ref[cnt + 1];
242 if (0 < idx)
243 System.arraycopy(list, 0, newList, 0, idx);
244 newList[idx] = ref;
245 if (idx < cnt)
246 System.arraycopy(list, idx, newList, idx + 1, cnt - idx);
247 return new RefList<>(newList, cnt + 1);
248 }
249
250
251
252
253
254
255
256
257
258
259
260 public final RefList<T> remove(int idx) {
261 if (cnt == 1)
262 return emptyList();
263 Ref[] newList = new Ref[cnt - 1];
264 if (0 < idx)
265 System.arraycopy(list, 0, newList, 0, idx);
266 if (idx + 1 < cnt)
267 System.arraycopy(list, idx + 1, newList, idx, cnt - (idx + 1));
268 return new RefList<>(newList, cnt - 1);
269 }
270
271
272
273
274
275
276
277
278
279
280
281
282 public final RefList<T> put(T ref) {
283 int idx = find(ref.getName());
284 if (0 <= idx)
285 return set(idx, ref);
286 return add(idx, ref);
287 }
288
289
290 @Override
291 public String toString() {
292 StringBuilder r = new StringBuilder();
293 r.append('[');
294 if (cnt > 0) {
295 r.append(list[0]);
296 for (int i = 1; i < cnt; i++) {
297 r.append(", ");
298 r.append(list[i]);
299 }
300 }
301 r.append(']');
302 return r.toString();
303 }
304
305
306
307
308
309
310
311
312
313 public static <T extends Ref> Collector<T, ?, RefList<T>> toRefList(
314 @Nullable BinaryOperator<T> mergeFunction) {
315 return Collector.of(
316 () -> new Builder<>(),
317 Builder<T>::add, (b1, b2) -> {
318 Builder<T> b = new Builder<>();
319 b.addAll(b1);
320 b.addAll(b2);
321 return b;
322 }, (b) -> {
323 if (mergeFunction != null) {
324 b.sort();
325 b.dedupe(mergeFunction);
326 }
327 return b.toRefList();
328 });
329 }
330
331
332
333
334
335
336
337 public static class Builder<T extends Ref> {
338 private Ref[] list;
339
340 private int size;
341
342
343 public Builder() {
344 this(16);
345 }
346
347
348
349
350
351
352
353
354 public Builder(int capacity) {
355 list = new Ref[Math.max(capacity, 16)];
356 }
357
358
359 public int size() {
360 return size;
361 }
362
363
364
365
366
367
368
369
370 @SuppressWarnings("unchecked")
371 public T get(int idx) {
372 return (T) list[idx];
373 }
374
375
376
377
378
379
380
381 public void remove(int idx) {
382 System.arraycopy(list, idx + 1, list, idx, size - (idx + 1));
383 size--;
384 }
385
386
387
388
389
390
391
392
393
394 public void add(T ref) {
395 if (list.length == size) {
396 Ref[] n = new Ref[size * 2];
397 System.arraycopy(list, 0, n, 0, size);
398 list = n;
399 }
400 list[size++] = ref;
401 }
402
403
404
405
406
407
408
409 public void addAll(Builder other) {
410 addAll(other.list, 0, other.size);
411 }
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426 public void addAll(Ref[] src, int off, int cnt) {
427 if (list.length < size + cnt) {
428 Ref[] n = new Ref[Math.max(size * 2, size + cnt)];
429 System.arraycopy(list, 0, n, 0, size);
430 list = n;
431 }
432 System.arraycopy(src, off, list, size, cnt);
433 size += cnt;
434 }
435
436
437
438
439
440
441
442
443
444 public void set(int idx, T ref) {
445 list[idx] = ref;
446 }
447
448
449 public void sort() {
450 Arrays.sort(list, 0, size, RefComparator.INSTANCE);
451 }
452
453
454
455
456
457
458 @SuppressWarnings("unchecked")
459 void dedupe(BinaryOperator<T> mergeFunction) {
460 if (size == 0) {
461 return;
462 }
463 int lastElement = 0;
464 for (int i = 1; i < size; i++) {
465 if (RefComparator.INSTANCE.compare(list[lastElement],
466 list[i]) == 0) {
467 list[lastElement] = mergeFunction
468 .apply((T) list[lastElement], (T) list[i]);
469 } else {
470 list[lastElement + 1] = list[i];
471 lastElement++;
472 }
473 }
474 size = lastElement + 1;
475 Arrays.fill(list, size, list.length, null);
476 }
477
478
479 public RefList<T> toRefList() {
480 return new RefList<>(list, size);
481 }
482
483 @Override
484 public String toString() {
485 return toRefList().toString();
486 }
487 }
488 }