InStream/OutStream
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
#include <c_BufferOutputStream.h>
|
||||
|
||||
typedef struct {
|
||||
c_OutStream_t base;
|
||||
char* data;
|
||||
c_size_t capacity;
|
||||
c_size_t size;
|
||||
c_Allocator_t allocator;
|
||||
} c_BufferOutImpl_t;
|
||||
|
||||
static c_err_t _BufferOut_Write(c_OutStream_t* self, const void* buf, c_size_t len, c_size_t* written) {
|
||||
c_BufferOutImpl_t* impl = (c_BufferOutImpl_t*)self;
|
||||
if (impl->size + len > impl->capacity) {
|
||||
c_size_t new_cap = impl->capacity == 0 ? 16 : impl->capacity * 2;
|
||||
while (impl->size + len > new_cap) new_cap *= 2;
|
||||
char* new_data = (char*)c_Allocator_Realloc(&impl->allocator, impl->data, impl->capacity, new_cap);
|
||||
if (!new_data) return C_ERR_NOMEM;
|
||||
impl->data = new_data;
|
||||
impl->capacity = new_cap;
|
||||
}
|
||||
memcpy(impl->data + impl->size, buf, len);
|
||||
impl->size += len;
|
||||
if (written) *written = len;
|
||||
return C_SUCCESS;
|
||||
}
|
||||
|
||||
static c_err_t _BufferOut_Flush(c_OutStream_t* self) { (void)self; return C_SUCCESS; }
|
||||
|
||||
static void _BufferOut_Destroy(c_OutStream_t* self) {
|
||||
c_BufferOutImpl_t* impl = (c_BufferOutImpl_t*)self;
|
||||
c_Allocator_t alloc = impl->allocator;
|
||||
if (impl->data) c_Allocator_Free(&alloc, impl->data);
|
||||
c_Allocator_Free(&alloc, impl);
|
||||
}
|
||||
|
||||
static const c_OutStreamVtbl_t g_BufferOutVtbl = { _BufferOut_Write, _BufferOut_Flush, _BufferOut_Destroy };
|
||||
|
||||
c_err_t c_BufferOutputStream_Create(c_OutStream_t** out_stream, c_size_t initial_capacity, c_Allocator_t* allocator) {
|
||||
if (!out_stream) return C_ERR_PARAM;
|
||||
c_Allocator_t alloc = allocator ? *allocator : c_DefaultAllocator;
|
||||
c_BufferOutImpl_t* impl = (c_BufferOutImpl_t*)c_Allocator_Calloc(&alloc, 1, sizeof(c_BufferOutImpl_t));
|
||||
if (!impl) return C_ERR_NOMEM;
|
||||
impl->base.vtbl = &g_BufferOutVtbl;
|
||||
impl->allocator = alloc;
|
||||
if (initial_capacity > 0) {
|
||||
impl->data = (char*)c_Allocator_Calloc(&impl->allocator, initial_capacity, sizeof(char));
|
||||
if (!impl->data) { c_Allocator_Free(&alloc, impl); return C_ERR_NOMEM; }
|
||||
impl->capacity = initial_capacity;
|
||||
}
|
||||
*out_stream = &impl->base;
|
||||
return C_SUCCESS;
|
||||
}
|
||||
|
||||
c_err_t c_BufferOutputStream_GetBuffer(c_OutStream_t* self, const void** out_ptr, c_size_t* out_len) {
|
||||
if (!self || self->vtbl != &g_BufferOutVtbl || !out_ptr || !out_len) return C_ERR_PARAM;
|
||||
c_BufferOutImpl_t* impl = (c_BufferOutImpl_t*)self;
|
||||
*out_ptr = impl->data;
|
||||
*out_len = impl->size;
|
||||
return C_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user