240 lines
6.4 KiB
C
240 lines
6.4 KiB
C
#include <assert.h>
|
|
#include <fx/compress/compressor.h>
|
|
#include <fx/core/ringbuffer.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define COMPRESSOR_DISPATCH_STATIC(func, compressor, ...) \
|
|
do { \
|
|
struct compressor_data _compressor; \
|
|
enum fx_status status \
|
|
= compressor_get_data(compressor, &_compressor); \
|
|
if (!FX_OK(status)) { \
|
|
return status; \
|
|
} \
|
|
return func(&_compressor, __VA_ARGS__); \
|
|
} while (0)
|
|
#define COMPRESSOR_DISPATCH_STATIC_0(func, compressor) \
|
|
do { \
|
|
struct compressor_data _compressor; \
|
|
enum fx_status status \
|
|
= compressor_get_data(compressor, &_compressor); \
|
|
if (!FX_OK(status)) { \
|
|
return status; \
|
|
} \
|
|
return func(&_compressor); \
|
|
} while (0)
|
|
|
|
/*** PRIVATE DATA *************************************************************/
|
|
|
|
struct compressor_data {
|
|
fx_compressor *c_obj;
|
|
fx_compressor_class *c_ops;
|
|
fx_compressor_data *c_data;
|
|
};
|
|
|
|
/*** PRIVATE FUNCTIONS ********************************************************/
|
|
|
|
static enum fx_status compressor_get_data(
|
|
fx_compressor *compressor, struct compressor_data *out)
|
|
{
|
|
out->c_obj = compressor;
|
|
return fx_object_get_data(
|
|
compressor, FX_TYPE_COMPRESSOR, NULL, (void **)&out->c_data,
|
|
(void **)&out->c_ops);
|
|
}
|
|
|
|
static enum fx_status compressor_get_mode(
|
|
struct compressor_data *p, enum fx_compressor_mode *out)
|
|
{
|
|
if (out) {
|
|
*out = p->c_data->c_mode;
|
|
}
|
|
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static enum fx_status compressor_set_mode(
|
|
struct compressor_data *p, enum fx_compressor_mode mode)
|
|
{
|
|
if (!p->c_ops->c_set_mode) {
|
|
return FX_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
return p->c_ops->c_set_mode(p->c_obj, mode);
|
|
}
|
|
|
|
static enum fx_status compressor_set_buffer(
|
|
struct compressor_data *p, fx_ringbuffer *inbuf, fx_ringbuffer *outbuf)
|
|
{
|
|
p->c_data->c_in = inbuf;
|
|
p->c_data->c_out = outbuf;
|
|
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static enum fx_status compress(struct compressor_data *p)
|
|
{
|
|
if (p->c_data->c_mode != FX_COMPRESSOR_MODE_COMPRESS) {
|
|
return FX_ERR_BAD_STATE;
|
|
}
|
|
|
|
if (!p->c_ops->c_compress) {
|
|
return FX_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
return p->c_ops->c_compress(p->c_obj);
|
|
}
|
|
|
|
static enum fx_status decompress(struct compressor_data *p)
|
|
{
|
|
if (p->c_data->c_mode != FX_COMPRESSOR_MODE_DECOMPRESS) {
|
|
return FX_ERR_BAD_STATE;
|
|
}
|
|
|
|
if (!p->c_ops->c_decompress) {
|
|
return FX_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
return p->c_ops->c_decompress(p->c_obj);
|
|
}
|
|
|
|
static enum fx_status compressor_step(struct compressor_data *p)
|
|
{
|
|
switch (p->c_data->c_mode) {
|
|
case FX_COMPRESSOR_MODE_COMPRESS:
|
|
return compress(p);
|
|
case FX_COMPRESSOR_MODE_DECOMPRESS:
|
|
return decompress(p);
|
|
default:
|
|
return FX_ERR_BAD_STATE;
|
|
}
|
|
}
|
|
|
|
static enum fx_status compressor_end(struct compressor_data *p)
|
|
{
|
|
if (p->c_data->c_mode != FX_COMPRESSOR_MODE_COMPRESS) {
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
if (!p->c_ops->c_compress_end) {
|
|
return FX_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
while (fx_ringbuffer_available_data_remaining(p->c_data->c_in)) {
|
|
if (!fx_ringbuffer_write_capacity_remaining(p->c_data->c_out)) {
|
|
return FX_ERR_NO_SPACE;
|
|
}
|
|
|
|
enum fx_status status = compressor_step(p);
|
|
if (!FX_OK(status)) {
|
|
return status;
|
|
}
|
|
}
|
|
|
|
return p->c_ops->c_compress_end(p->c_obj);
|
|
}
|
|
|
|
static enum fx_status compressor_reset(struct compressor_data *p)
|
|
{
|
|
p->c_data->c_flags &= ~FX_COMPRESSOR_EOF;
|
|
|
|
if (p->c_ops->c_reset) {
|
|
return p->c_ops->c_reset(p->c_obj);
|
|
}
|
|
|
|
return FX_SUCCESS;
|
|
}
|
|
|
|
static bool compressor_eof(const struct compressor_data *p)
|
|
{
|
|
return (p->c_data->c_flags & FX_COMPRESSOR_EOF) != 0;
|
|
}
|
|
|
|
/*** PUBLIC FUNCTIONS *********************************************************/
|
|
|
|
enum fx_status fx_compressor_get_buffer_size(
|
|
fx_type type, fx_compressor_mode mode, size_t *inbuf_size, size_t *outbuf_size)
|
|
{
|
|
fx_class *c = fx_class_get(type);
|
|
if (!c) {
|
|
return FX_ERR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
fx_compressor_class *ops = fx_class_get_interface(c, FX_TYPE_COMPRESSOR);
|
|
if (!ops) {
|
|
return FX_ERR_INVALID_ARGUMENT;
|
|
}
|
|
|
|
if (!ops->c_buffer_size) {
|
|
return FX_ERR_NOT_SUPPORTED;
|
|
}
|
|
|
|
return ops->c_buffer_size(mode, inbuf_size, outbuf_size);
|
|
}
|
|
|
|
enum fx_status fx_compressor_get_mode(
|
|
const fx_compressor *compressor, enum fx_compressor_mode *out)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC(
|
|
compressor_get_mode, (fx_compressor *)compressor, out);
|
|
}
|
|
|
|
enum fx_status fx_compressor_set_mode(
|
|
fx_compressor *compressor, enum fx_compressor_mode mode)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC(compressor_set_mode, compressor, mode);
|
|
}
|
|
|
|
enum fx_status fx_compressor_set_buffer(
|
|
fx_compressor *compressor, fx_ringbuffer *inbuf, fx_ringbuffer *outbuf)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC(compressor_set_buffer, compressor, inbuf, outbuf);
|
|
}
|
|
|
|
enum fx_status fx_compressor_step(fx_compressor *compressor)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC_0(compressor_step, compressor);
|
|
}
|
|
|
|
enum fx_status fx_compressor_end(fx_compressor *compressor)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC_0(compressor_end, compressor);
|
|
}
|
|
|
|
enum fx_status fx_compressor_reset(fx_compressor *compressor)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC_0(compressor_reset, compressor);
|
|
}
|
|
|
|
bool fx_compressor_eof(const fx_compressor *compressor)
|
|
{
|
|
COMPRESSOR_DISPATCH_STATIC_0(compressor_eof, (fx_compressor *)compressor);
|
|
}
|
|
|
|
/*** VIRTUAL FUNCTIONS ********************************************************/
|
|
|
|
static void compressor_init(fx_object *obj, void *priv)
|
|
{
|
|
}
|
|
|
|
static void compressor_fini(fx_object *obj, void *priv)
|
|
{
|
|
}
|
|
|
|
/*** CLASS DEFINITION *********************************************************/
|
|
|
|
FX_TYPE_CLASS_DEFINITION_BEGIN(fx_compressor)
|
|
FX_TYPE_CLASS_INTERFACE_BEGIN(fx_object, FX_TYPE_OBJECT)
|
|
FX_INTERFACE_ENTRY(to_string) = NULL;
|
|
FX_TYPE_CLASS_INTERFACE_END(fx_object, FX_TYPE_OBJECT)
|
|
FX_TYPE_CLASS_DEFINITION_END(fx_compressor)
|
|
|
|
FX_TYPE_DEFINITION_BEGIN(fx_compressor)
|
|
FX_TYPE_ID(0x452ee0f9, 0xfe12, 0x48a1, 0xb596, 0xad5b7a3940e7);
|
|
FX_TYPE_CLASS(fx_compressor_class);
|
|
FX_TYPE_INSTANCE_PROTECTED(fx_compressor_data);
|
|
FX_TYPE_INSTANCE_INIT(compressor_init);
|
|
FX_TYPE_INSTANCE_FINI(compressor_fini);
|
|
FX_TYPE_DEFINITION_END(fx_compressor)
|