mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Add compress and decompress examples
This commit is contained in:
parent
54e6f564c1
commit
6bf6f9e376
3 changed files with 204 additions and 3 deletions
92
examples/compress.c
Normal file
92
examples/compress.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
#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/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
#define CHUNK 4096
|
||||
|
||||
// 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
|
||||
// clang-format on
|
||||
|
||||
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, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS,
|
||||
DEF_MEM_LEVEL, Z_DEFAULT_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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc;
|
||||
rc = compressor(0, 1);
|
||||
if (rc == Z_OK) {
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "error: compressor: %s\n", zerr(rc));
|
||||
return 1;
|
||||
}
|
||||
}
|
100
examples/decompress.c
Normal file
100
examples/decompress.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
#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/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
#define CHUNK 4096
|
||||
|
||||
// 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
|
||||
// clang-format on
|
||||
|
||||
int decompressor(int infd, int outfd) {
|
||||
int rc;
|
||||
unsigned have;
|
||||
z_stream zs;
|
||||
unsigned char *inbuf;
|
||||
unsigned char *outbuf;
|
||||
inbuf = gc(valloc(CHUNK));
|
||||
outbuf = gc(valloc(CHUNK));
|
||||
zs.zalloc = Z_NULL;
|
||||
zs.zfree = Z_NULL;
|
||||
zs.opaque = Z_NULL;
|
||||
zs.avail_in = 0;
|
||||
zs.next_in = Z_NULL;
|
||||
rc = inflateInit(&zs);
|
||||
if (rc != Z_OK) return rc;
|
||||
do {
|
||||
rc = read(infd, inbuf, CHUNK);
|
||||
if (rc == -1) {
|
||||
inflateEnd(&zs);
|
||||
return Z_ERRNO;
|
||||
}
|
||||
if (!rc) {
|
||||
break;
|
||||
}
|
||||
zs.avail_in = rc;
|
||||
zs.next_in = inbuf;
|
||||
do {
|
||||
zs.avail_out = CHUNK;
|
||||
zs.next_out = outbuf;
|
||||
rc = inflate(&zs, Z_SYNC_FLUSH);
|
||||
assert(rc != Z_STREAM_ERROR);
|
||||
switch (rc) {
|
||||
case Z_NEED_DICT:
|
||||
rc = Z_DATA_ERROR;
|
||||
// fallthrough
|
||||
case Z_DATA_ERROR:
|
||||
case Z_MEM_ERROR:
|
||||
inflateEnd(&zs);
|
||||
return rc;
|
||||
}
|
||||
have = CHUNK - zs.avail_out;
|
||||
if (write(outfd, outbuf, have) != have) {
|
||||
inflateEnd(&zs);
|
||||
return Z_ERRNO;
|
||||
}
|
||||
} while (!zs.avail_out);
|
||||
} while (rc != Z_STREAM_END);
|
||||
inflateEnd(&zs);
|
||||
return rc == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
|
||||
}
|
||||
|
||||
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:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc;
|
||||
rc = decompressor(0, 1);
|
||||
if (rc == Z_OK) {
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "error: decompressor: %s\n", zerr(rc));
|
||||
return 1;
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/check.h"
|
||||
|
@ -34,6 +35,7 @@
|
|||
#include "libc/sysv/consts/clone.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/sysv/consts/rlimit.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
@ -141,6 +143,14 @@ int Worker(void *id) {
|
|||
char inbuf[1500], outbuf[512], *p, *q;
|
||||
int clientip, client, inmsglen, outmsglen;
|
||||
|
||||
__atomic_load(&closingtime, &itsover, __ATOMIC_SEQ_CST);
|
||||
if (itsover) break;
|
||||
|
||||
if (!IsLinux() &&
|
||||
poll(&(struct pollfd){server, POLLIN}, 1, HEARTBEAT) < 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// wait for client connection
|
||||
clientaddrsize = sizeof(clientaddr);
|
||||
client = accept(server, &clientaddr, &clientaddrsize);
|
||||
|
@ -154,8 +164,6 @@ int Worker(void *id) {
|
|||
// side-effect that the listening socket fails with EAGAIN, every
|
||||
// several seconds. we can use that to our advantage to check for
|
||||
// the ctrl-c shutdown event; otherwise, we retry the accept call
|
||||
__atomic_load(&closingtime, &itsover, __ATOMIC_SEQ_CST);
|
||||
if (itsover) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -274,7 +282,8 @@ int main(int argc, char *argv[]) {
|
|||
__atomic_load(&workers, &haveleft, __ATOMIC_SEQ_CST);
|
||||
if (!haveleft) break;
|
||||
__builtin_ia32_pause();
|
||||
if (usleep(HEARTBEAT * 1000) == -1 && closingtime) {
|
||||
usleep(HEARTBEAT * 1000);
|
||||
if (closingtime) {
|
||||
kprintf("\rgreenbean is shutting down...\n");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue