/* * Copyright 2016 The Simple File Server 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 org.sfs.block; import java.util.Objects; import static com.google.common.base.Preconditions.checkState; import static java.util.Objects.hash; public class Range { private final long first; private final long last; private final long blockCount; public Range(long first, long last) { checkState(last >= first, "Last must be >= first"); this.first = first; this.last = last; this.blockCount = last - first + 1; } public long getFirst() { return first; } public long getLast() { return last; } public long getBlockCount() { return blockCount; } public boolean isEmpty() { return first == last; } @Override public String toString() { return "Range{" + "first=" + first + ", last=" + last + ", blockCount=" + blockCount + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Range)) return false; Range range = (Range) o; return Objects.equals(first, range.first) && Objects.equals(last, range.last); } @Override public int hashCode() { return hash(first, last); } public boolean intersects(Range other) { if (other.first >= first && other.first <= last) { return true; } return other.last <= last && other.last >= first; } public boolean adjacent(Range other) { if (other.last == first - 1) { return true; } return other.first == last + 1; } public Range merge(Range other) { checkState(other.intersects(this) || other.adjacent(this), "Range does not intersect or is not adjacent to this range"); long newFirst = other.first < first ? other.first : first; long newLast = other.last > last ? other.last : last; return new Range(newFirst, newLast); } public boolean encloses(long first, long last) { return this.first <= first && this.last >= last; } public boolean encloses(Range other) { return encloses(other.first, other.last); } public Range[] remove(Range toRemove) { return remove(toRemove.first, toRemove.last); } public Range[] remove(long first, long last) { checkState(encloses(first, last), "Range does not enclose this range"); if (this.first == first && this.last == last) { return new Range[]{}; } else if (this.first == first) { return new Range[]{new Range(last + 1, this.last)}; } else if (this.last == last) { return new Range[]{new Range(this.first, first - 1)}; } else { return new Range[]{new Range(this.first, first - 1), new Range(last + 1, this.last)}; } } }