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

160 lines
4.9 KiB
Java
Raw Normal View History

2016-08-16 06:34:23 +00:00
package com.bytezone.diskbrowser.wizardry;
2022-05-27 08:30:30 +00:00
import java.util.ArrayList;
import java.util.List;
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 11:33:27 +00:00
// link for possible display algorithm:
// http://stackoverflow.com/questions/14184655/set-position-for-drawing-binary-tree
2020-02-11 07:29:55 +00:00
// -----------------------------------------------------------------------------------//
class Huffman extends AbstractFile
// -----------------------------------------------------------------------------------//
2016-08-16 06:34:23 +00:00
{
2016-08-18 04:03:13 +00:00
private static final byte[] mask = { 2, 1 }; // bits: 10 or 01
private static final int[] offset = { 512, 256 }; // offset to left/right nodes
2016-08-17 11:33:27 +00:00
2016-08-17 12:06:52 +00:00
private byte depth;
2016-08-16 22:55:51 +00:00
private int msgPtr;
2016-08-17 12:06:52 +00:00
private byte 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
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
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
}
2022-05-27 08:30:30 +00:00
// ---------------------------------------------------------------------------------//
2022-06-04 03:06:20 +00:00
byte[] decodeMessageOld (byte[] buffer, int offset, int length)
2022-05-27 08:30:30 +00:00
// ---------------------------------------------------------------------------------//
{
this.message = buffer;
List<Byte> decoded = new ArrayList<> ();
int retPtr = 0;
int max = offset + length;
depth = 0;
msgPtr = offset;
currentByte = 0;
while (msgPtr < max)
decoded.add (getChar ());
byte[] returnBuffer = new byte[decoded.size ()];
for (byte b : decoded)
returnBuffer[retPtr++] = b;
return returnBuffer;
}
2022-06-04 03:06:20 +00:00
// ---------------------------------------------------------------------------------//
byte[] decodeMessage (byte[] buffer, int offset)
// ---------------------------------------------------------------------------------//
{
this.message = buffer;
depth = 0;
msgPtr = offset;
currentByte = 0;
int size = (getChar () & 0xFF) + 1;
byte[] returnBuffer = new byte[size];
returnBuffer[0] = (byte) size;
int ptr = 1;
while (ptr < size)
returnBuffer[ptr++] = getChar ();
return returnBuffer;
}
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
String decodeMessage (byte[] message)
// ---------------------------------------------------------------------------------//
2016-08-16 06:34:23 +00:00
{
this.message = message;
2022-05-27 08:30:30 +00:00
2016-08-17 12:06:52 +00:00
depth = 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
2022-05-27 08:30:30 +00:00
int len = getChar () & 0xFF;
2016-08-16 06:34:23 +00:00
StringBuilder text = new StringBuilder ();
for (int i = 0; i < len; i++)
2022-05-27 08:30:30 +00:00
{
int c = getChar () & 0xFF;
text.append (switch (c)
{
case 0x09 -> " OF ";
case 0x0A -> "POTION";
case 0x0B -> "STAFF";
default -> c < 32 ? '?' : (char) c;
});
}
2016-08-16 22:55:51 +00:00
2016-08-16 06:34:23 +00:00
return text.toString ();
}
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-16 06:34:23 +00:00
private byte getChar ()
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-16 06:34:23 +00:00
{
2016-08-18 06:35:54 +00:00
int treePtr = 0; // start at the root
2016-08-16 06:34:23 +00:00
while (true)
{
2016-08-18 06:35:54 +00:00
if ((depth++ & 0x07) == 0) // every 8th bit...
currentByte = message[msgPtr++]; // ...get a new byte
2016-08-17 12:06:52 +00:00
2016-08-18 06:35:54 +00:00
int currentBit = currentByte & 0x01; // extract the next bit to process
2022-06-04 03:06:20 +00:00
currentByte >>>= 1; // and remove it from the current byte
2016-08-16 06:34:23 +00:00
2016-08-17 11:33:27 +00:00
// use currentBit to determine whether to use the left or right node
byte nodeValue = buffer[treePtr + offset[currentBit]];
// if the node is a leaf, return its contents
if ((buffer[treePtr] & mask[currentBit]) != 0)
return nodeValue;
// else continue traversal
treePtr = nodeValue & 0xFF;
2016-08-16 06:34:23 +00:00
}
}
2016-08-17 02:20:00 +00:00
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-17 02:20:00 +00:00
@Override
public String getText ()
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-17 02:20:00 +00:00
{
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
}
2022-06-04 03:06:20 +00:00
2016-08-17 09:42:28 +00:00
return bufferContents;
2016-08-17 02:20:00 +00:00
}
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-17 02:20:00 +00:00
private void walk (int treePtr, String path, StringBuilder text)
2020-02-11 07:29:55 +00:00
// ---------------------------------------------------------------------------------//
2016-08-17 02:20:00 +00:00
{
2016-08-18 04:03:13 +00:00
for (int currentBit = 1; currentBit >= 0; --currentBit)
if ((buffer[treePtr] & mask[currentBit]) == 0)
walk (buffer[treePtr + offset[currentBit]] & 0xFF, path + currentBit, text);
else
{
int val = buffer[treePtr + offset[currentBit]] & 0xFF;
char c = val < 32 || val >= 127 ? ' ' : (char) val;
text.append (String.format ("%3d %1.1s %s%n", val, c, path + currentBit));
}
2016-08-17 02:20:00 +00:00
}
2016-08-16 06:34:23 +00:00
}