Well, there's this:
Code:
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence));
Sets the starting position for the next gzread or gzwrite on the given
compressed file. The offset represents a number of bytes in the
uncompressed data stream. The whence parameter is defined as in lseek(2);
the value SEEK_END is not supported.
If the file is opened for reading, this function is emulated but can be
extremely slow. If the file is opened for writing, only forward seeks are
supported; gzseek then compresses a sequence of zeroes up to the new
starting position.
gzseek returns the resulting offset location as measured in bytes from
the beginning of the uncompressed stream, or -1 in case of error, in
particular if the file is opened for writing and the new starting position
would be before the current position.
But I think you can safely discard the offset, since there're no compression algorithms with random access anyway.
I mean, there're compressed formats with random access, but these are implemented by independently compressing data blocks,
so its not a part of actual compression algorithm.
Although I suppose you can still provide API like that to the user, just with your own emulation layer
(don't expect compression libraries to provide random access, just implement it in your wrapper).
However it would likely require adding some simple container format for compressed data.
Also, I'd like to note that i/o callbacks are very inconvenient for C++ programmers,
because its usually necessary to define global wrappers that pass control to methods
(if callbacks have support for an opaque pointer at all), and having standalone i/o methods
is already inconvenient, because of (un)necessary preparation required to use them
(local vars copied to class members, superclass pointers copied to class members...).
I suppose a reasonable "native" C++ solution would be to accept lambdas as callbacks,
but it would cause lots of compatibility/portability issues, and isn't especially efficient either.
So good compression libraries tend to use a coroutine-like API, where some function is
called multiple times for processing, and new buffers are passed to it depending on
returned status values.
https://github.com/facebook/zstd/blo...ib/zstd.h#L576
In my codecs the API is based on actual coroutines, and looks like this:
https://github.com/Shelwien/ppmd_sh/...er/pmd.cpp#L54