std.gzip
Der gzip-Container nach RFC 1952 — der Rahmen um DEFLATE, den std.zlib liefert. Erzeugte Dateien lassen sich mit gunzip auspacken, und von gzip erzeugte Dateien liest diese Unit.
Der Aufwand steckt nicht im Komprimieren, sondern in drei Kleinigkeiten des Formats:
- Die optionalen Kopffelder. Nach dem Flag-Byte können
FEXTRA(Länge + Daten),FNAMEundFCOMMENT(nullterminiert) undFHCRCfolgen. Wer sie nicht überspringt, setzt den DEFLATE-Strom an der falschen Stelle an — und merkt es erst, wenn der Trailer nicht passt. - Der Trailer wird geprüft, nicht nur gelesen. Eine mitgeführte, aber ungeprüfte Prüfsumme ist schlimmer als gar keine: Sie erweckt den Eindruck, der Inhalt sei abgesichert. Geprüft werden CRC-32 und ISIZE — und
FHCRCobendrein, obwohl der RFC dort auch bloßes Überspringen erlaubt. - Mehrere aneinandergehängte Member sind zulässig (
cat a.gz b.gz). Sie werden nacheinander ausgepackt und aneinandergehängt — so verhält sichgzip -dauch.
Autor: Andreas Röne
Copyright: 2024-2026 Andreas Röne
→ std.zlib · std.brotli · std.zstd · Standard Library
Funktionen
| Signatur | Beschreibung |
|---|---|
GzipCompressBound(srcLen: int64): int64 | Obergrenze der Ausgabegröße — so viel muss der Zielpuffer fassen |
GzipCompress(src, srcLen, dst, dstMax): int64 | Packt als ein gzip-Member; liefert die geschriebenen Bytes oder GZIP_OVERFLOW |
GzipDecompress(src, srcLen, dst, dstMax): int64 | Packt aus; liefert die geschriebenen Bytes, GZIP_ERR oder GZIP_OVERFLOW |
| Konstante | Wert | Bedeutung |
|---|---|---|
GZIP_OK | 0 | Erfolg |
GZIP_ERR | -1 | Kein gzip, verstümmelt oder Prüfsumme falsch |
GZIP_OVERFLOW | -2 | Ausgabepuffer zu klein |
import std.io;
import std.gzip;
fn main(): int64 {
var src: pchar := "Hallo Welt Hallo Welt Hallo Welt"c;
var bound: int64 := GzipCompressBound(32);
var dst: int64 := alloc(bound);
var n: int64 := GzipCompress(src as int64, 32, dst, bound);
PrintLn(IntToStr(n)); // geschriebene Bytes
var back: int64 := alloc(256);
var m: int64 := GzipDecompress(dst, n, back, 256);
PrintLn(IntToStr(m)); // 32 — wieder die Ausgangslänge
return 0;
}
Was der Container schreibt
GzipCompress schreibt den schlanken Kopf ohne optionale Felder: kein Dateiname, kein Kommentar, kein Zeitstempel. Nach RFC 1952 §2.3.1.2 genügt einem konformen Kompressor, ID1, ID2, CM, CRC32 und ISIZE richtig zu setzen und die übrigen Felder auf Vorgabewerten zu lassen.
MTIME = 0 heißt im RFC ausdrücklich „kein Zeitstempel vorhanden„. Das ist eine bewusste Entscheidung: Ein echter Zeitstempel wäre eine verdeckte Abhängigkeit von der Uhr und machte die Ausgabe unreproduzierbar — dieselbe Eingabe ergäbe bei jedem Lauf eine andere Datei.
Beim Auspacken werden alle optionalen Felder dagegen gelesen bzw. übersprungen. Ein gesetztes reserviertes Flag-Bit führt zu GZIP_ERR: Es könnte ein neues Feld ankündigen, das alles Folgende verschiebt — dann wäre stilles Weiterdekodieren Raten.
Anders als std.brotli und std.zstd, die nur den Store-Modus schreiben, komprimiert GzipCompress wirklich — über DeflateCompressLZ77 aus std.zlib. 4096 Byte mit vierstelligem Muster ergeben 65 Byte Ausgabe; sehr kurze, unregelmäßige Eingaben können durch Kopf und Trailer (18 Byte) dennoch wachsen. FDICT gibt es in gzip nicht und ist entsprechend nicht vorgesehen.
dstMaxmuss mindestensGzipCompressBound(srcLen)sein — nicht bloß groß genug für das Ergebnis. Die Prüfung steht vor dem Komprimieren und vergleicht gegen die Obergrenze:
GzipCompress(src, 4096, dst, 256) // -> GZIP_OVERFLOW (-2), obwohl 65 Byte gereicht hätten
Den Zielpuffer also immer mitGzipCompressBoundbemessen (srcLen + srcLen/8 + 128) und nach dem Aufruf auf die zurückgegebene Länge zuschneiden.
Letzte Aktualisierung: 2026-08-11
