welsonjs/lib/lz77.js

73 lines
2.4 KiB
JavaScript
Raw Normal View History

// lz77.js
// https://github.com/gnh1201/welsonjs
function compress(input) {
var compressed = '';
var searchBufferIndex = 0;
while (searchBufferIndex < input.length) {
var longestMatchLength = 0;
var longestMatchOffset = 0;
// Search for the longest match in the look-ahead buffer
for (var i = 0; i < searchBufferIndex; i++) {
var matchLength = 0;
while (matchLength < input.length - searchBufferIndex && input.charAt(i + matchLength) === input.charAt(searchBufferIndex + matchLength)) {
matchLength++;
}
if (matchLength > longestMatchLength) {
longestMatchLength = matchLength;
longestMatchOffset = searchBufferIndex - i;
}
}
// Output the token (offset, length)
if (longestMatchLength > 0) {
compressed += '(' + longestMatchOffset + ',' + longestMatchLength + ')';
searchBufferIndex += longestMatchLength;
} else {
compressed += '(0,' + input.charAt(searchBufferIndex) + ')';
searchBufferIndex++;
}
}
return compressed;
}
function decompress(compressedData) {
var decompressed = '';
var currentIndex = 0;
while (currentIndex < compressedData.length) {
if (compressedData.charAt(currentIndex) === '(') {
// Match case
var commaIndex = compressedData.indexOf(',', currentIndex);
var offset = parseInt(compressedData.substring(currentIndex + 1, commaIndex), 10);
var closingParenIndex = compressedData.indexOf(')', commaIndex);
var length = parseInt(compressedData.substring(commaIndex + 1, closingParenIndex), 10);
for (var i = 0; i < length; i++) {
var copyIndex = decompressed.length - offset;
decompressed += decompressed.charAt(copyIndex);
}
currentIndex = closingParenIndex + 1;
} else {
// Literal case
decompressed += compressedData.charAt(currentIndex);
currentIndex++;
}
}
return decompressed;
}
exports.compress = compress;
exports.decompress = decompress;
exports.VERSIONINFO = "LZ77 (MsCompress) algorithm implementation version 0.1";
exports.AUTHOR = "abuse@catswords.net";
exports.global = global;
exports.require = global.require;