mirror of
https://github.com/gnh1201/welsonjs.git
synced 2024-11-26 07:21:43 +00:00
Add LZ77 (MsCompress) algorithm implementation
This commit is contained in:
parent
3cfc3fccf5
commit
e7068f0f97
103
WelsonJS.Toolkit/WelsonJS.Toolkit/Compression/LZ77.cs
Normal file
103
WelsonJS.Toolkit/WelsonJS.Toolkit/Compression/LZ77.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* WelsonJS.Toolkit: WelsonJS dotNET native component
|
||||
*
|
||||
* filename:
|
||||
* LZ77.cs
|
||||
*
|
||||
* description:
|
||||
* WelsonJS - Build a Windows app on the Windows built-in JavaScript engine
|
||||
*
|
||||
* website:
|
||||
* - https://github.com/gnh1201/welsonjs
|
||||
* - https://catswords.social/@catswords_oss
|
||||
*
|
||||
* author:
|
||||
* Namhyeon Go <abuse@catswords.net>
|
||||
*
|
||||
* license:
|
||||
* GPLv3 or MS-RL(Microsoft Reciprocal License)
|
||||
*
|
||||
*/
|
||||
using System.Text;
|
||||
|
||||
namespace WelsonJS.Compression
|
||||
{
|
||||
public class LZ77
|
||||
{
|
||||
public static string Compress(string input)
|
||||
{
|
||||
StringBuilder compressed = new StringBuilder();
|
||||
int searchBufferIndex = 0;
|
||||
|
||||
while (searchBufferIndex < input.Length)
|
||||
{
|
||||
int longestMatchLength = 0;
|
||||
int longestMatchOffset = 0;
|
||||
|
||||
// Search for the longest match in the look-ahead buffer
|
||||
for (int i = 0; i < searchBufferIndex; i++)
|
||||
{
|
||||
int matchLength = 0;
|
||||
while (matchLength < input.Length - searchBufferIndex && input[i + matchLength] == input[searchBufferIndex + matchLength])
|
||||
{
|
||||
matchLength++;
|
||||
}
|
||||
|
||||
if (matchLength > longestMatchLength)
|
||||
{
|
||||
longestMatchLength = matchLength;
|
||||
longestMatchOffset = searchBufferIndex - i;
|
||||
}
|
||||
}
|
||||
|
||||
// Output the token (offset, length)
|
||||
if (longestMatchLength > 0)
|
||||
{
|
||||
compressed.Append($"({longestMatchOffset},{longestMatchLength})");
|
||||
searchBufferIndex += longestMatchLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
compressed.Append($"(0,{input[searchBufferIndex]})");
|
||||
searchBufferIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return compressed.ToString();
|
||||
}
|
||||
|
||||
public static string Decompress(string compressedData)
|
||||
{
|
||||
StringBuilder decompressed = new StringBuilder();
|
||||
int currentIndex = 0;
|
||||
|
||||
while (currentIndex < compressedData.Length)
|
||||
{
|
||||
if (compressedData[currentIndex] == '(')
|
||||
{
|
||||
// Match case
|
||||
int commaIndex = compressedData.IndexOf(',', currentIndex);
|
||||
int offset = int.Parse(compressedData.Substring(currentIndex + 1, commaIndex - currentIndex - 1));
|
||||
int closingParenIndex = compressedData.IndexOf(')', commaIndex);
|
||||
int length = int.Parse(compressedData.Substring(commaIndex + 1, closingParenIndex - commaIndex - 1));
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
int copyIndex = decompressed.Length - offset;
|
||||
decompressed.Append(decompressed[copyIndex]);
|
||||
}
|
||||
|
||||
currentIndex = closingParenIndex + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Literal case
|
||||
decompressed.Append(compressedData[currentIndex]);
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
return decompressed.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -209,5 +209,17 @@ namespace WelsonJS
|
|||
sharedMemory.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
[ComVisible(true)]
|
||||
public void CompressLZ77(string input)
|
||||
{
|
||||
Compression.LZ77.Compress(input);
|
||||
}
|
||||
|
||||
[ComVisible(true)]
|
||||
public string DecompressLZ77(string compressData)
|
||||
{
|
||||
return Compression.LZ77.Decompress(compressData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,35 +232,6 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scope": [],
|
||||
"name": "MsCompress for Windows",
|
||||
"author": "gnuwin32",
|
||||
"distributer": "gnuwin32",
|
||||
"license": "GPL",
|
||||
"architecture": ["x86"],
|
||||
"website": "https://gnuwin32.sourceforge.net/packages/mscompress.htm",
|
||||
"release": {
|
||||
"version": "0.3",
|
||||
"build": "2004-03-14",
|
||||
"date": "2004-03-14",
|
||||
"changelog": "https://gnuwin32.sourceforge.net/packages/mscompress.htm"
|
||||
},
|
||||
"environment": {
|
||||
"knownAs": [
|
||||
"mscompress",
|
||||
"mscompress.exe"
|
||||
],
|
||||
"knownPath": []
|
||||
},
|
||||
"binaries": [
|
||||
{
|
||||
"architecture": "x86",
|
||||
"downloadLink": "https://gnuwin32.sourceforge.net/downlinks/mscompress-bin-zip.php",
|
||||
"tags": ["archive", "lz77", "standalone"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"scope": [],
|
||||
"name": "github.com/philr/bzip2-windows",
|
||||
|
|
72
lib/lz77.js
Normal file
72
lib/lz77.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
// 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;
|
Loading…
Reference in New Issue
Block a user