First release of the v1 feature set: a codec registry with a uniform byte-in/byte-out API, one vendored codec family, and a stable C ABI.
komp_compress() and komp_decompress(),
over identity, deflate-raw, zlib
and gzip. Raw vectors only — encoding is the caller’s
decision, so character input is refused.
komp_detect() and codec = "auto".
Detection is a registry property, and it refuses to guess: headerless
formats return NA and must be named, because guessing wrong
there returns wrong bytes rather than an error.
komp_codecs(), the capability table. It also lists
the codec names zukomp reserves for future implementations
(zstd, brotli, …) with
available = FALSE; none has been released yet, and asking
for one is a zukomp_unsupported_codec error that says so.
Its columns include can_flush, and
level_fast/level_best — where the abstract
level names land for each codec.
level accepts a codec-native whole number,
NULL for the codec’s default, or one of the abstract names
"fast", "default" and "best".
Numeric levels are codec-native and deliberately not comparable between
codecs, so the names are the portable way to say “compress harder”; they
work on every codec, including ones with no level axis, where all three
mean the codec’s one behaviour.
The names are declared by each codec rather than derived from
level_min/level_max, because the range is
which integers are accepted, not which ones mean cheap and
thorough: DEFLATE’s level 0 is stored blocks, and a codec whose level is
an acceleration factor inverts the mapping entirely.
komp_codec_available() and komp_info().
komp_info()$version is a character string, so it pastes
into a log line directly.
Structured conditions carrying codec,
input_bytes, output_bytes and
native_status, so callers branch on the class rather than
on the message.
options(zukomp.max_output = ). An optional
max_ratio is off by default, since legitimately
compressible data routinely exceeds any safe-looking threshold.0 means no limit — so a fractional value in
(0, 1) would otherwise disable the guard it was asked to
impose. NULL, 0 and Inf are the
spellings for unlimited.MZ_ASSERT expands to assert() at sites
reachable from malformed input, and upstream defines it unconditionally,
so its behaviour was left entirely to NDEBUG; a local patch
makes it overridable so that a -UNDEBUG build cannot
abort() where an ordinary build raises a condition.A versioned C ABI in inst/include/zukomp.h, reached
through zukomp-r.h and R’s registered C-callable
mechanism.
Other packages can register codecs at
ZU_CODEC_VENDOR_BASE. Adding a codec changes no existing
declaration and needs no ABI bump. Registration is experimental
in this release: zu_register_codec() and
zu_codec_vtable are outside the ABI stability promise until
a real satellite codec has used them, and may change in a minor release.
The core limits apply to a registered codec regardless.
zukomp.so exports R_init_zukomp and
nothing else (on ELF and Mach-O; Windows exports through R’s
.def file). Everything is reached through R’s registration
tables, and an exported miniz could otherwise bind to another package’s
vendored copy in the same process.
ZU_FINISH is delivered to a codec together with the
final bytes, not only on a later call with an empty buffer. A codec can
therefore tell “these are the last bytes” from “here are some bytes” –
which gzip’s next-member probe needs, so that a stream ending in a lone
0x1f is consumed exactly rather than one byte
over.
Registration enforces codec identity for every registration, declared or not: a declared id must carry its declared name, an undeclared id must be in the vendor range, and names and content-coding tokens must be unique — including against declared codecs whose implementation is absent, whose names are reserved for a satellite to claim with the declared id. The registry is process-global and has no removal API, so one ambiguous registration would otherwise poison codec discovery for the session.
A satellite is usable regardless of load order.
komp_codecs() caches on a registry mutation counter, so an
implementation registered after the table was first read is picked
up.
zu_codec_vtable, zu_codec_info,
zu_encoder_opts and zu_decoder_opts may all
gain fields without an ABI bump: each check requires only the prefix the
core dereferences, so a consumer compiled against an older header keeps
working and simply does not supply the newer fields. Options structs are
copied bounded by the caller’s own struct_size, so a
shorter one is never read past its end.
A second route, for a consumer that needs the ZIP
container layer rather than a codec – the members of an
.xlsx, for one. An installed zukomp ships
lib/libzukomp.a and include/miniz.h, so that
layer can be linked through LinkingTo instead of vendoring
a second ZIP implementation. The archive is a separate compilation of
the vendored miniz.c with the archive APIs left in;
zukomp.so keeps exactly the trim it has, and contains no
mz_zip_* code at all. The archive’s symbols have hidden
visibility too: they link into the consumer as usual, but the consumer’s
shared object does not re-export them. See “Using zukomp from C” in the
README.
Resolve it with
system.file("lib", .Platform$r_arch, package = "zukomp").
It is architecture-specific object code, so it installs under
R_ARCH beside the shared object’s directory –
lib/ on every single-arch platform and
lib/x64/ on Windows.
Compile miniz.h with
MINIZ_NO_ZLIB_COMPATIBLE_NAMES defined and nothing else.
MINIZ_NO_TIME in particular changes MZ_TIME_T,
and with it the layout of mz_zip_archive_file_stat, between
the consumer’s translation unit and the archive – a silent mismatch
rather than a link error.
realloc’d buffer
owned by an R external pointer, so growth releases superseded blocks as
it goes and a large decode does not hold several at once.tools/vendor/manifest.tsv and verifiable offline with
tools/vendor/verify. Its MIT notice is installed at
licenses/miniz-LICENSE: miniz.h carries no
copyright line of its own, and an installed zukomp ships both that
header and compiled miniz code.komp_compress_text(), dictionaries, and
the brotli/zstd/LZ4/Snappy satellite packages.