#include #include #include #include #include #define COMPRESSOR_DISPATCH_STATIC(func, compressor, ...) \ do { \ struct compressor_data _compressor; \ enum b_status status \ = compressor_get_data(compressor, &_compressor); \ if (!B_OK(status)) { \ return status; \ } \ return func(&_compressor, __VA_ARGS__); \ } while (0) #define COMPRESSOR_DISPATCH_STATIC_0(func, compressor) \ do { \ struct compressor_data _compressor; \ enum b_status status \ = compressor_get_data(compressor, &_compressor); \ if (!B_OK(status)) { \ return status; \ } \ return func(&_compressor); \ } while (0) /*** PRIVATE DATA *************************************************************/ struct compressor_data { b_compressor *c_obj; b_compressor_class *c_ops; b_compressor_data *c_data; }; /*** PRIVATE FUNCTIONS ********************************************************/ static enum b_status compressor_get_data( b_compressor *compressor, struct compressor_data *out) { out->c_obj = compressor; return b_object_get_data( compressor, B_TYPE_COMPRESSOR, NULL, (void **)&out->c_data, (void **)&out->c_ops); } static enum b_status compressor_get_mode( struct compressor_data *p, enum b_compressor_mode *out) { if (out) { *out = p->c_data->c_mode; } return B_SUCCESS; } static enum b_status compressor_set_mode( struct compressor_data *p, enum b_compressor_mode mode) { if (!p->c_ops->c_set_mode) { return B_ERR_NOT_SUPPORTED; } return p->c_ops->c_set_mode(p->c_obj, mode); } static enum b_status compressor_set_buffer( struct compressor_data *p, b_ringbuffer *inbuf, b_ringbuffer *outbuf) { p->c_data->c_in = inbuf; p->c_data->c_out = outbuf; return B_SUCCESS; } static enum b_status compress(struct compressor_data *p) { if (p->c_data->c_mode != B_COMPRESSOR_MODE_COMPRESS) { return B_ERR_BAD_STATE; } if (!p->c_ops->c_compress) { return B_ERR_NOT_SUPPORTED; } return p->c_ops->c_compress(p->c_obj); } static enum b_status decompress(struct compressor_data *p) { if (p->c_data->c_mode != B_COMPRESSOR_MODE_DECOMPRESS) { return B_ERR_BAD_STATE; } if (!p->c_ops->c_decompress) { return B_ERR_NOT_SUPPORTED; } return p->c_ops->c_decompress(p->c_obj); } static enum b_status compressor_step(struct compressor_data *p) { switch (p->c_data->c_mode) { case B_COMPRESSOR_MODE_COMPRESS: return compress(p); case B_COMPRESSOR_MODE_DECOMPRESS: return decompress(p); default: return B_ERR_BAD_STATE; } } static enum b_status compressor_end(struct compressor_data *p) { if (p->c_data->c_mode != B_COMPRESSOR_MODE_COMPRESS) { return B_SUCCESS; } if (!p->c_ops->c_compress_end) { return B_ERR_NOT_SUPPORTED; } while (b_ringbuffer_available_data_remaining(p->c_data->c_in)) { if (!b_ringbuffer_write_capacity_remaining(p->c_data->c_out)) { return B_ERR_NO_SPACE; } enum b_status status = compressor_step(p); if (!B_OK(status)) { return status; } } return p->c_ops->c_compress_end(p->c_obj); } static enum b_status compressor_reset(struct compressor_data *p) { p->c_data->c_flags &= ~B_COMPRESSOR_EOF; if (p->c_ops->c_reset) { return p->c_ops->c_reset(p->c_obj); } return B_SUCCESS; } static bool compressor_eof(const struct compressor_data *p) { return (p->c_data->c_flags & B_COMPRESSOR_EOF) != 0; } /*** PUBLIC FUNCTIONS *********************************************************/ enum b_status b_compressor_get_buffer_size( b_type type, b_compressor_mode mode, size_t *inbuf_size, size_t *outbuf_size) { b_class *c = b_class_get(type); if (!c) { return B_ERR_INVALID_ARGUMENT; } b_compressor_class *ops = b_class_get_interface(c, B_TYPE_COMPRESSOR); if (!ops) { return B_ERR_INVALID_ARGUMENT; } if (!ops->c_buffer_size) { return B_ERR_NOT_SUPPORTED; } return ops->c_buffer_size(mode, inbuf_size, outbuf_size); } enum b_status b_compressor_get_mode( const b_compressor *compressor, enum b_compressor_mode *out) { COMPRESSOR_DISPATCH_STATIC( compressor_get_mode, (b_compressor *)compressor, out); } enum b_status b_compressor_set_mode( b_compressor *compressor, enum b_compressor_mode mode) { COMPRESSOR_DISPATCH_STATIC(compressor_set_mode, compressor, mode); } enum b_status b_compressor_set_buffer( b_compressor *compressor, b_ringbuffer *inbuf, b_ringbuffer *outbuf) { COMPRESSOR_DISPATCH_STATIC(compressor_set_buffer, compressor, inbuf, outbuf); } enum b_status b_compressor_step(b_compressor *compressor) { COMPRESSOR_DISPATCH_STATIC_0(compressor_step, compressor); } enum b_status b_compressor_end(b_compressor *compressor) { COMPRESSOR_DISPATCH_STATIC_0(compressor_end, compressor); } enum b_status b_compressor_reset(b_compressor *compressor) { COMPRESSOR_DISPATCH_STATIC_0(compressor_reset, compressor); } bool b_compressor_eof(const b_compressor *compressor) { COMPRESSOR_DISPATCH_STATIC_0(compressor_eof, (b_compressor *)compressor); } /*** VIRTUAL FUNCTIONS ********************************************************/ static void compressor_init(b_object *obj, void *priv) { } static void compressor_fini(b_object *obj, void *priv) { } /*** CLASS DEFINITION *********************************************************/ B_TYPE_CLASS_DEFINITION_BEGIN(b_compressor) B_TYPE_CLASS_INTERFACE_BEGIN(b_object, B_TYPE_OBJECT) B_INTERFACE_ENTRY(to_string) = NULL; B_TYPE_CLASS_INTERFACE_END(b_object, B_TYPE_OBJECT) B_TYPE_CLASS_DEFINITION_END(b_compressor) B_TYPE_DEFINITION_BEGIN(b_compressor) B_TYPE_ID(0x452ee0f9, 0xfe12, 0x48a1, 0xb596, 0xad5b7a3940e7); B_TYPE_CLASS(b_compressor_class); B_TYPE_INSTANCE_PROTECTED(b_compressor_data); B_TYPE_INSTANCE_INIT(compressor_init); B_TYPE_INSTANCE_FINI(compressor_fini); B_TYPE_DEFINITION_END(b_compressor)