Recast more code in terms of the ptr_vector abstraction.
The mail_menu.c code also made a lot of unnecessary copies
of strings. For example, there was this code sequence:
for (i = z; i < lines - 1; i++) {
free(content[i]);
content[i] = strdup(content[i + 1]);
}
free(content[i]);
lines--;
content = (char **)realloc(content, sizeof(char *) * lines);
Here, `content` represents an array of lines of text.
This code is removing an element from somewhere in that
array (possibly in the middle), and then shifting the
remaining elements over one position.
But observe the calls to `free` and `strdup` in the loop
body: the content is already dynamically allocated. We
free whatever was in the selected position, and then make
*another copy* of the data in the next position to put
into the now-available slot in the array: repeat for the
remainder of the array's elements.
Instead, we could change this code to just shift things
down:
free(content[z]);
for (i = z; i < (lines - 1); ++i)
content[i] = content[i + 1];
--lines;
ncontent = realloc(content, sizeof(char *) * lines);
assert(ncontent == NULL);
content = ncontent;
However, the ptr_vector abstraction provides us a function,
`ptr_vector_del` that deletes an element from the array and
returns the pointer, so we can rewrite this as simply:
free(ptr_vector_del(&content, z));
No additional malloc()/free() required, which means less
pressure on the memory allocator and less copying of data.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
More cleaning up construction of arrays of things.
Introduce a utility function called, `split_on_space`
that tokenizes a string on a space character; use
it in most places where `strtok()` had been called.
More use of the ptr_vector type. Introduce a utility
function to get access to the pointers without consuming
the vector; this is used in the files code.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>
A repeated pattern in Magicka is to append to dynamically
sized arrays via malloc()/realloc(). Introduce the notion
of a "pointer vector": that is, a growable vector of
pointers, that can be reused to implement that logic more
safely and efficiently (this implementation uses power-of-two
growing).
Many malloc()/realloc() calls were not checked; these
assert() that the return value from realloc() is not NULL.
Add a method to consume the pointer vector: that is, realloc()
it to the current length and return the underlying pointers.
Make the `fmt` argument to dolog() const.
Include <sys/wait.h> in bluewave.c to squash a warning.
Signed-off-by: Dan Cross <patchdev@fat-dragon.org>