dmolony-DiskBrowser/src/com/bytezone/diskbrowser/wizardry/Huffman.java

100 lines
2.6 KiB
Java
Raw Normal View History

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
}