24 ws->
data = (uint8_t*)data;
25 ws->
cap = (data ==
nullptr) ? 0U : cap;
32 if ((ws ==
nullptr) || (ws->
data ==
nullptr) || (bytes == 0U) || (alignment == 0U) ||
33 ((alignment & (alignment - 1U)) != 0U)) {
36 const size_t mask = alignment - 1U;
38 static_assert(
sizeof(base) >=
sizeof(ws->
data),
"uintptr_t must preserve object pointers");
39 (void)
memcpy((
void*)&base, (
const void*)&ws->
data,
sizeof(ws->
data));
40 if ((ws->
used > (
size_t)(UINTPTR_MAX - base)) ||
41 ((base + (uintptr_t)ws->
used) > (UINTPTR_MAX - (uintptr_t)mask))) {
44 const uintptr_t cursor = base + (uintptr_t)ws->
used;
45 const uintptr_t aligned = (cursor + (uintptr_t)mask) & ~(uintptr_t)mask;
46 const size_t start = (size_t)(aligned - base);
47 if ((start > ws->
cap) || (bytes > (ws->
cap - start))) {
50 ws->
used = start + bytes;
54 return &ws->
data[start];
Package a downloaded chapter folder into a reader-openable container.
struct mdl_export_workspace mdl_export_workspace_t
Caller-owned bounded arena for all exporter scratch state.
void * mdl_export_workspace_take(mdl_export_workspace_t *ws, size_t bytes, size_t alignment)
Reserve aligned bytes from an exporter arena.
void mdl_export_workspace_init(mdl_export_workspace_t *ws, void *data, size_t cap)
Bind an exporter arena without allocating memory.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
size_t high_water
Largest used value observed.
size_t used
Current allocation high edge.
size_t cap
Total arena capacity.
uint8_t * data
Writable arena bytes.