cosmopolitan/examples/compress.c
Justine Tunney 23e235b7a5
Fix bugs in cosmocc toolchain
This change integrates e58abc1110b335a3341e8ad5821ad8e3880d9bb2 from
https://github.com/ahgamut/musl-cross-make/ which fixes the issues we
were having with our C language extension for symbolic constants. This
change also performs some code cleanup and bug fixes to getaddrinfo().
It's now possible to compile projects like ncurses, readline and python
without needing to patch anything upstream, except maybe a line or two.
Pretty soon it should be possible to build a Linux distro on Cosmo.
2023-06-08 23:44:03 -07:00

229 lines
7.5 KiB
C

#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/log/check.h"
#include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/ex.h"
#include "libc/sysv/consts/exit.h"
#include "third_party/getopt/getopt.h"
#include "third_party/zlib/zlib.h"
#define CHUNK 32768
#define USAGE \
" <STDIN >STDOUT\n\
\n\
SYNOPSIS\n\
\n\
Zlib Compressor\n\
\n\
FLAGS\n\
\n\
-?\n\
-h help\n\
-0 disable compression\n\
-1 fastest compression\n\
-4 coolest compression\n\
-9 maximum compression\n\
-F fixed strategy (advanced)\n\
-L filtered strategy (advanced)\n\
-R run length strategy (advanced)\n\
-H huffman only strategy (advanced)\n\
\n"
// clang-format off
// make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b
/*
#!/bin/bash
# data file is o/dbg/third_party/python/python.com
# level 1 348739 compress 22.8 MB/s decompress 444 MB/s
# level 2 347549 compress 37.8 MB/s decompress 457 MB/s
# level 3 346902 compress 33.3 MB/s decompress 463 MB/s
# level 4 345671 compress 29.3 MB/s decompress 467 MB/s
# level 5 344392 compress 22.4 MB/s decompress 506 MB/s
# level 6 342105 compress 10.9 MB/s decompress 516 MB/s
# level 7 342046 compress 7.9 MB/s decompress 515 MB/s
# level 8 342009 compress 5.8 MB/s decompress 518 MB/s
# level 9 342001 compress 5.7 MB/s decompress 524 MB/s
# level F 1 362426 compress 48.2 MB/s decompress 488 MB/s
# level F 2 360875 compress 42.7 MB/s decompress 484 MB/s
# level F 3 359992 compress 37.1 MB/s decompress 499 MB/s
# level F 4 358460 compress 32.9 MB/s decompress 503 MB/s
# level F 5 356431 compress 24.0 MB/s decompress 547 MB/s
# level F 6 352274 compress 11.6 MB/s decompress 558 MB/s
# level F 7 352155 compress 8.7 MB/s decompress 554 MB/s
# level F 8 352065 compress 6.3 MB/s decompress 554 MB/s
# level F 9 352051 compress 6.2 MB/s decompress 556 MB/s
# level L 1 348739 compress 41.1 MB/s decompress 446 MB/s
# level L 2 347549 compress 37.4 MB/s decompress 443 MB/s
# level L 3 346902 compress 32.3 MB/s decompress 462 MB/s
# level L 4 351932 compress 28.8 MB/s decompress 511 MB/s
# level L 5 351384 compress 23.6 MB/s decompress 520 MB/s
# level L 6 351328 compress 12.1 MB/s decompress 522 MB/s
# level L 7 351230 compress 7.3 MB/s decompress 518 MB/s
# level L 8 351192 compress 5.7 MB/s decompress 522 MB/s
# level L 9 351182 compress 6.5 MB/s decompress 519 MB/s
# level R 1 388209 compress 83.1 MB/s decompress 371 MB/s
# level R 2 388209 compress 82.3 MB/s decompress 362 MB/s
# level R 3 388209 compress 81.8 MB/s decompress 361 MB/s
# level R 4 388209 compress 81.7 MB/s decompress 364 MB/s
# level R 5 388209 compress 81.7 MB/s decompress 363 MB/s
# level R 6 388209 compress 80.1 MB/s decompress 359 MB/s
# level R 7 388209 compress 80.3 MB/s decompress 354 MB/s
# level R 8 388209 compress 80.3 MB/s decompress 363 MB/s
# level R 9 388209 compress 81.3 MB/s decompress 364 MB/s
# level H 1 390207 compress 87.6 MB/s decompress 371 MB/s
# level H 2 390207 compress 87.5 MB/s decompress 372 MB/s
# level H 3 390207 compress 85.5 MB/s decompress 364 MB/s
# level H 4 390207 compress 87.3 MB/s decompress 375 MB/s
# level H 5 390207 compress 89.0 MB/s decompress 373 MB/s
# level H 6 390207 compress 87.3 MB/s decompress 372 MB/s
# level H 7 390207 compress 87.0 MB/s decompress 368 MB/s
# level H 8 390207 compress 86.2 MB/s decompress 367 MB/s
# level H 9 390207 compress 86.9 MB/s decompress 369 MB/s
m=
make -j8 MODE=$m o/$m/examples || exit
for strategy in ' ' F L R H; do
for level in $(seq 1 9); do
o/$m/examples/compress.com -$level$strategy <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
size=$(o/$m/examples/compress.com -$level$strategy <o/$m/examples/compress.com | wc -c)
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
done
done
*/
// clang-format on
int level;
int strategy;
wontreturn void PrintUsage(int rc, FILE *f) {
fputs("usage: ", f);
fputs(program_invocation_name, f);
fputs(USAGE, f);
exit(rc);
}
void GetOpts(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "?hFLRH0123456789")) != -1) {
switch (opt) {
case 'F':
strategy = Z_FIXED;
break;
case 'L':
strategy = Z_FILTERED;
break;
case 'R':
strategy = Z_RLE;
break;
case 'H':
strategy = Z_HUFFMAN_ONLY;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
level = opt - '0';
break;
case 'h':
case '?':
PrintUsage(EXIT_SUCCESS, stdout);
default:
PrintUsage(EX_USAGE, stderr);
}
}
}
int compressor(int infd, int outfd) {
z_stream zs;
int rc, flush;
unsigned have;
unsigned char *inbuf;
unsigned char *outbuf;
inbuf = gc(valloc(CHUNK));
outbuf = gc(valloc(CHUNK));
zs.zalloc = 0;
zs.zfree = 0;
zs.opaque = 0;
rc = deflateInit2(&zs, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, strategy);
if (rc != Z_OK) return rc;
do {
rc = read(infd, inbuf, CHUNK);
if (rc == -1) {
deflateEnd(&zs);
return Z_ERRNO;
}
zs.avail_in = rc;
flush = !rc ? Z_FINISH : Z_SYNC_FLUSH;
zs.next_in = inbuf;
do {
zs.avail_out = CHUNK;
zs.next_out = outbuf;
rc = deflate(&zs, flush);
assert(rc != Z_STREAM_ERROR);
have = CHUNK - zs.avail_out;
if (write(outfd, outbuf, have) != have) {
deflateEnd(&zs);
return Z_ERRNO;
}
} while (!zs.avail_out);
assert(!zs.avail_in);
} while (flush != Z_FINISH);
assert(rc == Z_STREAM_END);
deflateEnd(&zs);
return Z_OK;
}
const char *zerr(int rc) {
switch (rc) {
case Z_ERRNO:
return strerror(errno);
case Z_STREAM_ERROR:
return "invalid compression level";
case Z_DATA_ERROR:
return "invalid or incomplete deflate data";
case Z_MEM_ERROR:
return "out of memory";
case Z_VERSION_ERROR:
return "zlib version mismatch!";
default:
__builtin_unreachable();
}
}
int main(int argc, char *argv[]) {
int rc;
level = Z_DEFAULT_COMPRESSION;
strategy = Z_DEFAULT_STRATEGY;
GetOpts(argc, argv);
rc = compressor(0, 1);
if (rc == Z_OK) {
return 0;
} else {
fprintf(stderr, "error: compressor: %s\n", zerr(rc));
return 1;
}
}