#include typedef struct { c_InStream_t base; const char* data; c_size_t size; c_size_t ptr; c_Allocator_t allocator; } c_BufferInImpl_t; static c_err_t _BufferIn_Read(c_InStream_t* self, void* buf, c_size_t len, c_size_t* bytes_read) { c_BufferInImpl_t* impl = (c_BufferInImpl_t*)self; if (!buf || len == 0) return C_ERR_PARAM; if (impl->ptr >= impl->size) { if (bytes_read) *bytes_read = 0; return C_ERR_OUTOFBOUND; } c_size_t available = impl->size - impl->ptr; c_size_t to_copy = (len < available) ? len : available; memcpy(buf, impl->data + impl->ptr, to_copy); impl->ptr += to_copy; if (bytes_read) *bytes_read = to_copy; return (to_copy == len) ? C_SUCCESS : C_ERR_OUTOFBOUND; } static void _BufferIn_Destroy(c_InStream_t* self) { c_BufferInImpl_t* impl = (c_BufferInImpl_t*)self; c_Allocator_t alloc = impl->allocator; c_Allocator_Free(&alloc, impl); } static const c_InStreamVtbl_t g_BufferInVtbl = { _BufferIn_Read, _BufferIn_Destroy }; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ c_err_t c_BufferInputStream_Create(c_InStream_t** out_stream, const void* buffer_ptr, c_size_t buffer_len, c_Allocator_t* allocator) { if (!out_stream || !buffer_ptr || buffer_len == 0) return C_ERR_PARAM; c_Allocator_t alloc = allocator ? *allocator : c_DefaultAllocator; c_BufferInImpl_t* impl = (c_BufferInImpl_t*)c_Allocator_Calloc(&alloc, 1, sizeof(c_BufferInImpl_t)); if (!impl) return C_ERR_NOMEM; impl->base.vtbl = &g_BufferInVtbl; impl->data = (const char*)buffer_ptr; impl->size = buffer_len; impl->ptr = 0; impl->allocator = alloc; *out_stream = &impl->base; return C_SUCCESS; }