Search code examples
phpjavascriptcompressionlzw

Trouble understanding php function for LZW decompression in JSend


I'm trying to convert the LZW decompressor from JSend which is in php to javascript, and I've gotten to a function I can't quite make sense of.

 private static function decompressLZW($aCodes) 
  {
    $sData = '';
    $oDictionary = range("\x0000", "\xff");
    foreach ($aCodes as $sKey => $iCode) 
    {
      $sElement = $oDictionary[$iCode]; 
      if (!isset($sElement))
          $sElement = $sWord . $sWord[0];
      $sData .= $sElement;
      if ($sKey)
          $oDictionary[] = $sWord . $sElement[0];
      $sWord = $sElement;
    }
    return $sData;
  }

This is what I have in javascript so far, but I when I run this in javascript, it complains that sWord isn't defined and looking at the php function, I don't see how this doesn't produce an error?

Here's what I have in javscript so far:

function decompressLZW(aCodes) {
  var sData = '';
  var oDictionary = [];

  for (var i = 0; i < 256; i++) {
    oDictionary[String.fromCharCode(i)] = i; 
  }

  for(var i=0, iLn = aCodes.length; i < iLn; i++) {
    var sElement = oDictionary[aCodes[i]];

    if(!sElement) {
      sElement = sWord + sWord[0];
    }

    //some magic needs to happen here
  }

  return sData;
}

Solution

  • Well its kind of bad IMO but.... $sWord is essentially $sElement which is defined near the end of the iteration. They are counting on the first two if statements be true only after the at least a single run of the loop in which case $sWord would be the same as the previous iteration's $sElement.

    Im not sure what the significance of that assumption is but if it were me i would still test for the existence of $sWord and throw an exception if that happened (even if it should theoretically never happen)...

    So you need to figure out why sElement = oDictionary[aCodes[i]]; isnt evaluating to something truthy. It may be as simple as testing angainst undefined (which is more like doing isset()) instead of doing loose falsy check.

    if(sElement === undefined) {
      sElement = sWord + sWord[0];
    }