blob: f38c02a1f5ba831dbef1a58fee1f2a9e4c365d0d [file] [log] [blame]
// Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionIterator;
import com.android.tools.r8.ir.code.InstructionListIterator;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.Predicate;
public class IteratorUtils {
public static <T, S extends T> Iterator<S> filter(
Iterator<? extends T> iterator, Predicate<T> predicate) {
return new Iterator<S>() {
private S next = advance();
@SuppressWarnings("unchecked")
private S advance() {
while (iterator.hasNext()) {
T element = iterator.next();
if (predicate.test(element)) {
return (S) element;
}
}
return null;
}
@Override
public boolean hasNext() {
return next != null;
}
@Override
public S next() {
S current = next;
if (current == null) {
throw new NoSuchElementException();
}
next = advance();
return current;
}
};
}
public static <T> T peekPrevious(ListIterator<T> iterator) {
T previous = iterator.previous();
T next = iterator.next();
assert previous == next;
return previous;
}
public static <T> T peekNext(ListIterator<T> iterator) {
if (iterator.hasNext()) {
T next = iterator.next();
T previous = iterator.previous();
assert previous == next;
return next;
}
return null;
}
public static <T> T previousUntil(ListIterator<T> iterator, Predicate<T> predicate) {
while (iterator.hasPrevious()) {
T previous = iterator.previous();
if (predicate.test(previous)) {
return previous;
}
}
throw new Unreachable();
}
public static <T> void removeIf(Iterator<T> iterator, Predicate<T> predicate) {
while (iterator.hasNext()) {
T item = iterator.next();
if (predicate.test(item)) {
iterator.remove();
}
}
}
/** @deprecated Use {@link #removeIf(InstructionListIterator, Predicate)} instead. */
@Deprecated
public static void removeIf(InstructionIterator iterator, Predicate<Instruction> predicate) {
throw new Unimplemented();
}
public static void removeIf(InstructionListIterator iterator, Predicate<Instruction> predicate) {
removeIf((Iterator<Instruction>) iterator, predicate);
}
public static <T> boolean allRemainingMatch(ListIterator<T> iterator, Predicate<T> predicate) {
return !anyRemainingMatch(iterator, remaining -> !predicate.test(remaining));
}
public static <T> boolean anyRemainingMatch(ListIterator<T> iterator, Predicate<T> predicate) {
T state = peekNext(iterator);
boolean result = false;
while (iterator.hasNext()) {
T item = iterator.next();
if (predicate.test(item)) {
result = true;
break;
}
}
while (iterator.hasPrevious() && iterator.previous() != state) {
// Restore the state of the iterator.
}
assert peekNext(iterator) == state;
return result;
}
}