| // Copyright (c) 2020, 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.google.common.collect.Iterables; | |
| import com.google.common.collect.Iterators; | |
| import java.util.ArrayList; | |
| import java.util.Collections; | |
| import java.util.Comparator; | |
| import java.util.Iterator; | |
| import java.util.List; | |
| import java.util.function.BiFunction; | |
| import java.util.function.BiPredicate; | |
| import java.util.function.Consumer; | |
| import java.util.function.Function; | |
| import java.util.function.Predicate; | |
| public class IterableUtils { | |
| public static <S, T> boolean allIdentical(Iterable<S> iterable) { | |
| return allIdentical(iterable, Function.identity()); | |
| } | |
| public static <S, T> boolean allIdentical(Iterable<S> iterable, Function<S, T> fn) { | |
| Iterator<S> iterator = iterable.iterator(); | |
| if (!iterator.hasNext()) { | |
| return true; | |
| } | |
| T first = fn.apply(iterator.next()); | |
| while (iterator.hasNext()) { | |
| T other = fn.apply(iterator.next()); | |
| if (other != first) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| public static <S, T> boolean any( | |
| Iterable<S> iterable, Function<S, T> transform, Predicate<T> predicate) { | |
| for (S element : iterable) { | |
| if (predicate.test(transform.apply(element))) { | |
| return true; | |
| } | |
| } | |
| return false; | |
| } | |
| public static <T> Iterable<T> append(Iterable<T> iterable, T element) { | |
| return Iterables.concat(iterable, singleton(element)); | |
| } | |
| public static <T> List<T> ensureUnmodifiableList(Iterable<T> iterable) { | |
| List<T> list; | |
| if (iterable instanceof List<?>) { | |
| list = (List<T>) iterable; | |
| } else { | |
| list = toNewArrayList(iterable); | |
| } | |
| return Collections.unmodifiableList(list); | |
| } | |
| @SuppressWarnings("unchecked") | |
| public static <T, R extends T> R findOrDefault( | |
| Iterable<T> iterable, Predicate<T> predicate, R defaultValue) { | |
| for (T element : iterable) { | |
| if (predicate.test(element)) { | |
| return (R) element; | |
| } | |
| } | |
| return defaultValue; | |
| } | |
| public static <T> T first(Iterable<T> iterable) { | |
| return iterable.iterator().next(); | |
| } | |
| public static <T> int firstIndexMatching(Iterable<T> iterable, Predicate<T> tester) { | |
| int i = 0; | |
| for (T element : iterable) { | |
| if (tester.test(element)) { | |
| return i; | |
| } | |
| i++; | |
| } | |
| return -1; | |
| } | |
| public static <S, T extends S> Iterable<T> filter( | |
| Iterable<S> iterable, Predicate<? super S> predicate) { | |
| return () -> IteratorUtils.filter(iterable.iterator(), predicate); | |
| } | |
| public static <T> boolean hasNext(Iterable<T> iterable) { | |
| return iterable.iterator().hasNext(); | |
| } | |
| public static <T> T min(Iterable<T> iterable, Comparator<T> comparator) { | |
| T min = null; | |
| for (T element : iterable) { | |
| if (min == null || comparator.compare(element, min) < 0) { | |
| min = element; | |
| } | |
| } | |
| return min; | |
| } | |
| public static <T> int size(Iterable<T> iterable) { | |
| int result = 0; | |
| for (T element : iterable) { | |
| result++; | |
| } | |
| return result; | |
| } | |
| public static <T> List<T> toNewArrayList(Iterable<T> iterable) { | |
| List<T> result = new ArrayList<>(); | |
| iterable.forEach(result::add); | |
| return result; | |
| } | |
| public static <S, T> Iterable<T> transform(Iterable<S> iterable, Function<S, T> fn) { | |
| return Iterables.transform(iterable, fn::apply); | |
| } | |
| public static <T> boolean isEmpty(Iterable<T> iterable) { | |
| return !iterable.iterator().hasNext(); | |
| } | |
| public static <T> Iterable<T> singleton(T element) { | |
| return () -> Iterators.singletonIterator(element); | |
| } | |
| public static <T> Iterable<T> prependSingleton(T t, Iterable<T> iterable) { | |
| return Iterables.concat(singleton(t), iterable); | |
| } | |
| public static <T> T reduce(T init, BiFunction<T, T, T> combine, Iterable<? extends T> iterable) { | |
| T v = init; | |
| for (T t : iterable) { | |
| v = combine.apply(v, t); | |
| } | |
| return v; | |
| } | |
| public static int sumInt(Iterable<Integer> iterable) { | |
| return reduce(0, Integer::sum, iterable); | |
| } | |
| public static <F> int sumInt(Iterable<F> iterable, Function<? super F, Integer> fn) { | |
| Iterable<Integer> integers = Iterables.transform(iterable, fn::apply); | |
| return sumInt(integers); | |
| } | |
| public static <T> Iterable<T> flatten(Iterable<? extends Iterable<T>> iterable) { | |
| return flatMap(iterable, Function.identity()); | |
| } | |
| public static <T, U> Iterable<U> flatMap( | |
| Iterable<T> iterable, Function<? super T, Iterable<U>> map) { | |
| return Iterables.concat(Iterables.transform(iterable, map::apply)); | |
| } | |
| public static <T> Iterable<T> empty() { | |
| return Collections.emptyList(); | |
| } | |
| public static <T> Iterable<T> emptyIf(Iterable<T> iterable, boolean condition) { | |
| if (condition) { | |
| return Collections.emptySet(); | |
| } else { | |
| return iterable; | |
| } | |
| } | |
| /** | |
| * Utility method for testing the the elements in one and other pair-wise. Returns false if the | |
| * lengths differ. | |
| */ | |
| public static <T> boolean testPairs( | |
| BiPredicate<T, T> predicate, Iterable<T> one, Iterable<T> other) { | |
| Iterator<T> iterator = other.iterator(); | |
| for (T first : one) { | |
| if (!iterator.hasNext()) { | |
| return false; | |
| } | |
| T second = iterator.next(); | |
| if (!predicate.test(first, second)) { | |
| return false; | |
| } | |
| } | |
| return !iterator.hasNext(); | |
| } | |
| public static <T, R> Iterable<R> fromMethod(Consumer<Consumer<T>> method, Function<T, R> mapper) { | |
| List<R> ts = new ArrayList<>(); | |
| method.accept(t -> ts.add(mapper.apply(t))); | |
| return ts; | |
| } | |
| } |