From 0823979013457bc1dfae1087e027e154852b79d5 Mon Sep 17 00:00:00 2001 From: Thomas Schmucker Date: Thu, 16 Jul 2026 23:21:15 +0200 Subject: Beispiel für die Streaming-API hinzugefügt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/stream.c | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/stream.c (limited to 'src') diff --git a/src/stream.c b/src/stream.c new file mode 100644 index 0000000..286f41a --- /dev/null +++ b/src/stream.c @@ -0,0 +1,187 @@ +// Standard C +#include +#include +#include +#include + +// System +#include + +// zlib +#include + +enum { BUFFER_SIZE = 8192 }; + +static void +usage(void) +{ + (void) fprintf(stderr, "compress [-d] infile outfile\n"); +} + +static void +print_zlib_error(const char *operation, int error) +{ + if ( error == Z_ERRNO ) { + (void) fprintf(stderr, "%s error: %s\n", operation, strerror(errno)); + } + else { + (void) fprintf(stderr, "%s error: %s\n", operation, zError(error)); + } +} + +int +do_compress(FILE *in_file, FILE *out_file, int compress_level) +{ + z_stream strm = { 0 }; + + int error = deflateInit(&strm, compress_level); + if ( error ) { + return error; + } + + unsigned char in_buffer[BUFFER_SIZE]; + unsigned char out_buffer[BUFFER_SIZE]; + int flush = Z_NO_FLUSH; + + do { + strm.avail_in = fread(in_buffer, 1, BUFFER_SIZE, in_file); + + if ( ferror(in_file) ) { + deflateEnd(&strm); + return Z_ERRNO; + } + + flush = feof(in_file) ? Z_FINISH : Z_NO_FLUSH; + strm.next_in = in_buffer; + + do { + strm.avail_out = BUFFER_SIZE; + strm.next_out = out_buffer; + + error = deflate(&strm, flush); + + size_t have = BUFFER_SIZE - strm.avail_out; + if ( fwrite(out_buffer, 1, have, out_file) != have || ferror(out_file) ) { + deflateEnd(&strm); + return Z_ERRNO; + } + } while ( strm.avail_out == 0 ); + } while ( flush != Z_FINISH ); + + deflateEnd(&strm); + return Z_OK; +} + +int +do_uncompress(FILE *in_file, FILE *out_file) +{ + z_stream strm = { 0 }; + + int error = inflateInit(&strm); + if ( error ) { + return error; + } + + unsigned char in_buffer[BUFFER_SIZE]; + unsigned char out_buffer[BUFFER_SIZE]; + + do { + strm.avail_in = fread(in_buffer, 1, BUFFER_SIZE, in_file); + + if ( ferror(in_file) ) { + inflateEnd(&strm); + return Z_ERRNO; + } + + if ( strm.avail_in == 0 ) { + break; + } + + strm.next_in = in_buffer; + + do { + strm.avail_out = BUFFER_SIZE; + strm.next_out = out_buffer; + + error = inflate(&strm, Z_NO_FLUSH); + + switch ( error ) { + case Z_NEED_DICT: + error = Z_DATA_ERROR; /* and fall through */ + case Z_DATA_ERROR: + case Z_MEM_ERROR: + (void) inflateEnd(&strm); + return error; + default: + break; + } + + size_t have = BUFFER_SIZE - strm.avail_out; + if ( fwrite(out_buffer, 1, have, out_file) != have || ferror(out_file) ) { + (void) inflateEnd(&strm); + return Z_ERRNO; + } + } while ( strm.avail_out == 0 ); + } while ( error != Z_STREAM_END ); + + inflateEnd(&strm); + + return error == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; +} + +int +main(int argc, char *argv[]) +{ + enum { + COMPRESSION_STD = 5, + COMPRESSION_BEST = 9 + }; + + int decompress = 0; + int compress_level = COMPRESSION_STD; + + int opt = 0; + while ( (opt = getopt(argc, argv, "dl")) != -1 ) { + switch ( opt ) { + case 'd': + decompress = 1; + break; + + case 'l': + compress_level = COMPRESSION_BEST; + break; + + case '?': + default: + usage(); + return EXIT_SUCCESS; + } + } + argc -= optind; + argv += optind; + + if ( argc != 2 ) { + usage(); + } + + FILE *in_file = fopen(argv[0], "rb"); + FILE *out_file = fopen(argv[1], "wb"); + + if ( !decompress ) { + int error = do_compress(in_file, out_file, compress_level); + if ( error ) { + print_zlib_error("compression", error); + } + } + else { + int error = do_uncompress(in_file, out_file); + if ( error ) { + print_zlib_error("extraction", error); + } + } + + (void) fclose(out_file); + (void) fclose(in_file); + + return EXIT_SUCCESS; +} -- cgit v1.3