Affix
view release on metacpan or search on metacpan
infix/src/core/arena.c view on Meta::CPAN
if (next_cap < size + alignment)
next_cap = size + alignment;
block->next_block = infix_arena_create(next_cap);
if (!block->next_block) {
block->error = true;
return nullptr;
}
block = block->next_block;
}
}
/**
* @internal
* @brief Allocates and zero-initializes a block of memory from an arena.
*
* This function is a convenience wrapper around `infix_arena_alloc` that also
* ensures the allocated memory is set to zero, mimicking the behavior of `calloc`.
* It includes a check for integer overflow on the `num * size` calculation and
* will set a detailed error on failure.
*
* @param arena The arena to allocate from.
* @param num The number of elements to allocate.
* @param size The size of each element.
* @param alignment The required alignment for the allocation. Must be a power of two.
* @return A pointer to the zero-initialized memory, or `nullptr` on failure.
*/
INFIX_API c23_nodiscard void * infix_arena_calloc(infix_arena_t * arena, size_t num, size_t size, size_t alignment) {
// Security: Check for multiplication overflow.
if (size > 0 && num > SIZE_MAX / size) {
if (arena)
arena->error = true;
_infix_set_error(INFIX_CATEGORY_GENERAL, INFIX_CODE_INTEGER_OVERFLOW, 0);
return nullptr;
}
size_t total_size = num * size;
void * ptr = infix_arena_alloc(arena, total_size, alignment);
if (ptr != nullptr)
memset(ptr, 0, total_size);
return ptr;
}
/**
* @brief Captures the current allocation state of an arena chain.
*/
INFIX_API c23_nodiscard infix_arena_mark_t infix_arena_get_mark(infix_arena_t * arena) {
infix_arena_mark_t mark = {nullptr, 0};
if (arena == nullptr)
return mark;
infix_arena_t * current = arena;
while (current->next_block != nullptr && current->next_block->current_offset > 0)
current = current->next_block;
mark.block = current;
mark.offset = current->current_offset;
return mark;
}
/**
* @brief Rewinds an arena chain back to a previously captured mark,
* resetting all secondary blocks for immediate reuse.
*/
INFIX_API void infix_arena_rewind(infix_arena_t * arena, infix_arena_mark_t mark) {
if (arena == nullptr || mark.block == nullptr)
return;
// Reset offset in the marked block
mark.block->current_offset = mark.offset;
mark.block->error = false;
// Reset offsets in all subsequent blocks so they can be reused
infix_arena_t * current = mark.block->next_block;
while (current != nullptr) {
current->current_offset = 0;
current->error = false;
current = current->next_block;
}
}
( run in 0.627 second using v1.01-cache-2.11-cpan-d01c6094234 )