From 703e03aba33f234712206769f57717ba7d92d23d Mon Sep 17 00:00:00 2001 From: LinuxWizard42 Date: Wed, 12 Oct 2022 22:54:37 +0300 Subject: Added export_allowed file to make repository visible in cgit --- .../src/fileCompareHandler/lineBasedFileCompare.js | 196 +++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js (limited to 'node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js') diff --git a/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js b/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js new file mode 100644 index 0000000..c2de4b2 --- /dev/null +++ b/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js @@ -0,0 +1,196 @@ +/** + * Compare files line by line with options to ignore + * line endings and white space differencies. + */ +var fs = require('fs') +var FileDescriptorQueue = require('../fs/FileDescriptorQueue') +var closeFilesSync = require('./closeFile').closeFilesSync +var closeFilesAsync = require('./closeFile').closeFilesAsync +var fsPromise = require('../fs/fsPromise') +var BufferPool = require('../fs/BufferPool') + +const LINE_TOKENIZER_REGEXP = /[^\n]+\n?|\n/g +const TRIM_LINE_ENDING_REGEXP = /\r\n$/g +const SPLIT_CONTENT_AND_LINE_ENDING_REGEXP = /([^\r\n]*)([\r\n]*)/ +const TRIM_WHITE_SPACES_REGEXP = /^[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+|[ \f\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+$/g + +var MAX_CONCURRENT_FILE_COMPARE = 8 +var BUF_SIZE = 100000 +var fdQueue = new FileDescriptorQueue(MAX_CONCURRENT_FILE_COMPARE * 2) +var bufferPool = new BufferPool(BUF_SIZE, MAX_CONCURRENT_FILE_COMPARE); // fdQueue guarantees there will be no more than MAX_CONCURRENT_FILE_COMPARE async processes accessing the buffers concurrently + +function compareSync(path1, stat1, path2, stat2, options) { + var fd1, fd2 + var bufferPair = bufferPool.allocateBuffers() + var bufferSize = options.lineBasedHandlerBufferSize || BUF_SIZE + try { + fd1 = fs.openSync(path1, 'r') + fd2 = fs.openSync(path2, 'r') + var buf1 = bufferPair.buf1 + var buf2 = bufferPair.buf2 + var nextPosition1 = 0, nextPosition2 = 0 + while (true) { + var lines1 = readLinesSync(fd1, buf1, bufferSize, nextPosition1) + var lines2 = readLinesSync(fd2, buf2, bufferSize, nextPosition2) + if (lines1.length === 0 && lines2.length === 0) { + // End of file reached + return true + } + var equalLines = compareLines(lines1, lines2, options) + if (equalLines === 0) { + return false + } + nextPosition1 += calculateSize(lines1, equalLines) + nextPosition2 += calculateSize(lines2, equalLines) + } + } finally { + closeFilesSync(fd1, fd2) + bufferPool.freeBuffers(bufferPair) + } +} + +async function compareAsync(path1, stat1, path2, stat2, options) { + var fd1, fd2 + var bufferSize = options.lineBasedHandlerBufferSize || BUF_SIZE + var bufferPair + try { + var fds = await Promise.all([fdQueue.promises.open(path1, 'r'), fdQueue.promises.open(path2, 'r')]) + bufferPair = bufferPool.allocateBuffers() + fd1 = fds[0] + fd2 = fds[1] + var buf1 = bufferPair.buf1 + var buf2 = bufferPair.buf2 + var nextPosition1 = 0, nextPosition2 = 0 + while (true) { + var lines1 = await readLinesAsync(fd1, buf1, bufferSize, nextPosition1) + var lines2 = await readLinesAsync(fd2, buf2, bufferSize, nextPosition2) + if (lines1.length === 0 && lines2.length === 0) { + // End of file reached + return true + } + var equalLines = compareLines(lines1, lines2, options) + if (equalLines === 0) { + return false + } + nextPosition1 += calculateSize(lines1, equalLines) + nextPosition2 += calculateSize(lines2, equalLines) + } + } finally { + bufferPool.freeBuffers(bufferPair) + await closeFilesAsync(fd1, fd2, fdQueue) + } +} + +/** + * Read lines from file starting with nextPosition. + * Returns 0 lines if eof is reached, otherwise returns at least one complete line. + */ +function readLinesSync(fd, buf, bufferSize, nextPosition) { + var lines = [] + var chunk = "" + while (true) { + var size = fs.readSync(fd, buf, 0, bufferSize, nextPosition) + if (size === 0) { + // end of file + normalizeLastFileLine(lines) + return lines + } + chunk += buf.toString('utf8', 0, size) + lines = chunk.match(LINE_TOKENIZER_REGEXP) + if (lines.length > 1) { + return removeLastIncompleteLine(lines) + } + nextPosition += size + } +} + +/** + * Read lines from file starting with nextPosition. + * Returns 0 lines if eof is reached, otherwise returns at least one complete line. + */ +async function readLinesAsync(fd, buf, bufferSize, nextPosition) { + var lines = [] + var chunk = "" + while (true) { + var size = await fsPromise.read(fd, buf, 0, bufferSize, nextPosition) + if (size === 0) { + // end of file + normalizeLastFileLine(lines) + return lines + } + chunk += buf.toString('utf8', 0, size) + lines = chunk.match(LINE_TOKENIZER_REGEXP) + if (lines.length > 1) { + return removeLastIncompleteLine(lines) + } + nextPosition += size + } +} + +function removeLastIncompleteLine(lines) { + const lastLine = lines[lines.length - 1] + if (!lastLine.endsWith('\n')) { + return lines.slice(0, lines.length - 1) + } + return lines +} + +function normalizeLastFileLine(lines) { + if (lines.length === 0) { + return + } + const lastLine = lines[lines.length - 1] + if (!lastLine.endsWith('\n')) { + lines[lines.length - 1] = lastLine + '\n' + } +} + +function calculateSize(lines, numberOfLines) { + var size = 0 + for (var i = 0; i < numberOfLines; i++) { + var line = lines[i] + size += line.length + } + return size +} + +function compareLines(lines1, lines2, options) { + var equalLines = 0 + var len = lines1.length < lines2.length ? lines1.length : lines2.length + for (var i = 0; i < len; i++) { + var line1 = lines1[i] + var line2 = lines2[i] + if (options.ignoreLineEnding) { + line1 = trimLineEnding(line1) + line2 = trimLineEnding(line2) + } + if (options.ignoreWhiteSpaces) { + line1 = trimSpaces(line1) + line2 = trimSpaces(line2) + } + if (line1 !== line2) { + return equalLines + } + equalLines++ + } + return equalLines +} + +// Trims string like ' abc \n' into 'abc\n' +function trimSpaces(s) { + var matchResult = s.match(SPLIT_CONTENT_AND_LINE_ENDING_REGEXP); + var content = matchResult[1] + var lineEnding = matchResult[2] + var trimmed = content.replace(TRIM_WHITE_SPACES_REGEXP, '') + return trimmed + lineEnding +} + +// Trims string like 'abc\r\n' into 'abc\n' +function trimLineEnding(s) { + return s.replace(TRIM_LINE_ENDING_REGEXP, '\n') +} + +module.exports = { + compareSync: compareSync, + compareAsync: compareAsync +} -- cgit v1.2.3-86-g962b