SegmentedRange.js 1.7 KB

1234567891011121314
  1. export class Segment{constructor(begin,end,data){if(begin>end){throw new Error('Invalid segment');}
  2. this.begin=begin;this.end=end;this.data=data;}
  3. intersects(that){return this.begin<that.end&&that.begin<this.end;}}
  4. export class SegmentedRange{constructor(mergeCallback){this._segments=[];this._mergeCallback=mergeCallback;}
  5. append(newSegment){let startIndex=this._segments.lowerBound(newSegment,(a,b)=>a.begin-b.begin);let endIndex=startIndex;let merged=null;if(startIndex>0){const precedingSegment=this._segments[startIndex-1];merged=this._tryMerge(precedingSegment,newSegment);if(merged){--startIndex;newSegment=merged;}else if(this._segments[startIndex-1].end>=newSegment.begin){if(newSegment.end<precedingSegment.end){this._segments.splice(startIndex,0,new Segment(newSegment.end,precedingSegment.end,precedingSegment.data));}
  6. precedingSegment.end=newSegment.begin;}}
  7. while(endIndex<this._segments.length&&this._segments[endIndex].end<=newSegment.end){++endIndex;}
  8. if(endIndex<this._segments.length){merged=this._tryMerge(newSegment,this._segments[endIndex]);if(merged){endIndex++;newSegment=merged;}else if(newSegment.intersects(this._segments[endIndex])){this._segments[endIndex].begin=newSegment.end;}}
  9. this._segments.splice(startIndex,endIndex-startIndex,newSegment);}
  10. appendRange(that){that.segments().forEach(segment=>this.append(segment));}
  11. segments(){return this._segments;}
  12. _tryMerge(first,second){const merged=this._mergeCallback&&this._mergeCallback(first,second);if(!merged){return null;}
  13. merged.begin=first.begin;merged.end=Math.max(first.end,second.end);return merged;}}
  14. self.Common=self.Common||{};Common=Common||{};Common.Segment=Segment;Common.SegmentedRange=SegmentedRange;