(path: string)
| 493 | } |
| 494 | |
| 495 | async scanTextFile(path: string): Promise<TextFileScan> { |
| 496 | const resolved = this._resolvePath(path); |
| 497 | const fh = await open(resolved, 'r'); |
| 498 | try { |
| 499 | const buf = Buffer.alloc(READ_CHUNK_SIZE); |
| 500 | const flags: LineEndingFlags = { hasCrLf: false, hasLf: false, hasLoneCr: false }; |
| 501 | const validator = createUtf8Validator(); |
| 502 | let totalLines = 0; |
| 503 | let totalBytes = 0; |
| 504 | let endsWithNewline = false; |
| 505 | let hasNul = false; |
| 506 | let prevWasCr = false; |
| 507 | |
| 508 | while (true) { |
| 509 | const { bytesRead } = await fh.read(buf, 0, buf.length, null); |
| 510 | if (bytesRead === 0) break; |
| 511 | const chunk = buf.subarray(0, bytesRead); |
| 512 | validator.write(chunk); |
| 513 | for (let i = 0; i < chunk.length; i += 1) { |
| 514 | const byte = chunk[i]; |
| 515 | if (byte === undefined) continue; |
| 516 | if (byte === 0) hasNul = true; |
| 517 | if (byte === 0x0a) totalLines += 1; |
| 518 | } |
| 519 | prevWasCr = updateLineEndingFlagsFromBytes(flags, chunk, prevWasCr); |
| 520 | totalBytes += bytesRead; |
| 521 | endsWithNewline = chunk[bytesRead - 1] === 0x0a; |
| 522 | } |
| 523 | |
| 524 | if (prevWasCr) flags.hasLoneCr = true; |
| 525 | validator.end(); |
| 526 | if (totalBytes > 0 && !endsWithNewline) totalLines += 1; |
| 527 | return { totalLines, endsWithNewline, hasNul, lineEndingFlags: flags }; |
| 528 | } finally { |
| 529 | await fh.close(); |
| 530 | } |
| 531 | } |
| 532 | |
| 533 | async *readLineRange( |
| 534 | path: string, |
no test coverage detected