summaryrefslogtreecommitdiff
path: root/node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js
diff options
context:
space:
mode:
authorLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
committerLinuxWizard42 <computerwizard@linuxmail.org>2022-10-12 22:54:37 +0300
commit703e03aba33f234712206769f57717ba7d92d23d (patch)
tree0041f04ccb75bd5379c764e9fe42249fffe75fc3 /node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js
parentab6e257e6e9d9a483d7e86f220d8b209a2cd7753 (diff)
downloadFlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.gz
FlashRunner-703e03aba33f234712206769f57717ba7d92d23d.tar.zst
Added export_allowed file to make repository visible in cgit
Diffstat (limited to 'node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js')
-rw-r--r--node_modules/dir-compare/src/fileCompareHandler/lineBasedFileCompare.js196
1 files changed, 196 insertions, 0 deletions
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
+}