LZMA-Decoder

Beschreibung

LZMA ist ein Algorithmus zum komprimieren von Daten. Er wurde ursprünglich von Igor Pavlov entwickelt. Das Verfahren ist dem von Deflate bzw. RAR sehr ähnlich, unterscheidet sich jedoch hinsichtlich der Wörterbuchgröße und Datenkodierung. Anstatt einer Huffman-Kodierung wird ein Rangecoder eingesetzt. Die Symbolfrequenz wird über die Häufigkeiten der einzelnen Symbolbits, abhängig von den vorhergehenden Symbolbits, ermittelt. Das ist auch schon das ganze Geheimnis.

Funktionsübersicht

1. Headerdaten ermitteln:

static void CLZMADecoder::ProcessHeader(
  unsigned char* pInput,
  int& nDictSize,
  LZMADECODER_POSITION_REGSIZE& nRealLength,
  int& nLiteralBits,
  int& nLiteralPosBits,
  int& nPosBits);
pInput bildet den Zeiger auf den Anfang des Headers, die restlichen Variablen sind Ausgabewerte.
nRealLength gibt die Ursprungsgröße der Daten zurück.
Wichtig: Der Header muss eine Mindestgröße von 13 Byte haben.

2. Decoderobjekt erzeugen mit:

CLZMADecoder::CLZMADecoder(
  int nDictionarySize,
  int nLiteralBits,
  int nLiteralPosBits,
  int nPosBits);
Hier werden, die aus dem ersten Schritt, ermittelten Daten benutzt um den Decoder zu erzeugen.

3. Eingangsstream setzen:

void CLZMADecoder::SetStream(unsigned char* pInput);
pInput wird hier als Zeiger auf die Datenbytes des Streams verstanden.

4. Einen Block dekodieren:

int CLZMADecoder::ProcessBlock(
  unsigned char* pOutput,
  int nBlockLength,
  LZMADECODER_POSITION_REGSIZE nRealLength);
pOutput zeigt auf den Ausgabepuffer, der die entpackten Daten enthält.
nBlockLength gibt an wie groß der Ausgabepuffer ist. Eine Mindestgröße von 280 Byte sollte nicht unterschritten werden.
Der Rückgabewert bestimmt, wieviele Bytes dekodiert wurden.
Besondere Rückgabewerte:
CLZMADecoder::LZMA_STREAM_DONE = Stream komplett ausgelesen
CLZMADecoder::LZMA_STREAM_DAMAGED = Fehler aufgetreten

5. Position des Eingangsstream ermitteln:

int CLZMADecoder::GetStreamPos();
Diese Funktion wird nur benötigt, falls ein Stream Stück für Stück entschlüsselt wird.
Sie gibt zurück, wie viele Bytes der Eingangsdaten bisher benötigt wurden.
Nach dieser Funktion folgt normalerweise wieder der Schritt 3.

Anpassungen

Momentan wird der Eingabepuffer immer wieder um, die von CLZMADecoder::GetStreamPos() Bytes, zurückgeschoben. Dies kostet natürlich Zeit. Wer sich ein wenig Zeit nimmt, kann die Klasse CLZMAStream abändern, um die Daten z.B. im "Kreis" auszulesen oder diese direkt vom Eingabegerät zu holen.
Zu beachten ist LZMADECODER_POSITION_REGSIZE, welches auf einen 64Bit Integerwert geändert werden muss, sofern Datenströme grösser als 4GB dekodiert werden sollen.

Download

Beispielprogramme und die kompletten Quelldateien: lzmadecode.zip
ACHTUNG! Einige Virenscanner sind der Meinung, das es sich bei der selbst extrahierenden Beispielanwendung, innerhalb der ZIP-Datei, um einen Trojaner/Virus handelt. Dies kann aber ignoriert werden.

Lizenz

Dieser Code wurde unter der Lizenz Creative Commons 2.0 Deutschland (BY-SA) entworfen.
Wird Code dieser Basis in anderer Software verwendet, ist der Autor unter den Credits zu nennen.
Der Autor übernimmt zusätzlich auch keinerlei Haftung für Schäden die durch den Code entstehen könnten.
(Es ist halt freie Software.)