2016-08-16 06:34:23 +00:00
|
|
|
package com.bytezone.diskbrowser.wizardry;
|
|
|
|
|
2016-08-17 02:20:00 +00:00
|
|
|
import com.bytezone.diskbrowser.applefile.AbstractFile;
|
|
|
|
|
2016-08-16 22:55:51 +00:00
|
|
|
// Based on a pascal routine by Tom Ewers
|
|
|
|
|
2016-08-17 02:20:00 +00:00
|
|
|
public class Huffman extends AbstractFile
|
2016-08-16 06:34:23 +00:00
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
private static final int LEFT = 256;
|
|
|
|
private static final int RIGHT = 512;
|
2016-08-16 06:34:23 +00:00
|
|
|
|
2016-08-16 22:55:51 +00:00
|
|
|
private int bitNo;
|
|
|
|
private int msgPtr;
|
|
|
|
private int currentByte;
|
2016-08-16 06:34:23 +00:00
|
|
|
private byte[] message;
|
|
|
|
|
2016-08-17 09:42:28 +00:00
|
|
|
private String bufferContents;
|
2016-08-17 02:20:00 +00:00
|
|
|
|
|
|
|
public Huffman (String name, byte[] buffer)
|
2016-08-16 06:34:23 +00:00
|
|
|
{
|
2016-08-17 02:20:00 +00:00
|
|
|
super (name, buffer);
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public String getMessage (byte[] message)
|
|
|
|
{
|
|
|
|
this.message = message;
|
2016-08-16 09:04:17 +00:00
|
|
|
bitNo = 0;
|
2016-08-16 06:34:23 +00:00
|
|
|
msgPtr = 0;
|
2016-08-16 09:04:17 +00:00
|
|
|
currentByte = 0;
|
2016-08-16 06:34:23 +00:00
|
|
|
|
|
|
|
int len = getChar ();
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
for (int i = 0; i < len; i++)
|
|
|
|
text.append ((char) getChar ());
|
2016-08-16 22:55:51 +00:00
|
|
|
|
2016-08-16 06:34:23 +00:00
|
|
|
return text.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
private byte getChar ()
|
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
int treePtr = 0; // start at the root
|
2016-08-16 06:34:23 +00:00
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
2016-08-16 22:55:51 +00:00
|
|
|
if (bitNo-- == 0)
|
2016-08-16 06:34:23 +00:00
|
|
|
{
|
2016-08-17 02:20:00 +00:00
|
|
|
bitNo += 8;
|
2016-08-16 09:04:17 +00:00
|
|
|
currentByte = message[msgPtr++] & 0xFF;
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
|
|
|
|
2016-08-17 09:42:28 +00:00
|
|
|
int currentBit = currentByte % 2; // get the next bit to process
|
2016-08-16 09:04:17 +00:00
|
|
|
currentByte /= 2;
|
2016-08-16 06:34:23 +00:00
|
|
|
|
2016-08-17 09:42:28 +00:00
|
|
|
if (currentBit == 0) // take right path
|
2016-08-16 06:34:23 +00:00
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
if ((buffer[treePtr] & 0x02) != 0) // if has right leaf...
|
|
|
|
return buffer[treePtr + RIGHT]; // return that character
|
|
|
|
treePtr = buffer[treePtr + RIGHT] & 0xFF; // else traverse right node
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
2016-08-17 09:42:28 +00:00
|
|
|
else // take left path
|
2016-08-16 06:34:23 +00:00
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
if ((buffer[treePtr] & 0x01) != 0) // if has left leaf...
|
|
|
|
return buffer[treePtr + LEFT]; // return that character
|
|
|
|
treePtr = buffer[treePtr + LEFT] & 0xFF; // else traverse left node
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-08-17 02:20:00 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getText ()
|
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
if (bufferContents == null)
|
2016-08-17 02:20:00 +00:00
|
|
|
{
|
|
|
|
StringBuilder text = new StringBuilder ();
|
|
|
|
walk (0, "", text);
|
2016-08-17 09:42:28 +00:00
|
|
|
bufferContents = text.toString ();
|
2016-08-17 02:20:00 +00:00
|
|
|
}
|
2016-08-17 09:42:28 +00:00
|
|
|
return bufferContents;
|
2016-08-17 02:20:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void walk (int treePtr, String path, StringBuilder text)
|
|
|
|
{
|
2016-08-17 09:42:28 +00:00
|
|
|
if ((buffer[treePtr] & 0x01) == 0)
|
|
|
|
walk (buffer[treePtr + LEFT] & 0xFF, path + "1", text);
|
2016-08-17 02:20:00 +00:00
|
|
|
else
|
2016-08-17 09:42:28 +00:00
|
|
|
print (path + "1", buffer[treePtr + LEFT], text);
|
2016-08-17 02:20:00 +00:00
|
|
|
|
2016-08-17 09:42:28 +00:00
|
|
|
if ((buffer[treePtr] & 0x02) == 0)
|
|
|
|
walk (buffer[treePtr + RIGHT] & 0xFF, path + "0", text);
|
2016-08-17 02:20:00 +00:00
|
|
|
else
|
2016-08-17 09:42:28 +00:00
|
|
|
print (path + "0", buffer[treePtr + RIGHT], text);
|
2016-08-17 02:20:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void print (String path, byte value, StringBuilder text)
|
|
|
|
{
|
|
|
|
int val = value & 0xFF;
|
|
|
|
char c = val < 32 || val >= 127 ? ' ' : (char) val;
|
|
|
|
text.append (String.format ("%3d %1.1s %s%n", val, c, path));
|
|
|
|
}
|
2016-08-16 06:34:23 +00:00
|
|
|
}
|