import { TextRange } from './textRange' ; export class TextRangeCollection < T extends TextRange > { private _items : T [ ] ; constructor ( items ) { this . _items = items ; } get start ( ) : number { return this . _items . length > 0 ? this . _items [ 0 ] . start : 0 ; } get end ( ) : number { const lastItem = this . _items [ this . _items . length - 1 ] ; return this . _items . length > 0 ? lastItem . start + lastItem . length : 0 ; } get length ( ) : number { return this . end - this . start ; } get count ( ) : number { return this . _items . length ; } contains ( position ) { return position >= this . start && position < this . end ; } getItemAt ( index ) { if ( index < 0 || index >= this . _items . length ) { throw new Error ( 'index is out of range' ) ; } return this . _items [ index ] ; } getItemAtPosition ( position ) { if ( this . count === 0 ) { return - 1 ; } if ( position < this . start ) { return - 1 ; } if ( position > this . end ) { return - 1 ; } let min = 0 ; let max = this . count - 1 ; while ( min < max ) { const mid = Math . floor ( min + ( max - min ) / 2 ) ; const item = this . _items [ mid ] ; if ( position >= item . start ) { if ( mid >= this . count - 1 || position < this . _items [ mid + 1 ] . start ) { return mid ; } } if ( position < item . start ) { max = mid - 1 ; } else { min = mid + 1 ; } } return min ; } getItemContaining ( position ) { if ( this . count === 0 ) { return - 1 ; } if ( position < this . start ) { return - 1 ; } if ( position > this . end ) { return - 1 ; } let min = 0 ; let max = this . count - 1 ; while ( min <= max ) { const mid = Math . floor ( min + ( max - min ) / 2 ) ; const item = this . _items [ mid ] ; if ( TextRange . contains ( item , position ) ) { return mid ; } if ( mid < this . count - 1 && TextRange . getEnd ( item ) <= position && position < this . _items [ mid + 1 ] . start ) { return - 1 ; } if ( position < item . start ) { max = mid - 1 ; } else { min = mid + 1 ; } } return - 1 ; } }