java9.util.ArrayDequeSpliterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of android-retrostreams Show documentation
Show all versions of android-retrostreams Show documentation
Backport of Java 9 java.util.stream API for Android Studio 3+ desugar toolchain,
forked from http://sourceforge.net/projects/streamsupport
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java9.util;
import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java9.util.Spliterator;
import java9.util.Spliterators;
import java9.util.function.Consumer;
// NOTE: this implementation can only be used on Java 8 or below!
// The recent substantial Java 9 rewrite of ArrayDeque starting
// with CVS rev. 1.75 precludes this from being applicable on Java 9.
// Cf. https://sourceforge.net/p/streamsupport/tickets/273/
// and https://sourceforge.net/p/streamsupport/tickets/299/
final class ArrayDequeSpliterator implements Spliterator {
// CVS rev. 1.74
private final ArrayDeque deq;
private int fence; // -1 until first use
private int index; // current index, modified on traverse/split
/** Constructs a new spliterator covering the given array and range. */
private ArrayDequeSpliterator(ArrayDeque deq, int origin, int fence) {
this.deq = deq;
this.index = origin;
this.fence = fence;
}
static Spliterator spliterator(ArrayDeque deque) {
return new ArrayDequeSpliterator(deque, -1, -1);
}
/** Ensures late-binding initialization; then returns fence. */
private int getFence() { // force initialization
int t;
if ((t = fence) < 0) {
t = fence = getTail(deq);
index = getHead(deq);
}
return t;
}
public ArrayDequeSpliterator trySplit() {
int t = getFence(), h = index, n = getData(deq).length;
if (h != t && ((h + 1) & (n - 1)) != t) {
if (h > t) {
t += n;
}
int m = ((h + t) >>> 1) & (n - 1);
return new ArrayDequeSpliterator(deq, h, index = m);
}
return null;
}
@Override
public void forEachRemaining(Consumer super E> action) {
Objects.requireNonNull(action);
Object[] a = getData(deq);
int m = a.length - 1, f = getFence(), i = index;
index = f;
while (i != f) {
@SuppressWarnings("unchecked") E e = (E) a[i];
i = (i + 1) & m;
if (e == null) {
throw new ConcurrentModificationException();
}
action.accept(e);
}
}
@Override
public boolean tryAdvance(Consumer super E> action) {
Objects.requireNonNull(action);
Object[] a = getData(deq);
int m = a.length - 1, f = getFence(), i = index;
if (i != fence) {
@SuppressWarnings("unchecked") E e = (E) a[i];
index = (i + 1) & m;
if (e == null) {
throw new ConcurrentModificationException();
}
action.accept(e);
return true;
}
return false;
}
@Override
public long estimateSize() {
int n = getFence() - index;
if (n < 0) {
n += getData(deq).length;
}
return n;
}
@Override
public int characteristics() {
return Spliterator.NONNULL
| Spliterator.ORDERED
| Spliterator.SIZED
| Spliterator.SUBSIZED;
}
private static int getTail(ArrayDeque deq) {
return U.getInt(deq, TAIL_OFF);
}
private static int getHead(ArrayDeque deq) {
return U.getInt(deq, HEAD_OFF);
}
private static Object[] getData(ArrayDeque deq) {
return (Object[]) U.getObject(deq, DATA_OFF);
}
// Unsafe mechanics
private static final sun.misc.Unsafe U = UnsafeAccess.unsafe;
private static final long TAIL_OFF;
private static final long HEAD_OFF;
private static final long DATA_OFF;
static {
try {
TAIL_OFF = U.objectFieldOffset(ArrayDeque.class
.getDeclaredField("tail"));
HEAD_OFF = U.objectFieldOffset(ArrayDeque.class
.getDeclaredField("head"));
DATA_OFF = U.objectFieldOffset(ArrayDeque.class
.getDeclaredField("elements"));
} catch (Exception e) {
throw new Error(e);
}
}
}