#include #include #include #include #include #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)