blob: 3ca376f71a3db29bc79d58b0f16997f3fde35876 [file] [log] [blame]
part of lists;
/// Range list.
class RangeList extends Object with ListMixin<int> {
final int end;
final int start;
int _length;
RangeList(this.start, this.end) {
if (start == null) {
throw new ArgumentError("start: $start");
}
if (end == null) {
throw new ArgumentError("end: $end");
}
if (start > end) {
throw new StateError("Start '$start' greater then end '$end'");
}
_length = end - start + 1;
}
/// Returns the length of list.
int get length => _length;
/// Sets the length of list.
void set length(int length) {
throw new UnsupportedError("length=");
}
bool operator ==(other) {
if (identical(this, other)) {
return true;
}
if (other is RangeList) {
return start == other.start && end == other.end;
}
return false;
}
RangeList operator +(RangeList other) {
if (other == null) {
throw new ArgumentError("other: $other");
}
int start;
int end;
if (this.start < other.start) {
start = this.start;
} else {
start = other.start;
}
if (this.end > other.end) {
end = this.end;
} else {
end = other.end;
}
return new RangeList(start, end);
}
int operator [](int index) {
if (index == null) {
throw new ArgumentError("index: $index");
}
if (index < 0 || index >= _length) {
throw new RangeError(index);
}
return start + index;
}
void operator []=(int index, int value) {
throw new UnsupportedError("operator []=");
}
/// Returns true if range list contains the [value]; otherwise false.
// ignore: strong_mode_invalid_method_override
bool contains(int value) {
if (value == null || value > end || value < start) {
return false;
}
return true;
}
/// Returns true if this range list includes [other]; otherwise false.
bool includes(RangeList other) {
if (other == null) {
throw new ArgumentError("other: $other");
}
return (other.start >= start && other.start <= end) && (other.end >= start && other.end <= end);
}
/// Returns true if this range list intersect [other]; otherwise false.
bool intersect(RangeList other) {
if (other == null) {
throw new ArgumentError("other: $other");
}
return (start <= other.start && end >= other.start) || (other.start <= start && other.end >= start);
}
/// Returns the intersection of this range list and the [other] range list;
/// otherwise null.
RangeList intersection(RangeList other) {
if (other == null) {
throw new ArgumentError("other: $other");
}
if (!intersect(other)) {
return null;
}
if (this == other) {
return new RangeList(this.start, this.end);
}
var start = this.start;
if (other.start > start) {
start = other.start;
}
var end = this.end;
if (other.end < end) {
end = other.end;
}
return new RangeList(start, end);
}
/// Subtracts from this range the [other] range and returns the the resulting
/// ranges.
List<RangeList> subtract(RangeList other) {
if (other == null) {
throw new ArgumentError("other: $other");
}
var result = <RangeList>[];
if (!intersect(other)) {
return result;
}
if (start < other.start) {
result.add(new RangeList(start, other.start - 1));
}
if (other.end < end) {
result.add(new RangeList(other.end + 1, end));
}
return result;
}
/// Returns the list of elements with specified step.
StepList toStepList(int step) => new StepList(start, end, step);
/// Returns the string representation of range list.
String toString() {
return "[$start..$end]";
}
}