1/* 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16class IndexRange { 17 readonly start: number; // inclusive 18 readonly end: number; // exclusive 19 20 constructor(start: number, end: number) { 21 this.start = start; 22 this.end = end; 23 if (this.start > this.end) { 24 throw new Error('Invalid range'); 25 } 26 } 27 28 get length(): number { 29 return this.end - this.start; 30 } 31 32 contains(value: IndexRange | number): boolean { 33 if (typeof value === 'object') { 34 return this.start <= (value as IndexRange).start && (value as IndexRange).end <= this.end; 35 } else { 36 return this.start <= (value as number) && (value as number) < this.end; 37 } 38 } 39 40 subtract(other: IndexRange): IndexRangeArray { 41 const result = new IndexRangeArray(); 42 if (other.start > this.start) { 43 result.push(new IndexRange(this.start, Math.min(this.end, other.start))); 44 } 45 if (other.end < this.end) { 46 result.push(new IndexRange(Math.max(other.end, this.start), this.end)); 47 } 48 return result; 49 } 50 51 // Expand the range to contain another. 52 // When `this` and `other` intersect, this is a union. 53 expandedWith(other: IndexRange): IndexRange { 54 return new IndexRange(Math.min(this.start, other.start), Math.max(this.end, other.end)); 55 } 56 57 forEachIndex(callback: (index: number) => void): void { 58 for (let i = this.start; i < this.end; ++i) { 59 callback(i); 60 } 61 } 62 63 format(): string { 64 return `[${this.start}..${this.end})`; 65 } 66} 67 68class IndexRangeArray extends Array<IndexRange> { 69 forEachIndex(callback: (index: number) => void): void { 70 this.forEach((range) => { 71 range.forEachIndex(callback); 72 }); 73 } 74} 75