RosettaCodeData/Task/LZW-compression/JavaScript/lzw-compression-2.js

111 lines
2.7 KiB
JavaScript

'use strict';
/**
Namespace for LZW compression and decompression.
Methods:
LZW.compress(uncompressed)
LZW.decompress(compressed)
*/
class LZW
{
/**
Perform the LZW compression
uncompressed - String. The string on which to perform the compression.
*/
static compress(uncompressed)
{
// Initialize dictionary
let dictionary = {};
for (let i = 0; i < 256; i++)
{
dictionary[String.fromCharCode(i)] = i;
}
let word = '';
let result = [];
let dictSize = 256;
for (let i = 0, len = uncompressed.length; i < len; i++)
{
let curChar = uncompressed[i];
let joinedWord = word + curChar;
// Do not use dictionary[joinedWord] because javascript objects
// will return values for myObject['toString']
if (dictionary.hasOwnProperty(joinedWord))
{
word = joinedWord;
}
else
{
result.push(dictionary[word]);
// Add wc to the dictionary.
dictionary[joinedWord] = dictSize++;
word = curChar;
}
}
if (word !== '')
{
result.push(dictionary[word]);
}
return result;
}
/**
Decompress LZW array generated by LZW.compress()
compressed - Array. The array that holds LZW compressed data.
*/
static decompress(compressed)
{
// Initialize Dictionary (inverse of compress)
let dictionary = {};
for (let i = 0; i < 256; i++)
{
dictionary[i] = String.fromCharCode(i);
}
let word = String.fromCharCode(compressed[0]);
let result = word;
let entry = '';
let dictSize = 256;
for (let i = 1, len = compressed.length; i < len; i++)
{
let curNumber = compressed[i];
if (dictionary[curNumber] !== undefined)
{
entry = dictionary[curNumber];
}
else
{
if (curNumber === dictSize)
{
entry = word + word[0];
}
else
{
throw 'Error in processing';
return null;
}
}
result += entry;
// Add word + entry[0] to dictionary
dictionary[dictSize++] = word + entry[0];
word = entry;
}
return result;
}
}
let comp = LZW.compress('TOBEORNOTTOBEORTOBEORNOT');
let decomp = LZW.decompress(comp);
console.log(`${comp}
${decomp}`);