2025-07-30 18:33:33 +01:00
|
|
|
#include <assert.h>
|
2026-05-05 21:17:21 +01:00
|
|
|
#include <fx/compression/compressor.h>
|
|
|
|
|
#include <fx/compression/cstream.h>
|
|
|
|
|
#include <fx/compression/zstd.h>
|
|
|
|
|
#include <fx/ringbuffer.h>
|
|
|
|
|
#include <fx/stream.h>
|
2025-07-30 18:33:33 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#define BUF_SIZE 32
|
|
|
|
|
|
2026-05-05 19:03:22 +01:00
|
|
|
static int compress(fx_type_id compressor_type, FILE *in, FILE *out)
|
2025-07-30 18:33:33 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_stream *out_stream = fx_stream_open_fp(out);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream *cstream;
|
|
|
|
|
fx_status status = fx_cstream_open(
|
2026-05-05 21:17:21 +01:00
|
|
|
out_stream,
|
|
|
|
|
compressor_type,
|
|
|
|
|
FX_COMPRESSOR_MODE_COMPRESS,
|
|
|
|
|
&cstream);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
if (!FX_OK(status)) {
|
2025-07-30 18:33:33 +01:00
|
|
|
fprintf(stderr, "cannot initialise compressor\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream_begin_compressed_section(cstream, NULL);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
|
|
|
|
char buf[4096];
|
|
|
|
|
while (1) {
|
|
|
|
|
size_t r = fread(buf, 1, sizeof buf, in);
|
|
|
|
|
|
|
|
|
|
size_t w = 0;
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream_write(cstream, buf, r, &w);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
|
|
|
|
if (r != w) {
|
|
|
|
|
fprintf(stderr, "write error\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r < sizeof buf) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream_end_compressed_section(cstream, NULL, NULL);
|
|
|
|
|
fx_cstream_unref(cstream);
|
|
|
|
|
fx_stream_unref(out_stream);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-05 19:03:22 +01:00
|
|
|
static int decompress(fx_type_id compressor_type, FILE *in, FILE *out)
|
2025-07-30 18:33:33 +01:00
|
|
|
{
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_stream *in_stream = fx_stream_open_fp(in);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream *cstream;
|
|
|
|
|
fx_status status = fx_cstream_open(
|
2026-05-05 21:17:21 +01:00
|
|
|
in_stream,
|
|
|
|
|
compressor_type,
|
|
|
|
|
FX_COMPRESSOR_MODE_DECOMPRESS,
|
|
|
|
|
&cstream);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
if (!FX_OK(status)) {
|
2025-07-30 18:33:33 +01:00
|
|
|
fprintf(stderr, "cannot initialise compressor\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream_begin_compressed_section(cstream, NULL);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
|
|
|
|
char buf[4096];
|
|
|
|
|
while (1) {
|
|
|
|
|
size_t r = 0;
|
2026-05-05 21:17:21 +01:00
|
|
|
fx_status status = fx_cstream_read(
|
|
|
|
|
cstream,
|
|
|
|
|
buf,
|
|
|
|
|
sizeof buf,
|
|
|
|
|
&r);
|
2026-03-16 10:35:43 +00:00
|
|
|
if (!FX_OK(status)) {
|
2026-05-05 21:17:21 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"read error: %s\n",
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_status_description(status));
|
2025-07-30 18:33:33 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t w = fwrite(buf, 1, r, out);
|
|
|
|
|
if (r != w) {
|
|
|
|
|
fprintf(stderr, "write error\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (r < sizeof buf) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_cstream_end_compressed_section(cstream, NULL, NULL);
|
|
|
|
|
fx_cstream_unref(cstream);
|
|
|
|
|
fx_stream_unref(in_stream);
|
2025-07-30 18:33:33 +01:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char **argv)
|
|
|
|
|
{
|
|
|
|
|
if (argc < 4) {
|
2026-05-05 21:17:21 +01:00
|
|
|
fprintf(stderr,
|
|
|
|
|
"usage: %s <C/D> <inpath> <outpath>\n",
|
|
|
|
|
argv[0]);
|
2025-07-30 18:33:33 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-16 10:35:43 +00:00
|
|
|
fx_compressor_mode mode;
|
2025-07-30 18:33:33 +01:00
|
|
|
if (!strcmp(argv[1], "C")) {
|
2026-03-16 10:35:43 +00:00
|
|
|
mode = FX_COMPRESSOR_MODE_COMPRESS;
|
2025-07-30 18:33:33 +01:00
|
|
|
} else if (!strcmp(argv[1], "D")) {
|
2026-03-16 10:35:43 +00:00
|
|
|
mode = FX_COMPRESSOR_MODE_DECOMPRESS;
|
2025-07-30 18:33:33 +01:00
|
|
|
} else {
|
|
|
|
|
fprintf(stderr, "invalid mode %s\n", argv[1]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *in_fp = fopen(argv[2], "rb");
|
|
|
|
|
if (!in_fp) {
|
|
|
|
|
fprintf(stderr, "cannot open input file %s\n", argv[2]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FILE *out_fp = fopen(argv[3], "wb");
|
|
|
|
|
if (!out_fp) {
|
|
|
|
|
fclose(in_fp);
|
|
|
|
|
fprintf(stderr, "cannot open output file %s\n", argv[3]);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int ret = 0;
|
|
|
|
|
switch (mode) {
|
2026-03-16 10:35:43 +00:00
|
|
|
case FX_COMPRESSOR_MODE_COMPRESS:
|
|
|
|
|
ret = compress(FX_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
|
2025-07-30 18:33:33 +01:00
|
|
|
break;
|
2026-03-16 10:35:43 +00:00
|
|
|
case FX_COMPRESSOR_MODE_DECOMPRESS:
|
|
|
|
|
ret = decompress(FX_TYPE_ZSTD_COMPRESSOR, in_fp, out_fp);
|
2025-07-30 18:33:33 +01:00
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ret = -1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("Done\n");
|
|
|
|
|
|
|
|
|
|
fclose(in_fp);
|
|
|
|
|
fclose(out_fp);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|