Files
bluelib/compress/compressor.c

144 lines
3.0 KiB
C

#include "compressor.h"
#include "function.h"
#include <blue/compress/compressor.h>
#include <blue/core/ringbuffer.h>
#include <stdlib.h>
#include <string.h>
enum b_status b_compressor_create(
const struct b_compression_function *func, enum b_compression_mode mode,
struct b_ringbuffer *inbuf, struct b_ringbuffer *outbuf,
struct b_compressor **out)
{
size_t ctx_size = sizeof(struct b_compressor) + func->f_ctx_size;
struct b_compressor *compressor = malloc(ctx_size);
if (!compressor) {
return B_ERR_NO_MEMORY;
}
memset(compressor, 0x0, ctx_size);
compressor->c_func = func;
compressor->c_in = inbuf;
compressor->c_out = outbuf;
compressor->c_mode = mode;
enum b_status status = B_SUCCESS;
if (func->f_init) {
status = func->f_init(compressor);
}
if (!B_OK(status)) {
free(compressor);
compressor = NULL;
}
*out = compressor;
return status;
}
enum b_status b_compressor_destroy(struct b_compressor *compressor)
{
enum b_status status = B_SUCCESS;
if (compressor->c_func->f_fini) {
status = compressor->c_func->f_fini(compressor);
}
if (!B_OK(status)) {
return status;
}
free(compressor);
return B_SUCCESS;
}
static enum b_status compress(struct b_compressor *compressor)
{
if (compressor->c_mode != B_COMPRESSION_MODE_COMPRESS) {
return B_ERR_BAD_STATE;
}
if (!compressor->c_func->f_compress) {
return B_ERR_NOT_SUPPORTED;
}
return compressor->c_func->f_compress(compressor);
}
static enum b_status decompress(struct b_compressor *compressor)
{
if (compressor->c_mode != B_COMPRESSION_MODE_DECOMPRESS) {
return B_ERR_BAD_STATE;
}
if (!compressor->c_func->f_decompress) {
return B_ERR_NOT_SUPPORTED;
}
return compressor->c_func->f_decompress(compressor);
}
enum b_status b_compressor_step(struct b_compressor *compressor)
{
switch (compressor->c_mode) {
case B_COMPRESSION_MODE_COMPRESS:
return compress(compressor);
case B_COMPRESSION_MODE_DECOMPRESS:
return decompress(compressor);
default:
return B_ERR_BAD_STATE;
}
}
enum b_status b_compressor_end(struct b_compressor *compressor)
{
if (compressor->c_mode != B_COMPRESSION_MODE_COMPRESS) {
return B_SUCCESS;
}
if (!compressor->c_func->f_compress_end) {
return B_ERR_NOT_SUPPORTED;
}
while (b_ringbuffer_available_data_remaining(compressor->c_in)) {
if (!b_ringbuffer_write_capacity_remaining(compressor->c_out)) {
return B_ERR_NO_SPACE;
}
enum b_status status = b_compressor_step(compressor);
if (!B_OK(status)) {
return status;
}
}
return compressor->c_func->f_compress_end(compressor);
}
enum b_status b_compressor_reset(struct b_compressor *compressor)
{
compressor->c_flags &= ~COMPRESSOR_EOF;
if (compressor->c_func->f_reset) {
return compressor->c_func->f_reset(compressor);
}
return B_SUCCESS;
}
bool b_compressor_eof(const struct b_compressor *compressor)
{
return (compressor->c_flags & COMPRESSOR_EOF) != 0;
}
void *b_compressor_get_function_ctx(struct b_compressor *compressor)
{
unsigned char *p = (unsigned char *)compressor;
p += sizeof *compressor;
return p;
}