resizable: Replace grow_cap function
This replaces the grow_cap function with the ensure_cap family of functions, as they actually do what you want: You'll likely not want to blindly increase the capacity of a growable, but you want to make sure that the capacity is large enough to hold the elements you're about to insert.
This commit is contained in:
parent
eea7e8f840
commit
80ad5c979d
3 changed files with 26 additions and 21 deletions
12
src/parser.c
12
src/parser.c
|
|
@ -79,9 +79,11 @@ static enum parse_fragment_result parse_fragment(apfl_parser_ptr, struct fragmen
|
|||
static bool
|
||||
grow_fragment_cap(struct fragment_list *list, size_t inc)
|
||||
{
|
||||
return apfl_resizable_grow_cap(
|
||||
return apfl_resizable_ensure_cap_for_more_elements(
|
||||
sizeof(struct fragment),
|
||||
APFL_RESIZABLE_ARGS(*list, children),
|
||||
(void **)&list->children,
|
||||
list->len,
|
||||
&list->cap,
|
||||
inc
|
||||
);
|
||||
}
|
||||
|
|
@ -1536,9 +1538,11 @@ break_inner:
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (!apfl_resizable_grow_cap(
|
||||
if (!apfl_resizable_ensure_cap_for_more_elements(
|
||||
sizeof(struct partial_assignment),
|
||||
APFL_RESIZABLE_ARGS(partial_assignments, items),
|
||||
(void **)&partial_assignments.items,
|
||||
partial_assignments.len,
|
||||
&partial_assignments.cap,
|
||||
1
|
||||
)) {
|
||||
p->error = apfl_error_simple(APFL_ERR_MALLOC_FAILED);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ apfl_resizable_resize(size_t elem_size, void **mem, size_t *len, size_t *cap, si
|
|||
|
||||
assert(newlen >= *cap);
|
||||
|
||||
if (!apfl_resizable_grow_cap(elem_size, mem, len, cap, newlen - *cap)) {
|
||||
if (!apfl_resizable_ensure_cap(elem_size, mem, cap, newlen)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -34,37 +34,36 @@ apfl_resizable_resize(size_t elem_size, void **mem, size_t *len, size_t *cap, si
|
|||
}
|
||||
|
||||
bool
|
||||
apfl_resizable_grow_cap(size_t elem_size, void **mem, size_t *len, size_t *cap, size_t inc_cap)
|
||||
apfl_resizable_ensure_cap(size_t elem_size, void **mem, size_t *cap, size_t want_cap)
|
||||
{
|
||||
(void)len;// \mystuff\TODO:better not even have the arg
|
||||
|
||||
if (inc_cap == 0) {
|
||||
if (want_cap <= *cap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t newcap = *cap + inc_cap;
|
||||
|
||||
// TODO: We currently simply grow the memory to have space for exactly
|
||||
// inc_cap more elements. It would probably be smarter to grow the
|
||||
// memory a bit larger to reduce calls to realloc.
|
||||
void *newmem = realloc(*mem, newcap * elem_size);
|
||||
// want_cap elements. It would probably be smarter to grow the memory
|
||||
// a bit larger to reduce calls to realloc.
|
||||
void *newmem = realloc(*mem, want_cap * elem_size);
|
||||
if (newmem == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*mem = newmem;
|
||||
*cap = newcap;
|
||||
*cap = want_cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
apfl_resizable_ensure_cap_for_more_elements(size_t elem_size, void **mem, size_t len, size_t *cap, size_t more_elements)
|
||||
{
|
||||
return apfl_resizable_ensure_cap(elem_size, mem, cap, len + more_elements); // TODO: What if len + more_elements overflows?
|
||||
}
|
||||
|
||||
bool
|
||||
apfl_resizable_append(size_t elem_size, void **mem, size_t *len, size_t *cap, const void *other_mem, size_t other_len)
|
||||
{
|
||||
size_t newlen = *len + other_len;
|
||||
if (newlen > *cap) {
|
||||
if (!apfl_resizable_grow_cap(elem_size, mem, len, cap, newlen - *cap)) {
|
||||
return false;
|
||||
}
|
||||
if (!apfl_resizable_ensure_cap_for_more_elements(elem_size, mem, *len, cap, other_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(*((char**)mem) + (elem_size * *len), other_mem, other_len * elem_size);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@ void apfl_resizable_init(void **mem, size_t *len, size_t *cap);
|
|||
|
||||
bool apfl_resizable_resize(size_t elem_size, void **mem, size_t *len, size_t *cap, size_t newlen);
|
||||
|
||||
bool apfl_resizable_grow_cap(size_t elem_size, void **mem, size_t *len, size_t *cap, size_t inc_cap);
|
||||
bool apfl_resizable_ensure_cap(size_t elem_size, void **mem, size_t *cap, size_t want_cap);
|
||||
bool apfl_resizable_ensure_cap_for_more_elements(size_t elem_size, void **mem, size_t len, size_t *cap, size_t more_elements);
|
||||
|
||||
|
||||
bool apfl_resizable_append(size_t elem_size, void **mem, size_t *len, size_t *cap, const void *other_mem, size_t other_len);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue