#include #include #include #include #include #include #define BUF_SIZE 32 int refill_input_buffer(FILE *fp, fx_ringbuffer *dest) { while (1) { void *buf; size_t capacity; fx_status status = fx_ringbuffer_open_write_buffer(dest, &buf, &capacity); if (status == FX_ERR_NO_SPACE) { break; } if (!FX_OK(status)) { return -1; } size_t r = fread(buf, 1, capacity, fp); fx_ringbuffer_close_write_buffer(dest, &buf, r); if (r == 0) { return ferror(fp) ? -1 : 0; } if (r < capacity) { break; } } return 0; } int flush_output_buffer(FILE *fp, fx_ringbuffer *src) { while (1) { const void *buf; size_t capacity; fx_status status = fx_ringbuffer_open_read_buffer(src, &buf, &capacity); if (status == FX_ERR_NO_DATA) { break; } if (!FX_OK(status)) { return -1; } size_t w = fwrite(buf, 1, capacity, fp); fx_ringbuffer_close_read_buffer(src, &buf, w); if (w < capacity) { return -1; } } return 0; } int main(int argc, const char **argv) { if (argc < 4) { fprintf(stderr, "usage: %s \n", argv[0]); return -1; } fx_compressor_mode mode; if (!strcmp(argv[1], "C")) { mode = FX_COMPRESSOR_MODE_COMPRESS; } else if (!strcmp(argv[1], "D")) { mode = FX_COMPRESSOR_MODE_DECOMPRESS; } 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; } fx_status status = FX_SUCCESS; fx_type compressor_type = FX_TYPE_ZSTD_COMPRESSOR; fx_compressor *compressor = fx_object_create(compressor_type); size_t inbuf_size, outbuf_size; fx_compressor_get_buffer_size( compressor_type, mode, &inbuf_size, &outbuf_size); fx_ringbuffer *in = fx_ringbuffer_create(inbuf_size); fx_ringbuffer *out = fx_ringbuffer_create(outbuf_size); if (!in || !out) { fprintf(stderr, "memory allocation failure"); return -1; } fx_compressor_set_buffer(compressor, in, out); fx_compressor_set_mode(compressor, mode); int ret = 0; while (1) { ret = refill_input_buffer(in_fp, in); if (ret != 0) { fprintf(stderr, "read error\n"); break; } if (!fx_ringbuffer_available_data_remaining(in)) { break; } status = fx_compressor_step(compressor); if (status == FX_ERR_NO_DATA) { break; } else if (status == FX_ERR_NO_SPACE) { ret = flush_output_buffer(out_fp, out); if (ret != 0) { fprintf(stderr, "write error\n"); break; } } else if (!FX_OK(status)) { ret = -1; break; } } ret = flush_output_buffer(out_fp, out); if (ret != 0) { fprintf(stderr, "write error\n"); return -1; } if (mode == FX_COMPRESSOR_MODE_COMPRESS) { while (!fx_compressor_eof(compressor)) { status = fx_compressor_end(compressor); if (!FX_OK(status)) { fprintf(stderr, "compression finalisation error\n"); return -1; } if (!fx_ringbuffer_available_data_remaining(out)) { break; } ret = flush_output_buffer(out_fp, out); if (ret != 0) { fprintf(stderr, "write error\n"); return -1; } } } printf("Done\n"); fx_compressor_unref(compressor); fclose(in_fp); fclose(out_fp); fx_ringbuffer_unref(in); fx_ringbuffer_unref(out); return ret; }