Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Run tests
run: pub run test
- name: Measure coverage
run: pub run test_coverage
run: pub run test_cov
- name: Upload coverage
uses: codecov/codecov-action@v1.0.6
with:
Expand Down
44 changes: 19 additions & 25 deletions lib/interval_tree.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ class Interval extends Comparable<Interval> {
/// final b = Interval(3, 5);
/// print(b.intersection(a)); // null
///
Interval intersection(Interval other) {
Interval? intersection(Interval other) {
if (!intersects(other)) return null;
return Interval(_max(start, other.start), _min(end, other.end));
}
Expand All @@ -177,7 +177,7 @@ class Interval extends Comparable<Interval> {
/// print(a.difference(b)); // [[1, 2], [4, 5]]
/// print(b.difference(a)); // null
///
Iterable<Interval> difference(Interval other) {
Iterable<Interval>? difference(Interval other) {
if (other.contains(this)) return null;
if (!other.intersects(this)) return [this];
if (other.start > start && other.end >= end) {
Expand Down Expand Up @@ -324,24 +324,24 @@ class IntervalTree with IterableMixin<Interval> {
}

/// Creates a tree from [intervals].
factory IntervalTree.of(Iterable<Interval> intervals) =>
factory IntervalTree.of(Iterable<Interval?> intervals) =>
IntervalTree()..addAll(intervals);

/// Adds an [interval] into this tree.
void add(dynamic interval) {
Interval iv = _asInterval(interval);
void add(dynamic? interval) {
Interval? iv = _asInterval(interval);
if (iv == null) return;

bool joined = false;
BidirectionalIterator<Interval> it = _tree.fromIterator(iv);
BidirectionalIterator<Interval?> it = _tree.fromIterator(iv);
while (it.movePrevious()) {
final union = _tryJoin(it.current, iv);
if (union == null) break;
it = _tree.fromIterator(iv = union, inclusive: false);
joined = true;
}

it = _tree.fromIterator(iv, inclusive: false);
it = _tree.fromIterator(iv!, inclusive: false);
while (it.moveNext()) {
final union = _tryJoin(it.current, iv);
if (union == null) break;
Expand All @@ -350,13 +350,12 @@ class IntervalTree with IterableMixin<Interval> {
}

if (!joined) {
_tree.add(iv);
_tree.add(iv!);
}
}

/// Adds all [intervals] into this tree.
void addAll(Iterable intervals) {
if (intervals == null) return;
for (final interval in intervals) {
add(interval);
}
Expand All @@ -365,9 +364,8 @@ class IntervalTree with IterableMixin<Interval> {
/// Removes an [interval] from this tree.
void remove(dynamic interval) {
final iv = _asInterval(interval);
if (iv == null) return;

BidirectionalIterator<Interval> it = _tree.fromIterator(iv);
BidirectionalIterator<Interval> it = _tree.fromIterator(iv!);
while (it.movePrevious()) {
final current = it.current;
if (!_trySplit(it.current, iv)) break;
Expand All @@ -384,7 +382,6 @@ class IntervalTree with IterableMixin<Interval> {

/// Removes all [intervals] from this tree.
void removeAll(Iterable intervals) {
if (intervals == null) return;
for (final interval in intervals) {
remove(interval);
}
Expand Down Expand Up @@ -423,15 +420,13 @@ class IntervalTree with IterableMixin<Interval> {
@override
bool contains(dynamic interval) {
final iv = _asInterval(interval);
if (iv == null) return false;

BidirectionalIterator<Interval> it = _tree.fromIterator(iv);
while (it.movePrevious() && iv.intersects(it.current)) {
if (it.current.contains(iv)) return true;
BidirectionalIterator<Interval?> it = _tree.fromIterator(iv!);
while (it.movePrevious() && iv.intersects(it.current!)) {
if (it.current!.contains(iv)) return true;
}
it = _tree.fromIterator(iv, inclusive: false);
while (it.moveNext() && it.current.intersects(iv)) {
if (it.current.contains(iv)) return true;
while (it.moveNext() && it.current!.intersects(iv)) {
if (it.current!.contains(iv)) return true;
}
return false;
}
Expand All @@ -448,11 +443,11 @@ class IntervalTree with IterableMixin<Interval> {
@override
bool get isNotEmpty => _tree.isNotEmpty;

/// Returns the first interval in tree, or `null` if this tree is empty.
/// Returns the first interval in tree, otherwise throw StateError.
@override
Interval get first => _tree.first;

/// Returns the first interval in tree, or `null` if this tree is empty.
/// Returns the first interval in tree, otherwise throw StateError.
@override
Interval get last => _tree.last;

Expand All @@ -468,17 +463,17 @@ class IntervalTree with IterableMixin<Interval> {
@override
String toString() => 'IntervalTree' + super.toString();

Interval _asInterval(dynamic interval) {
Interval? _asInterval(dynamic? interval) {
if (interval is Iterable) {
if (interval.length != 2 || interval.first is Iterable) {
throw ArgumentError('$interval is not an interval');
}
return Interval(interval.first, interval.last);
}
return interval as Interval;
return interval;
}

Interval _tryJoin(Interval a, Interval b) {
Interval? _tryJoin(Interval? a, Interval? b) {
if (a == null || b == null) return null;
if (a.contains(b)) return a;
if (!a.intersects(b)) return null;
Expand All @@ -490,7 +485,6 @@ class IntervalTree with IterableMixin<Interval> {
}

bool _trySplit(Interval a, Interval b) {
if (a == null || b == null) return false;
if (!a.intersects(b)) return false;
_tree.remove(a);
_tree.addAll([...?a.difference(b)]);
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ repository: https://github.com/jpnurmi/interval_tree
issue_tracker: https://github.com/jpnurmi/interval_tree/issues

environment:
sdk: ">=2.7.0 <3.0.0"
sdk: '>=2.12.0 <3.0.0'
dependencies:
meta: ^1.1.8
quiver: ^2.0.5
quiver: ^3.0.1
dev_dependencies:
test: ^1.14.2
test_coverage: ^0.4.1
test_cov: ^1.0.1
4 changes: 2 additions & 2 deletions test/interval_tree_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,8 @@ void main() {
IntervalTree empty = IntervalTree();
expect(empty.isEmpty, isTrue);
expect(empty.isNotEmpty, isFalse);
expect(empty.first, isNull);
expect(empty.last, isNull);
expect(() => empty.first, throwsA(isA<StateError>()));
expect(() => empty.last, throwsA(isA<StateError>()));
expect(empty.length, 0);
expect(() => empty.single, throwsStateError);

Expand Down