-
Notifications
You must be signed in to change notification settings - Fork 27.8k
/
offsetRange.ts
93 lines (80 loc) · 2.96 KB
/
offsetRange.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { BugIndicatingError } from 'vs/base/common/errors';
/**
* A range of offsets (0-based).
*/
export class OffsetRange {
public static addRange(range: OffsetRange, sortedRanges: OffsetRange[]): void {
let i = 0;
while (i < sortedRanges.length && sortedRanges[i].endExclusive < range.start) {
i++;
}
let j = i;
while (j < sortedRanges.length && sortedRanges[j].start <= range.endExclusive) {
j++;
}
if (i === j) {
sortedRanges.splice(i, 0, range);
} else {
const start = Math.min(range.start, sortedRanges[i].start);
const end = Math.max(range.endExclusive, sortedRanges[j - 1].endExclusive);
sortedRanges.splice(i, j - i, new OffsetRange(start, end));
}
}
public static tryCreate(start: number, endExclusive: number): OffsetRange | undefined {
if (start > endExclusive) {
return undefined;
}
return new OffsetRange(start, endExclusive);
}
constructor(public readonly start: number, public readonly endExclusive: number) {
if (start > endExclusive) {
throw new BugIndicatingError(`Invalid range: ${this.toString()}`);
}
}
get isEmpty(): boolean {
return this.start === this.endExclusive;
}
public delta(offset: number): OffsetRange {
return new OffsetRange(this.start + offset, this.endExclusive + offset);
}
public get length(): number {
return this.endExclusive - this.start;
}
public toString() {
return `[${this.start}, ${this.endExclusive})`;
}
public equals(other: OffsetRange): boolean {
return this.start === other.start && this.endExclusive === other.endExclusive;
}
public containsRange(other: OffsetRange): boolean {
return this.start <= other.start && other.endExclusive <= this.endExclusive;
}
public contains(offset: number): boolean {
return this.start <= offset && offset < this.endExclusive;
}
/**
* for all numbers n: range1.contains(n) or range2.contains(n) => range1.join(range2).contains(n)
* The joined range is the smallest range that contains both ranges.
*/
public join(other: OffsetRange): OffsetRange {
return new OffsetRange(Math.min(this.start, other.start), Math.max(this.endExclusive, other.endExclusive));
}
/**
* for all numbers n: range1.contains(n) and range2.contains(n) <=> range1.intersect(range2).contains(n)
*
* The resulting range is empty if the ranges do not intersect, but touch.
* If the ranges don't even touch, the result is undefined.
*/
public intersect(other: OffsetRange): OffsetRange | undefined {
const start = Math.max(this.start, other.start);
const end = Math.min(this.endExclusive, other.endExclusive);
if (start <= end) {
return new OffsetRange(start, end);
}
return undefined;
}
}