#include #include #include #include #include #include #define BUF_SIZE 32 int refill_input_buffer(FILE *fp, b_ringbuffer *dest) { while (1) { void *buf; size_t capacity; b_status status = b_ringbuffer_open_write_buffer(dest, &buf, &capacity); if (status == B_ERR_NO_SPACE) { break; } if (!B_OK(status)) { return -1; } size_t r = fread(buf, 1, capacity, fp); b_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, b_ringbuffer *src) { while (1) { const void *buf; size_t capacity; b_status status = b_ringbuffer_open_read_buffer(src, &buf, &capacity); if (status == B_ERR_NO_DATA) { break; } if (!B_OK(status)) { return -1; } size_t w = fwrite(buf, 1, capacity, fp); b_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; } b_compressor_mode mode; if (!strcmp(argv[1], "C")) { mode = B_COMPRESSOR_MODE_COMPRESS; } else if (!strcmp(argv[1], "D")) { mode = B_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; } b_status status = B_SUCCESS; b_type compressor_type = B_TYPE_ZSTD_COMPRESSOR; b_compressor *compressor = b_object_create(compressor_type); size_t inbuf_size, outbuf_size; b_compressor_get_buffer_size( compressor_type, mode, &inbuf_size, &outbuf_size); b_ringbuffer *in = b_ringbuffer_create(inbuf_size); b_ringbuffer *out = b_ringbuffer_create(outbuf_size); if (!in || !out) { fprintf(stderr, "memory allocation failure"); return -1; } b_compressor_set_buffer(compressor, in, out); b_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 (!b_ringbuffer_available_data_remaining(in)) { break; } status = b_compressor_step(compressor); if (status == B_ERR_NO_DATA) { break; } else if (status == B_ERR_NO_SPACE) { ret = flush_output_buffer(out_fp, out); if (ret != 0) { fprintf(stderr, "write error\n"); break; } } else if (!B_OK(status)) { ret = -1; break; } } ret = flush_output_buffer(out_fp, out); if (ret != 0) { fprintf(stderr, "write error\n"); return -1; } if (mode == B_COMPRESSOR_MODE_COMPRESS) { while (!b_compressor_eof(compressor)) { status = b_compressor_end(compressor); if (!B_OK(status)) { fprintf(stderr, "compression finalisation error\n"); return -1; } if (!b_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"); b_compressor_unref(compressor); fclose(in_fp); fclose(out_fp); b_ringbuffer_unref(in); b_ringbuffer_unref(out); return ret; }