in packages/selector/src/text/seeker.ts [324:390]
private _readOrSeekTo(
read: boolean,
target: number,
roundUp = false,
lessIsFine = false,
): string | void {
let result = '';
if (this.position <= target) {
while (true) {
const endOfChunk =
this.currentChunkPosition + this.currentChunk.data.length;
if (endOfChunk <= target) {
// The target is beyond the current chunk.
// (we use ≤ not <: if the target is *at* the end of the chunk, possibly
// because the current chunk is empty, we prefer to take the next chunk)
const [data, nextChunk] = this._readToNextChunk();
if (read) result += data;
if (nextChunk === null) {
if (this.position === target || lessIsFine) break;
else throw new RangeError(E_END);
}
} else {
// The target is within the current chunk.
const newOffset = roundUp
? this.currentChunk.data.length
: target - this.currentChunkPosition;
if (read)
result += this.currentChunk.data.substring(
this.offsetInChunk,
newOffset,
);
this.offsetInChunk = newOffset;
// If we finish end at the end of the chunk, seek to the start of the next non-empty node.
// (TODO decide: should we keep this guarantee of not finishing at the end of a chunk?)
if (roundUp) this.seekBy(0);
break;
}
}
} else {
// Similar to the if-block, but moving backward in the text.
while (this.position > target) {
if (this.currentChunkPosition <= target) {
// The target is within the current chunk.
const newOffset = roundUp ? 0 : target - this.currentChunkPosition;
if (read)
result =
this.currentChunk.data.substring(newOffset, this.offsetInChunk) +
result;
this.offsetInChunk = newOffset;
break;
} else {
const [data, previousChunk] = this._readToPreviousChunk();
if (read) result = data + result;
if (previousChunk === null) {
if (lessIsFine) break;
else throw new RangeError(E_END);
}
}
}
}
if (read) return result;
}