Files
cKit/Foundation/c_BufferOutputStream.c
T
2026-09-07 21:22:01 +08:00

60 lines
2.4 KiB
C

#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;
}