1 /* 2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.util.stream; 26 27 import java.util.ArrayList; 28 import java.util.Arrays; 29 import java.util.Iterator; 30 import java.util.List; 31 import java.util.Objects; 32 import java.util.PrimitiveIterator; 33 import java.util.Spliterator; 34 import java.util.Spliterators; 35 import java.util.function.Consumer; 36 import java.util.function.DoubleConsumer; 37 import java.util.function.IntConsumer; 38 import java.util.function.IntFunction; 39 import java.util.function.LongConsumer; 40 41 /** 42 * An ordered collection of elements. Elements can be added, but not removed. 43 * Goes through a building phase, during which elements can be added, and a 44 * traversal phase, during which elements can be traversed in order but no 45 * further modifications are possible. 46 * 47 * <p> One or more arrays are used to store elements. The use of a multiple 48 * arrays has better performance characteristics than a single array used by 49 * {@link ArrayList}, as when the capacity of the list needs to be increased 50 * no copying of elements is required. This is usually beneficial in the case 51 * where the results will be traversed a small number of times. 52 * 53 * @param <E> the type of elements in this list 54 * @since 1.8 55 * @hide Visible for CTS testing only (OpenJDK8 tests). 56 */ 57 // Android-changed: Made public for CTS tests only. 58 public class SpinedBuffer<E> 59 extends AbstractSpinedBuffer 60 implements Consumer<E>, Iterable<E> { 61 62 /* 63 * We optimistically hope that all the data will fit into the first chunk, 64 * so we try to avoid inflating the spine[] and priorElementCount[] arrays 65 * prematurely. So methods must be prepared to deal with these arrays being 66 * null. If spine is non-null, then spineIndex points to the current chunk 67 * within the spine, otherwise it is zero. The spine and priorElementCount 68 * arrays are always the same size, and for any i <= spineIndex, 69 * priorElementCount[i] is the sum of the sizes of all the prior chunks. 70 * 71 * The curChunk pointer is always valid. The elementIndex is the index of 72 * the next element to be written in curChunk; this may be past the end of 73 * curChunk so we have to check before writing. When we inflate the spine 74 * array, curChunk becomes the first element in it. When we clear the 75 * buffer, we discard all chunks except the first one, which we clear, 76 * restoring it to the initial single-chunk state. 77 */ 78 79 /** 80 * Chunk that we're currently writing into; may or may not be aliased with 81 * the first element of the spine. 82 */ 83 protected E[] curChunk; 84 85 /** 86 * All chunks, or null if there is only one chunk. 87 */ 88 protected E[][] spine; 89 90 /** 91 * Constructs an empty list with the specified initial capacity. 92 * 93 * @param initialCapacity the initial capacity of the list 94 * @throws IllegalArgumentException if the specified initial capacity 95 * is negative 96 */ 97 @SuppressWarnings("unchecked") 98 // Android-changed: Made public for CTS tests only. SpinedBuffer(int initialCapacity)99 public SpinedBuffer(int initialCapacity) { 100 super(initialCapacity); 101 curChunk = (E[]) new Object[1 << initialChunkPower]; 102 } 103 104 /** 105 * Constructs an empty list with an initial capacity of sixteen. 106 */ 107 @SuppressWarnings("unchecked") 108 // Android-changed: Made public for CTS tests only. SpinedBuffer()109 public SpinedBuffer() { 110 super(); 111 curChunk = (E[]) new Object[1 << initialChunkPower]; 112 } 113 114 /** 115 * Returns the current capacity of the buffer 116 */ capacity()117 protected long capacity() { 118 return (spineIndex == 0) 119 ? curChunk.length 120 : priorElementCount[spineIndex] + spine[spineIndex].length; 121 } 122 123 @SuppressWarnings("unchecked") inflateSpine()124 private void inflateSpine() { 125 if (spine == null) { 126 spine = (E[][]) new Object[MIN_SPINE_SIZE][]; 127 priorElementCount = new long[MIN_SPINE_SIZE]; 128 spine[0] = curChunk; 129 } 130 } 131 132 /** 133 * Ensure that the buffer has at least capacity to hold the target size 134 */ 135 @SuppressWarnings("unchecked") ensureCapacity(long targetSize)136 protected final void ensureCapacity(long targetSize) { 137 long capacity = capacity(); 138 if (targetSize > capacity) { 139 inflateSpine(); 140 for (int i=spineIndex+1; targetSize > capacity; i++) { 141 if (i >= spine.length) { 142 int newSpineSize = spine.length * 2; 143 spine = Arrays.copyOf(spine, newSpineSize); 144 priorElementCount = Arrays.copyOf(priorElementCount, newSpineSize); 145 } 146 int nextChunkSize = chunkSize(i); 147 spine[i] = (E[]) new Object[nextChunkSize]; 148 priorElementCount[i] = priorElementCount[i-1] + spine[i-1].length; 149 capacity += nextChunkSize; 150 } 151 } 152 } 153 154 /** 155 * Force the buffer to increase its capacity. 156 */ increaseCapacity()157 protected void increaseCapacity() { 158 ensureCapacity(capacity() + 1); 159 } 160 161 /** 162 * Retrieve the element at the specified index. 163 */ get(long index)164 public E get(long index) { 165 // @@@ can further optimize by caching last seen spineIndex, 166 // which is going to be right most of the time 167 168 // Casts to int are safe since the spine array index is the index minus 169 // the prior element count from the current spine 170 if (spineIndex == 0) { 171 if (index < elementIndex) 172 return curChunk[((int) index)]; 173 else 174 throw new IndexOutOfBoundsException(Long.toString(index)); 175 } 176 177 if (index >= count()) 178 throw new IndexOutOfBoundsException(Long.toString(index)); 179 180 for (int j=0; j <= spineIndex; j++) 181 if (index < priorElementCount[j] + spine[j].length) 182 return spine[j][((int) (index - priorElementCount[j]))]; 183 184 throw new IndexOutOfBoundsException(Long.toString(index)); 185 } 186 187 /** 188 * Copy the elements, starting at the specified offset, into the specified 189 * array. 190 */ copyInto(E[] array, int offset)191 public void copyInto(E[] array, int offset) { 192 long finalOffset = offset + count(); 193 if (finalOffset > array.length || finalOffset < offset) { 194 throw new IndexOutOfBoundsException("does not fit"); 195 } 196 197 if (spineIndex == 0) 198 System.arraycopy(curChunk, 0, array, offset, elementIndex); 199 else { 200 // full chunks 201 for (int i=0; i < spineIndex; i++) { 202 System.arraycopy(spine[i], 0, array, offset, spine[i].length); 203 offset += spine[i].length; 204 } 205 if (elementIndex > 0) 206 System.arraycopy(curChunk, 0, array, offset, elementIndex); 207 } 208 } 209 210 /** 211 * Create a new array using the specified array factory, and copy the 212 * elements into it. 213 */ asArray(IntFunction<E[]> arrayFactory)214 public E[] asArray(IntFunction<E[]> arrayFactory) { 215 long size = count(); 216 if (size >= Nodes.MAX_ARRAY_SIZE) 217 throw new IllegalArgumentException(Nodes.BAD_SIZE); 218 E[] result = arrayFactory.apply((int) size); 219 copyInto(result, 0); 220 return result; 221 } 222 223 @Override clear()224 public void clear() { 225 if (spine != null) { 226 curChunk = spine[0]; 227 for (int i=0; i<curChunk.length; i++) 228 curChunk[i] = null; 229 spine = null; 230 priorElementCount = null; 231 } 232 else { 233 for (int i=0; i<elementIndex; i++) 234 curChunk[i] = null; 235 } 236 elementIndex = 0; 237 spineIndex = 0; 238 } 239 240 @Override iterator()241 public Iterator<E> iterator() { 242 return Spliterators.iterator(spliterator()); 243 } 244 245 @Override forEach(Consumer<? super E> consumer)246 public void forEach(Consumer<? super E> consumer) { 247 // completed chunks, if any 248 for (int j = 0; j < spineIndex; j++) 249 for (E t : spine[j]) 250 consumer.accept(t); 251 252 // current chunk 253 for (int i=0; i<elementIndex; i++) 254 consumer.accept(curChunk[i]); 255 } 256 257 @Override accept(E e)258 public void accept(E e) { 259 if (elementIndex == curChunk.length) { 260 inflateSpine(); 261 if (spineIndex+1 >= spine.length || spine[spineIndex+1] == null) 262 increaseCapacity(); 263 elementIndex = 0; 264 ++spineIndex; 265 curChunk = spine[spineIndex]; 266 } 267 curChunk[elementIndex++] = e; 268 } 269 270 @Override toString()271 public String toString() { 272 List<E> list = new ArrayList<>(); 273 forEach(list::add); 274 return "SpinedBuffer:" + list.toString(); 275 } 276 277 private static final int SPLITERATOR_CHARACTERISTICS 278 = Spliterator.SIZED | Spliterator.ORDERED | Spliterator.SUBSIZED; 279 280 /** 281 * Return a {@link Spliterator} describing the contents of the buffer. 282 */ spliterator()283 public Spliterator<E> spliterator() { 284 class Splitr implements Spliterator<E> { 285 // The current spine index 286 int splSpineIndex; 287 288 // Last spine index 289 final int lastSpineIndex; 290 291 // The current element index into the current spine 292 int splElementIndex; 293 294 // Last spine's last element index + 1 295 final int lastSpineElementFence; 296 297 // When splSpineIndex >= lastSpineIndex and 298 // splElementIndex >= lastSpineElementFence then 299 // this spliterator is fully traversed 300 // tryAdvance can set splSpineIndex > spineIndex if the last spine is full 301 302 // The current spine array 303 E[] splChunk; 304 305 Splitr(int firstSpineIndex, int lastSpineIndex, 306 int firstSpineElementIndex, int lastSpineElementFence) { 307 this.splSpineIndex = firstSpineIndex; 308 this.lastSpineIndex = lastSpineIndex; 309 this.splElementIndex = firstSpineElementIndex; 310 this.lastSpineElementFence = lastSpineElementFence; 311 assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0; 312 splChunk = (spine == null) ? curChunk : spine[firstSpineIndex]; 313 } 314 315 @Override 316 public long estimateSize() { 317 return (splSpineIndex == lastSpineIndex) 318 ? (long) lastSpineElementFence - splElementIndex 319 : // # of elements prior to end - 320 priorElementCount[lastSpineIndex] + lastSpineElementFence - 321 // # of elements prior to current 322 priorElementCount[splSpineIndex] - splElementIndex; 323 } 324 325 @Override 326 public int characteristics() { 327 return SPLITERATOR_CHARACTERISTICS; 328 } 329 330 @Override 331 public boolean tryAdvance(Consumer<? super E> consumer) { 332 Objects.requireNonNull(consumer); 333 334 if (splSpineIndex < lastSpineIndex 335 || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { 336 consumer.accept(splChunk[splElementIndex++]); 337 338 if (splElementIndex == splChunk.length) { 339 splElementIndex = 0; 340 ++splSpineIndex; 341 if (spine != null && splSpineIndex <= lastSpineIndex) 342 splChunk = spine[splSpineIndex]; 343 } 344 return true; 345 } 346 return false; 347 } 348 349 @Override 350 public void forEachRemaining(Consumer<? super E> consumer) { 351 Objects.requireNonNull(consumer); 352 353 if (splSpineIndex < lastSpineIndex 354 || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { 355 int i = splElementIndex; 356 // completed chunks, if any 357 for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) { 358 E[] chunk = spine[sp]; 359 for (; i < chunk.length; i++) { 360 consumer.accept(chunk[i]); 361 } 362 i = 0; 363 } 364 // last (or current uncompleted) chunk 365 E[] chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex]; 366 int hElementIndex = lastSpineElementFence; 367 for (; i < hElementIndex; i++) { 368 consumer.accept(chunk[i]); 369 } 370 // mark consumed 371 splSpineIndex = lastSpineIndex; 372 splElementIndex = lastSpineElementFence; 373 } 374 } 375 376 @Override 377 public Spliterator<E> trySplit() { 378 if (splSpineIndex < lastSpineIndex) { 379 // split just before last chunk (if it is full this means 50:50 split) 380 Spliterator<E> ret = new Splitr(splSpineIndex, lastSpineIndex - 1, 381 splElementIndex, spine[lastSpineIndex-1].length); 382 // position to start of last chunk 383 splSpineIndex = lastSpineIndex; 384 splElementIndex = 0; 385 splChunk = spine[splSpineIndex]; 386 return ret; 387 } 388 else if (splSpineIndex == lastSpineIndex) { 389 int t = (lastSpineElementFence - splElementIndex) / 2; 390 if (t == 0) 391 return null; 392 else { 393 Spliterator<E> ret = Arrays.spliterator(splChunk, splElementIndex, splElementIndex + t); 394 splElementIndex += t; 395 return ret; 396 } 397 } 398 else { 399 return null; 400 } 401 } 402 } 403 return new Splitr(0, spineIndex, 0, elementIndex); 404 } 405 406 /** 407 * An ordered collection of primitive values. Elements can be added, but 408 * not removed. Goes through a building phase, during which elements can be 409 * added, and a traversal phase, during which elements can be traversed in 410 * order but no further modifications are possible. 411 * 412 * <p> One or more arrays are used to store elements. The use of a multiple 413 * arrays has better performance characteristics than a single array used by 414 * {@link ArrayList}, as when the capacity of the list needs to be increased 415 * no copying of elements is required. This is usually beneficial in the case 416 * where the results will be traversed a small number of times. 417 * 418 * @param <E> the wrapper type for this primitive type 419 * @param <T_ARR> the array type for this primitive type 420 * @param <T_CONS> the Consumer type for this primitive type 421 */ 422 abstract static class OfPrimitive<E, T_ARR, T_CONS> 423 extends AbstractSpinedBuffer implements Iterable<E> { 424 425 /* 426 * We optimistically hope that all the data will fit into the first chunk, 427 * so we try to avoid inflating the spine[] and priorElementCount[] arrays 428 * prematurely. So methods must be prepared to deal with these arrays being 429 * null. If spine is non-null, then spineIndex points to the current chunk 430 * within the spine, otherwise it is zero. The spine and priorElementCount 431 * arrays are always the same size, and for any i <= spineIndex, 432 * priorElementCount[i] is the sum of the sizes of all the prior chunks. 433 * 434 * The curChunk pointer is always valid. The elementIndex is the index of 435 * the next element to be written in curChunk; this may be past the end of 436 * curChunk so we have to check before writing. When we inflate the spine 437 * array, curChunk becomes the first element in it. When we clear the 438 * buffer, we discard all chunks except the first one, which we clear, 439 * restoring it to the initial single-chunk state. 440 */ 441 442 // The chunk we're currently writing into 443 T_ARR curChunk; 444 445 // All chunks, or null if there is only one chunk 446 T_ARR[] spine; 447 448 /** 449 * Constructs an empty list with the specified initial capacity. 450 * 451 * @param initialCapacity the initial capacity of the list 452 * @throws IllegalArgumentException if the specified initial capacity 453 * is negative 454 */ OfPrimitive(int initialCapacity)455 OfPrimitive(int initialCapacity) { 456 super(initialCapacity); 457 curChunk = newArray(1 << initialChunkPower); 458 } 459 460 /** 461 * Constructs an empty list with an initial capacity of sixteen. 462 */ OfPrimitive()463 OfPrimitive() { 464 super(); 465 curChunk = newArray(1 << initialChunkPower); 466 } 467 468 @Override iterator()469 public abstract Iterator<E> iterator(); 470 471 @Override forEach(Consumer<? super E> consumer)472 public abstract void forEach(Consumer<? super E> consumer); 473 474 /** Create a new array-of-array of the proper type and size */ newArrayArray(int size)475 protected abstract T_ARR[] newArrayArray(int size); 476 477 /** Create a new array of the proper type and size */ newArray(int size)478 public abstract T_ARR newArray(int size); 479 480 /** Get the length of an array */ arrayLength(T_ARR array)481 protected abstract int arrayLength(T_ARR array); 482 483 /** Iterate an array with the provided consumer */ arrayForEach(T_ARR array, int from, int to, T_CONS consumer)484 protected abstract void arrayForEach(T_ARR array, int from, int to, 485 T_CONS consumer); 486 capacity()487 protected long capacity() { 488 return (spineIndex == 0) 489 ? arrayLength(curChunk) 490 : priorElementCount[spineIndex] + arrayLength(spine[spineIndex]); 491 } 492 inflateSpine()493 private void inflateSpine() { 494 if (spine == null) { 495 spine = newArrayArray(MIN_SPINE_SIZE); 496 priorElementCount = new long[MIN_SPINE_SIZE]; 497 spine[0] = curChunk; 498 } 499 } 500 ensureCapacity(long targetSize)501 protected final void ensureCapacity(long targetSize) { 502 long capacity = capacity(); 503 if (targetSize > capacity) { 504 inflateSpine(); 505 for (int i=spineIndex+1; targetSize > capacity; i++) { 506 if (i >= spine.length) { 507 int newSpineSize = spine.length * 2; 508 spine = Arrays.copyOf(spine, newSpineSize); 509 priorElementCount = Arrays.copyOf(priorElementCount, newSpineSize); 510 } 511 int nextChunkSize = chunkSize(i); 512 spine[i] = newArray(nextChunkSize); 513 priorElementCount[i] = priorElementCount[i-1] + arrayLength(spine[i - 1]); 514 capacity += nextChunkSize; 515 } 516 } 517 } 518 increaseCapacity()519 protected void increaseCapacity() { 520 ensureCapacity(capacity() + 1); 521 } 522 chunkFor(long index)523 protected int chunkFor(long index) { 524 if (spineIndex == 0) { 525 if (index < elementIndex) 526 return 0; 527 else 528 throw new IndexOutOfBoundsException(Long.toString(index)); 529 } 530 531 if (index >= count()) 532 throw new IndexOutOfBoundsException(Long.toString(index)); 533 534 for (int j=0; j <= spineIndex; j++) 535 if (index < priorElementCount[j] + arrayLength(spine[j])) 536 return j; 537 538 throw new IndexOutOfBoundsException(Long.toString(index)); 539 } 540 copyInto(T_ARR array, int offset)541 public void copyInto(T_ARR array, int offset) { 542 long finalOffset = offset + count(); 543 if (finalOffset > arrayLength(array) || finalOffset < offset) { 544 throw new IndexOutOfBoundsException("does not fit"); 545 } 546 547 if (spineIndex == 0) 548 System.arraycopy(curChunk, 0, array, offset, elementIndex); 549 else { 550 // full chunks 551 for (int i=0; i < spineIndex; i++) { 552 System.arraycopy(spine[i], 0, array, offset, arrayLength(spine[i])); 553 offset += arrayLength(spine[i]); 554 } 555 if (elementIndex > 0) 556 System.arraycopy(curChunk, 0, array, offset, elementIndex); 557 } 558 } 559 asPrimitiveArray()560 public T_ARR asPrimitiveArray() { 561 long size = count(); 562 if (size >= Nodes.MAX_ARRAY_SIZE) 563 throw new IllegalArgumentException(Nodes.BAD_SIZE); 564 T_ARR result = newArray((int) size); 565 copyInto(result, 0); 566 return result; 567 } 568 preAccept()569 protected void preAccept() { 570 if (elementIndex == arrayLength(curChunk)) { 571 inflateSpine(); 572 if (spineIndex+1 >= spine.length || spine[spineIndex+1] == null) 573 increaseCapacity(); 574 elementIndex = 0; 575 ++spineIndex; 576 curChunk = spine[spineIndex]; 577 } 578 } 579 clear()580 public void clear() { 581 if (spine != null) { 582 curChunk = spine[0]; 583 spine = null; 584 priorElementCount = null; 585 } 586 elementIndex = 0; 587 spineIndex = 0; 588 } 589 590 @SuppressWarnings("overloads") forEach(T_CONS consumer)591 public void forEach(T_CONS consumer) { 592 // completed chunks, if any 593 for (int j = 0; j < spineIndex; j++) 594 arrayForEach(spine[j], 0, arrayLength(spine[j]), consumer); 595 596 // current chunk 597 arrayForEach(curChunk, 0, elementIndex, consumer); 598 } 599 600 abstract class BaseSpliterator<T_SPLITR extends Spliterator.OfPrimitive<E, T_CONS, T_SPLITR>> 601 implements Spliterator.OfPrimitive<E, T_CONS, T_SPLITR> { 602 // The current spine index 603 int splSpineIndex; 604 605 // Last spine index 606 final int lastSpineIndex; 607 608 // The current element index into the current spine 609 int splElementIndex; 610 611 // Last spine's last element index + 1 612 final int lastSpineElementFence; 613 614 // When splSpineIndex >= lastSpineIndex and 615 // splElementIndex >= lastSpineElementFence then 616 // this spliterator is fully traversed 617 // tryAdvance can set splSpineIndex > spineIndex if the last spine is full 618 619 // The current spine array 620 T_ARR splChunk; 621 BaseSpliterator(int firstSpineIndex, int lastSpineIndex, int firstSpineElementIndex, int lastSpineElementFence)622 BaseSpliterator(int firstSpineIndex, int lastSpineIndex, 623 int firstSpineElementIndex, int lastSpineElementFence) { 624 this.splSpineIndex = firstSpineIndex; 625 this.lastSpineIndex = lastSpineIndex; 626 this.splElementIndex = firstSpineElementIndex; 627 this.lastSpineElementFence = lastSpineElementFence; 628 assert spine != null || firstSpineIndex == 0 && lastSpineIndex == 0; 629 splChunk = (spine == null) ? curChunk : spine[firstSpineIndex]; 630 } 631 newSpliterator(int firstSpineIndex, int lastSpineIndex, int firstSpineElementIndex, int lastSpineElementFence)632 abstract T_SPLITR newSpliterator(int firstSpineIndex, int lastSpineIndex, 633 int firstSpineElementIndex, int lastSpineElementFence); 634 arrayForOne(T_ARR array, int index, T_CONS consumer)635 abstract void arrayForOne(T_ARR array, int index, T_CONS consumer); 636 arraySpliterator(T_ARR array, int offset, int len)637 abstract T_SPLITR arraySpliterator(T_ARR array, int offset, int len); 638 639 @Override estimateSize()640 public long estimateSize() { 641 return (splSpineIndex == lastSpineIndex) 642 ? (long) lastSpineElementFence - splElementIndex 643 : // # of elements prior to end - 644 priorElementCount[lastSpineIndex] + lastSpineElementFence - 645 // # of elements prior to current 646 priorElementCount[splSpineIndex] - splElementIndex; 647 } 648 649 @Override characteristics()650 public int characteristics() { 651 return SPLITERATOR_CHARACTERISTICS; 652 } 653 654 @Override tryAdvance(T_CONS consumer)655 public boolean tryAdvance(T_CONS consumer) { 656 Objects.requireNonNull(consumer); 657 658 if (splSpineIndex < lastSpineIndex 659 || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { 660 arrayForOne(splChunk, splElementIndex++, consumer); 661 662 if (splElementIndex == arrayLength(splChunk)) { 663 splElementIndex = 0; 664 ++splSpineIndex; 665 if (spine != null && splSpineIndex <= lastSpineIndex) 666 splChunk = spine[splSpineIndex]; 667 } 668 return true; 669 } 670 return false; 671 } 672 673 @Override forEachRemaining(T_CONS consumer)674 public void forEachRemaining(T_CONS consumer) { 675 Objects.requireNonNull(consumer); 676 677 if (splSpineIndex < lastSpineIndex 678 || (splSpineIndex == lastSpineIndex && splElementIndex < lastSpineElementFence)) { 679 int i = splElementIndex; 680 // completed chunks, if any 681 for (int sp = splSpineIndex; sp < lastSpineIndex; sp++) { 682 T_ARR chunk = spine[sp]; 683 arrayForEach(chunk, i, arrayLength(chunk), consumer); 684 i = 0; 685 } 686 // last (or current uncompleted) chunk 687 T_ARR chunk = (splSpineIndex == lastSpineIndex) ? splChunk : spine[lastSpineIndex]; 688 arrayForEach(chunk, i, lastSpineElementFence, consumer); 689 // mark consumed 690 splSpineIndex = lastSpineIndex; 691 splElementIndex = lastSpineElementFence; 692 } 693 } 694 695 @Override trySplit()696 public T_SPLITR trySplit() { 697 if (splSpineIndex < lastSpineIndex) { 698 // split just before last chunk (if it is full this means 50:50 split) 699 T_SPLITR ret = newSpliterator(splSpineIndex, lastSpineIndex - 1, 700 splElementIndex, arrayLength(spine[lastSpineIndex - 1])); 701 // position us to start of last chunk 702 splSpineIndex = lastSpineIndex; 703 splElementIndex = 0; 704 splChunk = spine[splSpineIndex]; 705 return ret; 706 } 707 else if (splSpineIndex == lastSpineIndex) { 708 int t = (lastSpineElementFence - splElementIndex) / 2; 709 if (t == 0) 710 return null; 711 else { 712 T_SPLITR ret = arraySpliterator(splChunk, splElementIndex, t); 713 splElementIndex += t; 714 return ret; 715 } 716 } 717 else { 718 return null; 719 } 720 } 721 } 722 } 723 724 /** 725 * An ordered collection of {@code int} values. 726 * @hide Visible for CTS testing only (OpenJDK8 tests). 727 */ 728 @SuppressWarnings("overloads") 729 // Android-changed: Made public for CTS tests only. 730 public static class OfInt extends SpinedBuffer.OfPrimitive<Integer, int[], IntConsumer> 731 implements IntConsumer { 732 // Android-changed: Made public for CTS tests only. OfInt()733 public OfInt() { } 734 735 // Android-changed: Made public for CTS tests only. OfInt(int initialCapacity)736 public OfInt(int initialCapacity) { 737 super(initialCapacity); 738 } 739 740 @Override forEach(Consumer<? super Integer> consumer)741 public void forEach(Consumer<? super Integer> consumer) { 742 if (consumer instanceof IntConsumer) { 743 forEach((IntConsumer) consumer); 744 } 745 else { 746 if (Tripwire.ENABLED) 747 Tripwire.trip(getClass(), "{0} calling SpinedBuffer.OfInt.forEach(Consumer)"); 748 spliterator().forEachRemaining(consumer); 749 } 750 } 751 752 @Override newArrayArray(int size)753 protected int[][] newArrayArray(int size) { 754 return new int[size][]; 755 } 756 757 @Override newArray(int size)758 public int[] newArray(int size) { 759 return new int[size]; 760 } 761 762 @Override arrayLength(int[] array)763 protected int arrayLength(int[] array) { 764 return array.length; 765 } 766 767 @Override arrayForEach(int[] array, int from, int to, IntConsumer consumer)768 protected void arrayForEach(int[] array, 769 int from, int to, 770 IntConsumer consumer) { 771 for (int i = from; i < to; i++) 772 consumer.accept(array[i]); 773 } 774 775 @Override accept(int i)776 public void accept(int i) { 777 preAccept(); 778 curChunk[elementIndex++] = i; 779 } 780 get(long index)781 public int get(long index) { 782 // Casts to int are safe since the spine array index is the index minus 783 // the prior element count from the current spine 784 int ch = chunkFor(index); 785 if (spineIndex == 0 && ch == 0) 786 return curChunk[(int) index]; 787 else 788 return spine[ch][(int) (index - priorElementCount[ch])]; 789 } 790 791 @Override iterator()792 public PrimitiveIterator.OfInt iterator() { 793 return Spliterators.iterator(spliterator()); 794 } 795 spliterator()796 public Spliterator.OfInt spliterator() { 797 @SuppressWarnings("overloads") 798 class Splitr extends BaseSpliterator<Spliterator.OfInt> 799 implements Spliterator.OfInt { 800 Splitr(int firstSpineIndex, int lastSpineIndex, 801 int firstSpineElementIndex, int lastSpineElementFence) { 802 super(firstSpineIndex, lastSpineIndex, 803 firstSpineElementIndex, lastSpineElementFence); 804 } 805 806 @Override 807 Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex, 808 int firstSpineElementIndex, int lastSpineElementFence) { 809 return new Splitr(firstSpineIndex, lastSpineIndex, 810 firstSpineElementIndex, lastSpineElementFence); 811 } 812 813 @Override 814 void arrayForOne(int[] array, int index, IntConsumer consumer) { 815 consumer.accept(array[index]); 816 } 817 818 @Override 819 Spliterator.OfInt arraySpliterator(int[] array, int offset, int len) { 820 return Arrays.spliterator(array, offset, offset+len); 821 } 822 } 823 return new Splitr(0, spineIndex, 0, elementIndex); 824 } 825 826 @Override toString()827 public String toString() { 828 int[] array = asPrimitiveArray(); 829 if (array.length < 200) { 830 return String.format("%s[length=%d, chunks=%d]%s", 831 getClass().getSimpleName(), array.length, 832 spineIndex, Arrays.toString(array)); 833 } 834 else { 835 int[] array2 = Arrays.copyOf(array, 200); 836 return String.format("%s[length=%d, chunks=%d]%s...", 837 getClass().getSimpleName(), array.length, 838 spineIndex, Arrays.toString(array2)); 839 } 840 } 841 } 842 843 /** 844 * An ordered collection of {@code long} values. 845 * @hide Visible for CTS testing only (OpenJDK8 tests). 846 */ 847 @SuppressWarnings("overloads") 848 // Android-changed: Made public for CTS tests only. 849 public static class OfLong extends SpinedBuffer.OfPrimitive<Long, long[], LongConsumer> 850 implements LongConsumer { 851 // Android-changed: Made public for CTS tests only. OfLong()852 public OfLong() { } 853 854 // Android-changed: Made public for CTS tests only. OfLong(int initialCapacity)855 public OfLong(int initialCapacity) { 856 super(initialCapacity); 857 } 858 859 @Override forEach(Consumer<? super Long> consumer)860 public void forEach(Consumer<? super Long> consumer) { 861 if (consumer instanceof LongConsumer) { 862 forEach((LongConsumer) consumer); 863 } 864 else { 865 if (Tripwire.ENABLED) 866 Tripwire.trip(getClass(), "{0} calling SpinedBuffer.OfLong.forEach(Consumer)"); 867 spliterator().forEachRemaining(consumer); 868 } 869 } 870 871 @Override newArrayArray(int size)872 protected long[][] newArrayArray(int size) { 873 return new long[size][]; 874 } 875 876 @Override newArray(int size)877 public long[] newArray(int size) { 878 return new long[size]; 879 } 880 881 @Override arrayLength(long[] array)882 protected int arrayLength(long[] array) { 883 return array.length; 884 } 885 886 @Override arrayForEach(long[] array, int from, int to, LongConsumer consumer)887 protected void arrayForEach(long[] array, 888 int from, int to, 889 LongConsumer consumer) { 890 for (int i = from; i < to; i++) 891 consumer.accept(array[i]); 892 } 893 894 @Override accept(long i)895 public void accept(long i) { 896 preAccept(); 897 curChunk[elementIndex++] = i; 898 } 899 get(long index)900 public long get(long index) { 901 // Casts to int are safe since the spine array index is the index minus 902 // the prior element count from the current spine 903 int ch = chunkFor(index); 904 if (spineIndex == 0 && ch == 0) 905 return curChunk[(int) index]; 906 else 907 return spine[ch][(int) (index - priorElementCount[ch])]; 908 } 909 910 @Override iterator()911 public PrimitiveIterator.OfLong iterator() { 912 return Spliterators.iterator(spliterator()); 913 } 914 915 spliterator()916 public Spliterator.OfLong spliterator() { 917 @SuppressWarnings("overloads") 918 class Splitr extends BaseSpliterator<Spliterator.OfLong> 919 implements Spliterator.OfLong { 920 Splitr(int firstSpineIndex, int lastSpineIndex, 921 int firstSpineElementIndex, int lastSpineElementFence) { 922 super(firstSpineIndex, lastSpineIndex, 923 firstSpineElementIndex, lastSpineElementFence); 924 } 925 926 @Override 927 Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex, 928 int firstSpineElementIndex, int lastSpineElementFence) { 929 return new Splitr(firstSpineIndex, lastSpineIndex, 930 firstSpineElementIndex, lastSpineElementFence); 931 } 932 933 @Override 934 void arrayForOne(long[] array, int index, LongConsumer consumer) { 935 consumer.accept(array[index]); 936 } 937 938 @Override 939 Spliterator.OfLong arraySpliterator(long[] array, int offset, int len) { 940 return Arrays.spliterator(array, offset, offset+len); 941 } 942 } 943 return new Splitr(0, spineIndex, 0, elementIndex); 944 } 945 946 @Override toString()947 public String toString() { 948 long[] array = asPrimitiveArray(); 949 if (array.length < 200) { 950 return String.format("%s[length=%d, chunks=%d]%s", 951 getClass().getSimpleName(), array.length, 952 spineIndex, Arrays.toString(array)); 953 } 954 else { 955 long[] array2 = Arrays.copyOf(array, 200); 956 return String.format("%s[length=%d, chunks=%d]%s...", 957 getClass().getSimpleName(), array.length, 958 spineIndex, Arrays.toString(array2)); 959 } 960 } 961 } 962 963 /** 964 * An ordered collection of {@code double} values. 965 * @hide Visible for CTS testing only (OpenJDK8 tests). 966 */ 967 @SuppressWarnings("overloads") 968 // Android-changed: Made public for CTS tests only. 969 public static class OfDouble 970 extends SpinedBuffer.OfPrimitive<Double, double[], DoubleConsumer> 971 implements DoubleConsumer { 972 // Android-changed: Made public for CTS tests only. OfDouble()973 public OfDouble() { } 974 975 // Android-changed: Made public for CTS tests only. OfDouble(int initialCapacity)976 public OfDouble(int initialCapacity) { 977 super(initialCapacity); 978 } 979 980 @Override forEach(Consumer<? super Double> consumer)981 public void forEach(Consumer<? super Double> consumer) { 982 if (consumer instanceof DoubleConsumer) { 983 forEach((DoubleConsumer) consumer); 984 } 985 else { 986 if (Tripwire.ENABLED) 987 Tripwire.trip(getClass(), "{0} calling SpinedBuffer.OfDouble.forEach(Consumer)"); 988 spliterator().forEachRemaining(consumer); 989 } 990 } 991 992 @Override newArrayArray(int size)993 protected double[][] newArrayArray(int size) { 994 return new double[size][]; 995 } 996 997 @Override newArray(int size)998 public double[] newArray(int size) { 999 return new double[size]; 1000 } 1001 1002 @Override arrayLength(double[] array)1003 protected int arrayLength(double[] array) { 1004 return array.length; 1005 } 1006 1007 @Override arrayForEach(double[] array, int from, int to, DoubleConsumer consumer)1008 protected void arrayForEach(double[] array, 1009 int from, int to, 1010 DoubleConsumer consumer) { 1011 for (int i = from; i < to; i++) 1012 consumer.accept(array[i]); 1013 } 1014 1015 @Override accept(double i)1016 public void accept(double i) { 1017 preAccept(); 1018 curChunk[elementIndex++] = i; 1019 } 1020 get(long index)1021 public double get(long index) { 1022 // Casts to int are safe since the spine array index is the index minus 1023 // the prior element count from the current spine 1024 int ch = chunkFor(index); 1025 if (spineIndex == 0 && ch == 0) 1026 return curChunk[(int) index]; 1027 else 1028 return spine[ch][(int) (index - priorElementCount[ch])]; 1029 } 1030 1031 @Override iterator()1032 public PrimitiveIterator.OfDouble iterator() { 1033 return Spliterators.iterator(spliterator()); 1034 } 1035 spliterator()1036 public Spliterator.OfDouble spliterator() { 1037 @SuppressWarnings("overloads") 1038 class Splitr extends BaseSpliterator<Spliterator.OfDouble> 1039 implements Spliterator.OfDouble { 1040 Splitr(int firstSpineIndex, int lastSpineIndex, 1041 int firstSpineElementIndex, int lastSpineElementFence) { 1042 super(firstSpineIndex, lastSpineIndex, 1043 firstSpineElementIndex, lastSpineElementFence); 1044 } 1045 1046 @Override 1047 Splitr newSpliterator(int firstSpineIndex, int lastSpineIndex, 1048 int firstSpineElementIndex, int lastSpineElementFence) { 1049 return new Splitr(firstSpineIndex, lastSpineIndex, 1050 firstSpineElementIndex, lastSpineElementFence); 1051 } 1052 1053 @Override 1054 void arrayForOne(double[] array, int index, DoubleConsumer consumer) { 1055 consumer.accept(array[index]); 1056 } 1057 1058 @Override 1059 Spliterator.OfDouble arraySpliterator(double[] array, int offset, int len) { 1060 return Arrays.spliterator(array, offset, offset+len); 1061 } 1062 } 1063 return new Splitr(0, spineIndex, 0, elementIndex); 1064 } 1065 1066 @Override toString()1067 public String toString() { 1068 double[] array = asPrimitiveArray(); 1069 if (array.length < 200) { 1070 return String.format("%s[length=%d, chunks=%d]%s", 1071 getClass().getSimpleName(), array.length, 1072 spineIndex, Arrays.toString(array)); 1073 } 1074 else { 1075 double[] array2 = Arrays.copyOf(array, 200); 1076 return String.format("%s[length=%d, chunks=%d]%s...", 1077 getClass().getSimpleName(), array.length, 1078 spineIndex, Arrays.toString(array2)); 1079 } 1080 } 1081 } 1082 } 1083 1084