146 lines
3.1 KiB
C
146 lines
3.1 KiB
C
#include "compressor.h"
|
|
|
|
#include "function.h"
|
|
|
|
#include <assert.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)
|
|
{
|
|
assert(compressor->c_func->f_buffer_size > 0);
|
|
unsigned char *p = (unsigned char *)compressor;
|
|
p += sizeof *compressor;
|
|
return p;
|
|
}
|