diff options
author | Yohann Roussel <yroussel@google.com> | 2014-03-19 16:25:37 +0100 |
---|---|---|
committer | Yohann Roussel <yroussel@google.com> | 2014-03-20 15:13:33 +0100 |
commit | 4eceb95409e844fdc33c9c706e1dc307bfd40303 (patch) | |
tree | ee9f4f3fc79f757c79081c336bce4f1782c6ccd8 /guava/src/com/google/common/collect/GeneralRange.java | |
parent | 3d2402901b1a6462e2cf47a6fd09711f327961c3 (diff) | |
download | toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.zip toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.gz toolchain_jack-4eceb95409e844fdc33c9c706e1dc307bfd40303.tar.bz2 |
Initial Jack import.
Change-Id: I953cf0a520195a7187d791b2885848ad0d5a9b43
Diffstat (limited to 'guava/src/com/google/common/collect/GeneralRange.java')
-rw-r--r-- | guava/src/com/google/common/collect/GeneralRange.java | 304 |
1 files changed, 304 insertions, 0 deletions
diff --git a/guava/src/com/google/common/collect/GeneralRange.java b/guava/src/com/google/common/collect/GeneralRange.java new file mode 100644 index 0000000..c083d83 --- /dev/null +++ b/guava/src/com/google/common/collect/GeneralRange.java @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2011 The Guava Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.common.collect; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.collect.BoundType.CLOSED; +import static com.google.common.collect.BoundType.OPEN; + +import com.google.common.annotations.GwtCompatible; +import com.google.common.base.Objects; + +import java.io.Serializable; +import java.util.Comparator; + +import javax.annotation.Nullable; + +/** + * A generalized interval on any ordering, for internal use. Supports {@code null}. Unlike + * {@link Range}, this allows the use of an arbitrary comparator. This is designed for use in the + * implementation of subcollections of sorted collection types. + * + * <p>Whenever possible, use {@code Range} instead, which is better supported. + * + * @author Louis Wasserman + */ +@GwtCompatible(serializable = true) +final class GeneralRange<T> implements Serializable { + /** + * Converts a Range to a GeneralRange. + */ + static <T extends Comparable> GeneralRange<T> from(Range<T> range) { + @Nullable + T lowerEndpoint = range.hasLowerBound() ? range.lowerEndpoint() : null; + BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : OPEN; + + @Nullable + T upperEndpoint = range.hasUpperBound() ? range.upperEndpoint() : null; + BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : OPEN; + return new GeneralRange<T>(Ordering.natural(), range.hasLowerBound(), lowerEndpoint, + lowerBoundType, range.hasUpperBound(), upperEndpoint, upperBoundType); + } + + /** + * Returns the whole range relative to the specified comparator. + */ + static <T> GeneralRange<T> all(Comparator<? super T> comparator) { + return new GeneralRange<T>(comparator, false, null, OPEN, false, null, OPEN); + } + + /** + * Returns everything above the endpoint relative to the specified comparator, with the specified + * endpoint behavior. + */ + static <T> GeneralRange<T> downTo(Comparator<? super T> comparator, @Nullable T endpoint, + BoundType boundType) { + return new GeneralRange<T>(comparator, true, endpoint, boundType, false, null, OPEN); + } + + /** + * Returns everything below the endpoint relative to the specified comparator, with the specified + * endpoint behavior. + */ + static <T> GeneralRange<T> upTo(Comparator<? super T> comparator, @Nullable T endpoint, + BoundType boundType) { + return new GeneralRange<T>(comparator, false, null, OPEN, true, endpoint, boundType); + } + + /** + * Returns everything between the endpoints relative to the specified comparator, with the + * specified endpoint behavior. + */ + static <T> GeneralRange<T> range(Comparator<? super T> comparator, @Nullable T lower, + BoundType lowerType, @Nullable T upper, BoundType upperType) { + return new GeneralRange<T>(comparator, true, lower, lowerType, true, upper, upperType); + } + + private final Comparator<? super T> comparator; + private final boolean hasLowerBound; + @Nullable + private final T lowerEndpoint; + private final BoundType lowerBoundType; + private final boolean hasUpperBound; + @Nullable + private final T upperEndpoint; + private final BoundType upperBoundType; + + private GeneralRange(Comparator<? super T> comparator, boolean hasLowerBound, + @Nullable T lowerEndpoint, BoundType lowerBoundType, boolean hasUpperBound, + @Nullable T upperEndpoint, BoundType upperBoundType) { + this.comparator = checkNotNull(comparator); + this.hasLowerBound = hasLowerBound; + this.hasUpperBound = hasUpperBound; + this.lowerEndpoint = lowerEndpoint; + this.lowerBoundType = checkNotNull(lowerBoundType); + this.upperEndpoint = upperEndpoint; + this.upperBoundType = checkNotNull(upperBoundType); + + if (hasLowerBound) { + comparator.compare(lowerEndpoint, lowerEndpoint); + } + if (hasUpperBound) { + comparator.compare(upperEndpoint, upperEndpoint); + } + if (hasLowerBound && hasUpperBound) { + int cmp = comparator.compare(lowerEndpoint, upperEndpoint); + // be consistent with Range + checkArgument(cmp <= 0, "lowerEndpoint (%s) > upperEndpoint (%s)", lowerEndpoint, + upperEndpoint); + if (cmp == 0) { + checkArgument(lowerBoundType != OPEN | upperBoundType != OPEN); + } + } + } + + Comparator<? super T> comparator() { + return comparator; + } + + boolean hasLowerBound() { + return hasLowerBound; + } + + boolean hasUpperBound() { + return hasUpperBound; + } + + boolean isEmpty() { + return (hasUpperBound() && tooLow(getUpperEndpoint())) + || (hasLowerBound() && tooHigh(getLowerEndpoint())); + } + + boolean tooLow(@Nullable T t) { + if (!hasLowerBound()) { + return false; + } + T lbound = getLowerEndpoint(); + int cmp = comparator.compare(t, lbound); + return cmp < 0 | (cmp == 0 & getLowerBoundType() == OPEN); + } + + boolean tooHigh(@Nullable T t) { + if (!hasUpperBound()) { + return false; + } + T ubound = getUpperEndpoint(); + int cmp = comparator.compare(t, ubound); + return cmp > 0 | (cmp == 0 & getUpperBoundType() == OPEN); + } + + boolean contains(@Nullable T t) { + return !tooLow(t) && !tooHigh(t); + } + + /** + * Returns the intersection of the two ranges, or an empty range if their intersection is empty. + */ + GeneralRange<T> intersect(GeneralRange<T> other) { + checkNotNull(other); + checkArgument(comparator.equals(other.comparator)); + + boolean hasLowBound = this.hasLowerBound; + @Nullable + T lowEnd = getLowerEndpoint(); + BoundType lowType = getLowerBoundType(); + if (!hasLowerBound()) { + hasLowBound = other.hasLowerBound; + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } else if (other.hasLowerBound()) { + int cmp = comparator.compare(getLowerEndpoint(), other.getLowerEndpoint()); + if (cmp < 0 || (cmp == 0 && other.getLowerBoundType() == OPEN)) { + lowEnd = other.getLowerEndpoint(); + lowType = other.getLowerBoundType(); + } + } + + boolean hasUpBound = this.hasUpperBound; + @Nullable + T upEnd = getUpperEndpoint(); + BoundType upType = getUpperBoundType(); + if (!hasUpperBound()) { + hasUpBound = other.hasUpperBound; + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } else if (other.hasUpperBound()) { + int cmp = comparator.compare(getUpperEndpoint(), other.getUpperEndpoint()); + if (cmp > 0 || (cmp == 0 && other.getUpperBoundType() == OPEN)) { + upEnd = other.getUpperEndpoint(); + upType = other.getUpperBoundType(); + } + } + + if (hasLowBound && hasUpBound) { + int cmp = comparator.compare(lowEnd, upEnd); + if (cmp > 0 || (cmp == 0 && lowType == OPEN && upType == OPEN)) { + // force allowed empty range + lowEnd = upEnd; + lowType = OPEN; + upType = CLOSED; + } + } + + return new GeneralRange<T>(comparator, hasLowBound, lowEnd, lowType, hasUpBound, upEnd, upType); + } + + @Override + public boolean equals(@Nullable Object obj) { + if (obj instanceof GeneralRange) { + GeneralRange<?> r = (GeneralRange<?>) obj; + return comparator.equals(r.comparator) && hasLowerBound == r.hasLowerBound + && hasUpperBound == r.hasUpperBound && getLowerBoundType().equals(r.getLowerBoundType()) + && getUpperBoundType().equals(r.getUpperBoundType()) + && Objects.equal(getLowerEndpoint(), r.getLowerEndpoint()) + && Objects.equal(getUpperEndpoint(), r.getUpperEndpoint()); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(comparator, getLowerEndpoint(), getLowerBoundType(), getUpperEndpoint(), + getUpperBoundType()); + } + + private transient GeneralRange<T> reverse; + + /** + * Returns the same range relative to the reversed comparator. + */ + GeneralRange<T> reverse() { + GeneralRange<T> result = reverse; + if (result == null) { + result = new GeneralRange<T>( + Ordering.from(comparator).reverse(), hasUpperBound, getUpperEndpoint(), + getUpperBoundType(), hasLowerBound, getLowerEndpoint(), getLowerBoundType()); + result.reverse = this; + return this.reverse = result; + } + return result; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append(comparator).append(":"); + switch (getLowerBoundType()) { + case CLOSED: + builder.append('['); + break; + case OPEN: + builder.append('('); + break; + } + if (hasLowerBound()) { + builder.append(getLowerEndpoint()); + } else { + builder.append("-\u221e"); + } + builder.append(','); + if (hasUpperBound()) { + builder.append(getUpperEndpoint()); + } else { + builder.append("\u221e"); + } + switch (getUpperBoundType()) { + case CLOSED: + builder.append(']'); + break; + case OPEN: + builder.append(')'); + break; + } + return builder.toString(); + } + + T getLowerEndpoint() { + return lowerEndpoint; + } + + BoundType getLowerBoundType() { + return lowerBoundType; + } + + T getUpperEndpoint() { + return upperEndpoint; + } + + BoundType getUpperBoundType() { + return upperBoundType; + } +} |